[Checkins] SVN: megrok.traject/ Initial import.

Martijn Faassen faassen at startifact.com
Fri Oct 23 11:30:59 EDT 2009


Log message for revision 105245:
  Initial import.
  

Changed:
  A   megrok.traject/
  A   megrok.traject/trunk/
  A   megrok.traject/trunk/CHANGES.txt
  A   megrok.traject/trunk/bootstrap.py
  A   megrok.traject/trunk/buildout.cfg
  A   megrok.traject/trunk/setup.py
  A   megrok.traject/trunk/src/
  A   megrok.traject/trunk/src/megrok/
  A   megrok.traject/trunk/src/megrok/__init__.py
  A   megrok.traject/trunk/src/megrok/traject/
  A   megrok.traject/trunk/src/megrok/traject/__init__.py
  A   megrok.traject/trunk/src/megrok/traject/components.py
  A   megrok.traject/trunk/src/megrok/traject/ftesting.zcml
  A   megrok.traject/trunk/src/megrok/traject/ftests/
  A   megrok.traject/trunk/src/megrok/traject/ftests/__init__.py
  A   megrok.traject/trunk/src/megrok/traject/ftests/test_traject_functional.py
  A   megrok.traject/trunk/src/megrok/traject/ftests/traject/
  A   megrok.traject/trunk/src/megrok/traject/ftests/traject/__init__.py
  A   megrok.traject/trunk/src/megrok/traject/ftests/traject/deepertraject.py
  A   megrok.traject/trunk/src/megrok/traject/ftests/traject/notfound.py
  A   megrok.traject/trunk/src/megrok/traject/ftests/traject/root.py
  A   megrok.traject/trunk/src/megrok/traject/ftests/traject/traject.py
  A   megrok.traject/trunk/src/megrok/traject/interfaces.py
  A   megrok.traject/trunk/src/megrok/traject/meta.py
  A   megrok.traject/trunk/src/megrok/traject/meta.zcml

-=-
Added: megrok.traject/trunk/CHANGES.txt
===================================================================
--- megrok.traject/trunk/CHANGES.txt	                        (rev 0)
+++ megrok.traject/trunk/CHANGES.txt	2009-10-23 15:30:59 UTC (rev 105245)
@@ -0,0 +1,3 @@
+CHANGES.txt
+===========
+

