skip to navigation
skip to content

megrok.resourcelibrary 0.9.2

Static resource library support for Grok.

Downloads ↓

megrok.resourcelibrary: Resources in Grok

Introduction

Grok already comes equipped with a simple way to expose static file resources, the static directory.

megrok.resourcelibrary allows the more flexible inclusion of static file resources in Grok. It uses the zc.resourcelibrary package to do this.

A resource library is essentially like a directory like the static directory of a package, full of static resources, such as CSS files, javascript files and images. Resources are intended to be used from HTML pages, as additional resources to help display a particular layout or user interface.

How is megrok.resourcelibrary more flexible than Grok's default static directory?

  • A resource library can be in a layer.
  • A resource library can have a non-public permission.
  • A resource library can more easily be packaged for reuse by other libraries. Resource libraries have unique names under the control of the developer.
  • A resource library can automatically include some resources (such as javascript or css) in the head section of a web page whenever a particular widget needs it.
  • A resource library can also depend on other libraries.

Basic example

Let's see how this all works. First we need to grok this package itself (this is normally done from ZCML):

>>> from grok.testing import grok
>>> grok('megrok.resourcelibrary.meta')

Now we can set up a simple resource library:

>>> import grok
>>> import megrok.resourcelibrary
>>> class SomeLibrary(megrok.resourcelibrary.ResourceLibrary):
...     megrok.resourcelibrary.directory('tests/example')

We need to grok this to make it available (in normal use this is done automatically for you):

>>> from grok.testing import grok_component
>>> grok_component('SomeLibrary', SomeLibrary)
True

The resources in this directory are now published, by default under the class name of the library, lower cased (therefore somelibrary):

>>> from zope.testbrowser.testing import Browser
>>> browser = Browser()
>>> browser.open('http://localhost/@@/somelibrary/my-lib/included.js')
>>> print browser.contents
    function be_annoying() {
    alert('Hi there!');
}

The default name can be overridden by using the grok.name directive:

>>> class SomeLibrary2(megrok.resourcelibrary.ResourceLibrary):
...     grok.name('some-library')
...     megrok.resourcelibrary.directory('tests/example')
>>> grok_component('SomeLibrary2', SomeLibrary2)
True
>>> browser.open('http://localhost/@@/some-library/my-lib/included.js')
>>> print browser.contents
    function be_annoying() {
    alert('Hi there!');
}

It's an error to point to a directory that doesn't exist:

>>> class WrongDirectory(megrok.resourcelibrary.ResourceLibrary):
...     grok.name('wrong-directory')
...     megrok.resourcelibrary.directory('tests/doesnt_exist')
>>> grok_component('WrongDirectory', WrongDirectory)
Traceback (most recent call last):
  ...
GrokError: Directory 'tests/doesnt_exist' is not a valid directory passed to the 'wrong-directory' directive.

Automactic inclusion of resources

We now set up a resource library that automatically includes two resources whenever it is used in a web page, namely included.js and included.css:

>>> class MyLib(megrok.resourcelibrary.ResourceLibrary):
...    grok.name('my-lib')
...    megrok.resourcelibrary.directory('tests/example/my-lib')
...    megrok.resourcelibrary.include('included.js')
...    megrok.resourcelibrary.include('included.css')
>>> grok_component('MyLib', MyLib)
True

This is how you require the library to be loaded in a particular page template:

<tal:block replace="resource_library:my-lib"/>

test_template_2 makes this requirement, so the included Javascript should be included:

>>> browser.open('http://localhost/zc.resourcelibrary.test_template_2')
>>> '/@@/my-lib/included.js' in browser.contents
True

And the resource is also published:

>>> browser.open('/@@/my-lib/included.js')
>>> print browser.contents
    function be_annoying() {
    alert('Hi there!');
}

A reference to the CSS is also inserted into the HTML:

>>> browser.open('http://localhost/zc.resourcelibrary.test_template_2')
>>> '/@@/my-lib/included.css' in browser.contents
True

And the CSS is available from the URL referenced:

