|
15 | 15 | # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, |
16 | 16 | # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
17 | 17 | # |
18 | | -#$Id: back_anydbm.py,v 1.142 2004-04-25 22:19:15 richard Exp $ |
| 18 | +#$Id: back_anydbm.py,v 1.143 2004-04-26 00:46:34 richard Exp $ |
19 | 19 | '''This module defines a backend that saves the hyperdatabase in a |
20 | 20 | database chosen by anydbm. It is guaranteed to always be available in python |
21 | 21 | versions >2.1.1 (the dumbdbm fallback in 2.1.1 and earlier has several |
@@ -1662,7 +1662,7 @@ def filter(self, search_matches, filterspec, sort=(None,None), |
1662 | 1662 | filterspec = l |
1663 | 1663 |
|
1664 | 1664 | # now, find all the nodes that are active and pass filtering |
1665 | | - l = [] |
| 1665 | + matches = [] |
1666 | 1666 | cldb = self.db.getclassdb(cn) |
1667 | 1667 | try: |
1668 | 1668 | # TODO: only full-scan once (use items()) |
@@ -1724,123 +1724,70 @@ def filter(self, search_matches, filterspec, sort=(None,None), |
1724 | 1724 | if node[k] != v: |
1725 | 1725 | break |
1726 | 1726 | else: |
1727 | | - l.append((nodeid, node)) |
| 1727 | + matches.append([nodeid, node]) |
1728 | 1728 | finally: |
1729 | 1729 | cldb.close() |
1730 | | - l.sort() |
1731 | 1730 |
|
1732 | 1731 | # filter based on full text search |
1733 | 1732 | if search_matches is not None: |
1734 | 1733 | k = [] |
1735 | | - for v in l: |
| 1734 | + for v in matches: |
1736 | 1735 | if search_matches.has_key(v[0]): |
1737 | 1736 | k.append(v) |
1738 | | - l = k |
1739 | | - |
1740 | | - # now, sort the result |
1741 | | - def sortfun(a, b, sort=sort, group=group, properties=self.getprops(), |
1742 | | - db = self.db, cl=self): |
1743 | | - a_id, an = a |
1744 | | - b_id, bn = b |
1745 | | - # sort by group and then sort |
1746 | | - for dir, prop in group, sort: |
1747 | | - if dir is None or prop is None: continue |
1748 | | - |
1749 | | - # sorting is class-specific |
1750 | | - propclass = properties[prop] |
| 1737 | + matches = k |
1751 | 1738 |
|
| 1739 | + # add sorting information to the match entries |
| 1740 | + directions = [] |
| 1741 | + for dir, prop in sort, group: |
| 1742 | + if dir is None or prop is None: |
| 1743 | + continue |
| 1744 | + directions.append(dir) |
| 1745 | + propclass = props[prop] |
| 1746 | + for entry in matches: |
| 1747 | + itemid = entry[-2] |
| 1748 | + item = entry[-1] |
1752 | 1749 | # handle the properties that might be "faked" |
1753 | 1750 | # also, handle possible missing properties |
1754 | 1751 | try: |
1755 | | - if not an.has_key(prop): |
1756 | | - an[prop] = cl.get(a_id, prop) |
1757 | | - av = an[prop] |
| 1752 | + v = self.get(itemid, prop) |
1758 | 1753 | except KeyError: |
1759 | 1754 | # the node doesn't have a value for this property |
1760 | | - if isinstance(propclass, Multilink): av = [] |
1761 | | - else: av = '' |
1762 | | - try: |
1763 | | - if not bn.has_key(prop): |
1764 | | - bn[prop] = cl.get(b_id, prop) |
1765 | | - bv = bn[prop] |
1766 | | - except KeyError: |
1767 | | - # the node doesn't have a value for this property |
1768 | | - if isinstance(propclass, Multilink): bv = [] |
1769 | | - else: bv = '' |
| 1755 | + if isinstance(propclass, Multilink): v = [] |
| 1756 | + else: v = None |
| 1757 | + s.append((v, itemid, item)) |
| 1758 | + continue |
1770 | 1759 |
|
1771 | | - # String and Date values are sorted in the natural way |
1772 | 1760 | if isinstance(propclass, String): |
1773 | | - # clean up the strings |
1774 | | - if av and av[0] in string.uppercase: |
1775 | | - av = av.lower() |
1776 | | - if bv and bv[0] in string.uppercase: |
1777 | | - bv = bv.lower() |
1778 | | - if (isinstance(propclass, String) or |
1779 | | - isinstance(propclass, Date)): |
1780 | 1761 | # it might be a string that's really an integer |
1781 | | - try: |
1782 | | - av = int(av) |
1783 | | - bv = int(bv) |
1784 | | - except: |
1785 | | - pass |
1786 | | - if dir == '+': |
1787 | | - r = cmp(av, bv) |
1788 | | - if r != 0: return r |
1789 | | - elif dir == '-': |
1790 | | - r = cmp(bv, av) |
1791 | | - if r != 0: return r |
1792 | | - |
1793 | | - # Link properties are sorted according to the value of |
1794 | | - # the "order" property on the linked nodes if it is |
1795 | | - # present; or otherwise on the key string of the linked |
1796 | | - # nodes; or finally on the node ids. |
| 1762 | + try: tv = int(v) |
| 1763 | + except: v = v.lower() |
| 1764 | + else: v = tv |
1797 | 1765 | elif isinstance(propclass, Link): |
1798 | | - link = db.classes[propclass.classname] |
1799 | | - if av is None and bv is not None: return -1 |
1800 | | - if av is not None and bv is None: return 1 |
1801 | | - if av is None and bv is None: continue |
| 1766 | + link = self.db.classes[propclass.classname] |
1802 | 1767 | if link.getprops().has_key('order'): |
1803 | | - if dir == '+': |
1804 | | - r = cmp(link.get(av, 'order'), |
1805 | | - link.get(bv, 'order')) |
1806 | | - if r != 0: return r |
1807 | | - elif dir == '-': |
1808 | | - r = cmp(link.get(bv, 'order'), |
1809 | | - link.get(av, 'order')) |
1810 | | - if r != 0: return r |
| 1768 | + v = link.get(v, 'order') |
1811 | 1769 | elif link.getkey(): |
1812 | 1770 | key = link.getkey() |
1813 | | - if dir == '+': |
1814 | | - r = cmp(link.get(av, key), link.get(bv, key)) |
1815 | | - if r != 0: return r |
1816 | | - elif dir == '-': |
1817 | | - r = cmp(link.get(bv, key), link.get(av, key)) |
1818 | | - if r != 0: return r |
| 1771 | + v = link.get(v, key) |
| 1772 | + entry.insert(0, v) |
| 1773 | + |
| 1774 | + if directions: |
| 1775 | + # sort using the first one or two columns |
| 1776 | + def sortfun(a, b, directions=directions, n=range(len(directions))): |
| 1777 | + for i in n: |
| 1778 | + if a[i] == b[i]: continue |
| 1779 | + if directions[i] == '-': |
| 1780 | + return cmp(a[i],b[i]) |
1819 | 1781 | else: |
1820 | | - if dir == '+': |
1821 | | - r = cmp(av, bv) |
1822 | | - if r != 0: return r |
1823 | | - elif dir == '-': |
1824 | | - r = cmp(bv, av) |
1825 | | - if r != 0: return r |
| 1782 | + return cmp(b[i],a[i]) |
| 1783 | + return 0 |
| 1784 | + matches.sort(sortfun) |
1826 | 1785 |
|
1827 | | - else: |
1828 | | - # all other types just compare |
1829 | | - if dir == '+': |
1830 | | - r = cmp(av, bv) |
1831 | | - elif dir == '-': |
1832 | | - r = cmp(bv, av) |
1833 | | - if r != 0: return r |
1834 | | - |
1835 | | - # end for dir, prop in sort, group: |
1836 | | - # if all else fails, compare the ids |
1837 | | - return cmp(a[0], b[0]) |
1838 | | - |
1839 | | - l.sort(sortfun) |
1840 | | - l = [i[0] for i in l] |
| 1786 | + # pull the id out of the individual entries |
| 1787 | + matches = [entry[-2] for entry in matches] |
1841 | 1788 | if __debug__: |
1842 | 1789 | self.db.stats['filtering'] += (time.time() - start_t) |
1843 | | - return l |
| 1790 | + return matches |
1844 | 1791 |
|
1845 | 1792 | def count(self): |
1846 | 1793 | '''Get the number of nodes in this class. |
|
0 commit comments