Added: megrok.traject/trunk/bootstrap.py
===================================================================
--- megrok.traject/trunk/bootstrap.py	                        (rev 0)
+++ megrok.traject/trunk/bootstrap.py	2009-10-23 15:30:59 UTC (rev 105245)
@@ -0,0 +1,84 @@
+##############################################################################
+#
+# Copyright (c) 2006 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+
+$Id$
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+is_jython = sys.platform.startswith('java')
+
+try:
+    import pkg_resources
+except ImportError:
+    ez = {}
+    exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+                         ).read() in ez
+    ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+    import pkg_resources
+
+if sys.platform == 'win32':
+    def quote(c):
+        if ' ' in c:
+            return '"%s"' % c # work around spawn lamosity on windows
+        else:
+            return c
+else:
+    def quote (c):
+        return c
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+ws  = pkg_resources.working_set
+
+if len(sys.argv) > 2 and sys.argv[1] == '--version':
+    VERSION = '==%s' % sys.argv[2]
+    args = sys.argv[3:] + ['bootstrap']
+else:
+    VERSION = ''
+    args = sys.argv[1:] + ['bootstrap']
+
+if is_jython:
+    import subprocess
+
+    assert subprocess.Popen([sys.executable] + ['-c', quote(cmd), '-mqNxd',
+           quote(tmpeggs), 'zc.buildout' + VERSION],
+           env=dict(os.environ,
+               PYTHONPATH=
+               ws.find(pkg_resources.Requirement.parse('setuptools')).location
+               ),
+           ).wait() == 0
+
+else:
+    assert os.spawnle(
+        os.P_WAIT, sys.executable, quote (sys.executable),
+        '-c', quote (cmd), '-mqNxd', quote (tmpeggs), 'zc.buildout' + VERSION,
+        dict(os.environ,
+            PYTHONPATH=
+            ws.find(pkg_resources.Requirement.parse('setuptools')).location
+            ),
+        ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout' + VERSION)
+import zc.buildout.buildout
+zc.buildout.buildout.main(args)
+shutil.rmtree(tmpeggs)

Added: megrok.traject/trunk/buildout.cfg
===================================================================
--- megrok.traject/trunk/buildout.cfg	                        (rev 0)
+++ megrok.traject/trunk/buildout.cfg	2009-10-23 15:30:59 UTC (rev 105245)
@@ -0,0 +1,11 @@
+[buildout]
+develop = . ../traject
+parts = test
+find-links = http://download.zope.org/distribution/
+extends = http://grok.zope.org/releaseinfo/grok-1.0a4.cfg
+versions = versions
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = megrok.traject
+defaults = ['--tests-pattern', '^f?tests$', '-v']

Added: megrok.traject/trunk/setup.py
===================================================================
--- megrok.traject/trunk/setup.py	                        (rev 0)
+++ megrok.traject/trunk/setup.py	2009-10-23 15:30:59 UTC (rev 105245)
@@ -0,0 +1,45 @@
+import os
+from setuptools import setup, find_packages
+
+version = '0.1dev'
+
+def read(*filenames):
+    return open(os.path.join(os.path.dirname(__file__), *filenames)).read()
+
+setup(name='megrok.traject',
+      version=version,
+      description="Traject integration for Grok applications",
+      
+      # Use classifiers that are already listed at:
+      # http://pypi.python.org/pypi?%3Aaction=list_classifiers
+      classifiers=['Development Status :: 5 - Production/Stable',
+                   'Environment :: Web Environment',
+                   'Framework :: Zope3',
+                   'Intended Audience :: Developers',
+                   'License :: OSI Approved :: Zope Public License',
+                   'Operating System :: OS Independent',
+                   'Programming Language :: Python',
+                   'Topic :: Internet :: WWW/HTTP',
+                   'Topic :: Software Development :: Libraries',
+                   ],
+      keywords="grok megrok url traject traversal routing route",
+      author="Martijn Faassen",
+      author_email="faassen at startifact.com",
+      license="ZPL",
+      package_dir={'': 'src'},
+      namespace_packages=['megrok'],
+      packages=find_packages('src'),
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['setuptools',
+                        'grok', # for grok.Traverser, ideally get rid of that
+                        'traject',
+                        'martian',
+                        'grokcore.component',
+                        'zope.publisher',
+                        'zope.component',
+                        ],
+      entry_points="""
+      # Add entry points here
+      """,
+      )

Added: megrok.traject/trunk/src/megrok/__init__.py
===================================================================
--- megrok.traject/trunk/src/megrok/__init__.py	                        (rev 0)
+++ megrok.traject/trunk/src/megrok/__init__.py	2009-10-23 15:30:59 UTC (rev 105245)
@@ -0,0 +1,6 @@
+# namespace package boilerplate
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError, e:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)

