root/tags/v1.0/object.py

Revision 4, 5.8 KB (checked in by daedalus, 5 years ago)

Added initial code attempts

Line 
1#
2# Configuration objects
3#
4
5import sys
6
7class ConfigKlass:
8    """
9    A ConfigObject is an abstract representation of something
10    that has configuration. We can perform common configuration
11    operations on ConfigObjects, based on what their configuration
12    is.
13    """
14    def __init__(self, name):
15        # attributes that all configuration objects have
16
17        # The generic class name of object, just a string
18        self.name = name
19
20        # A list of attributes that this object may have.
21        # This is an attribute vocabulary.
22        self.attrib = {}
23
24        # A list of klasses I can contain
25        self.can_contain = {}
26
27        # A list of klasses I can connect to
28        self.can_connect = {}
29
30    def attribute(self, name, attrib_type):
31        """
32        Add an attribute to this config object
33        """
34        self.attrib[name] = Attribute(name, attrib_type)
35
36    def contains(self, klassname, min=1, max=sys.maxint):
37        """
38        Add a containment relationship to the list
39        """
40        r = Contains(klassname, min, max)
41        self.can_contain[klassname] = r
42
43    def connects_to(self, klassname, min=1, max=sys.maxint):
44        r = ConnectsTo(klassname, min, max)
45        self.can_connect[klassname] = r
46
47    def __str__(self):
48        retstr = ['ConfigKlass: %s' % self.name, ]
49        retstr += ['  Attributes:',] + [ '    %s' % a for a in self.attrib.values() ]
50        retstr += ['  Contains:',] + [ '    %s' % a for a in self.can_contain.values() ]
51        retstr += ['  Connects to:',] + [ '    %s' % a for a in self.can_connect.values() ]
52        return '\n'.join(retstr)
53
54class Attribute:
55    """
56    An Attribute is a description of a single attribute that
57    a configuration object can have.
58
59    Attributes are stored in a database in some method. This
60    could be, in postgres, a set of tables, one for each type,
61    so the table would be something like:
62
63    attrib_int ( object_id FOREIGN_KEY, name VARCHAR, value INTEGER )
64    attrib_ipaddr ( object_id FOREIGN_KEY, name VARCHAR, value IPADDR )
65
66    which would key into the main object entity table:
67
68    objects ( object_id PRIMARY_KEY, klass VARCHAR UNIQUE )
69
70    Then, to get a particular object's information:
71
72    select * from objects LEFT JOIN attrib_int,attrib_varchar,attrib_ipaddr... etc for all tables
73    joining on the object_id
74   
75    """
76    def __init__(self, name, type):
77
78        # all attributes must have a name
79        self.name = name
80
81        # Type provides an indication of the database style
82        # type that would be used for this attribute, eg:
83        #    string
84        #    boolean
85        #    int
86        #    long
87        #    float
88        #    ipaddr
89        #   
90        self.type = type
91
92    def __str__(self):
93        return 'Attribute: %s [%s]' % (self.name, self.type)
94
95class RelationshipType:
96    """
97    Objects are related to one another by a Relationship, which
98    will be of a particular RelationshipType that constrains
99    the nature of the relationship.
100
101    Stored in a database thus:
102
103    relationships = ( object_id FOREIGN_KEY, relation_type, related_obj
104    """
105    def __init__(self, klass, min, max):
106
107        # The klass of object that this object can be related to
108        self.related_klass = klass
109
110        # The minimum number of other objects this object should
111        # be related to.
112        self.related_min = min
113
114        # The maximum number of other objects this object should
115        # be related to.
116        self.related_max = max
117
118    def __str__(self):
119        return 'Relationship: %s [min: %d, max: %d]' % (self.related_klass, self.related_min, self.related_max)
120       
121class Contains(RelationshipType):
122    """
123    The contains relationship says that an object contains
124    some number of other objects.
125    """
126
127class ConnectsTo(RelationshipType):
128    """
129    An object connects to another by some mechanism.
130    """
131
132class ConfigObject:
133    """
134    A ConfigObject is a specific instance of a ConfigKlass.
135
136    The ConfigKlass governs the possible configuration parameters
137    of this object.
138    """
139    def __init__(self, klass):
140        self.klass = klass
141
142        # name, value pairs for my attributes
143        self.attrib = {}
144
145        # name, value pairs for my relationships
146
147    def __setitem__(self, name, value):
148        """
149        Set attribute named 'name' to value.
150        Performs various constraint checks on the
151        attribute first.
152        """
153        # attempt to fetch the attribute from my klass, raising exceptions as required
154        try:
155            self.klass.attrib[name]
156        except KeyError, e:
157            raise KeyError("ConfigObject klass type '%s' does not support attribute: %s" % (self.klass.name, e))
158
159        print "attribute valid!"
160
161        self.attrib[name] = value
162
163    def __getitem__(self, name):
164        """
165        Try fetching an attribute value
166        """
167        try:
168            return self.attrib[name]
169        except KeyError:
170            # check to see if this attribute is available on this object's klass
171            if not self.klass.attrib.has_key(name):
172                raise KeyError("Attribute %s is not available on objects of type %s" % (name, self.klass.name))
173
174if __name__ == '__main__':
175
176    klasslist = {}
177
178    # set up a switch object class
179    switch = ConfigKlass('switch')
180
181    switch.attribute('name', 'varchar')
182
183    switch.contains('port', 24, 24)
184    switch.contains('cpu', 1)
185    switch.connects_to('switch')
186   
187    # Doing this when loading, I'll have to temporarily store objects
188    # if they can contain or connect to ones that haven't been loaded yet
189    # and then fix all the relationships at the end.
190
191    klasslist['switch'] = switch
192   
193    port = ConfigKlass('switchport')
194
195    klasslist['port'] = port
196
197    obj = ConfigObject(klasslist['switch'])
198
199    for klass in klasslist.values():
200        print '%s' % klass
201
202    obj['name'] = 'fred'
203    obj['port'] = 'fred'
204   
Note: See TracBrowser for help on using the browser.