>>> browser.open('/@@/my-lib/included.css')
>>> print browser.contents
div .border {
    border: 1px silid black;
}

Programmatically signalling resource requirements

Above we've demonstrated the use of the resource_library namespace in ZPT. Library usage can also be signalled programmatically, for instance in a view:

>>> import grok
>>> from zope.interface import Interface
>>> class View(grok.View):
...   grok.context(Interface)
...   def render(self):
...      MyLib.need()
...      return '<html><head></head><body>Example</body></html>'
>>> grok_component('View', View)
True

>>> browser.open('http://localhost/view')
>>> '/@@/my-lib/included.js' in browser.contents
True

This also works for libraries which don't have an explicit grok.name:

>>> class MyLib2(megrok.resourcelibrary.ResourceLibrary):
...    megrok.resourcelibrary.directory('tests/example/my-lib')
...    megrok.resourcelibrary.include('included.js')
...    megrok.resourcelibrary.include('included.css')
>>> grok_component('MyLib2', MyLib2)
True

>>> class View2(grok.View):
...   grok.context(Interface)
...   def render(self):
...      MyLib2.need()
...      return '<html><head></head><body>Example</body></html>'
>>> grok_component('View2', View2)
True

>>> browser.open('http://localhost/view2')
>>> '/@@/mylib2/included.js' in browser.contents
True

You can also signal inclusion by library name instead (like is done in page templates):

>>> class View3(grok.View):
...   grok.context(Interface)
...   def render(self):
...      megrok.resourcelibrary.need('my-lib')
...      return '<html><head></head><body>Example</body></html>'

>>> grok_component('View3', View3)
True

>>> browser.open('http://localhost/view3')
>>> '/@@/my-lib/included.js' in browser.contents
True

Making resource libraries depend on other ones

We can make a resource library depend on another one:

>>> class Dependency(megrok.resourcelibrary.ResourceLibrary):
...    megrok.resourcelibrary.directory('tests/example')
...    megrok.resourcelibrary.include('1.js')
>>> grok_component('Dependency', Dependency)
True

>>> class Dependent(megrok.resourcelibrary.ResourceLibrary):
...    megrok.resourcelibrary.directory('tests/example')
...    megrok.resourcelibrary.include('2.css')
...    megrok.resourcelibrary.depend(Dependency)
>>> grok_component('Dependent', Dependent)
True

Let's make a view that needs Dependent:

>>> class DependentView(grok.View):
...   grok.context(Interface)
...   def render(self):
...      Dependent.need()
...      return '<html><head></head><body>Example</body></html>'
>>> grok_component('DependentView', DependentView)
True

The included code of both the original and the dependency will now show up:

>>> browser.open('http://localhost/dependentview')
>>> '/@@/dependency/1.js' in browser.contents
True
>>> '/@@/dependent/2.css' in browser.contents
True

Protecting resources

It's possible to give a resource a permission:

>>> class MyPermission(grok.Permission):
...    grok.name("my.permission")
>>> grok_component('MyPermission', MyPermission)
True

>>> class MyLib3(megrok.resourcelibrary.ResourceLibrary):
...    megrok.resourcelibrary.directory('tests/example/my-lib')
...    grok.require(MyPermission)
>>> grok_component('MyLib3', MyLib3)
True

XXX This doesn't work yet, as resources don't do their own security checks but rely on proxies, which Grok has removed... Need to introduce new resources/factories to do checks by hand.

Changes

0.9.2 (2008-08-08)

  • Grokker mistakenly relied on (not imported) GrokImportError in failure case. Corrected this to GrokError and added a test for it.
  • Rename use directive to depend and make it take a class argument instead of a library name.

0.9.1 (2008-08-06)

  • Turn off zip-safeness.
  • Actually add a meta.zcml that loads up the grokker!

0.9 (2008-08-06)

  • Initial public release.
 
File Type Py Version Uploaded on Size # downloads
megrok.resourcelibrary-0.9.2.tar.gz (md5) Source 2008-08-08 7KB 1430