zope.browserresource

Latest release Supported Python versions https://travis-ci.com/zopefoundation/zope.browserresource.svg?branch=master https://coveralls.io/repos/github/zopefoundation/zope.browserresource/badge.svg?branch=master Documentation Status

Note

This package is at present not reusable without depending on a large chunk of the Zope Toolkit and its assumptions. It is maintained by the Zope Toolkit project.

This package provides an implementation of browser resources. It also provides directives for defining those resources using ZCML.

Resources are static files and directories that are served to the browser directly from the filesystem. The most common example are images, CSS style sheets, or JavaScript files.

Resources are be registered under a symbolic name and can later be referred to by that name, so their usage is independent from their physical location. Resources can also easily be internationalized.

Documentation is hosted at https://zopebrowserresource.readthedocs.io

Documentation:

Overview

This package provides an implementation of browser resources. It also provides directives for defining those resources using ZCML.

Resources are static files and directories that are served to the browser directly from the filesystem. The most common example are images, CSS style sheets, or JavaScript files.

Resources are be registered under a symbolic name and can later be referred to by that name, so their usage is independent from their physical location.

Registering Resources

You can register a single file with the <browser:resource> directive, and a whole directory with the <browser:resourceDirectory> directive, for example:

<browser:resource
  file="/path/to/static.file"
  name="myfile"
  />

<browser:resourceDirectory
  directory="/path/to/images"
  name="main-images"
  />

This causes a named default adapter to be registered that adapts the request to zope.interface.Interface so to later retrieve a resource, use zope.component.getAdapter(request, name='myfile').

Note

The default adapter (the one that adapts to zope.interface.Interface) is used to reduce coupling between projects, specifically between this project and zope.traversing.namespace.

Internationalization

Resources can also be internationalized, which means that a single resource name can refer to any one of a number of files that are specific to different languages. When the resource is retrieved and served, the file that corresponds to the request’s language is automatically sent:

<browser:i18n-resource
  name="myfile"
  defaultLanguage="en">
  <browser:translation
    language="en"
    file="path/to/static.file"
    />
  <browser:translation
    language="de"
    file="path/to/static.file.de"
    />
</browser:i18n-resource>

Using Resources

There are two ways to traverse to a resource:

  1. with the ‘empty’ view on a site, e. g. http://localhost/@@/myfile (This is declared by zope.browserresource’s configure.zcml to be Resources.)
  2. with the ++resource++ namespace, e. g. http://localhost/++resource++myfile (This is declared by zope.traversing.namespace)

In case of resource-directories traversal simply continues through its contents, e. g. http://localhost/@@/main-images/subdir/sample.jpg

Rather than putting together the URL to a resource manually, you should use zope.traversing.browser.interfaces.IAbsoluteURL to get the URL, or for a shorthand, call the resource object. This has an additional benefit:

If you want to serve resources from a different URL, for example because you want to use a web server specialized in serving static files instead of the appserver, you can register an IAbsoluteURL adapter for the site under the name resource that will be used to compute the base URLs for resources. (See AbsoluteURL for the implementation.)

For example, if you register http://static.example.com/ as the base resource URL, the resources from the above example would yield the following absolute URLs: http://static.example.com/@@/myfile and http://static.example.com/@@/main-images.

API Documentation:

Interfaces: zope.browserresource.interfaces

Resource interfaces

interface zope.browserresource.interfaces.IResource[source]

A resource.

Resources are static files and directories that are served to the browser directly from the filesystem. The most common example are images, CSS style sheets, or JavaScript files.

Resources are be registered under a symbolic name and can later be referred to by that name, so their usage is independent from their physical location.

request

Request object that is requesting the resource

__call__()

Return the absolute URL of this resource.

interface zope.browserresource.interfaces.IFileResource[source]

Extends: zope.browserresource.interfaces.IResource

A resource representing a single file.

interface zope.browserresource.interfaces.IResourceFactory[source]

A callable object to produce IResource objects.

__call__(request)

Return an IResource object

interface zope.browserresource.interfaces.IResourceFactoryFactory[source]

A factory for IResourceFactory objects

These factories are registered as named utilities that can be selected for creating resource factories in a pluggable way.

