[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