[Checkins] SVN: grok/trunk/src/grok/ Sometimes it's convenient to have a top-level URL function. Abstract out

Martijn Faassen faassen at infrae.com
Sat Apr 21 10:39:14 EDT 2007


Log message for revision 74325:
  Sometimes it's convenient to have a top-level URL function. Abstract out
  the relevant behavior from view.url() into a url() function.
  

Changed:
  U   grok/trunk/src/grok/__init__.py
  U   grok/trunk/src/grok/components.py
  A   grok/trunk/src/grok/ftests/url/url_function.py
  U   grok/trunk/src/grok/interfaces.py
  U   grok/trunk/src/grok/util.py

-=-
Modified: grok/trunk/src/grok/__init__.py
===================================================================
--- grok/trunk/src/grok/__init__.py	2007-04-21 11:54:05 UTC (rev 74324)
+++ grok/trunk/src/grok/__init__.py	2007-04-21 14:39:13 UTC (rev 74325)
@@ -42,6 +42,7 @@
 from grok._grok import SubscribeDecorator as subscribe
 from grok.error import GrokError, GrokImportError
 from grok.formlib import action, AutoFields, Fields
+from grok.util import url
 
 # Our __init__ provides the grok API directly so using 'import grok' is enough.
 from grok.interfaces import IGrokAPI

Modified: grok/trunk/src/grok/components.py
===================================================================
--- grok/trunk/src/grok/components.py	2007-04-21 11:54:05 UTC (rev 74324)
+++ grok/trunk/src/grok/components.py	2007-04-21 14:39:13 UTC (rev 74325)
@@ -200,13 +200,7 @@
         elif name is not None and obj is None:
             # create URL to view on context
             obj = self.context
-        url = component.getMultiAdapter((obj, self.request), IAbsoluteURL)()
-        if name is None:
-            # URL to obj itself
-            return url
-        # URL to view on obj
-        return url + '/' + urllib.quote(name.encode('utf-8'),
-                                        SAFE_URL_CHARACTERS)
+        return util.url(self.request, obj, name)
 
     def redirect(self, url):
         return self.request.response.redirect(url)

Added: grok/trunk/src/grok/ftests/url/url_function.py
===================================================================
--- grok/trunk/src/grok/ftests/url/url_function.py	2007-04-21 11:54:05 UTC (rev 74324)
+++ grok/trunk/src/grok/ftests/url/url_function.py	2007-04-21 14:39:13 UTC (rev 74325)
@@ -0,0 +1,83 @@
+# -*- coding: UTF-8 -*-
+"""
+There is a url function that can be imported from grok to determine the
+absolute URL of objects.
+
+  >>> from grok import url
+  >>> import grok
+  >>> grok.grok('grok.ftests.url.url_function')
+  
+  >>> from grok.ftests.url.url import Herd, Mammoth
+  >>> herd = Herd()
+  >>> getRootFolder()['herd'] = herd
+  >>> manfred = Mammoth()
+  >>> herd['manfred'] = manfred
+
+Now let's use url on some things::
+
+  >>> from zope.testbrowser.testing import Browser
+  >>> browser = Browser()
+  >>> browser.handleErrors = False
+  >>> browser.open("http://localhost/herd/manfred/index")
+  >>> print browser.contents
+  http://localhost/herd/manfred/index
+  >>> browser.open("http://localhost/herd/manfred/another")
+  >>> print browser.contents
+  http://localhost/herd/manfred/another
+  
+We get the views manually so we can do a greater variety of url() calls:
+
+  >>> from zope import component
+  >>> from zope.publisher.browser import TestRequest
+  >>> request = TestRequest()
+  >>> index_view = component.getMultiAdapter((manfred, request), name='index')
+  >>> url(request, index_view)
+  'http://127.0.0.1/herd/manfred/index'
+  >>> another_view = component.getMultiAdapter((manfred, request),
+  ...                                              name='another')
+  >>> url(request, another_view)
+  'http://127.0.0.1/herd/manfred/another'
+
+Now let's get a URL for a specific object:
+
+  >>> url(request, manfred)
+  'http://127.0.0.1/herd/manfred'
+
+We can get the URL for any object in content-space:
+
+  >>> url(request, herd)
+  'http://127.0.0.1/herd'
+
+We can also pass a name along with this, to generate a URL to a
+particular view on the object:
+
+  >>> url(request, herd, 'something')
+  'http://127.0.0.1/herd/something'
+
+It works properly in the face of non-ascii characters in URLs:
+
+  >>> u = url(request, herd, unicode('árgh', 'UTF-8'))
+  >>> u
+  'http://127.0.0.1/herd/%C3%A1rgh'
+  >>> import urllib
+  >>> expected = unicode('http://127.0.0.1/herd/árgh', 'UTF-8')
+  >>> urllib.unquote(u).decode('utf-8') == expected
+  True
+"""
+import grok
+
+class Herd(grok.Container, grok.Model):
+    pass
+
+class Mammoth(grok.Model):
+    pass
+
+grok.context(Mammoth)
+
+class Index(grok.View):
+    def render(self):
+        return url(self.request, self)
+    
+class Another(grok.View):
+    def render(self):
+        return url(self.request, self)

Modified: grok/trunk/src/grok/interfaces.py
===================================================================
--- grok/trunk/src/grok/interfaces.py	2007-04-21 11:54:05 UTC (rev 74324)
+++ grok/trunk/src/grok/interfaces.py	2007-04-21 14:39:13 UTC (rev 74325)
@@ -183,6 +183,10 @@
     def grok(dotted_name):
         """Grok a module or package specified by ``dotted_name``."""
 
+    def url(request, obj, name=None):
+        """Generate the URL to an object with optional name attached.
+        """
+
     def notify(event):
         """Send ``event`` to event subscribers."""
 

Modified: grok/trunk/src/grok/util.py
===================================================================
--- grok/trunk/src/grok/util.py	2007-04-21 11:54:05 UTC (rev 74324)
+++ grok/trunk/src/grok/util.py	2007-04-21 14:39:13 UTC (rev 74325)
@@ -18,9 +18,12 @@
 import types
 import sys
 import inspect
+import urllib
 
 from zope import component
 from zope import interface
+from zope.traversing.browser.interfaces import IAbsoluteURL
+from zope.traversing.browser.absoluteurl import _safe as SAFE_URL_CHARACTERS
 
 from zope.security.checker import NamesChecker, defineChecker
 from zope.security.interfaces import IPermission
@@ -190,4 +193,13 @@
     check_permission(factory, result)
     return result
 
+def url(request, obj, name=None):
+    """Given a request and an object, give the URL.
 
+    Optionally pass a third argument name which gets added to the URL.
+    """    
+    url = component.getMultiAdapter((obj, request), IAbsoluteURL)()
+    if name is None:
+        return url
+    return url + '/' + urllib.quote(name.encode('utf-8'),
+                                    SAFE_URL_CHARACTERS)



More information about the Checkins mailing list