Added: megrok.traject/trunk/src/megrok/traject/__init__.py
===================================================================
--- megrok.traject/trunk/src/megrok/traject/__init__.py	                        (rev 0)
+++ megrok.traject/trunk/src/megrok/traject/__init__.py	2009-10-23 15:30:59 UTC (rev 105245)
@@ -0,0 +1,18 @@
+##############################################################################
+#
+# Copyright (c) 2009 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+"""megrok.traject - URL routing for Grok
+"""
+from megrok.traject.components import Traject
+

Added: megrok.traject/trunk/src/megrok/traject/components.py
===================================================================
--- megrok.traject/trunk/src/megrok/traject/components.py	                        (rev 0)
+++ megrok.traject/trunk/src/megrok/traject/components.py	2009-10-23 15:30:59 UTC (rev 105245)
@@ -0,0 +1,48 @@
+##############################################################################
+#
+# Copyright (c) 2009 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+"""megrok.traject components"""
+
+import grok
+import traject
+
+class Traject(object):
+    grok.baseclass()
+
+    pattern = None
+    model = None
+    
+    def factory(**kw):
+        raise NotImplementedError
+
+    def arguments(obj):
+        return NotImplementedError
+
+class TrajectTraverser(grok.Traverser):
+    grok.baseclass()
+        
+    def traverse(self, name):
+        stack = self.request.getTraversalStack()
+        stack.append(name)
+        unconsumed, obj = traject.consume_stack(
+            self.context, stack, DefaultModel)
+        # if we haven't consumed *anything* we can't traverse, fall back
+        if obj is self.context:
+            return None
+        self.request.setTraversalStack(unconsumed)
+        return obj
+
+class DefaultModel(grok.Model):
+    def __init__(self, **kw):
+        self.kw = kw

Added: megrok.traject/trunk/src/megrok/traject/ftesting.zcml
===================================================================
--- megrok.traject/trunk/src/megrok/traject/ftesting.zcml	                        (rev 0)
+++ megrok.traject/trunk/src/megrok/traject/ftesting.zcml	2009-10-23 15:30:59 UTC (rev 105245)
@@ -0,0 +1,37 @@
+<configure
+   xmlns="http://namespaces.zope.org/zope"
+   xmlns:grok="http://namespaces.zope.org/grok"
+   i18n_domain="grok"
+   package="megrok.traject"
+   >
+
+  <include package="grok" />
+  <include package="megrok.traject" file="meta.zcml" />
+
+  <grok:grok package="megrok.traject.ftests" />
+
+  <securityPolicy
+      component="zope.securitypolicy.zopepolicy.ZopeSecurityPolicy"
+      />
+
+  <unauthenticatedPrincipal
+      id="zope.anybody"
+      title="Unauthenticated User"
+      />
+  <grant
+      permission="zope.View"
+      principal="zope.anybody"
+      />
+
+  <principal
+      id="zope.mgr"
+      title="Manager"
+      login="mgr"
+      password="mgrpw"
+      />
+
+  <role id="zope.Manager" title="Site Manager" />
+  <grantAll role="zope.Manager" />
+  <grant role="zope.Manager" principal="zope.mgr" />
+
+</configure>

Added: megrok.traject/trunk/src/megrok/traject/ftests/__init__.py
===================================================================
--- megrok.traject/trunk/src/megrok/traject/ftests/__init__.py	                        (rev 0)
+++ megrok.traject/trunk/src/megrok/traject/ftests/__init__.py	2009-10-23 15:30:59 UTC (rev 105245)
@@ -0,0 +1 @@
+"""Functional tests for megrok.traject."""

Added: megrok.traject/trunk/src/megrok/traject/ftests/test_traject_functional.py
===================================================================
--- megrok.traject/trunk/src/megrok/traject/ftests/test_traject_functional.py	                        (rev 0)
+++ megrok.traject/trunk/src/megrok/traject/ftests/test_traject_functional.py	2009-10-23 15:30:59 UTC (rev 105245)
@@ -0,0 +1,58 @@
+import re
+import unittest
+import megrok.traject
+import os
+
+from pkg_resources import resource_listdir
+from zope.testing import doctest, renormalizing
+from zope.app.testing.functional import (HTTPCaller, getRootFolder,
+                                         FunctionalTestSetup, sync, ZCMLLayer)
+
+ftesting_zcml = os.path.join(os.path.dirname(megrok.traject.__file__),
+                             'ftesting.zcml')
+FunctionalLayer = ZCMLLayer(ftesting_zcml, __name__, 'FunctionalLayer')
+
+def setUp(test):
+    FunctionalTestSetup().setUp()
+
+def tearDown(test):
+    FunctionalTestSetup().tearDown()
+
+checker = renormalizing.RENormalizing([
+    # Accommodate to exception wrapping in newer versions of mechanize
+    (re.compile(r'httperror_seek_wrapper:', re.M), 'HTTPError:'),
+    ])
+
+def suiteFromPackage(name):
+    files = resource_listdir(__name__, name)
+    suite = unittest.TestSuite()
+    for filename in files:
+        if not filename.endswith('.py'):
+            continue
+        if filename == '__init__.py':
+            continue
+
+        dottedname = 'megrok.traject.ftests.%s.%s' % (name, filename[:-3])
+        test = doctest.DocTestSuite(
+            dottedname, setUp=setUp, tearDown=tearDown,
+            checker=checker,
+            extraglobs=dict(http=HTTPCaller(),
+                            getRootFolder=getRootFolder,
+                            sync=sync),
+            optionflags=(doctest.ELLIPSIS+
+                         doctest.NORMALIZE_WHITESPACE+
+                         doctest.REPORT_NDIFF)
+            )
+        test.layer = FunctionalLayer
+
+        suite.addTest(test)
+    return suite
+
+def test_suite():
+    suite = unittest.TestSuite()
+    for name in ['traject']:
+        suite.addTest(suiteFromPackage(name))
+    return suite
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')

Added: megrok.traject/trunk/src/megrok/traject/ftests/traject/__init__.py
===================================================================
--- megrok.traject/trunk/src/megrok/traject/ftests/traject/__init__.py	                        (rev 0)
+++ megrok.traject/trunk/src/megrok/traject/ftests/traject/__init__.py	2009-10-23 15:30:59 UTC (rev 105245)
@@ -0,0 +1 @@
+"""Traversal functional tests for megrok.traject."""

Added: megrok.traject/trunk/src/megrok/traject/ftests/traject/deepertraject.py
===================================================================
--- megrok.traject/trunk/src/megrok/traject/ftests/traject/deepertraject.py	                        (rev 0)
+++ megrok.traject/trunk/src/megrok/traject/ftests/traject/deepertraject.py	2009-10-23 15:30:59 UTC (rev 105245)
@@ -0,0 +1,109 @@
+##############################################################################
+#
+# Copyright (c) 2009 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+
+We create an app:
+
+  >>> getRootFolder()["app"] = App()
+
+We set up a test browser:
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+  >>> browser.handleErrors = False
+
+Let's look at a department::
+
+  >>> browser.open("http://localhost/app/departments/1")
+  >>> print browser.contents
+  Department: 1
+
+We can also go to an employee::
+
+  >>> browser.open("http://localhost/app/departments/1/employees/2")
+  >>> print browser.contents
+  Employee: 1 2
+
+We cannot go to departments as there's no view for it::
+
+  >>> browser.open("http://localhost/app/departments")
+  Traceback (most recent call last):
+    ...
+  NotFound: Object: <megrok.traject.components.DefaultModel object at ...>,
+  name: u'@@index'
+    
+Nor can we go to employees::
+
+  >>> browser.open("http://localhost/app/departments/1/employees")
+  Traceback (most recent call last):
+    ...
+  NotFound: Object: <megrok.traject.components.DefaultModel object at ...>,
+  name: u'@@index'
+"""
+
+import grok
+
+from megrok import traject
+
+class Department(grok.Model):
+    def __init__(self, department_id):
+        self.department_id = department_id
+
+class Employee(grok.Model):
+    def __init__(self, department_id, employee_id):
+        self.department_id = department_id
+        self.employee_id = employee_id
+
+class DepartmentIndex(grok.View):
+    grok.context(Department)
+    grok.name('index')
+    def render(self):
+        return 'Department: %s' % self.context.department_id
+
+class EmployeeIndex(grok.View):
+    grok.context(Employee)
+    grok.name('index')
+    def render(self):
+        return 'Employee: %s %s' % (self.context.department_id,
+                                    self.context.employee_id)
+
+class App(grok.Application, grok.Model):
+    pass
+
+class DepartmentTraject(traject.Traject):
+    grok.context(App)
+
+    pattern = 'departments/:department_id'
+    model = Department
+
+    def factory(department_id):
+        return Department(department_id)
+
+    def arguments(department):
+        return dict(department_id=department.department_id)
+
+class EmployeeTraject(traject.Traject):
+    grok.context(App)
+
+    pattern = 'departments/:department_id/employees/:employee_id'
+    model = Employee
+
+    def factory(department_id, employee_id):
+        return Employee(department_id, employee_id)
+
+    def arguments(employee):
+        return dict(
+            department_id=employee.department_id,
+            employee_id=employee.employee_id)