Resource directories and the <browser:resource> directive use these utilities to choose what resource to create, depending on the file extension, so third-party packages could easily plug-in additional resource types.

__call__(path, checker, name)

Return an IResourceFactory

interface zope.browserresource.interfaces.IETag[source]

An adapter for computing resource ETags.

These should be registered as multi-adapters on the resource and the request.

__call__(mtime, content)

Compute an ETag for a resource.

Parameters:
  • mtime (float) – The filesystem modification time of the resource (os.path.getmtime)
  • content (bytes) – The contents of the resource.
Returns:

A string representing the ETag, or None to disable the ETag header.

Basic Resource: zope.browserresource.resource

Resource base class and AbsoluteURL adapter

class zope.browserresource.resource.Resource(request)[source]

Bases: zope.location.location.Location

Default implementation of IResource.

When called, this object gets a multi-adapter from itself and its request to zope.traversing.browser.interfaces.IAbsoluteURL and returns the str of that object.

class zope.browserresource.resource.AbsoluteURL(context, request)[source]

Bases: zope.traversing.browser.absoluteurl.AbsoluteURL

Default implementation of zope.traversing.browser.interfaces.IAbsoluteURL for IResource.

This object always produces URLs based on the current site and the empty view, e.g., path/to/site/@@/resource-name.

When str is called on this object, it will first get the current site using zope.component.hooks.getSite. It will then attempt to adapt that site and the request to zope.traversing.browser.interfaces.IAbsoluteURL named resource, and if that isn’t available it will use the unnamed adapter. The URL of that object (i.e., the URL of the site) will be combined with the name of the resource to produce the final URL.

See also

zope.browserresource.resources.Resources For the unnamed view that the URLs we produce usually refer to.

File Resources: zope.browserresource.file

File-based browser resources.

zope.browserresource.file.parse_etags(value)[source]

Parse a list of entity tags.

HTTP/1.1 specifies the following syntax for If-Match/If-None-Match headers:

