[Checkins] SVN: grok/trunk/ Introduce grok.order directive.

Martijn Faassen faassen at infrae.com
Wed Jan 23 13:01:08 EST 2008


Log message for revision 83116:
  Introduce grok.order directive.
  

Changed:
  _U  grok/trunk/
  U   grok/trunk/CHANGES.txt
  U   grok/trunk/buildout.cfg
  U   grok/trunk/setup.py
  U   grok/trunk/src/grok/__init__.py
  U   grok/trunk/src/grok/directive.py
  U   grok/trunk/src/grok/interfaces.py
  A   grok/trunk/src/grok/tests/order/
  A   grok/trunk/src/grok/tests/order/__init__.py
  A   grok/trunk/src/grok/tests/order/arg_orderdirective.py
  A   grok/trunk/src/grok/tests/order/combined_orderdirective.py
  A   grok/trunk/src/grok/tests/order/combinednoorder_orderdirective.py
  A   grok/trunk/src/grok/tests/order/inter1.py
  A   grok/trunk/src/grok/tests/order/inter2.py
  A   grok/trunk/src/grok/tests/order/noarg_orderdirective.py
  A   grok/trunk/src/grok/tests/order/nodirective.py
  U   grok/trunk/src/grok/tests/test_grok.py
  U   grok/trunk/src/grok/util.py
  U   grok/trunk/versions.cfg

-=-

Property changes on: grok/trunk
___________________________________________________________________
Name: svn:externals
   - bootstrap svn://svn.zope.org/repos/main/zc.buildout/trunk/bootstrap/

   + bootstrap svn://svn.zope.org/repos/main/zc.buildout/trunk/bootstrap/
martian svn://svn.zope.org/repos/main/martian/trunk



Modified: grok/trunk/CHANGES.txt
===================================================================
--- grok/trunk/CHANGES.txt	2008-01-23 17:24:48 UTC (rev 83115)
+++ grok/trunk/CHANGES.txt	2008-01-23 18:01:08 UTC (rev 83116)
@@ -4,6 +4,15 @@
 0.12 (unreleased)
 =================
 
+Feature changes
+---------------
+
+* Add a new directive, ``grok.order()``, which can be used to help
+  sort components. At the time it is not used yet, but we intend to
+  use it for the viewlets support. Note that this means Grok now
+  requires Martian 0.9.3 or higher. See ``grok.interfaces`` for more
+  documentation on this directive.
+ 
 Bug fixes
 ---------
 

Modified: grok/trunk/buildout.cfg
===================================================================
--- grok/trunk/buildout.cfg	2008-01-23 17:24:48 UTC (rev 83115)
+++ grok/trunk/buildout.cfg	2008-01-23 18:01:08 UTC (rev 83116)
@@ -1,10 +1,13 @@
 [buildout]
-develop = . doc grokwiki
+develop = . doc grokwiki martian
 parts = docs interpreter grokwiki zopectl data test
 find-links = http://download.zope.org/distribution/
 extends = versions.cfg
 versions = versions
 
+[versions]
+martian = 0.9.3dev
+
 [docs]
 recipe = zc.recipe.egg
 eggs = grokdocs

Modified: grok/trunk/setup.py
===================================================================
--- grok/trunk/setup.py	2008-01-23 17:24:48 UTC (rev 83115)
+++ grok/trunk/setup.py	2008-01-23 18:01:08 UTC (rev 83116)
@@ -35,7 +35,7 @@
     include_package_data = True,
     zip_safe=False,
     install_requires=['setuptools',
-                      'martian >= 0.9.2',
+                      'martian >= 0.9.3dev',
                       'simplejson',
                       'pytz',
                       'ZODB3',

Modified: grok/trunk/src/grok/__init__.py
===================================================================
--- grok/trunk/src/grok/__init__.py	2008-01-23 17:24:48 UTC (rev 83115)
+++ grok/trunk/src/grok/__init__.py	2008-01-23 18:01:08 UTC (rev 83116)
@@ -42,7 +42,7 @@
 from grok.interfaces import IRESTSkinType
 from grok.directive import (context, name, title, template, templatedir,
                             provides, baseclass, global_utility, local_utility,
-                            permissions, require, site, layer, direct)
+                            permissions, require, site, layer, direct, order)
 from grok.decorators import subscribe, adapter, implementer
 from martian.error import GrokError, GrokImportError
 

