[Checkins] SVN: megrok.resource/trunk/src/megrok/resource/ Updated tests

Souheil CHELFOUH souheil at chelfouh.com
Sun Dec 20 18:52:43 EST 2009


Log message for revision 106819:
  Updated tests

Changed:
  U   megrok.resource/trunk/src/megrok/resource/README.txt
  U   megrok.resource/trunk/src/megrok/resource/components.py
  U   megrok.resource/trunk/src/megrok/resource/directive.py
  U   megrok.resource/trunk/src/megrok/resource/utils.py

-=-
Modified: megrok.resource/trunk/src/megrok/resource/README.txt
===================================================================
--- megrok.resource/trunk/src/megrok/resource/README.txt	2009-12-20 20:13:56 UTC (rev 106818)
+++ megrok.resource/trunk/src/megrok/resource/README.txt	2009-12-20 23:52:42 UTC (rev 106819)
@@ -3,8 +3,13 @@
 ===============
 
 `megrok.resource` is a package destined to integrate `hurry.resource`
-and `z3c.hashedresource` into Grok applications.
+and `z3c.hashedresource` into Grok applications. 
 
+Setup
+=====
+
+Let's import and init the necessary work environment.
+
   >>> import grokcore.component as grok
   >>> from zope.testbrowser.testing import Browser
 
@@ -15,7 +20,8 @@
 Library
 =======
 
-Resources are generally files you 
+A Library is a component meant to expose a folder containing
+resources::
 
   >>> from megrok import resource
 
@@ -25,6 +31,9 @@
   >>> grok.testing.grok_component('somecss', SomeCSS)
   True
 
+Once grokked, the library provides the ILibrary interface and gets an
+accessible name::
+
   >>> from megrok.resource import ILibrary
   >>> ILibrary.providedBy(SomeCSS)
   True
@@ -32,6 +41,9 @@
   >>> SomeCSS.name
   'somecss'
 
+At this point, it should be accessible via the component architecture
+as a named adapter::
+
   >>> from zope.component import getAdapter
   >>> from zope.publisher.browser import TestRequest
   >>> library = getAdapter(TestRequest(), name='somecss')
@@ -45,12 +57,18 @@
 Simple resources
 ----------------
 
+Resources can be declared as part of their library, with their
+dependencies.
+
   >>> css_a = resource.ResourceInclusion(SomeCSS, 'a.css')
   >>> css_b = resource.ResourceInclusion(SomeCSS, 'b.css')
 
 Grouping resources
 ------------------
 
