Welcome, guest | Sign In | My Account | Store | Cart

Notice! PyPM is being replaced with the ActiveState Platform, which enhances PyPM’s build and deploy capabilities. Create your free Platform account to download ActivePython or customize Python with the packages you require and get automatic updates.

Download
ActivePython
INSTALL>
pypm install megrok.resource

How to install megrok.resource

  1. Download and install ActivePython
  2. Open Command Prompt
  3. Type pypm install megrok.resource
 Python 2.7Python 3.2Python 3.3
Windows (32-bit)
0.5 Available View build log
Windows (64-bit)
0.5 Available View build log
Mac OS X (10.5+)
0.5 Available View build log
Linux (32-bit)
0.5 Available View build log
Linux (64-bit)
0.5 Available View build log
 
License
ZPL 2.1
Lastest release
version 0.5 on Jan 5th, 2011

megrok.resource is a package destined to integrate hurry.resource 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
>>> browser = Browser()
>>> browser.handleErrors = False

Library

A Library is a component meant to expose a folder containing resources:

>>> from megrok import resource
>>> class SomeCSS(resource.Library):
...    resource.path('ftests/css')
>>> 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)

System Message: ERROR/3 (<string>, line 39)

Inconsistent literal block quoting.

True

>>> 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')
>>> library

System Message: ERROR/3 (<string>, line 51)

Inconsistent literal block quoting.

<grokcore.view.components.DirectoryResource object at ...>

Resources

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()

System Message: ERROR/3 (<string>, line 74)

Inconsistent literal block quoting.

[<ResourceInclusion 'a.css' in library 'somecss'>, <ResourceInclusion 'b.css' in library 'somecss'>]

Library resource

Sometimes, it can be too cumbersome to declare the resources and the library separatly. When the resource is not destined to be re-used, it can be tempting to register everything with a single declaration. The ResourceLibrary component is what you need in these situations.

A Resource library is a mix between a library and a group inclusion. You need to define the usual path and name and then, the linked resources:

>>> class EasyResources(resource.ResourceLibrary):

System Message: ERROR/3 (<string>, line 90)

Inconsistent literal block quoting.

... resource.path('ftests/css') ... resource.resource('a.css') ... resource.resource('b.css')

>>> grok.testing.grok_component('someresources', EasyResources)
True

Once the component has been grokked, the resources are available:

>>> EasyResources.inclusions()

System Message: ERROR/3 (<string>, line 100)

Inconsistent literal block quoting.

[<ResourceInclusion 'a.css' in library 'easyresources'>, <ResourceInclusion 'b.css' in library 'easyresources'>]

Including resources in components

When rendering a web page we want to be able to include the resources where we need them.

There are several ways to include them. It can be done automatically upon traversal on any IResourcesIncluder component, or manually specified.

Traversal inclusion

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(Interface)
...   resource.include(css_a)
...
...   def render(self): return ""

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. This is done automatically, when using the "include" directive:

>>> resource.IResourcesIncluder.implementedBy(MyView)

System Message: ERROR/3 (<string>, line 135)

Inconsistent literal block quoting.

True

Of course, this should not remove the existing interfaces implementations:

>>> from zope.interface import Interface
>>> class IMySuperIface(Interface): pass
>>> class MyView(view.View):
...   grok.context(Interface)
...   grok.implements(IMySuperIface)
...   resource.include(css_a)
...
...   def render(self): return "<html><head></head></html>"
>>> resource.IResourcesIncluder.implementedBy(MyView)
True
>>> IMySuperIface.implementedBy(MyView)
True

The include directive can be stacked, if several resources are to be included:

>>> class AnotherView(MyView):

System Message: ERROR/3 (<string>, line 159)

Inconsistent literal block quoting.

... resource.include(css_a) ... resource.include(css_b)

>>> grok.testing.grok_component('AnotherView', AnotherView)
True
>>> browser.open('http://localhost/@@anotherview')
>>> print browser.contents
<html><head>
<link... href="http://localhost/@@/++noop++.../somecss/a.css" />
<link... href="http://localhost/@@/++noop++.../somecss/b.css" />
</head></html>

A ResourceLibrary component can be included just like a normal resource:

>>> class YetAnotherView(view.View):

System Message: ERROR/3 (<string>, line 175)

Inconsistent literal block quoting.

... grok.context(Interface) ... resource.include(EasyResources) ... ... def render(self): ... return u"<html><head></head></html>"

>>> grok.testing.grok_component('yav', YetAnotherView)
True
>>> browser.open('http://localhost/@@yetanotherview')
>>> print browser.contents
<html><head>
<link... href="http://localhost/@@/++noop++.../easyresources/a.css" />
<link... href="http://localhost/@@/++noop++.../easyresources/b.css" />
</head></html>
Include validation

The include directive will raise an error if the provided value is not a valid inclusion object:

