OLD | NEW |
| (Empty) |
1 # -*- test-case-name: twisted.test.test_reflector -*- | |
2 # Copyright (c) 2001-2007 Twisted Matrix Laboratories. | |
3 # See LICENSE for details. | |
4 | |
5 | |
6 import weakref, warnings | |
7 | |
8 from twisted.enterprise.util import DBError | |
9 | |
10 class Reflector: | |
11 """ | |
12 DEPRECATED. | |
13 | |
14 Base class for enterprise reflectors. This implements row caching. | |
15 """ | |
16 populated = 0 | |
17 | |
18 def __init__(self, rowClasses): | |
19 """ | |
20 Initialize me against a database. | |
21 | |
22 @param rowClasses: a list of row class objects that describe the | |
23 database schema. | |
24 """ | |
25 warnings.warn("twisted.enterprise.reflector is deprecated since " | |
26 "Twisted 8.0", category=DeprecationWarning, stacklevel=2) | |
27 # does not hold references to cached rows. | |
28 self.rowCache = weakref.WeakValueDictionary() | |
29 self.rowClasses = rowClasses | |
30 self.schema = {} | |
31 self._populate() | |
32 | |
33 def __getstate__(self): | |
34 d = self.__dict__.copy() | |
35 del d['rowCache'] | |
36 return d | |
37 | |
38 def __setstate__(self, state): | |
39 self.__dict__ = state | |
40 self.rowCache = weakref.WeakValueDictionary() | |
41 self._populate() | |
42 | |
43 def _populate(self): | |
44 """Implement me to populate schema information for the reflector. | |
45 """ | |
46 raise DBError("not implemented") | |
47 | |
48 def populateSchemaFor(self, tableInfo): | |
49 """This is called once for each registered rowClass to add it | |
50 and its foreign key relationships for that rowClass to the | |
51 schema.""" | |
52 | |
53 self.schema[ tableInfo.rowTableName ] = tableInfo | |
54 | |
55 # add the foreign key to the foreign table. | |
56 for foreignTableName, childColumns, parentColumns, containerMethod, auto
Load in tableInfo.rowForeignKeys: | |
57 self.schema[foreignTableName].addForeignKey(childColumns, | |
58 parentColumns, tableInfo
.rowClass, | |
59 containerMethod, autoLoa
d) | |
60 | |
61 def getTableInfo(self, rowObject): | |
62 """Get a TableInfo record about a particular instance. | |
63 | |
64 This record contains various information about the instance's | |
65 class as registered with this reflector. | |
66 | |
67 @param rowObject: a L{RowObject} instance of a class previously | |
68 registered with me. | |
69 @raises twisted.enterprise.row.DBError: raised if this class was not | |
70 previously registered. | |
71 """ | |
72 try: | |
73 return self.schema[rowObject.rowTableName] | |
74 except KeyError: | |
75 raise DBError("class %s was not registered with %s" % ( | |
76 rowObject.__class__, self)) | |
77 | |
78 def buildWhereClause(self, relationship, row): | |
79 """util method used by reflectors. builds a where clause to link a row t
o another table. | |
80 """ | |
81 whereClause = [] | |
82 for i in range(0,len(relationship.childColumns)): | |
83 value = getattr(row, relationship.parentColumns[i][0]) | |
84 whereClause.append( [relationship.childColumns[i][0], EQUAL, value]
) | |
85 return whereClause | |
86 | |
87 def addToParent(self, parentRow, rows, tableName): | |
88 """util method used by reflectors. adds these rows to the parent row obj
ect. | |
89 If a rowClass does not have a containerMethod, then a list attribute "ch
ildRows" | |
90 will be used. | |
91 """ | |
92 parentInfo = self.getTableInfo(parentRow) | |
93 relationship = parentInfo.getRelationshipFor(tableName) | |
94 if not relationship: | |
95 raise DBError("no relationship from %s to %s" % ( parentRow.rowTable
Name, tableName) ) | |
96 | |
97 if not relationship.containerMethod: | |
98 if hasattr(parentRow, "childRows"): | |
99 for row in rows: | |
100 if row not in parentRow.childRows: | |
101 parentRow.childRows.append(row) | |
102 else: | |
103 parentRow.childRows = rows | |
104 return | |
105 | |
106 if not hasattr(parentRow, relationship.containerMethod): | |
107 raise DBError("parent row (%s) doesnt have container method <%s>!" %
(parentRow, relationship.containerMethod)) | |
108 | |
109 meth = getattr(parentRow, relationship.containerMethod) | |
110 for row in rows: | |
111 meth(row) | |
112 | |
113 ####### Row Cache ######## | |
114 | |
115 def addToCache(self, rowObject): | |
116 """NOTE: Should this be recursive?! requires better container knowledge.
..""" | |
117 self.rowCache[ rowObject.getKeyTuple() ] = rowObject | |
118 | |
119 def findInCache(self, rowClass, kw): | |
120 keys = [] | |
121 keys.append(rowClass.rowTableName) | |
122 for keyName, keyType in rowClass.rowKeyColumns: | |
123 keys.append( kw[keyName] ) | |
124 keyTuple = tuple(keys) | |
125 return self.rowCache.get(keyTuple) | |
126 | |
127 def removeFromCache(self, rowObject): | |
128 """NOTE: should this be recursive!??""" | |
129 key = rowObject.getKeyTuple() | |
130 if self.rowCache.has_key(key): | |
131 del self.rowCache[key] | |
132 | |
133 ####### Row Operations ######## | |
134 | |
135 def loadObjectsFrom(self, tableName, parent=None, data=None, | |
136 whereClause=[], loadChildren=1): | |
137 """Implement me to load objects from the database. | |
138 | |
139 @param whereClause: a list of tuples of (columnName, conditional, value) | |
140 so it can be parsed by all types of reflectors. eg.:: | |
141 whereClause = [("name", EQUALS, "fred"), ("age", GREATERTHAN, 18)] | |
142 """ | |
143 raise DBError("not implemented") | |
144 | |
145 def updateRow(self, rowObject): | |
146 """update this rowObject to the database. | |
147 """ | |
148 raise DBError("not implemented") | |
149 | |
150 def insertRow(self, rowObject): | |
151 """insert a new row for this object instance. | |
152 """ | |
153 raise DBError("not implemented") | |
154 | |
155 def deleteRow(self, rowObject): | |
156 """delete the row for this object from the database. | |
157 """ | |
158 raise DBError("not implemented") | |
159 | |
160 # conditionals | |
161 EQUAL = 0 | |
162 LESSTHAN = 1 | |
163 GREATERTHAN = 2 | |
164 LIKE = 3 | |
165 | |
166 | |
167 __all__ = ['Reflector', 'EQUAL', 'LESSTHAN', 'GREATERTHAN', 'LIKE'] | |
OLD | NEW |