diff options
| author | Michael Merickel <michael@merickel.org> | 2015-02-17 11:39:29 -0600 |
|---|---|---|
| committer | Michael Merickel <michael@merickel.org> | 2015-02-17 11:39:29 -0600 |
| commit | 75f85c57e0f4d1069cef9feb6ab6182b5f651492 (patch) | |
| tree | 039ca762ddcf6e4946a2570136927d2773374969 | |
| parent | 6ea099ded65ff671c26753b9b30e4d19b3c47b81 (diff) | |
| parent | 5fdf9a5f63b7731963de7f49df6c29077155525f (diff) | |
| download | pyramid-75f85c57e0f4d1069cef9feb6ab6182b5f651492.tar.gz pyramid-75f85c57e0f4d1069cef9feb6ab6182b5f651492.tar.bz2 pyramid-75f85c57e0f4d1069cef9feb6ab6182b5f651492.zip | |
Merge pull request #1583 from Pylons/fix.remove-cachebust-tokens
remove the token from the ICacheBuster api
| -rw-r--r-- | CHANGES.txt | 5 | ||||
| -rw-r--r-- | docs/api/static.rst | 6 | ||||
| -rw-r--r-- | docs/narr/assets.rst | 15 | ||||
| -rw-r--r-- | pyramid/config/views.py | 4 | ||||
| -rw-r--r-- | pyramid/interfaces.py | 13 | ||||
| -rw-r--r-- | pyramid/static.py | 63 | ||||
| -rw-r--r-- | pyramid/tests/test_config/test_views.py | 12 | ||||
| -rw-r--r-- | pyramid/tests/test_static.py | 16 |
8 files changed, 84 insertions, 50 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 8cee9c09d..596e5f506 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -20,7 +20,10 @@ Features - Cache busting for static resources has been added and is available via a new argument to ``pyramid.config.Configurator.add_static_view``: ``cachebust``. - See https://github.com/Pylons/pyramid/pull/1380 + Core APIs are shipped for both cache busting via query strings and + path segments and may be extended to fit into custom asset pipelines. + See https://github.com/Pylons/pyramid/pull/1380 and + https://github.com/Pylons/pyramid/pull/1583 - Add ``pyramid.config.Configurator.root_package`` attribute and init parameter to assist with includeable packages that wish to resolve diff --git a/docs/api/static.rst b/docs/api/static.rst index 543e526ad..b6b279139 100644 --- a/docs/api/static.rst +++ b/docs/api/static.rst @@ -9,6 +9,12 @@ :members: :inherited-members: + .. autoclass:: PathSegmentCacheBuster + :members: + + .. autoclass:: QueryStringCacheBuster + :members: + .. autoclass:: PathSegmentMd5CacheBuster :members: diff --git a/docs/narr/assets.rst b/docs/narr/assets.rst index fc908c2b4..d6bc8cbb8 100644 --- a/docs/narr/assets.rst +++ b/docs/narr/assets.rst @@ -446,19 +446,20 @@ In order to implement your own cache buster, you can write your own class from scratch which implements the :class:`~pyramid.interfaces.ICacheBuster` interface. Alternatively you may choose to subclass one of the existing implementations. One of the most likely scenarios is you'd want to change the -way the asset token is generated. To do this just subclass an existing -implementation and replace the :meth:`~pyramid.interfaces.ICacheBuster.token` -method. Here is an example which just uses Git to get the hash of the -currently checked out code: +way the asset token is generated. To do this just subclass either +:class:`~pyramid.static.PathSegmentCacheBuster` or +:class:`~pyramid.static.QueryStringCacheBuster` and define a +``tokenize(pathspec)`` method. Here is an example which just uses Git to get +the hash of the currently checked out code: .. code-block:: python :linenos: import os import subprocess - from pyramid.static import PathSegmentMd5CacheBuster + from pyramid.static import PathSegmentCacheBuster - class GitCacheBuster(PathSegmentMd5CacheBuster): + class GitCacheBuster(PathSegmentCacheBuster): """ Assuming your code is installed as a Git checkout, as opposed to as an egg from an egg repository like PYPI, you can use this cachebuster to @@ -470,7 +471,7 @@ currently checked out code: ['git', 'rev-parse', 'HEAD'], cwd=here).strip() - def token(self, pathspec): + def tokenize(self, pathspec): return self.sha1 Choosing a Cache Buster diff --git a/pyramid/config/views.py b/pyramid/config/views.py index 85e252f2f..24c592f7a 100644 --- a/pyramid/config/views.py +++ b/pyramid/config/views.py @@ -1980,9 +1980,9 @@ class StaticURLInfo(object): cb = self._default_cachebust() if cb: def cachebust(subpath, kw): - token = cb.token(spec + subpath) subpath_tuple = tuple(subpath.split('/')) - subpath_tuple, kw = cb.pregenerate(token, subpath_tuple, kw) + subpath_tuple, kw = cb.pregenerate( + spec + subpath, subpath_tuple, kw) return '/'.join(subpath_tuple), kw else: cachebust = None diff --git a/pyramid/interfaces.py b/pyramid/interfaces.py index d7422bdde..1508f282e 100644 --- a/pyramid/interfaces.py +++ b/pyramid/interfaces.py @@ -1192,18 +1192,11 @@ class ICacheBuster(Interface): .. versionadded:: 1.6 """ - def token(pathspec): - """ - Computes and returns a token string used for cache busting. - ``pathspec`` is the path specification for the resource to be cache - busted. """ - - def pregenerate(token, subpath, kw): + def pregenerate(pathspec, subpath, kw): """ Modifies a subpath and/or keyword arguments from which a static asset - URL will be computed during URL generation. The ``token`` argument is - a token string computed by - :meth:`~pyramid.interfaces.ICacheBuster.token` for a particular asset. + URL will be computed during URL generation. The ``pathspec`` argument + is the path specification for the resource to be cache busted. The ``subpath`` argument is a tuple of path elements that represent the portion of the asset URL which is used to find the asset. The ``kw`` argument is a dict of keywords that are to be passed eventually to diff --git a/pyramid/static.py b/pyramid/static.py index c4a9e3cc4..4ff02f798 100644 --- a/pyramid/static.py +++ b/pyramid/static.py @@ -174,7 +174,7 @@ class Md5AssetTokenGenerator(object): def __init__(self): self.token_cache = {} - def token(self, pathspec): + def tokenize(self, pathspec): # An astute observer will notice that this use of token_cache doesn't # look particularly thread safe. Basic read/write operations on Python # dicts, however, are atomic, so simply accessing and writing values @@ -192,38 +192,54 @@ class Md5AssetTokenGenerator(object): self.token_cache[pathspec] = token = _generate_md5(pathspec) return token -class PathSegmentMd5CacheBuster(Md5AssetTokenGenerator): +class PathSegmentCacheBuster(object): """ An implementation of :class:`~pyramid.interfaces.ICacheBuster` which - inserts an md5 checksum token for cache busting in the path portion of an - asset URL. Generated md5 checksums are cached in order to speed up - subsequent calls. + inserts a token for cache busting in the path portion of an asset URL. + + To use this class, subclass it and provide a ``tokenize`` method which + accepts a ``pathspec`` and returns a token. .. versionadded:: 1.6 """ - def pregenerate(self, token, subpath, kw): + def pregenerate(self, pathspec, subpath, kw): + token = self.tokenize(pathspec) return (token,) + subpath, kw def match(self, subpath): return subpath[1:] -class QueryStringMd5CacheBuster(Md5AssetTokenGenerator): +class PathSegmentMd5CacheBuster(PathSegmentCacheBuster, + Md5AssetTokenGenerator): + """ + An implementation of :class:`~pyramid.interfaces.ICacheBuster` which + inserts an md5 checksum token for cache busting in the path portion of an + asset URL. Generated md5 checksums are cached in order to speed up + subsequent calls. + + .. versionadded:: 1.6 + """ + def __init__(self): + super(PathSegmentMd5CacheBuster, self).__init__() + +class QueryStringCacheBuster(object): """ An implementation of :class:`~pyramid.interfaces.ICacheBuster` which adds - an md5 checksum token for cache busting in the query string of an asset - URL. Generated md5 checksums are cached in order to speed up subsequent - calls. + a token for cache busting in the query string of an asset URL. The optional ``param`` argument determines the name of the parameter added to the query string and defaults to ``'x'``. + To use this class, subclass it and provide a ``tokenize`` method which + accepts a ``pathspec`` and returns a token. + .. versionadded:: 1.6 """ def __init__(self, param='x'): - super(QueryStringMd5CacheBuster, self).__init__() self.param = param - def pregenerate(self, token, subpath, kw): + def pregenerate(self, pathspec, subpath, kw): + token = self.tokenize(pathspec) query = kw.setdefault('_query', {}) if isinstance(query, dict): query[self.param] = token @@ -231,7 +247,23 @@ class QueryStringMd5CacheBuster(Md5AssetTokenGenerator): kw['_query'] = tuple(query) + ((self.param, token),) return subpath, kw -class QueryStringConstantCacheBuster(QueryStringMd5CacheBuster): +class QueryStringMd5CacheBuster(QueryStringCacheBuster, + Md5AssetTokenGenerator): + """ + An implementation of :class:`~pyramid.interfaces.ICacheBuster` which adds + an md5 checksum token for cache busting in the query string of an asset + URL. Generated md5 checksums are cached in order to speed up subsequent + calls. + + The optional ``param`` argument determines the name of the parameter added + to the query string and defaults to ``'x'``. + + .. versionadded:: 1.6 + """ + def __init__(self, param='x'): + super(QueryStringMd5CacheBuster, self).__init__(param=param) + +class QueryStringConstantCacheBuster(QueryStringCacheBuster): """ An implementation of :class:`~pyramid.interfaces.ICacheBuster` which adds an arbitrary token for cache busting in the query string of an asset URL. @@ -245,9 +277,8 @@ class QueryStringConstantCacheBuster(QueryStringMd5CacheBuster): .. versionadded:: 1.6 """ def __init__(self, token, param='x'): + super(QueryStringConstantCacheBuster, self).__init__(param=param) self._token = token - self.param = param - def token(self, pathspec): + def tokenize(self, pathspec): return self._token - diff --git a/pyramid/tests/test_config/test_views.py b/pyramid/tests/test_config/test_views.py index d1eb1ed3c..36c86f78c 100644 --- a/pyramid/tests/test_config/test_views.py +++ b/pyramid/tests/test_config/test_views.py @@ -3995,7 +3995,7 @@ class TestStaticURLInfo(unittest.TestCase): def test_add_cachebust_default(self): config = self._makeConfig() inst = self._makeOne() - inst._default_cachebust = DummyCacheBuster + inst._default_cachebust = lambda: DummyCacheBuster('foo') inst.add(config, 'view', 'mypackage:path', cachebust=True) cachebust = config.registry._static_url_registrations[0][3] subpath, kw = cachebust('some/path', {}) @@ -4014,7 +4014,7 @@ class TestStaticURLInfo(unittest.TestCase): config = self._makeConfig() inst = self._makeOne() inst.add(config, 'view', 'mypackage:path', - cachebust=DummyCacheBuster()) + cachebust=DummyCacheBuster('foo')) cachebust = config.registry._static_url_registrations[0][3] subpath, kw = cachebust('some/path', {}) self.assertEqual(subpath, 'some/path') @@ -4127,10 +4127,10 @@ class DummyMultiView: """ """ class DummyCacheBuster(object): - def token(self, pathspec): - return 'foo' - def pregenerate(self, token, subpath, kw): - kw['x'] = token + def __init__(self, token): + self.token = token + def pregenerate(self, pathspec, subpath, kw): + kw['x'] = self.token return subpath, kw def parse_httpdate(s): diff --git a/pyramid/tests/test_static.py b/pyramid/tests/test_static.py index 2f4de249e..a3df74b44 100644 --- a/pyramid/tests/test_static.py +++ b/pyramid/tests/test_static.py @@ -393,13 +393,13 @@ class TestMd5AssetTokenGenerator(unittest.TestCase): return cls() def test_package_resource(self): - fut = self._makeOne().token + fut = self._makeOne().tokenize expected = '76d653a3a044e2f4b38bb001d283e3d9' token = fut('pyramid.tests:fixtures/static/index.html') self.assertEqual(token, expected) def test_filesystem_resource(self): - fut = self._makeOne().token + fut = self._makeOne().tokenize expected = 'd5155f250bef0e9923e894dbc713c5dd' with open(self.fspath, 'w') as f: f.write("Are we rich yet?") @@ -407,7 +407,7 @@ class TestMd5AssetTokenGenerator(unittest.TestCase): self.assertEqual(token, expected) def test_cache(self): - fut = self._makeOne().token + fut = self._makeOne().tokenize expected = 'd5155f250bef0e9923e894dbc713c5dd' with open(self.fspath, 'w') as f: f.write("Are we rich yet?") @@ -425,11 +425,11 @@ class TestPathSegmentMd5CacheBuster(unittest.TestCase): def _makeOne(self): from pyramid.static import PathSegmentMd5CacheBuster as cls inst = cls() - inst.token = lambda pathspec: 'foo' + inst.tokenize = lambda pathspec: 'foo' return inst def test_token(self): - fut = self._makeOne().token + fut = self._makeOne().tokenize self.assertEqual(fut('whatever'), 'foo') def test_pregenerate(self): @@ -448,11 +448,11 @@ class TestQueryStringMd5CacheBuster(unittest.TestCase): inst = cls(param) else: inst = cls() - inst.token = lambda pathspec: 'foo' + inst.tokenize = lambda pathspec: 'foo' return inst def test_token(self): - fut = self._makeOne().token + fut = self._makeOne().tokenize self.assertEqual(fut('whatever'), 'foo') def test_pregenerate(self): @@ -490,7 +490,7 @@ class TestQueryStringConstantCacheBuster(TestQueryStringMd5CacheBuster): return inst def test_token(self): - fut = self._makeOne().token + fut = self._makeOne().tokenize self.assertEqual(fut('whatever'), 'foo') def test_pregenerate(self): |
