Static resource library support for Grok.
Project description
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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file megrok.resourcelibrary-0.9.2.tar.gz
.
File metadata
- Download URL: megrok.resourcelibrary-0.9.2.tar.gz
- Upload date:
- Size: 8.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 495c1c557eca82dbf5b364da7f9257d38ce72f24655b5bed8207b9d7a3aa7bfb |
|
MD5 | 6a8f3b917b823ef7d87e3bbc4ecc2344 |
|
BLAKE2b-256 | 551fc7c80135d09c88e82e2bdbaec5191046fb2b796229a49f4b103454062445 |