1515# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
1616# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1717#
18- #$Id: back_anydbm.py,v 1.55 2002-07-30 08: 22:38 richard Exp $
18+ #$Id: back_anydbm.py,v 1.56 2002-07-31 22:04:33 richard Exp $
1919'''
2020This module defines a backend that saves the hyperdatabase in a database
2121chosen by anydbm. It is guaranteed to always be available in python
@@ -1359,18 +1359,25 @@ def list(self):
13591359 l .sort ()
13601360 return l
13611361
1362- # XXX not in spec
13631362 def filter (self , search_matches , filterspec , sort , group ,
13641363 num_re = re .compile ('^\d+$' )):
13651364 ''' Return a list of the ids of the active nodes in this class that
13661365 match the 'filter' spec, sorted by the group spec and then the
1367- sort spec
1366+ sort spec.
1367+
1368+ "filterspec" is {propname: value(s)}
1369+ "sort" is ['+propname', '-propname', 'propname', ...]
1370+ "group is ['+propname', '-propname', 'propname', ...]
13681371 '''
13691372 cn = self .classname
13701373
13711374 # optimise filterspec
13721375 l = []
13731376 props = self .getprops ()
1377+ LINK = 0
1378+ MULTILINK = 1
1379+ STRING = 2
1380+ OTHER = 6
13741381 for k , v in filterspec .items ():
13751382 propclass = props [k ]
13761383 if isinstance (propclass , Link ):
@@ -1389,7 +1396,7 @@ def filter(self, search_matches, filterspec, sort, group,
13891396 k , entry , self .properties [k ].classname )
13901397 u .append (entry )
13911398
1392- l .append ((0 , k , u ))
1399+ l .append ((LINK , k , u ))
13931400 elif isinstance (propclass , Multilink ):
13941401 if type (v ) is not type ([]):
13951402 v = [v ]
@@ -1404,58 +1411,66 @@ def filter(self, search_matches, filterspec, sort, group,
14041411 raise ValueError , 'new property "%s": %s not a %s' % (
14051412 k , entry , self .properties [k ].classname )
14061413 u .append (entry )
1407- l .append ((1 , k , u ))
1414+ l .append ((MULTILINK , k , u ))
14081415 elif isinstance (propclass , String ):
14091416 # simple glob searching
14101417 v = re .sub (r'([\|\{\}\\\.\+\[\]\(\)])' , r'\\\1' , v )
14111418 v = v .replace ('?' , '.' )
14121419 v = v .replace ('*' , '.*?' )
1413- l .append ((2 , k , re .compile (v , re .I )))
1420+ l .append ((STRING , k , re .compile (v , re .I )))
14141421 elif isinstance (propclass , Boolean ):
14151422 if type (v ) is type ('' ):
14161423 bv = v .lower () in ('yes' , 'true' , 'on' , '1' )
14171424 else :
14181425 bv = v
1419- l .append ((6 , k , bv ))
1426+ l .append ((OTHER , k , bv ))
14201427 elif isinstance (propclass , Number ):
1421- l .append ((6 , k , int (v )))
1428+ l .append ((OTHER , k , int (v )))
14221429 else :
1423- l .append ((6 , k , v ))
1430+ l .append ((OTHER , k , v ))
14241431 filterspec = l
14251432
14261433 # now, find all the nodes that are active and pass filtering
14271434 l = []
14281435 cldb = self .db .getclassdb (cn )
14291436 try :
1437+ # TODO: only full-scan once (use items())
14301438 for nodeid in self .db .getnodeids (cn , cldb ):
14311439 node = self .db .getnode (cn , nodeid , cldb )
14321440 if node .has_key (self .db .RETIRED_FLAG ):
14331441 continue
14341442 # apply filter
14351443 for t , k , v in filterspec :
1436- # this node doesn't have this property, so reject it
1437- if not node .has_key (k ): break
1444+ # make sure the node has the property
1445+ if not node .has_key (k ):
1446+ # this node doesn't have this property, so reject it
1447+ break
14381448
1439- if t == 0 and node [k ] not in v :
1440- # link - if this node'd property doesn't appear in the
1449+ # now apply the property filter
1450+ if t == LINK :
1451+ # link - if this node's property doesn't appear in the
14411452 # filterspec's nodeid list, skip it
1442- break
1443- elif t == 1 :
1453+ if node [k ] not in v :
1454+ break
1455+ elif t == MULTILINK :
14441456 # multilink - if any of the nodeids required by the
14451457 # filterspec aren't in this node's property, then skip
14461458 # it
1447- for value in v :
1448- if value not in node [k ]:
1459+ have = node [k ]
1460+ for want in v :
1461+ if want not in have :
14491462 break
14501463 else :
14511464 continue
14521465 break
1453- elif t == 2 and ( node [ k ] is None or not v . search ( node [ k ])) :
1466+ elif t == STRING :
14541467 # RE search
1455- break
1456- elif t == 6 and node [k ] != v :
1468+ if node [k ] is None or not v .search (node [k ]):
1469+ break
1470+ elif t == OTHER :
14571471 # straight value comparison for the other types
1458- break
1472+ if node [k ] != v :
1473+ break
14591474 else :
14601475 l .append ((nodeid , node ))
14611476 finally :
@@ -1465,9 +1480,7 @@ def filter(self, search_matches, filterspec, sort, group,
14651480 # filter based on full text search
14661481 if search_matches is not None :
14671482 k = []
1468- l_debug = []
14691483 for v in l :
1470- l_debug .append (v [0 ])
14711484 if search_matches .has_key (v [0 ]):
14721485 k .append (v )
14731486 l = k
@@ -1778,6 +1791,12 @@ def __init__(self, db, classname, **properties):
17781791
17791792#
17801793#$Log: not supported by cvs2svn $
1794+ #Revision 1.55 2002/07/30 08:22:38 richard
1795+ #Session storage in the hyperdb was horribly, horribly inefficient. We use
1796+ #a simple anydbm wrapper now - which could be overridden by the metakit
1797+ #backend or RDB backend if necessary.
1798+ #Much, much better.
1799+ #
17811800#Revision 1.54 2002/07/26 08:26:59 richard
17821801#Very close now. The cgi and mailgw now use the new security API. The two
17831802#templates have been migrated to that setup. Lots of unit tests. Still some
0 commit comments