root / trunk / twisted / enterprise / reflector.py

Revision 23101, 5.8 kB (checked in by radix, 1 year ago)

Merge twisted-8.0.x-3085-4

Author: radix
Reviewer: therve
Fixes #3085

This includes lots of release shrapnel from the release of Twisted 8.0.0
and 8.0.1. release notes were written, version numbers were updated,
and deprecation warnings were updated.

Line 
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, autoLoad in tableInfo.rowForeignKeys:
57             self.schema[foreignTableName].addForeignKey(childColumns,
58                                                         parentColumns, tableInfo.rowClass,
59                                                         containerMethod, autoLoad)
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 to 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 object.
89         If a rowClass does not have a containerMethod, then a list attribute "childRows"
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.rowTableName, 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']
Note: See TracBrowser for help on using the browser.