+Sometimes, resources need to be grouped logically. They can be
+declared in a group inclusion:
+
   >>> css_group = resource.GroupInclusion([css_a, css_b])
   >>> css_group.inclusions()
   [<ResourceInclusion 'a.css' in library 'somecss'>,
@@ -60,25 +78,24 @@
 Including resources in components
 =================================
 
-Setup
------
+When rendering a web page we want to be able to include the resources
+where we need them. 
 
-  >>> from zope.app.testing.functional import getRootFolder
-  >>> from zope.site import SiteManagerContainer, LocalSiteManager
-  >>> from zope.site.hooks import setSite
+There are several ways to include them. It can be done automatically
+upon traversal on any IResourcesIncluder component, or manually specified.
 
-  >>> root = getRootFolder()
- 
 
-View & Include
---------------
+Traversal inclusion
+-------------------
 
-To include a resource 
+For this example, we'll create a view and use the automatic inclusion,
+using the `include` directive::
 
   >>> from grokcore import view
+  >>> from zope.interface import Interface
 
   >>> class MyView(view.View):
-  ...   grok.context(SiteManagerContainer)
+  ...   grok.context(Interface)
   ...   resource.include(css_a)
   ...
   ...   def render(self):
@@ -87,19 +104,35 @@
   >>> grok.testing.grok_component('MyView', MyView)
   True
 
+If we try to render the view, we notice that the HTML header is
+empty. The resources are not included.
+
   >>> browser.open('http://localhost/@@myview')
   >>> print browser.contents
+  <html><head></head></html>
+
+For the resources to be automatically included during the traversal,
+we need to inform the publishing machinery that our component (the
+view), is a IResourcesIncluder::
+
+  >>> from zope.interface import classImplements
+  >>> classImplements(MyView, resource.IResourcesIncluder)
+
+Now, when we render the view, the resources should be automatically
+added to the HTML result::
+
+  >>> browser.open('http://localhost/@@myview')
+  >>> print browser.contents
   <html><head>
       <link... href="http://localhost/@@/++noop++.../somecss/a.css" />
   </head></html>
 
-  >>> class AnotherView(view.View):
-  ...   grok.context(SiteManagerContainer)
+The `include` directive can be stacked, if several resources are to be
+included::
+
+  >>> class AnotherView(MyView):
   ...   resource.include(css_a)
   ...   resource.include(css_b)
-  ...
-  ...   def render(self):
-  ...	  return u"<html><head></head></html>"
 
   >>> grok.testing.grok_component('AnotherView', AnotherView)
   True
@@ -112,53 +145,93 @@
   </head></html>
 
 
+Include validation
+------------------
 
-Resources inclusion
--------------------
+The `include` directive will raise an error if the provided value is
+not a valid inclusion object::
 
-  >>> class ForeignView(view.View):
-  ...   grok.context(SiteManagerContainer)
+  >>> sneaky = object()
+
+  >>> class FailingView(view.View):
+  ...   grok.context(Interface)
+  ...   resource.include(sneaky)
   ...
   ...   def render(self):
+  ...	  return u""
+  Traceback (most recent call last):
+  ...
+  ValueError: You can only include IInclusions components.
+
+
+Remote inclusion
+-----------------
+
+Until now, we've seen that the resource inclusion could be made using
+the `include` directive. However, it can be very useful to be able to
+set inclusion on classes we don't "own". This "remote" inclusion is
+done using the `component_includes` function.
+
+We first register a view that includes no resources::
+
+  >>> class DummyView(view.View):
+  ...   grok.context(Interface)
+  ...
+  ...   def render(self):
   ...	  return u"<html><head></head></html>"
 
-  >>> grok.testing.grok_component('foreign', ForeignView)
+  >>> grok.testing.grok_component('dummy', DummyView)
   True
 
-  >>> resource.component_includes(ForeignView, css_group)
+The view class doesn't implement the needed interface::
 
-  >>> browser.open('http://localhost/@@foreignview')
-  >>> print browser.contents
-  <html><head>
-    <link... href="http://localhost/@@/++noop++.../somecss/a.css" />
-    <link... href="http://localhost/@@/++noop++.../somecss/b.css" />
-  </head></html>
+  >>> resource.IResourcesIncluder.implementedBy(DummyView)
+  False
 
-  >>> resource.component_includes(ForeignView)
-  >>> browser.open('http://localhost/@@foreignview')
-  >>> print browser.contents
-  <html><head></head></html>
+Now, we can use the remove inclusion function, to enable resources::
 
+  >>> resource.component_includes(DummyView, css_group)
+  >>> resource.IResourcesIncluder.implementedBy(DummyView)
+  True
+  >>> resource.include.bind().get(DummyView)
+  [<hurry.resource.core.GroupInclusion object at ...>]
 
-Include validation
-------------------
+This function can be used either on a class or an instance::
 
-  >>> toto = object()
-
-  >>> class FailingView(view.View):
-  ...   grok.context(SiteManagerContainer)
-  ...   resource.include(toto)
+  >>> class UselessView(view.View):
+  ...   grok.context(Interface)
   ...
-  ...   def render(self):
-  ...	  return u""
-  Traceback (most recent call last):
-  ...
-  GrokImportError: You can only include IInclusions components.
+  ...   def render(self): return u""
 
+  >>> grok.testing.grok_component('useless', UselessView)
+  True
 
-Cache & hash
-============
+  >>> from zope.component import getMultiAdapter
+  >>> useless = getMultiAdapter(
+  ...             (object(), TestRequest()), name="uselessview")
+  >>> useless
+  <megrok.resource.ftests.UselessView object at ...>
 
+  >>> resource.component_includes(useless, css_group)
+  >>> resource.IResourcesIncluder.providedBy(useless)
+  True
+  >>> resource.include.bind().get(useless)
+  (<hurry.resource.core.GroupInclusion object at ...>,)
+
+
+Cache and hash
+==============
+
+You probably noticed the "++noop++" traverser, in the resource
+URL. This is used to provide a hash and therefore, a unique URL. It
+can be very useful to work with caches and avoid outdated resources to
+be served.
+
+However, it can happen that this behavior (by default) is unwanted. To
+disable the use of the hashed URL, we can use the `use_hash` directive
+and set its value to False. This can be done either in the class
+definition or by using the directive `set` method::
+
   >>> from megrok.resource import use_hash
   >>> use_hash.set(SomeCSS, False)
   

Modified: megrok.resource/trunk/src/megrok/resource/components.py
===================================================================
--- megrok.resource/trunk/src/megrok/resource/components.py	2009-12-20 20:13:56 UTC (rev 106818)
+++ megrok.resource/trunk/src/megrok/resource/components.py	2009-12-20 23:52:42 UTC (rev 106819)
@@ -1,17 +1,14 @@
 # -*- coding: utf-8 -*-
 
 from grokcore.component import baseclass
-from grokcore.view import View
-from zope.interface import Interface, Attribute, classImplements
+from zope.interface import Interface, Attribute
 
 
 class IResourcesIncluder(Interface):
     """A publishable component that can include resources.
     """
 
-classImplements(View, IResourcesIncluder)
 
-
 class ILibrary(Interface):
     """A library, including resources.
     """

Modified: megrok.resource/trunk/src/megrok/resource/directive.py
===================================================================
--- megrok.resource/trunk/src/megrok/resource/directive.py	2009-12-20 20:13:56 UTC (rev 106818)
+++ megrok.resource/trunk/src/megrok/resource/directive.py	2009-12-20 23:52:42 UTC (rev 106819)
@@ -6,7 +6,7 @@
 
 def validateInclusion(directive, value):
     if not IInclusion.providedBy(value):
-        raise martian.error.GrokImportError(
+        raise ValueError(
             "You can only include IInclusions components.")
 
 

Modified: megrok.resource/trunk/src/megrok/resource/utils.py
===================================================================
--- megrok.resource/trunk/src/megrok/resource/utils.py	2009-12-20 20:13:56 UTC (rev 106818)
+++ megrok.resource/trunk/src/megrok/resource/utils.py	2009-12-20 23:52:42 UTC (rev 106819)
@@ -1,7 +1,16 @@
 #!/usr/bin/python
 # -*- coding: utf-8 -*-
 
-from megrok.resource import include
+from martian.util import isclass
+from megrok.resource import include, IResourcesIncluder
+from zope.interface import classImplements, alsoProvides
 
 def component_includes(component, *resources):
+    if isclass(component):
+        if not IResourcesIncluder.implementedBy(component):
+            classImplements(component, IResourcesIncluder)
+    else:
+        if not IResourcesIncluder.providedBy(component):
+            alsoProvides(component, IResourcesIncluder)
+            
     include.set(component, resources)



More information about the checkins mailing list