summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Merickel <michael@merickel.org>2015-02-17 11:39:29 -0600
committerMichael Merickel <michael@merickel.org>2015-02-17 11:39:29 -0600
commit75f85c57e0f4d1069cef9feb6ab6182b5f651492 (patch)
tree039ca762ddcf6e4946a2570136927d2773374969
parent6ea099ded65ff671c26753b9b30e4d19b3c47b81 (diff)
parent5fdf9a5f63b7731963de7f49df6c29077155525f (diff)
downloadpyramid-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.txt5
-rw-r--r--docs/api/static.rst6
-rw-r--r--docs/narr/assets.rst15
-rw-r--r--pyramid/config/views.py4
-rw-r--r--pyramid/interfaces.py13
-rw-r--r--pyramid/static.py63
-rw-r--r--pyramid/tests/test_config/test_views.py12
-rw-r--r--pyramid/tests/test_static.py16
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):