[POS-commit] Kiwi/Kiwi List.py,1.82,1.83

Christian Robottom Reis kiko at async.com.br
Wed Oct 15 04:16:59 BRST 2003


Update of /cvs/Kiwi/Kiwi
In directory anthem:/tmp/cvs-serv11571

Modified Files:
	List.py 
Log Message:
Overhaul CList._sort_rows_by_type: changed it to use decorators instead of the
(original and horrible) inline code and in the process sped it up, oh,
about 10 times for large lists. The API was changed to return rows
instead of mutating the original parameter.

Also fixed simple bug introduced in _get_insert_sorted_row() where we
were using "" as a default -- float/int/etc don't like this; they prefer
a zero.



Index: List.py
===================================================================
RCS file: /cvs/Kiwi/Kiwi/List.py,v
retrieving revision 1.82
retrieving revision 1.83
diff -u -d -r1.82 -r1.83
--- List.py	14 Oct 2003 23:50:13 -0000	1.82
+++ List.py	15 Oct 2003 04:16:56 -0000	1.83
@@ -1012,7 +1012,7 @@
             rowtext = _raw_get_text(self._o, middle, column)
             if decimal:
                 rowtext = translate(rowtext, decimal)
-            value = cmp(convert(text or ""), convert(rowtext or "")) * inc
+            value = cmp(convert(text or 0), convert(rowtext or 0)) * inc
 
             # We're down to a window of one element, just decide where
             # to put ours
@@ -1253,120 +1253,49 @@
                 return DateTimeFrom # Slow but works with most dates
         return lambda x: x
 
-    def _sort_rows_by_type(self, rows):
-        column = self.sort_column
-        tp = self._get_column_type(column)
-        # Do it all inline because the sort is so expensive. In case
-        # you're wondering why we sort ascending *and* descending
-        # (since you would think for descending we would only reverse
-        # the rows) you should realize that a column can be configured
-        # to *start up* as reverse sorted, in which case you need to
-        # sort in reverse the first time. The fast branch is handled in
-        # sort_with_type().
-        if self.sort_type == gtk.SORT_ASCENDING:
-            if tp in (IntType, FloatType):
-                #
-                # XXX: This ugliness will go away when somebody decides
-                # to rewrite the rows data structures, which I hope YOU
-                # do soon
-                #
-                if self._decimal_hack.has_key(column):
-                    trans = self._decimal_hack[column]
-                    for r in rows:
-                        r["text"][column] = string.translate(r["text"][column], trans)
-                rows.sort(lambda x, y, column=column: \
-                    # If values are equal
-                    (not x["text"][column] == y["text"][column]) and \
-                    # If x is none
-                    (x["text"][column] == "" and -1) or \
-                    # if y is none
-                    (y["text"][column] == "" and +1) or \
-                    # Normal cmp
-                    cmp(float(x["text"][column] or 0),
-                        float(y["text"][column] or 0))
-                    )
-                if self._decimal_hack.has_key(column):
-                    trans = self._decimal_hack[column]
-                    for r in rows:
-                        r["text"][column] = string.translate(r["text"][column], trans)
-            elif USE_MX and tp == DateTimeType:
-                if self.date_formats.has_key(column):
-                    format = self.date_formats[column]
-                    rows.sort(lambda x, y, column=column, format=format: \
-                        # If values are equal
-                        (not x["text"][column] == y["text"][column]) and \
-                        # If x is none
-                        (x["text"][column] == "" and -1) or \
-                        # if y is none
-                        (y["text"][column] == "" and +1) or \
-                        cmp(
-                            strptime(x["text"][column] or 0, format),
-                            strptime(y["text"][column] or 0, format)
-                        ))
-                else:
-                    rows.sort(lambda x, y, column=column: \
-                        # If values are equal
-                        (not x["text"][column] == y["text"][column]) and \
-                        # If x is none
-                        (x["text"][column] == "" and -1) or \
-                        # if y is none
-                        (y["text"][column] == "" and +1) or \
-                        # Normal cmp
-                        cmp(DateTimeFrom(x["text"][column] or 0),
-                            DateTimeFrom(y["text"][column] or 0))
-                        )
+    def _sort_rows_by_type(self, rows, direction):
+        # A sort function that uses a decorator to convert the row data
+        # into tuples. This sort function supports type-based sorting,
+        # which the GtkCList's internal sorting doesn't.
+        #
+        # Each branch defines a decorator function, that returns a
+        # tuple: first element is the data we want to sort, second is
+        # the original row data. The decorated data is sorted using
+        # Python's sort(), and the ordered original data returned.
+        #
+        # The code below suffers from intense obfuscation, and would be
+        # faster if not for Python1.5's lack of list comprehensions.
+        c = self.sort_column
+        tp = self._get_column_type(c)
+        if tp in (IntType, FloatType):
+            if self._decimal_hack.has_key(c):
+                d = self._decimal_hack[c]
+                t = string.translate
+                func = lambda x, c=c, t=t, d=d: \
+                        (float(t(x["text"][c], d) or 0), x)
             else:
