Anonymous committed 556b55e

Revert 82b9f9942bb (collection indexing/Sprox), see changelog 1.3b2 section.

Comments (0)

Files changed (2)

+1.3b2 (2011-03-20)
+* webhelpers.paginate:
+  - Revert Sprox patch (#59) from 1.3b1; it makes SQLAlchemy inefficient (#63).
+    The Sprox object is apparently incompatible because it's not sliceable.
+    Changed get_wrapper() test to require .__getslice__, and moved its stanza
+    below SQLAlchemy tests because SQLAlchemy queries and selects don't have
+    .__getslice__ either; but that's OK because their paginate wrappers
+    emulate it. 
 1.3b1 (2011-03-17)


     import sqlalchemy.orm   # Some users report errors if this is not imported.
     sqlalchemy_available = False
+    sqlalchemy_version = None
-    sqlalchemy_available = sqlalchemy.__version__
+    sqlalchemy_available = True
+    sqlalchemy_version = sqlalchemy.__version__
 def get_wrapper(obj, sqlalchemy_session=None):
     if isinstance(obj, (list, tuple)):
         return obj
-    # If object is iterable we can use it directly
-    if hasattr(obj, "__iter__") and hasattr(obj, "__len__"):
-        return obj
     # Is SQLAlchemy 0.4 or better available? (0.3 is not supported - sorry)
-    if sqlalchemy_available[:3] != '0.3':
+    # Note: SQLAlchemy objects aren't sliceable, so this has to be before
+    # the next if-stanza
+    if sqlalchemy_available and sqlalchemy_version[:3] != '0.3':
         # Is the collection a query?
         if isinstance(obj, sqlalchemy.orm.query.Query):
             return _SQLAlchemyQuery(obj)
             or isinstance(obj, sqlalchemy.sql.expression.Select):
                 return _SQLAlchemySelect(obj, sqlalchemy_session)
+    # If object is iterable and sliceable we can use it directly
+    required_methods = ["__iter__", "__len__", "__slice__"]
+    for meth in required_methods:
+        if not hasattr(obj, meth):
+            break
+    else:
+        return obj
     raise TypeError("Sorry, your collection type is not supported by the "
         "paginate module. You can provide a list, a tuple, a SQLAlchemy "
         "select object or a SQLAlchemy ORM-query object.")
     Iterable that allows to get slices from an SQLAlchemy Select object
     def __init__(self, obj, sqlalchemy_session=None):
-        if not isinstance(sqlalchemy_session, sqlalchemy.orm.scoping.ScopedSession):
+        session_types = (
+            sqlalchemy.orm.scoping.ScopedSession,
+            sqlalchemy.orm.Session)
+        if not isinstance(sqlalchemy_session, session_types):
             raise TypeError("If you want to page an SQLAlchemy 'select' object then you "
                     "have to provide a 'sqlalchemy_session' argument. See also: "
             if presliced_list:
                 self.items = self.collection
-                self.items = list(self.collection)[self.first_item-1:self.last_item]
+                self.items = list(self.collection[self.first_item-1:self.last_item])
             # Links to previous and next page
             if > self.first_page:
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.