Added: megrok.traject/trunk/src/megrok/traject/ftests/traject/notfound.py
===================================================================
--- megrok.traject/trunk/src/megrok/traject/ftests/traject/notfound.py	                        (rev 0)
+++ megrok.traject/trunk/src/megrok/traject/ftests/traject/notfound.py	2009-10-23 15:30:59 UTC (rev 105245)
@@ -0,0 +1,62 @@
+##############################################################################
+#
+# Copyright (c) 2009 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+
+We create an app:
+
+  >>> getRootFolder()["app"] = App()
+
+We set up a test browser:
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+
+When we traverse to an object that doesn't exist, we expect an error::
+
+  >>> browser.open("http://localhost/app/doesntexist")
+  Traceback (most recent call last):
+     ...
+  httperror_seek_wrapper: HTTP Error 404: Not Found
+
+"""
+
+import grok
+
+from megrok import traject
+
+class Mammoth(grok.Model):
+    def __init__(self, name):
+        self.name = name
+
+class MammothIndex(grok.View):
+    grok.context(Mammoth)
+    grok.name('index')
+    def render(self):
+        return 'The name of this mammoth is %s.' % self.context.name
+
+class App(grok.Application, grok.Model):
+    pass
+
+class MammothTraject(traject.Traject):
+    grok.context(App)
+
+    pattern = 'mammoths/:name'
+    model = Mammoth
+
+    def factory(name):
+        return Mammoth(name)
+
+    def arguments(mammoth):
+        return dict(name=mammoth.name)

Added: megrok.traject/trunk/src/megrok/traject/ftests/traject/root.py
===================================================================
--- megrok.traject/trunk/src/megrok/traject/ftests/traject/root.py	                        (rev 0)
+++ megrok.traject/trunk/src/megrok/traject/ftests/traject/root.py	2009-10-23 15:30:59 UTC (rev 105245)
@@ -0,0 +1,67 @@
+##############################################################################
+#
+# Copyright (c) 2009 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+
+We create an app:
+
+  >>> getRootFolder()["app"] = App()
+
+We set up a test browser:
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+
+Let's just go to the index view of the root::
+
+  >>> browser.open("http://localhost/app")
+  >>> print browser.contents
+  this is the app
+  
+"""
+
+import grok
+
+from megrok import traject
+
+class Mammoth(grok.Model):
+    def __init__(self, name):
+        self.name = name
+
+class MammothIndex(grok.View):
+    grok.context(Mammoth)
+    grok.name('index')
+    def render(self):
+        return 'The name of this mammoth is %s.' % self.context.name
+
+class App(grok.Application, grok.Model):
+    pass
+
+class AppIndex(grok.View):
+    grok.context(App)
+    grok.name('index')
+    def render(self):
+        return "this is the app"
+
+class MammothTraject(traject.Traject):
+    grok.context(App)
+
+    pattern = 'mammoths/:name'
+    model = Mammoth
+
+    def factory(name):
+        return Mammoth(name)
+
+    def arguments(mammoth):
+        return dict(name=mammoth.name)

