[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