>>> 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 IInclusion or ResourceLibrary components.

It should accept non-grokked ResourceLibraries as valid inclusions:

>>> class OtherResources(resource.ResourceLibrary):

System Message: ERROR/3 (<string>, line 213)

Inconsistent literal block quoting.

... resource.path('ftests/css') ... resource.resource('a.css')

>>> class TolerantView(view.View):
...   grok.context(Interface)
...   resource.include(OtherResources)
...
...   def render(self):
...       return u""
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):

System Message: ERROR/3 (<string>, line 235)

Inconsistent literal block quoting.

... grok.context(Interface) ... ... def render(self): ... return u"<html><head></head></html>"

>>> grok.testing.grok_component('dummy', DummyView)
True

The view class doesn't implement the needed interface:

>>> resource.IResourcesIncluder.implementedBy(DummyView)

System Message: ERROR/3 (<string>, line 246)

Inconsistent literal block quoting.

False

Now, we can use the remote inclusion function, to enable resources:

>>> resource.component_includes(DummyView, css_group)
>>> resource.IResourcesIncluder.implementedBy(DummyView)

System Message: ERROR/3 (<string>, line 252)

Inconsistent literal block quoting.

True >>> resource.include.bind().get(DummyView) [<hurry.resource.core.GroupInclusion object at ...>]

This function can be used either on a class or an instance:

>>> class UselessView(view.View):

System Message: ERROR/3 (<string>, line 259)

Inconsistent literal block quoting.

... grok.context(Interface) ... ... def render(self): return u""

>>> grok.testing.grok_component('useless', UselessView)
True
>>> 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)
>>> browser.open('http://localhost/@@anotherview')
>>> print browser.contents
<html><head>
<link... href="http://localhost/@@/somecss/a.css" />
<link... href="http://localhost/@@/somecss/b.css" />
</head></html>

Changelog

0.5 (2010-07-24)
  • Removed specific ILibrary interface and now use the one from hurry.resource

System Message: WARNING/2 (<string>, line 309)

Bullet list ends without a blank line; unexpected unindent.

so the ILibraryUrl adapter found is the same for megrok.resource.Library and hurry.resource.Library. You need hurry.zoperesource 0.5 to have hashed resource for hurry.resource.Library instances.

0.4.1 (2010-02-19)
  • Fixed the case where a ResourceLibrary is included using the

System Message: WARNING/2 (<string>, line 317)

Bullet list ends without a blank line; unexpected unindent.

"include" directive, in the same package. It was triggering an error because a non-grokked ResourceLibrary does not provide IInclusion. The directive now checks the subclass of the value to determine if the given inclusion is a valid IInclusion or a ResourceLibrary sub-class.

0.4 (2010-02-18)
  • Cleaned the dependencies : everything is declared as it

System Message: WARNING/2 (<string>, line 327)

Bullet list ends without a blank line; unexpected unindent.

should. zope.site is now a main and not test dependency.

  • Renamed module "traversal" to "url", to describe accurately what the

System Message: WARNING/2 (<string>, line 330)

Bullet list ends without a blank line; unexpected unindent.

module is about : url computation.

  • "mode" from hurry.resource is now exposed by the package.
0.3 (2009-12-23)
  • The IResourcesIncluder interface is now automatically implemented

System Message: WARNING/2 (<string>, line 338)

Bullet list ends without a blank line; unexpected unindent.

by the class while using the include directive. This makes the whole system a lot more natural.

  • The interfaces have been moved to a dedicated module. If you used

System Message: WARNING/2 (<string>, line 342)

Bullet list ends without a blank line; unexpected unindent.

to import from components, please, correct your code.

0.2 (2009-12-22)
  • Added a ResourceLibrary component that is a mix between a Library

System Message: WARNING/2 (<string>, line 348)

Bullet list ends without a blank line; unexpected unindent.

and a GroupInclusion. It allows to declare both the Library and the Resources in a single class but impacts the re-usability.

  • Library now directly inherits from grokcore.view.DirectoryResource,

System Message: WARNING/2 (<string>, line 352)

Bullet list ends without a blank line; unexpected unindent.

to inherit the get method behavior. This inheritance was avoided to prevent grokkers clash (grokcore.view.DirectoryResource grokker doesn't have a fallback for the name directive.). Our grokker has now the priority and explicitly set the name directive value.

0.1 (2009-12-21)
  • Initial release

Subscribe to package updates

Last updated Jan 5th, 2011

Download Stats

Last month:1

What does the lock icon mean?

Builds marked with a lock icon are only available via PyPM to users with a current ActivePython Business Edition subscription.

Need custom builds or support?

ActivePython Enterprise Edition guarantees priority access to technical support, indemnification, expert consulting and quality-assured language builds.

Plan on re-distributing ActivePython?

Get re-distribution rights and eliminate legal risks with ActivePython OEM Edition.