Modified: grok/trunk/src/grok/directive.py
===================================================================
--- grok/trunk/src/grok/directive.py	2008-01-23 17:24:48 UTC (rev 83115)
+++ grok/trunk/src/grok/directive.py	2008-01-23 18:01:08 UTC (rev 83116)
@@ -25,6 +25,7 @@
                                InterfaceDirective,
                                InterfaceOrClassDirective,
                                ModuleDirectiveContext,
+                               OptionalValueDirective,
                                ClassDirectiveContext,
                                ClassOrModuleDirectiveContext)
 from martian import util
@@ -104,6 +105,19 @@
     def value_factory(self, *args):
         return args
 
+class OrderDirective(OptionalValueDirective, OnceDirective):
+
+    order = 0
+
+    def value_factory(self, value=None):
+        OrderDirective.order += 1
+        if value is not None:
+            return value, OrderDirective.order
+        return super(OrderDirective, self).value_factory(value)
+
+    def default_value(self):
+        return 0, OrderDirective.order
+
 # Define grok directives
 name = SingleTextDirective('grok.name', ClassDirectiveContext())
 template = SingleTextDirective('grok.template', ClassDirectiveContext())
@@ -124,4 +138,5 @@
     'grok.permissions', ClassDirectiveContext())
 layer = InterfaceOrClassDirective('grok.layer',
                            ClassOrModuleDirectiveContext())
-direct = MarkerDirective('grok.direct', ClassDirectiveContext())
\ No newline at end of file
+direct = MarkerDirective('grok.direct', ClassDirectiveContext())
+order = OrderDirective('grok.order', ClassDirectiveContext())

Modified: grok/trunk/src/grok/interfaces.py
===================================================================
--- grok/trunk/src/grok/interfaces.py	2008-01-23 17:24:48 UTC (rev 83115)
+++ grok/trunk/src/grok/interfaces.py	2008-01-23 18:01:08 UTC (rev 83116)
@@ -157,7 +157,26 @@
         It can only be used inside grok.Indexes subclasses.
         """
 
+    def order(value=None):
+        """Control the ordering of components.
 