If-Match = "If-Match" ":" ( "*" | 1#entity-tag )
If-None-Match = "If-None-Match" ":" ( "*" | 1#entity-tag )

entity-tag = [ weak ] opaque-tag

weak       = "W/"
opaque-tag = quoted-string

quoted-string  = ( <"> *(qdtext) <"> )
qdtext         = <any TEXT except <">>

The backslash character ("\") may be used as a single-character
quoting mechanism only within quoted-string and comment constructs.

Examples:

>>> parse_etags('*')
['*']
>>> parse_etags(r' "qwerty", ,"foo",W/"bar" , "baz","\""')
['"qwerty"', '"foo"', 'W/"bar"', '"baz"', '"\\""']

Ill-formed headers are ignored

>>> parse_etags("not an etag at all")
[]
zope.browserresource.file.etag_matches(etag, tags)[source]

Check if the entity tag matches any of the given tags.

>>> etag_matches('"xyzzy"', ['"abc"', '"xyzzy"', 'W/"woof"'])
True
>>> etag_matches('"woof"', ['"abc"', 'W/"woof"'])
False
>>> etag_matches('"xyzzy"', ['*'])
True

Note that you pass quoted etags in both arguments!

zope.browserresource.file.quote_etag(etag)[source]

Quote an etag value

>>> quote_etag("foo")
'"foo"'

Special characters are escaped

>>> quote_etag('"')
'"\\""'
>>> quote_etag('\\')
'"\\\\"'
class zope.browserresource.file.File(path, name)[source]

Bases: object

An object representing a file on the filesystem.

These are created by FileResourceFactory for use with FileResource.

class zope.browserresource.file.FileResource(context, request)[source]

Bases: zope.publisher.browser.BrowserView, zope.browserresource.resource.Resource

Default implementation of IFileResource.

This class also implements zope.publisher.interfaces.browser.IBrowserPublisher.

publishTraverse(request, name)[source]

File resources can’t be traversed further, so raise NotFound if someone tries to traverse it.

>>> factory = FileResourceFactory(testFilePath, nullChecker, 'test.txt')
>>> request = TestRequest()
>>> resource = factory(request)
>>> resource.publishTraverse(request, '_testData')
Traceback (most recent call last):
...
NotFound: Object: None, name: '_testData'
browserDefault(request)[source]

Return a callable for processing browser requests.

>>> factory = FileResourceFactory(testFilePath, nullChecker, 'test.txt')
>>> request = TestRequest(REQUEST_METHOD='GET')
>>> resource = factory(request)
>>> view, next = resource.browserDefault(request)
>>> with open(testFilePath, 'rb') as f:
...     view() == f.read()
True
>>> next == ()
True
>>> request = TestRequest(REQUEST_METHOD='HEAD')
>>> resource = factory(request)
>>> view, next = resource.browserDefault(request)
>>> view() == b''
True
>>> next == ()
True
chooseContext()[source]

Choose the appropriate context.

This method can be overriden in subclasses, that need to choose appropriate file, based on current request or other condition, like, for example, i18n files.

See also

I18nFileResource

See also

II18nResourceDirective

GET()[source]

Return a file data for downloading with GET requests

>>> factory = FileResourceFactory(testFilePath, nullChecker, 'test.txt')
>>> request = TestRequest()
>>> resource = factory(request)
>>> with open(testFilePath, 'rb') as f:
...     resource.GET() == f.read()
True
>>> request.response.getHeader('Content-Type') == 'text/plain'
True
HEAD()[source]

Return proper headers and no content for HEAD requests

>>> factory = FileResourceFactory(testFilePath, nullChecker, 'test.txt')
>>> request = TestRequest()
>>> resource = factory(request)
>>> resource.HEAD() == b''
True
>>> request.response.getHeader('Content-Type') == 'text/plain'
True
class zope.browserresource.file.FileETag(context, request)[source]

Bases: object

Default implementation of IETag registered for IFileResource and zope.publisher.interfaces.browser.IBrowserRequest.

class zope.browserresource.file.FileResourceFactory(path, checker, name)[source]

Bases: object

Implementation of IResourceFactory producing FileResource.

The class itself provides IResourceFactoryFactory

resourceClass

alias of FileResource

Internationalized Files: zope.browserresource.i18nfile

Internationalized file resource.

class zope.browserresource.i18nfile.I18nFileResource(data, request, defaultLanguage='en')[source]

Bases: zope.browserresource.file.FileResource

A zope.i18n.interfaces.II18nAware file resource.

See also

II18nResourceDirective

Creates an internationalized file resource.

Parameters:data (dict) – A mapping from languages to File objects.
chooseContext()[source]

Choose the appropriate context (file) according to language.

getDefaultLanguage()[source]

See II18nAware

setDefaultLanguage(language)[source]

See II18nAware

getAvailableLanguages()[source]

The available languages are those defined in the data mapping given to this object.

Directories of Resources: zope.browserresource.directory

Resource Directory

A ‘resource directory’ is an on-disk directory which is registered as a resource using the <resourceDirectory> ZCML directive. The directory is treated as a source for individual resources; it can be traversed to retrieve resources represented by contained files, which can in turn be treated as resources. The contained files have __name__ values which include a ‘/’ separating the __name__ of the resource directory from the name of the file within the directory.

class zope.browserresource.directory.DirectoryResource(context, request)[source]

Bases: zope.publisher.browser.BrowserView, zope.browserresource.resource.Resource

A resource representing an entire directory.

It is traversable to the items contained within the directory. See get.

default_factory

alias of zope.browserresource.file.FileResourceFactory

directory_factory

The resource factory to use for directories.

alias of DirectoryResourceFactory

forbidden_names = ('.svn', '.git')

A sequence of name patterns usable with fnmatch.fnmatch. Traversing to files that match these names will not produce resources.

publishTraverse(request, name)[source]

Uses get to traverse to the name.

See also

zope.publisher.interfaces.browser.IBrowserPublisher.publishTraverse()

browserDefault(request)[source]

Returns an empty callable and tuple.

get(name, default=<object object>)[source]

Locate name on the filesystem and return a IResource for it.

If the name cannot be found and no default is given, then raise NotFound.

If the name matches one of the forbidden patterns then returns the default (if given) or raise NotFound (when not given).

When the name refers to a file, we query for a IResourceFactoryFactory utility named for the file’s extension (e.g., css) and use it to produce a resource. If no such utility can be found, we use our default.

When the name refers to a directory, we use our directory factory.

Resource View: zope.browserresource.resources

Resource URL access

class zope.browserresource.resources.Resources(context, request)[source]

Bases: zope.publisher.browser.BrowserView

A view that can be traversed further to access browser resources.

This view is usually registered for zope.component.interfaces.ISite objects with no name, so resources will be available at <site>/@@/<resource>.

Let’s test how it’s traversed to get registered resources. Let’s create a sample resource class and register it.

>>> from zope.component import provideAdapter
>>> from zope.interface import Interface
>>> from zope.publisher.interfaces import NotFound
>>> from zope.publisher.interfaces.browser import IDefaultBrowserLayer
>>> from zope.publisher.browser import TestRequest
>>> class Resource(object):
...     def __init__(self,request):
...         self.request = request
...     def __call__(self):
...         return 'http://localhost/testresource'
>>> provideAdapter(Resource, (IDefaultBrowserLayer,), Interface, 'test')

Now, create a site and request objects and get the Resources object to work with.

>>> site = object()
>>> request = TestRequest()
>>> resources = Resources(site, request)

Okay, let’s test the publishTraverse method. It should traverse to our registered resource.

>>> resource = resources.publishTraverse(request, 'test')
>>> resource.__parent__ is site
True
>>> resource.__name__ == 'test'
True
>>> resource()
'http://localhost/testresource'

However, it will raise NotFound exception if we try to traverse to an unregistered resource.

>>> resources.publishTraverse(request, 'does-not-exist')
Traceback (most recent call last):
...
NotFound: Object: <zope.browserresource.resources.Resources object at 0x...>,
          name: 'does-not-exist'

When accessed without further traversing, it returns an empty page and no futher traversing steps.

>>> view, path = resources.browserDefault(request)
>>> view() == b''
True
>>> path == ()
True

The Resources view also provides __getitem__ method for use in templates. It is equivalent to publishTraverse.

>>> resource = resources['test']
>>> resource.__parent__ is site
True
>>> resource.__name__ == 'test'
True
>>> resource()
'http://localhost/testresource'
publishTraverse(request, name)[source]

Query for the default adapter on request named name and return it.

This is usually a IResource as registered with IResourceDirective.

The resource object is located beneath the context of this object with the given name.

Raises:NotFound – If no adapter can be found.

See also

zope.publisher.interfaces.browser.IBrowserPublisher

browserDefault(request)[source]

See zope.publisher.interfaces.browser.IBrowserPublisher interface

ZCML Directives: zope.browserresource.metadirectives

ZCML directives for defining browser resources

interface zope.browserresource.metadirectives.IBasicResourceInformation[source]

This is the basic information for all browser resources.

layer

The layer the resource should be found in

For information on layers, see the documentation for the skin directive. Defaults to “default”.

Implementation:zope.configuration.fields.GlobalInterface
Read Only:False
Required:False
Default Value:None

Value Type

Implementation:zope.schema.InterfaceField
Read Only:False
Required:True
Default Value:None
permission

The permission needed to access the resource.

If a permission isn’t specified, the resource will always be accessible.

Implementation:zope.security.zcml.Permission
Read Only:False
Required:False
Default Value:None
Allowed Type:str
interface zope.browserresource.metadirectives.IResourceDirective[source]

Extends: zope.browserresource.metadirectives.IBasicResourceInformation

Defines a browser resource.

name

The name of the resource

This is the name used in resource urls. Resource urls are of the form <site>/@@/resourcename, where <site> is the url of “site”, a folder with a site manager.

We make resource urls site-relative (as opposed to content-relative) so as not to defeat caches.

Implementation:zope.schema.TextLine
Read Only:False
Required:True
Default Value:None
Allowed Type:unicode
factory

Resource Factory

The factory used to create the resource. The factory should only expect to get the request passed when called.

Implementation:zope.configuration.fields.GlobalObject
Read Only:False
Required:False
Default Value:None
file

File

The file containing the resource data. The resource type that will be created depends on file extension. The named IResourceFactoryFactory utilities are registered per extension. If no factory is registered for given file extension, the default FileResource factory will be used.

Implementation:zope.configuration.fields.Path
Read Only:False
Required:False
Default Value:None
Allowed Type:unicode
image

Image

If the image attribute is used, then an image resource, rather than a file resource will be created.

This attribute is deprecated in favor of pluggable resource types, registered per extension. Use the “file” attribute instead.

Implementation:zope.configuration.fields.Path
Read Only:False
Required:False
Default Value:None
Allowed Type:unicode
template

Template

If the template attribute is used, then a page template resource, rather than a file resource will be created.

This attribute is deprecated in favor of pluggable resource types, registered per extension. Use the “file” attribute instead. To use page template resources, you need to install zope.ptresource package.

Implementation:zope.configuration.fields.Path
Read Only:False
Required:False
Default Value:None
Allowed Type:unicode
interface zope.browserresource.metadirectives.II18nResourceDirective[source]

Extends: zope.browserresource.metadirectives.IBasicResourceInformation

Defines an i18n’d resource.

name

The name of the resource

This is the name used in resource urls. Resource urls are of the form <site>/@@/resourcename, where <site> is the url of “site”, a folder with a site manager.

We make resource urls site-relative (as opposed to content-relative) so as not to defeat caches.

Implementation:zope.schema.TextLine
Read Only:False
Required:True
Default Value:None
Allowed Type:unicode
defaultLanguage

Default language

Defines the default language

Implementation:zope.schema.TextLine
Read Only:False
Required:False
Default Value:None
Allowed Type:unicode
interface zope.browserresource.metadirectives.II18nResourceTranslationSubdirective[source]

Extends: zope.browserresource.metadirectives.IBasicResourceInformation

Subdirective to II18nResourceDirective.

language

Language

Language of this translation of the resource

Implementation:zope.schema.TextLine
Read Only:False
Required:True
Default Value:None
Allowed Type:unicode
file

File

The file containing the resource data.

Implementation:zope.configuration.fields.Path
Read Only:False
Required:False
Default Value:None
Allowed Type:unicode
image

Image

If the image attribute is used, then an image resource, rather than a file resource will be created.

This attribute is deprecated, as images are now simply files. Use the “file” attribute instead.

Implementation:zope.configuration.fields.Path
Read Only:False
Required:False
Default Value:None
Allowed Type:unicode
interface zope.browserresource.metadirectives.IResourceDirectoryDirective[source]

Extends: zope.browserresource.metadirectives.IBasicResourceInformation

Defines a directory containing browser resources.

name

The name of the resource

This is the name used in resource urls. Resource urls are of the form <site>/@@/resourcename, where <site> is the url of “site”, a folder with a site manager.

We make resource urls site-relative (as opposed to content-relative) so as not to defeat caches.

Implementation:zope.schema.TextLine
Read Only:False
Required:True
Default Value:None
Allowed Type:unicode
directory

Directory

The directory containing the resource data.

Implementation:zope.configuration.fields.Path
Read Only:False
Required:True
Default Value:None
Allowed Type:unicode
interface zope.browserresource.metadirectives.IIconDirective[source]

Define an icon for an interface.

name

The name of the icon.

The name shows up in URLs/paths. For example ‘foo’.

Implementation:zope.schema.TextLine
Read Only:False
Required:True
Default Value:None
Allowed Type:unicode
for_

The interface this icon is for.

The icon will be for all objects that implement this interface.

Implementation:zope.configuration.fields.GlobalInterface
Read Only:False
Required:True
Default Value:None

Value Type

Implementation:zope.schema.InterfaceField
Read Only:False
Required:True
Default Value:None
file

File

The file containing the icon.

Implementation:zope.configuration.fields.Path
Read Only:False
Required:False
Default Value:None
Allowed Type:unicode
resource

Resource

A resource containing the icon.

Implementation:zope.schema.TextLine
Read Only:False
Required:False
Default Value:None
Allowed Type:unicode
title

Title

Descriptive title

Implementation:zope.configuration.fields.MessageID
Read Only:False
Required:False
Default Value:None
Allowed Type:unicode
layer

The layer the icon should be found in

For information on layers, see the documentation for the skin directive. Defaults to “default”.

Implementation:zope.configuration.fields.GlobalInterface
Read Only:False
Required:False
Default Value:None

Value Type

Implementation:zope.schema.InterfaceField
Read Only:False
Required:True
Default Value:None
width

The width of the icon.

The width will be used for the <img width=”…” /> attribute. Defaults to 16.

Implementation:zope.schema.Int
Read Only:False
Required:False
Default Value:16
Allowed Type:int, long
height

The height of the icon.

The height will be used for the <img height=”…” /> attribute. Defaults to 16.

Implementation:zope.schema.Int
Read Only:False
Required:False
Default Value:16
Allowed Type:int, long

Changes

4.5 (unreleased)

  • Drop support for python setup.py test.

4.4 (2019-12-10)

  • Make the registration of the FileETag adapter conditional on the environment as Zope 4 registers this adapter explicitly in Products.Five.browser. See #12.
  • Add support for Python 3.8.
  • Drop support for Python 3.4.

4.3 (2018-10-05)

4.2.1 (2017-09-01)

  • Fix dependencies of the zcml extra.

4.2.0 (2017-08-04)

  • Add support for Python 3.5 and 3.6.
  • Drop support for Python 2.6 and 3.3.

4.1.0 (2014-12-26)

4.0.2 (2014-11-04)

  • Return no ETag if no adapter is registered, disabling the requirement for applications that was introduced in 3.11.0 (GitHub #1)

4.0.1 (2013-04-03)

  • Fix some Python 3 string vs bytes issues.

4.0.0 (2013-02-20)

3.12.0 (2010-12-14)

  • Add zcml extra dependencies and fixed dependencies of configure.zcml on other packages’ meta.zcml.
  • Add a test for including our own configure.zcml.

3.11.0 (2010-08-13)

  • Support the HTTP ETag header for file resources. ETag generation can be customized or disabled by providing an IETag multi-adapter on (IFileResource, your-application-skin).

3.10.3 (2010-04-30)

  • Prefer the standard libraries doctest module to the one from zope.testing.

3.10.2 (2009-11-25)

  • The previous release had a broken egg, sorry.

3.10.1 (2009-11-24)

  • Import hooks functionality from zope.component after it was moved there from zope.site. This lifts the dependency on zope.site and thereby, ZODB.
  • Import ISite and IPossibleSite from zope.component after they were moved there from zope.location.

3.10.0 (2009-09-25)

  • Add an ability to forbid publishing of some files in the resource directory, this is done by fnmatch’ing the wildcards in the forbidden_names``class attribute of ``DirectoryResource. By default, the .svn is in that attribute, so directories won’t publish subversion system directory that can contain private information.

3.9.0 (2009-08-27)

Initial release. This package was splitted off zope.app.publisher as a part of refactoring process.

Additional changes that are made during refactoring:

  • Resource class for file resources are now selected the pluggable way. The resource directory publisher and browser:resource ZCML directive now creating file resources using factory utility lookup based on the file extension, so it’s now possible to add new resource types without introducing new ZCML directives and they will work inside resource directories as well.

    NOTE: the “resource_factories” attribute from the DirectoryResource was removed, so if you were using this attribute for changing resource classes for some file extensions, you need to migrate your code to new utility-based mechanism.

    See zope.browserresource.interfaces.IResourceFactoryFactory interface.

  • The Image resource class was removed, as they are actually simple files. To migrate, simply rename the “image” argument in browser:resource and browser:i18n-resource directives to “file”, if you don’t do this, resouces will work, but you’ll get deprecation warnings.

    If you need custom behaviour for images, you can register a resource factory utility for needed file extensions.

  • The PageTemplateResource was moved into a separate package, “zope.ptresource”, which is a plugin for this package now. Because of that, the “template” argument of browser:resource directive was deprecated and you should rename it to “file” to migrate. The PageTemplateResource will be created for “pt”, “zpt” and “html” files automatically, if zope.ptresource package is included in your configuration.

  • Fix stripping the “I” from an interface name for icon title, if no title is specified.

  • When publishing a resource via Resources view, set resource parent to an ISite object, not to current site manager.

  • Clean up code and improve test coverage.

Indices and tables