Mercurial > p > roundup > code
comparison roundup/support.py @ 3635:53987aa153d2
Transitive-property support.
- Fixed some of the pet-peeves from pep8
- Better parameter names for new _subselect method
- use new-style class for support.Proptree but needed a new-style class
for the property I introduced anyway.
- Fix a bug where searching did the wrong thing (interestingly enough
the same wrong thing for all backends): A search for
{'messages': ['1'], 'messages.author': ['2']}
would ignore the 'messages' part (messages being non-leaf node in
proptree). Fixed and added a regression test for this.
- Added the transitive searching to the SearchAction. New method
get_transitive_prop introduced in hyperdb that does the transitive
version of getprops()[name]. Fixed two tests to use the (faked) method
instead of getprop.
Now searching for transitive props via the web-interface works for me.
Thanks to alexander smishlajev for pointing me at the coding style.
Sorry for stepping on the peeves -- I'm using a different coding style
in most other projects I'm doing ...
| author | Ralf Schlatterbeck <schlatterbeck@users.sourceforge.net> |
|---|---|
| date | Thu, 13 Jul 2006 10:14:56 +0000 |
| parents | 57c66056ffe4 |
| children | fa7becc62534 |
comparison
equal
deleted
inserted
replaced
| 3634:57c66056ffe4 | 3635:53987aa153d2 |
|---|---|
| 4 | 4 |
| 5 __docformat__ = 'restructuredtext' | 5 __docformat__ = 'restructuredtext' |
| 6 | 6 |
| 7 import os, time, sys | 7 import os, time, sys |
| 8 import hyperdb | 8 import hyperdb |
| 9 | |
| 10 from sets import Set | |
| 9 | 11 |
| 10 class TruthDict: | 12 class TruthDict: |
| 11 '''Returns True for valid keys, False for others. | 13 '''Returns True for valid keys, False for others. |
| 12 ''' | 14 ''' |
| 13 def __init__(self, keys): | 15 def __init__(self, keys): |
| 30 | 32 |
| 31 Currently only implements method 'append' and iteration from a | 33 Currently only implements method 'append' and iteration from a |
| 32 full list interface. | 34 full list interface. |
| 33 Implementation: We manage a "sorted" status and sort on demand. | 35 Implementation: We manage a "sorted" status and sort on demand. |
| 34 Appending to the list will require re-sorting before use. | 36 Appending to the list will require re-sorting before use. |
| 35 >>> p = PrioList () | 37 >>> p = PrioList() |
| 36 >>> for i in 5,7,1,-1 : | 38 >>> for i in 5,7,1,-1: |
| 37 ... p.append (i) | 39 ... p.append(i) |
| 38 ... | 40 ... |
| 39 >>> for k in p : | 41 >>> for k in p: |
| 40 ... print k | 42 ... print k |
| 41 ... | 43 ... |
| 42 -1 | 44 -1 |
| 43 1 | 45 1 |
| 44 5 | 46 5 |
| 48 def __init__(self): | 50 def __init__(self): |
| 49 self.list = [] | 51 self.list = [] |
| 50 self.sorted = True | 52 self.sorted = True |
| 51 | 53 |
| 52 def append(self, item): | 54 def append(self, item): |
| 53 self.list.append (item) | 55 self.list.append(item) |
| 54 self.sorted = False | 56 self.sorted = False |
| 55 | 57 |
| 56 def __iter__(self): | 58 def __iter__(self): |
| 57 if not self.sorted : | 59 if not self.sorted: |
| 58 self.list.sort () | 60 self.list.sort() |
| 59 self.sorted = True | 61 self.sorted = True |
| 60 return iter (self.list) | 62 return iter(self.list) |
| 61 | 63 |
| 62 class Progress: | 64 class Progress: |
| 63 '''Progress display for console applications. | 65 '''Progress display for console applications. |
| 64 | 66 |
| 65 See __main__ block at end of file for sample usage. | 67 See __main__ block at end of file for sample usage. |
| 117 else: | 119 else: |
| 118 s = '%s %d done'%(self.info, self.num) | 120 s = '%s %d done'%(self.info, self.num) |
| 119 sys.stdout.write(s + ' '*(75-len(s)) + '\r') | 121 sys.stdout.write(s + ' '*(75-len(s)) + '\r') |
| 120 sys.stdout.flush() | 122 sys.stdout.flush() |
| 121 | 123 |
| 122 class Proptree : | 124 class Proptree(object): |
| 123 ''' Simple tree data structure for optimizing searching of properties | 125 ''' Simple tree data structure for optimizing searching of properties |
| 124 ''' | 126 ''' |
| 125 | 127 |
| 126 def __init__ (self, db, cls, name, props, parent = None, val = None) : | 128 def __init__(self, db, cls, name, props, parent = None, val = None): |
| 127 self.db = db | 129 self.db = db |
| 128 self.name = name | 130 self.name = name |
| 129 self.props = props | 131 self.props = props |
| 130 self.parent = parent | 132 self.parent = parent |
| 131 self.val = val | 133 self._val = val |
| 132 self.cls = cls | 134 self.cls = cls |
| 133 self.classname = None | 135 self.classname = None |
| 134 self.uniqname = None | 136 self.uniqname = None |
| 135 self.children = [] | 137 self.children = [] |
| 136 self.propnames = {} | 138 self.propnames = {} |
| 137 if parent : | 139 if parent: |
| 138 self.root = parent.root | 140 self.root = parent.root |
| 139 self.prcls = self.parent.props [name] | 141 self.prcls = self.parent.props [name] |
| 140 else : | 142 else: |
| 141 self.root = self | 143 self.root = self |
| 142 self.seqno = 1 | 144 self.seqno = 1 |
| 143 self.id = self.root.seqno | 145 self.id = self.root.seqno |
| 144 self.root.seqno += 1 | 146 self.root.seqno += 1 |
| 145 if self.cls : | 147 if self.cls: |
| 146 self.classname = self.cls.classname | 148 self.classname = self.cls.classname |
| 147 self.uniqname = '%s%s' % (self.cls.classname, self.id) | 149 self.uniqname = '%s%s' % (self.cls.classname, self.id) |
| 148 if not self.parent : | 150 if not self.parent: |
| 149 self.uniqname = self.cls.classname | 151 self.uniqname = self.cls.classname |
| 150 | 152 |
| 151 def append (self, name) : | 153 def append(self, name): |
| 152 if name in self.propnames : | 154 """Append a property to self.children. Will create a new |
| 155 propclass for the child. | |
| 156 """ | |
| 157 if name in self.propnames: | |
| 153 return self.propnames [name] | 158 return self.propnames [name] |
| 154 propclass = self.props [name] | 159 propclass = self.props [name] |
| 155 cls = None | 160 cls = None |
| 156 props = None | 161 props = None |
| 157 if isinstance (propclass, (hyperdb.Link, hyperdb.Multilink)) : | 162 if isinstance(propclass, (hyperdb.Link, hyperdb.Multilink)): |
| 158 cls = self.db.getclass (propclass.classname) | 163 cls = self.db.getclass(propclass.classname) |
| 159 props = cls.getprops () | 164 props = cls.getprops() |
| 160 child = self.__class__ (self.db, cls, name, props, parent = self) | 165 child = self.__class__(self.db, cls, name, props, parent = self) |
| 161 self.children.append (child) | 166 self.children.append(child) |
| 162 self.propnames [name] = child | 167 self.propnames [name] = child |
| 163 return child | 168 return child |
| 164 | 169 |
| 165 def __iter__ (self) : | 170 def _set_val(self, val): |
| 171 """Check if self._val is already defined. If yes, we compute the | |
| 172 intersection of the old and the new value(s) | |
| 173 """ | |
| 174 if self._val: | |
| 175 v = self._val | |
| 176 if not isinstance(self._val, type([])): | |
| 177 v = [self._val] | |
| 178 vals = Set(v) | |
| 179 vals.intersection_update(val) | |
| 180 self._val = [v for v in vals] | |
| 181 else: | |
| 182 self._val = val | |
| 183 | |
| 184 val = property(lambda self: self._val, _set_val) | |
| 185 | |
| 186 def __iter__(self): | |
| 166 """ Yield nodes in depth-first order -- visited nodes first """ | 187 """ Yield nodes in depth-first order -- visited nodes first """ |
| 167 for p in self.children : | 188 for p in self.children: |
| 168 yield p | 189 yield p |
| 169 for c in p : | 190 for c in p: |
| 170 yield c | 191 yield c |
| 171 | 192 |
| 172 # vim: set et sts=4 sw=4 : | 193 # vim: set et sts=4 sw=4 : |
