diff options
| author | Chris McDonough <chrism@agendaless.com> | 2009-08-25 01:30:40 +0000 |
|---|---|---|
| committer | Chris McDonough <chrism@agendaless.com> | 2009-08-25 01:30:40 +0000 |
| commit | 3d1abbd5be1d1bc0f27e488059ccf7aaca225f31 (patch) | |
| tree | a47ad780bc4122d557ef139f812983b7bc3700e5 | |
| parent | 241390d911639cb658bbbbbf1bf3d8c21e0c0270 (diff) | |
| download | pyramid-3d1abbd5be1d1bc0f27e488059ccf7aaca225f31.tar.gz pyramid-3d1abbd5be1d1bc0f27e488059ccf7aaca225f31.tar.bz2 pyramid-3d1abbd5be1d1bc0f27e488059ccf7aaca225f31.zip | |
- The ``repoze.bfg.view.static`` class now accepts a string as its
first argument ("root_dir") that represents a package-relative name
e.g. ``somepackage:foo/bar/static``. This is now the preferred
mechanism for spelling package-relative static paths using this
class. A ``package_name`` keyword argument has been left around for
backwards compatibility. If it is supplied, it will be honored.
- Fixed documentation for ``repoze.bfg.view.static`` (in narrative
``Views`` chapter).
| -rw-r--r-- | CHANGES.txt | 16 | ||||
| -rw-r--r-- | docs/narr/views.rst | 116 | ||||
| -rw-r--r-- | repoze/bfg/tests/test_view.py | 18 | ||||
| -rw-r--r-- | repoze/bfg/view.py | 12 | ||||
| -rw-r--r-- | repoze/bfg/zcml.py | 2 |
5 files changed, 125 insertions, 39 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 50b9758f4..fc86ac5b6 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,8 +1,20 @@ Next release ============ -- Added ``static`` ZCML directive which registers a route for a static - view that serves up files in a directory. +- The ``repoze.bfg.view.static`` class now accepts a string as its + first argument ("root_dir") that represents a package-relative name + e.g. ``somepackage:foo/bar/static``. This is now the preferred + mechanism for spelling package-relative static paths using this + class. A ``package_name`` keyword argument has been left around for + backwards compatibility. If it is supplied, it will be honored. + +- Fixed documentation for ``repoze.bfg.view.static`` (in narrative + ``Views`` chapter). + +- Added ``static`` ZCML directive which registers a route for a view + that serves up files in a directory. See the "Views" narrative + documentation chapter's "Serving Static Resources Using a ZCML + Directive" section for more information. - "tests" module removed from the bfg_alchemy paster template; these tests didn't work. diff --git a/docs/narr/views.rst b/docs/narr/views.rst index 795fa61a6..389c4ddfc 100644 --- a/docs/narr/views.rst +++ b/docs/narr/views.rst @@ -630,72 +630,115 @@ includes other response types for Unauthorized, etc. .. _static_resources_section: -Serving Static Resources Using a ZCML directive +Serving Static Resources Using a ZCML Directive ----------------------------------------------- Using the ``static`` ZCML directive is the preferred way to serve -static resources (like JavaScript and CSS files) within -:mod:`repoze.bfg`. This directive makes static files available at a -name relative to the application root URL, e.g. ``/static``. +static resources (such as JavaScript and CSS files) within a +:mod:`repoze.bfg` application. This directive makes static files +available at a name relative to the application root URL, +e.g. ``/static``. -You can either use a package-relative path to a directory or a path -relative to the ZCML file (or an absolute path). +The directive can accept three attributes: + +name + + The (application-root-relative) URL prefix of the static directory. + For example, to serve static files from ``/static`` in most + applications, you would provide a ``name`` of ``static``. + +path + + A path to a directory on disk where the static files live. This + path may either be 1) absolute (e.g. ``/foo/bar/baz``) 2) + Python-package-relative (e.g. (``packagename:foo/bar/baz``) or 3) + relative to the package directory in which the ZCML file which + contains the directive (e.g. ``foo/bar/baz``). + +cache_max_age + + The number of seconds that the static resource can be cached, as + represented in the returned response's ``Expires`` and/or + ``Cache-Control`` headers, when any static file is served from this + directive. This defaults to 3600 (5 minutes). + +Here's an example of a ``static`` directive that will serve files up +``/static`` URL from the ``/var/www/static`` directory of the computer +which runs the :mod:`repoze.bfg` application. .. code-block:: xml :linenos: <static name="static" - path="some_package:static" + path="/var/www/static" /> +Here's an example of a ``static`` directive that will serve files up +``/static`` URL from the ``a/b/c/static`` directory of the Python +package named ``some_package``. + +.. code-block:: xml + :linenos: + <static name="static" - path="static" + path="some_package:a/b/c/static" /> +Here's an example of a ``static`` directive that will serve files up +under the ``/static`` URL from the ``static`` directory of the Python +package in which the ``configure.zcml`` file lives. + +.. code-block:: xml + :linenos: + <static name="static" - path="/var/www/static" + path="static" /> -Now put your static files (JS, etc) on your filesystem in the -directory represented as ``/path/to/static/dir``. After this is done, -you should be able to view the static files in this directory via a -browser at URLs prefixed with ``/static/``, for instance -``/static/foo.js`` will return the file +When you place your static files on filesystem in the directory +represented as the ``path`` of the directive you, you should be able +to view the static files in this directory via a browser at URLs +prefixed with the directive's ``name``. For instance if the +``static`` directive's ``name`` is ``static`` and the static +directive's ``path`` is ``/path/to/static``, +``http://localhost:6543/static/foo.js`` may return the file ``/path/to/static/dir/foo.js``. The static directory may contain subdirectories recursively, and any subdirectories may hold files; these will be resolved by the static view as you would expect. -.. note:: To ensure that model objects contained in the root don't - "shadow" your static view (model objects take precedence during - traversal), or to ensure that your root object's ``__getitem__`` is - never called when a static resource is requested, you can refer to - your static resources as registered above in URLs as, - e.g. ``/@@static/foo.js``. This is completely equivalent to - ``/static/foo.js``. See :ref:`traversal_chapter` for information - about "goggles" (``@@``). - Serving Static Resources Using a View ------------------------------------- For more flexibility, static resources can be served by a view which -you register manually. The :mod:`repoze.bfg.view` ``static`` helper -class is the preferred way to go about this. This class creates a -callable that is capable acting as a :mod:`repoze.bfg` view which -serves static resources from a directory. For instance, to serve -files within a directory located on your filesystem at -``/path/to/static/dir`` mounted at the URL path ``/static`` in your -application, create an instance of :mod:`repoze.bfg.view` 's -``static`` class inside a ``static.py`` file in your application root -as below. +you register manually. For example, you may want static resources to +only be available when the ``context`` of the view is of a particular +type, or when the request is of a particular type. + +The :mod:`repoze.bfg.view` ``static`` helper class is used to perform +this task. This class creates a callable that is capable acting as a +:mod:`repoze.bfg` view which serves static resources from a directory. +For instance, to serve files within a directory located on your +filesystem at ``/path/to/static/dir`` mounted at the URL path +``/static`` in your application, create an instance of +:mod:`repoze.bfg.view` 's ``static`` class inside a ``static.py`` file +in your application root as below. .. code-block:: python :linenos: from repoze.bfg.view import static static_view = static('/path/to/static/dir') + +.. note:: the argument to ``static`` can also be a relative pathname, + e.g. ``my/static`` (meaning relative to the Python package of the + module in which the view is being defined). It can also be a + package-relative path (e.g. ``anotherpackage:some/subdirectory``) + or it can be a "here-relative" path (e.g. ``some/subdirectory``). + If the path is "here-relative", it is relative to the package of + the module in which the static view is defined. Subsequently, wire this view up to be accessible as ``/static`` using ZCML in your application's ``configure.zcml`` against either the class @@ -719,6 +762,15 @@ In this case, ``.models.Root`` refers to the class of which your for ``/anything/static/foo.js`` too, as long as ``anything`` itself is resolveable. +.. note:: To ensure that model objects contained in the root don't + "shadow" your static view (model objects take precedence during + traversal), or to ensure that your root object's ``__getitem__`` is + never called when a static resource is requested, you can refer to + your static resources as registered above in URLs as, + e.g. ``/@@static/foo.js``. This is completely equivalent to + ``/static/foo.js``. See :ref:`traversal_chapter` for information + about "goggles" (``@@``). + Using Views to Handle Form Submissions (Unicode and Character Set Issues) ------------------------------------------------------------------------- diff --git a/repoze/bfg/tests/test_view.py b/repoze/bfg/tests/test_view.py index a35930f69..3c7d6f853 100644 --- a/repoze/bfg/tests/test_view.py +++ b/repoze/bfg/tests/test_view.py @@ -351,7 +351,23 @@ class TestStaticView(unittest.TestCase, BaseTest): def test_relpath_withpackage(self): import os path = 'fixtures' - view = self._makeOne(path, package_name='another') + view = self._makeOne('another:fixtures') + context = DummyContext() + request = DummyRequest() + request.subpath = ['__init__.py'] + request.environ = self._makeEnviron() + response = view(context, request) + self.assertEqual(request.copied, True) + here = os.path.abspath(os.path.dirname(__file__)) + self.assertEqual(response.root_resource, 'fixtures') + self.assertEqual(response.resource_name, 'fixtures') + self.assertEqual(response.package_name, 'another') + self.assertEqual(response.cache_max_age, 3600) + + def test_relpath_withpackage_name(self): + import os + path = 'fixtures' + view = self._makeOne('fixtures', package_name='another') context = DummyContext() request = DummyRequest() request.subpath = ['__init__.py'] diff --git a/repoze/bfg/view.py b/repoze/bfg/view.py index 4e5418175..3fd5a8499 100644 --- a/repoze/bfg/view.py +++ b/repoze/bfg/view.py @@ -161,14 +161,20 @@ class static(object): """ def __init__(self, root_dir, cache_max_age=3600, level=2, package_name=None): + # package_name is for bw compat; it is preferred to pass in a + # package-relative path as root_dir + # (e.g. ``anotherpackage:foo/static``). if os.path.isabs(root_dir): - root_dir = caller_path(root_dir, level=level) self.app = StaticURLParser(root_dir, cache_max_age=cache_max_age) + return + if ':' in root_dir: + package_name, root_dir = root_dir.split(':', 1) else: if package_name is None: package_name = caller_package().__name__ - self.app = PackageURLParser(package_name, root_dir, - cache_max_age=cache_max_age) + + self.app = PackageURLParser(package_name, root_dir, + cache_max_age=cache_max_age) def __call__(self, context, request): subpath = '/'.join(request.subpath) diff --git a/repoze/bfg/zcml.py b/repoze/bfg/zcml.py index e38fd3449..e0c8d2e8e 100644 --- a/repoze/bfg/zcml.py +++ b/repoze/bfg/zcml.py @@ -354,7 +354,7 @@ class IStaticDirective(Interface): required=True) cache_max_age = Int( - title=u"Cache maximum age", + title=u"Cache maximum age in seconds", required=False, default=None) |