+        If the value is specified, the order will be determined by sorting on 
+        it.
+        If no value is specified, the order will be determined by definition
+        order within the module.
+        If the directive is absent, the order will be determined by class name.
+        (unfortunately our preferred default behavior on absence which would
+        be like grok.order() without argument is hard to implement in Python)
+
+        Inter-module order is by dotted name of the module the
+        components are in; unless an explicit argument is specified to
+        ``grok.order()``, components are grouped by module.
+  
+        The function grok.util.sort_components can be used to sort
+        components according to these rules.
+        """
+
+
 class IGrokDecorators(interface.Interface):
 
     def subscribe(*classes_or_interfaces):

Added: grok/trunk/src/grok/tests/order/__init__.py
===================================================================
--- grok/trunk/src/grok/tests/order/__init__.py	                        (rev 0)
+++ grok/trunk/src/grok/tests/order/__init__.py	2008-01-23 18:01:08 UTC (rev 83116)
@@ -0,0 +1 @@
+#

Added: grok/trunk/src/grok/tests/order/arg_orderdirective.py
===================================================================
--- grok/trunk/src/grok/tests/order/arg_orderdirective.py	                        (rev 0)
+++ grok/trunk/src/grok/tests/order/arg_orderdirective.py	2008-01-23 18:01:08 UTC (rev 83116)
@@ -0,0 +1,33 @@
+"""
+
+If the grok.order directive is present with arguments, sorting will be
+done by the order specified.
+
+  >>> components = [First(), Second(), Third(), Fourth(), Fifth()]
+
+  >>> from grok.util import sort_components
+  >>> sort_components(components)
+  [<...Fifth object at ...>,
+   <...Fourth object at ...>,
+   <...Third object at ...>,
+   <...Second object at ...>,
+   <...First object at ...>]
+
+"""
+
+import grok
+
+class First(object):
+    grok.order(5)
+
+class Second(object):
+    grok.order(4)
+
+class Third(object):
+    grok.order(3)
+
+class Fourth(object):
+    grok.order(2)
+
+class Fifth(object):
+    grok.order(1)

Added: grok/trunk/src/grok/tests/order/combined_orderdirective.py
===================================================================
--- grok/trunk/src/grok/tests/order/combined_orderdirective.py	                        (rev 0)
+++ grok/trunk/src/grok/tests/order/combined_orderdirective.py	2008-01-23 18:01:08 UTC (rev 83116)
@@ -0,0 +1,34 @@
+"""
+
+If the grok.order directive is specified with other classes that don't
+have the order specified, then the order will be determined by first
+sorting on the order specified, and then by the definition order.
+
+  >>> components = [First(), Second(), Third(), Fourth(), Fifth()]
+
+  >>> from grok.util import sort_components
+  >>> sort_components(components)
+  [<...Third object at ...>,
+   <...Fourth object at ...>,
+   <...Second object at ...>,
+   <...Fifth object at ...>,
+   <...First object at ...>]
+
+"""
+
+import grok
+
+class First(object):
+    grok.order(2)
+
+class Second(object):
+    grok.order(1)
+
+class Third(object):
+    grok.order()
+
+class Fourth(object):
+    grok.order()
+
+class Fifth(object):
+    grok.order(1)

Added: grok/trunk/src/grok/tests/order/combinednoorder_orderdirective.py
===================================================================
--- grok/trunk/src/grok/tests/order/combinednoorder_orderdirective.py	                        (rev 0)
+++ grok/trunk/src/grok/tests/order/combinednoorder_orderdirective.py	2008-01-23 18:01:08 UTC (rev 83116)
@@ -0,0 +1,34 @@
+"""
+
+If the grok.order directive is specified with other classes that don't
+have the order specified, then the order will be determined by first
+sorting on the order specified, and then by the definition order.
+
+  >>> components = [First(), Second(), Third(), Fourth(), Fifth()]
+
+  >>> from grok.util import sort_components
+  >>> sort_components(components)
+  [<...Fifth object at ...>,
+   <...Third object at ...>,
+   <...First object at ...>,
+   <...Fourth object at ...>,
+   <...Second object at ...>]
+
+"""
+
+import grok
+
+class First(object):
+    grok.order()
+
+class Second(object):
+    grok.order(1)
+
+class Third(object):
+    pass
+
+class Fourth(object):
+    grok.order()
+
+class Fifth(object):
+    pass

Added: grok/trunk/src/grok/tests/order/inter1.py
===================================================================
--- grok/trunk/src/grok/tests/order/inter1.py	                        (rev 0)
+++ grok/trunk/src/grok/tests/order/inter1.py	2008-01-23 18:01:08 UTC (rev 83116)
@@ -0,0 +1,35 @@
+"""
+
+The ordering works like so:
+1. Objects with explicit ordering
+   (if combined with objects with no ordering not specified, then the orderless
+    objects come first)
+2. Objects with same ordering get grouped by module import order
+3. Internal order within module
+4. If no ordering is specified by any objects, then objects are sorted
+   alphabetically by class name
+
+  >>> from inter2 import Four, Five, Six
+  >>> components = [One(), Two(), Three(), Four(), Five(), Six()]
+
+  >>> from grok.util import sort_components
+  >>> sort_components(components)
+  [<...Three object at ...>,
+   <...One object at ...>,
+   <...Five object at ...>,
+   <...Six object at ...>,
+   <...Four object at ...>,
+   <...Two object at ...>]
+
+"""
+
+import grok
+
+class One(object):
+    grok.order()
+
+class Two(object):
+    grok.order(2)
+
+class Three(object):
+    pass

Added: grok/trunk/src/grok/tests/order/inter2.py
===================================================================
--- grok/trunk/src/grok/tests/order/inter2.py	                        (rev 0)
+++ grok/trunk/src/grok/tests/order/inter2.py	2008-01-23 18:01:08 UTC (rev 83116)
@@ -0,0 +1,14 @@
+"""
+This module used by inter1 tests
+"""
+
+import grok
+
+class Four(object):
+    grok.order(1)
+
+class Five(object):
+    pass
+
+class Six(object):
+    grok.order()

Added: grok/trunk/src/grok/tests/order/noarg_orderdirective.py
===================================================================
--- grok/trunk/src/grok/tests/order/noarg_orderdirective.py	                        (rev 0)
+++ grok/trunk/src/grok/tests/order/noarg_orderdirective.py	2008-01-23 18:01:08 UTC (rev 83116)
@@ -0,0 +1,33 @@
+"""
+
+If the grok.order directive is present with no arguments, sorting will
+be done by definition order.
+
+  >>> components = [First(), Second(), Third(), Fourth(), Fifth()]
+
+  >>> from grok.util import sort_components
+  >>> sort_components(components)
+  [<...First object at ...>,
+   <...Second object at ...>,
+   <...Third object at ...>,
+   <...Fourth object at ...>,
+   <...Fifth object at ...>]
+
+"""
+
+import grok
+
+class First(object):
+    grok.order()
+
+class Second(object):
+    grok.order()
+
+class Third(object):
+    grok.order()
+
+class Fourth(object):
+    grok.order()
+
+class Fifth(object):
+    grok.order()

Added: grok/trunk/src/grok/tests/order/nodirective.py
===================================================================
--- grok/trunk/src/grok/tests/order/nodirective.py	                        (rev 0)
+++ grok/trunk/src/grok/tests/order/nodirective.py	2008-01-23 18:01:08 UTC (rev 83116)
@@ -0,0 +1,31 @@
+"""
+
+If the grok.order directive is absent, sorting will be done by class
+name.
+
+  >>> components = [First(), Second(), Third(), Fourth(), Fifth()]
+
+  >>> from grok.util import sort_components
+  >>> sort_components(components)
+  [<...Fifth object at ...>,
+   <...First object at ...>,
+   <...Fourth object at ...>,
+   <...Second object at ...>,
+   <...Third object at ...>]
+
+"""
+
+class First(object):
+    pass
+
+class Second(object):
+    pass
+
+class Third(object):
+    pass
+
+class Fourth(object):
+    pass
+
+class Fifth(object):
+    pass

Modified: grok/trunk/src/grok/tests/test_grok.py
===================================================================
--- grok/trunk/src/grok/tests/test_grok.py	2008-01-23 17:24:48 UTC (rev 83115)
+++ grok/trunk/src/grok/tests/test_grok.py	2008-01-23 18:01:08 UTC (rev 83116)
@@ -45,7 +45,7 @@
     for name in ['adapter', 'error', 'view', 'event', 'security', 'catalog',
                  'zcml', 'static', 'utility', 'xmlrpc', 'json', 'container',
                  'traversal', 'form', 'grokker', 'directive', 'util',
-                 'baseclass', 'annotation', 'application', 'template']:
+                 'baseclass', 'annotation', 'application', 'template', 'order']:
         suite.addTest(suiteFromPackage(name))
     return suite
 

Modified: grok/trunk/src/grok/util.py
===================================================================
--- grok/trunk/src/grok/util.py	2008-01-23 17:24:48 UTC (rev 83115)
+++ grok/trunk/src/grok/util.py	2008-01-23 18:01:08 UTC (rev 83116)
@@ -109,3 +109,16 @@
 def public_methods_from_class(factory):
     return [m for m in methods_from_class(factory) if \
             not m.__name__.startswith('_')]
+
+def _sort_key(component):
+    explicit_order, implicit_order = class_annotation(component,
+                                                      'grok.order',
+                                                      (0,0))
+    return (explicit_order,
+            component.__module__,
+            implicit_order,
+            component.__class__.__name__)
+
+def sort_components(components):
+    # if components have a grok.order directive, sort by that
+    return sorted(components, key=_sort_key)

Modified: grok/trunk/versions.cfg
===================================================================
--- grok/trunk/versions.cfg	2008-01-23 17:24:48 UTC (rev 83115)
+++ grok/trunk/versions.cfg	2008-01-23 18:01:08 UTC (rev 83116)
@@ -1,7 +1,7 @@
 [versions]
 ClientForm = 0.2.7
 docutils = 0.4
-martian = 0.9.2
+martian = 0.9.3
 mechanize = 0.1.7b
 Pygments = 0.8.1
 pytz = 2007g



More information about the Checkins mailing list