1
# -*- test-case-name: twisted.test.test_reflector -*-
2
# Copyright (c) 2001-2007 Twisted Matrix Laboratories.
3
# See LICENSE for details.
6
import weakref, warnings
8
from twisted.enterprise.util import DBError
14
Base class for enterprise reflectors. This implements row caching.
18
def __init__(self, rowClasses):
20
Initialize me against a database.
22
@param rowClasses: a list of row class objects that describe the
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
33
def __getstate__(self):
34
d = self.__dict__.copy()
38
def __setstate__(self, state):
40
self.rowCache = weakref.WeakValueDictionary()
44
"""Implement me to populate schema information for the reflector.
46
raise DBError("not implemented")
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
53
self.schema[ tableInfo.rowTableName ] = tableInfo
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)
61
def getTableInfo(self, rowObject):
62
"""Get a TableInfo record about a particular instance.
64
This record contains various information about the instance's
65
class as registered with this reflector.
67
@param rowObject: a L{RowObject} instance of a class previously
69
@raises twisted.enterprise.row.DBError: raised if this class was not
70
previously registered.
73
return self.schema[rowObject.rowTableName]
75
raise DBError("class %s was not registered with %s" % (
76
rowObject.__class__, self))
78
def buildWhereClause(self, relationship, row):
79
"""util method used by reflectors. builds a where clause to link a row to another table.
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] )
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"
92
parentInfo = self.getTableInfo(parentRow)
93
relationship = parentInfo.getRelationshipFor(tableName)
95
raise DBError("no relationship from %s to %s" % ( parentRow.rowTableName, tableName) )
97
if not relationship.containerMethod:
98
if hasattr(parentRow, "childRows"):
100
if row not in parentRow.childRows:
101
parentRow.childRows.append(row)
103
parentRow.childRows = rows
106
if not hasattr(parentRow, relationship.containerMethod):
107
raise DBError("parent row (%s) doesnt have container method <%s>!" % (parentRow, relationship.containerMethod))
109
meth = getattr(parentRow, relationship.containerMethod)
113
####### Row Cache ########
115
def addToCache(self, rowObject):
116
"""NOTE: Should this be recursive?! requires better container knowledge..."""
117
self.rowCache[ rowObject.getKeyTuple() ] = rowObject
119
def findInCache(self, rowClass, kw):
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)
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]
133
####### Row Operations ########
135
def loadObjectsFrom(self, tableName, parent=None, data=None,
136
whereClause=[], loadChildren=1):
137
"""Implement me to load objects from the database.
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)]
143
raise DBError("not implemented")
145
def updateRow(self, rowObject):
146
"""update this rowObject to the database.
148
raise DBError("not implemented")
150
def insertRow(self, rowObject):
151
"""insert a new row for this object instance.
153
raise DBError("not implemented")
155
def deleteRow(self, rowObject):
156
"""delete the row for this object from the database.
158
raise DBError("not implemented")
167
__all__ = ['Reflector', 'EQUAL', 'LESSTHAN', 'GREATERTHAN', 'LIKE']