-                raise AssertionError, 'Tried to sort type %s' % tp
-        else:
-            # Pay attention. y and x are inverted in the lambda *arguments*
-            if tp in (IntType, FloatType):
-                if self._decimal_hack.has_key(column):
-                    trans = self._decimal_hack[column]
-                    for r in rows:
-                        r["text"][column] = string.translate(r["text"][column], trans)
-                rows.sort(lambda y, x, column=column: \
-                    # If values are equal
-                    (not x["text"][column] == y["text"][column]) and \
-                    # If x is none
-                    (x["text"][column] == "" and -1) or \
-                    # if y is none
-                    (y["text"][column] == "" and +1) or \
-                    cmp(float(x["text"][column] or 0),
-                        float(y["text"][column] or 0))
-                    )
-                if self._decimal_hack.has_key(column):
-                    trans = self._decimal_hack[column]
-                    for r in rows:
-                        r["text"][column] = string.translate(r["text"][column], trans)
-            elif USE_MX and tp == DateTimeType:
-                if self.date_formats.has_key(column):
-                    format = self.date_formats[column]
-                    rows.sort(lambda y, x, column=column, format=format: \
-                        # If values are equal
-                        (not x["text"][column] == y["text"][column]) and \
-                        # If x is none
-                        (x["text"][column] == "" and -1) or \
-                        # if y is none
-                        (y["text"][column] == "" and +1) or \
-                        # Normal cmp
-                        cmp(
-                            strptime(x["text"][column] or 0, format),
-                            strptime(y["text"][column] or 0, format)
-                        ))
-                else:
-                    rows.sort(lambda y, x, column=column: \
-                        # If values are equal
-                        (not x["text"][column] == y["text"][column]) and \
-                        # If x is none
-                        (x["text"][column] == "" and -1) or \
-                        # if y is none
-                        (y["text"][column] == "" and +1) or \
-                        # Normal cmp
-                        cmp(DateTimeFrom(x["text"][column] or 0),
-                            DateTimeFrom(y["text"][column] or 0))
-                        )
+                func = lambda x, c=c: (float(x["text"][c] or 0), x)
+        elif USE_MX and tp == DateTimeType:
+            if self.date_formats.has_key(c):
+                f = self.date_formats[c]
+                s = strptime
+                func = lambda x, c=c, s=s, f=f: (s(x["text"][c] or 0, f), x)
             else:
-                raise AssertionError, 'Tried to sort type %s' % tp
+                # I wish DateTimeFrom didn't suck so much as a date
+                # conversion thing -- it often gets stuff wrong.
+                d = DateTimeFrom
+                func = lambda x, c=c, d=d: (d(x["text"][c] or 0), x)
+        else:
+            raise AssertionError, 'Tried to sort type %s' % tp
+
+        sort_rows = map(func, rows)
+        sort_rows.sort()
+        if direction == gtk.SORT_DESCENDING:
+            # Currently, it is impossible to obtain a reverse sort using
+            # normal column clicks, but it is possible via the API.
+            sort_rows.reverse()
+
+        return map(lambda x: x[1], sort_rows)
 
     def update_column_arrow(self):
         """
@@ -1441,7 +1370,7 @@
             # _sort_rows_by_type.
             if self.last_direction == -1 or self.last_column != column \
                  or self.tainted:
-                self._sort_rows_by_type(rows)
+                rows = self._sort_rows_by_type(rows, direction)
                 self.tainted = FALSE
             # Avoid expensive sort if we are reordering the same column
             # and the data in it is the same.



More information about the POS-commit mailing list