Added: megrok.traject/trunk/src/megrok/traject/ftests/traject/traject.py
===================================================================
--- megrok.traject/trunk/src/megrok/traject/ftests/traject/traject.py	                        (rev 0)
+++ megrok.traject/trunk/src/megrok/traject/ftests/traject/traject.py	2009-10-23 15:30:59 UTC (rev 105245)
@@ -0,0 +1,74 @@
+##############################################################################
+#
+# Copyright (c) 2009 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+
+We create an app:
+
+  >>> getRootFolder()["app"] = App()
+
+We set up a test browser:
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.addHeader('Authorization', 'Basic mgr:mgrpw')
+  >>> browser.handleErrors = False
+
+We we traverse from the app URL, we expect things to happen::
+
+  >>> browser.open("http://localhost/app/mammoths/Knuth")
+  >>> print browser.contents
+  The name of this mammoth is Knuth.
+
+We can also go to another view::
+
+  >>> browser.open("http://localhost/app/mammoths/Knuth/other")
+  >>> print browser.contents
+  This is indeed Knuth
+  
+"""
+
+import grok
+
+from megrok import traject
+
+class Mammoth(grok.Model):
+    def __init__(self, name):
+        self.name = name
+
+class MammothIndex(grok.View):
+    grok.context(Mammoth)
+    grok.name('index')
+    def render(self):
+        return 'The name of this mammoth is %s.' % self.context.name
+
+class MammothOther(grok.View):
+    grok.context(Mammoth)
+    grok.name('other')
+    def render(self):
+        return "This is indeed %s" % self.context.name
+
+class App(grok.Application, grok.Model):
+    pass
+
+class MammothTraject(traject.Traject):
+    grok.context(App)
+
+    pattern = 'mammoths/:name'
+    model = Mammoth
+
+    def factory(name):
+        return Mammoth(name)
+
+    def arguments(mammoth):
+        return dict(name=mammoth.name)

Added: megrok.traject/trunk/src/megrok/traject/interfaces.py
===================================================================
--- megrok.traject/trunk/src/megrok/traject/interfaces.py	                        (rev 0)
+++ megrok.traject/trunk/src/megrok/traject/interfaces.py	2009-10-23 15:30:59 UTC (rev 105245)
@@ -0,0 +1,2 @@
+from zope.interface import Interface
+

Added: megrok.traject/trunk/src/megrok/traject/meta.py
===================================================================
--- megrok.traject/trunk/src/megrok/traject/meta.py	                        (rev 0)
+++ megrok.traject/trunk/src/megrok/traject/meta.py	2009-10-23 15:30:59 UTC (rev 105245)
@@ -0,0 +1,42 @@
+import traject
+import martian
+from megrok.traject import components
+import grokcore.component
+from zope import component
+from zope.publisher.interfaces.browser import (IBrowserPublisher)
+from zope.publisher.interfaces.http import IHTTPRequest
+
+class TrajectGrokker(martian.ClassGrokker):
+    martian.component(components.Traject)
+
+    martian.directive(grokcore.component.context)
+
+    def execute(self, factory, config, context, **kw):
+        pattern_str = factory.pattern
+        model = factory.model
+        factory_func = factory.factory.im_func
+        arguments_func = factory.arguments.im_func
+
+        # register
+        config.action(
+            discriminator=('traject.register', context, pattern_str),
+            callable=traject.register,
+            args=(context, pattern_str, factory_func),
+            )
+
+        # register_inverse
+        config.action(
+            discriminator=('traject.register_inverse', context, model,
+                           pattern_str),
+            callable=traject.register_inverse,
+            args=(context, model, pattern_str, arguments_func))
+
+        # register traverser on context; overwrite previous as they're
+        # all the same
+        config.action(
+            discriminator=object(), # we always want a different discriminator
+            callable=component.provideAdapter,
+            args=(components.TrajectTraverser, (context, IHTTPRequest),
+                  IBrowserPublisher),
+            )
+        return True

Added: megrok.traject/trunk/src/megrok/traject/meta.zcml
===================================================================
--- megrok.traject/trunk/src/megrok/traject/meta.zcml	                        (rev 0)
+++ megrok.traject/trunk/src/megrok/traject/meta.zcml	2009-10-23 15:30:59 UTC (rev 105245)
@@ -0,0 +1,6 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:grok="http://namespaces.zope.org/grok">
+  <include package="grokcore.component" file="meta.zcml" />
+  <grok:grok package=".meta" />
+</configure>



More information about the checkins mailing list