diff options
| author | Michael Merickel <michael@merickel.org> | 2014-02-27 23:45:24 -0500 |
|---|---|---|
| committer | Michael Merickel <michael@merickel.org> | 2014-02-28 01:03:35 -0500 |
| commit | 407b335ed9954c042377fd2e060c36edcd07cf60 (patch) | |
| tree | 8843394f7e827ab4873feaab47eabd12e7077abe | |
| parent | e175ffca6a3c005b61856d50802a289f0483cfb7 (diff) | |
| download | pyramid-407b335ed9954c042377fd2e060c36edcd07cf60.tar.gz pyramid-407b335ed9954c042377fd2e060c36edcd07cf60.tar.bz2 pyramid-407b335ed9954c042377fd2e060c36edcd07cf60.zip | |
add support for using an absolute path to override an asset
fixes #1229
| -rw-r--r-- | CHANGES.txt | 4 | ||||
| -rw-r--r-- | docs/narr/assets.rst | 3 | ||||
| -rw-r--r-- | pyramid/config/assets.py | 216 | ||||
| -rw-r--r-- | pyramid/tests/test_config/pkgs/asset/subpackage/templates/bar.pt | 0 | ||||
| -rw-r--r-- | pyramid/tests/test_config/test_assets.py | 439 |
5 files changed, 496 insertions, 166 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 434eab898..2350bb3de 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,7 @@ +- Assets can now be overidden by an absolute path on the filesystem when using + the ``config.override_asset`` API. + See https://github.com/Pylons/pyramid/issues/1229 + Unreleased ========== diff --git a/docs/narr/assets.rst b/docs/narr/assets.rst index b0a8d18b0..fec55ce7c 100644 --- a/docs/narr/assets.rst +++ b/docs/narr/assets.rst @@ -526,3 +526,6 @@ files. Any software which uses the :func:`pkg_resources.get_resource_string` APIs will obtain an overridden file when an override is used. +As of Pyramid 1.6, it is also possible to override an asset by supplying an +absolute path to a file or directory. This may be useful if the assets are +not distributed as part of a Python package. diff --git a/pyramid/config/assets.py b/pyramid/config/assets.py index 0616e6cda..9da092f08 100644 --- a/pyramid/config/assets.py +++ b/pyramid/config/assets.py @@ -1,3 +1,4 @@ +import os import pkg_resources import sys @@ -79,7 +80,8 @@ class OverrideProvider(pkg_resources.DefaultProvider): return result return pkg_resources.DefaultProvider.resource_listdir( self, resource_name) - + + @implementer(IPackageOverrides) class PackageOverrides(object): # pkg_resources arg in kw args below for testing @@ -97,57 +99,61 @@ class PackageOverrides(object): # optional)... # A __loader__ attribute is basically metadata, and setuptools # uses it as such. - package.__loader__ = self + package.__loader__ = self # we call register_loader_type for every instantiation of this # class; that's OK, it's idempotent to do it more than once. pkg_resources.register_loader_type(self.__class__, OverrideProvider) self.overrides = [] self.overridden_package_name = package.__name__ - def insert(self, path, package, prefix): + def insert(self, path, source): if not path or path.endswith('/'): - override = DirectoryOverride(path, package, prefix) + override = DirectoryOverride(path, source) else: - override = FileOverride(path, package, prefix) + override = FileOverride(path, source) self.overrides.insert(0, override) return override - def search_path(self, resource_name): + def filtered_sources(self, resource_name): for override in self.overrides: o = override(resource_name) if o is not None: - package, name = o - yield package, name + yield o def get_filename(self, resource_name): - for package, rname in self.search_path(resource_name): - if pkg_resources.resource_exists(package, rname): - return pkg_resources.resource_filename(package, rname) + for source, path in self.filtered_sources(resource_name): + result = source.get_filename(path) + if result is not None: + return result def get_stream(self, resource_name): - for package, rname in self.search_path(resource_name): - if pkg_resources.resource_exists(package, rname): - return pkg_resources.resource_stream(package, rname) + for source, path in self.filtered_sources(resource_name): + result = source.get_stream(path) + if result is not None: + return result def get_string(self, resource_name): - for package, rname in self.search_path(resource_name): - if pkg_resources.resource_exists(package, rname): - return pkg_resources.resource_string(package, rname) + for source, path in self.filtered_sources(resource_name): + result = source.get_string(path) + if result is not None: + return result def has_resource(self, resource_name): - for package, rname in self.search_path(resource_name): - if pkg_resources.resource_exists(package, rname): + for source, path in self.filtered_sources(resource_name): + if source.exists(path): return True def isdir(self, resource_name): - for package, rname in self.search_path(resource_name): - if pkg_resources.resource_exists(package, rname): - return pkg_resources.resource_isdir(package, rname) + for source, path in self.filtered_sources(resource_name): + result = source.isdir(path) + if result is not None: + return result def listdir(self, resource_name): - for package, rname in self.search_path(resource_name): - if pkg_resources.resource_exists(package, rname): - return pkg_resources.resource_listdir(package, rname) + for source, path in self.filtered_sources(resource_name): + result = source.listdir(path) + if result is not None: + return result @property def real_loader(self): @@ -174,72 +180,180 @@ class PackageOverrides(object): """ See IPEP302Loader. """ return self.real_loader.get_source(fullname) - + class DirectoryOverride: - def __init__(self, path, package, prefix): + def __init__(self, path, source): self.path = path - self.package = package - self.prefix = prefix self.pathlen = len(self.path) + self.source = source def __call__(self, resource_name): if resource_name.startswith(self.path): - name = '%s%s' % (self.prefix, resource_name[self.pathlen:]) - return self.package, name + new_path = resource_name[self.pathlen:] + return self.source, new_path class FileOverride: - def __init__(self, path, package, prefix): + def __init__(self, path, source): self.path = path - self.package = package - self.prefix = prefix + self.source = source def __call__(self, resource_name): if resource_name == self.path: - return self.package, self.prefix + return self.source, '' + + +class PackageAssetSource(object): + """ + An asset source relative to a package. + + If this asset source is a file, then we expect the ``prefix`` to point + to the new name of the file, and the incoming ``resource_name`` will be + the empty string, as returned by the ``FileOverride``. + + """ + def __init__(self, package, prefix): + self.package = package + self.prefix = prefix + + def get_path(self, resource_name): + return '%s%s' % (self.prefix, resource_name) + + def get_filename(self, resource_name): + path = self.get_path(resource_name) + if pkg_resources.resource_exists(self.package, path): + return pkg_resources.resource_filename(self.package, path) + + def get_stream(self, resource_name): + path = self.get_path(resource_name) + if pkg_resources.resource_exists(self.package, path): + return pkg_resources.resource_stream(self.package, path) + + def get_string(self, resource_name): + path = self.get_path(resource_name) + if pkg_resources.resource_exists(self.package, path): + return pkg_resources.resource_string(self.package, path) + + def exists(self, resource_name): + path = self.get_path(resource_name) + if pkg_resources.resource_exists(self.package, path): + return True + + def isdir(self, resource_name): + path = self.get_path(resource_name) + if pkg_resources.resource_exists(self.package, path): + return pkg_resources.resource_isdir(self.package, path) + + def listdir(self, resource_name): + path = self.get_path(resource_name) + if pkg_resources.resource_exists(self.package, path): + return pkg_resources.resource_listdir(self.package, path) + + +class FSAssetSource(object): + """ + An asset source relative to a path in the filesystem. + + """ + def __init__(self, prefix): + self.prefix = prefix + + def get_filename(self, resource_name): + if resource_name: + path = os.path.join(self.prefix, resource_name) + else: + path = self.prefix + + if os.path.exists(path): + return path + + def get_stream(self, resource_name): + path = self.get_filename(resource_name) + if path is not None: + return open(path, 'rb') + + def get_string(self, resource_name): + stream = self.get_stream(resource_name) + if stream is not None: + with stream: + return stream.read() + + def exists(self, resource_name): + path = self.get_filename(resource_name) + if path is not None: + return True + + def isdir(self, resource_name): + path = self.get_filename(resource_name) + if path is not None: + return os.path.isdir(path) + + def listdir(self, resource_name): + path = self.get_filename(resource_name) + if path is not None: + return os.listdir(path) class AssetsConfiguratorMixin(object): - def _override(self, package, path, override_package, override_prefix, + def _override(self, package, path, override_source, PackageOverrides=PackageOverrides): pkg_name = package.__name__ - override_pkg_name = override_package.__name__ override = self.registry.queryUtility(IPackageOverrides, name=pkg_name) if override is None: override = PackageOverrides(package) self.registry.registerUtility(override, IPackageOverrides, name=pkg_name) - override.insert(path, override_pkg_name, override_prefix) + override.insert(path, override_source) @action_method def override_asset(self, to_override, override_with, _override=None): """ Add a :app:`Pyramid` asset override to the current configuration state. - ``to_override`` is a :term:`asset specification` to the + ``to_override`` is an :term:`asset specification` to the asset being overridden. - ``override_with`` is a :term:`asset specification` to the - asset that is performing the override. + ``override_with`` is an :term:`asset specification` to the + asset that is performing the override. This may also be an absolute + path. See :ref:`assets_chapter` for more information about asset overrides.""" if to_override == override_with: - raise ConfigurationError('You cannot override an asset with itself') + raise ConfigurationError( + 'You cannot override an asset with itself') package = to_override path = '' if ':' in to_override: package, path = to_override.split(':', 1) - override_package = override_with - override_prefix = '' - if ':' in override_with: - override_package, override_prefix = override_with.split(':', 1) - # *_isdir = override is package or directory - overridden_isdir = path=='' or path.endswith('/') - override_isdir = override_prefix=='' or override_prefix.endswith('/') + overridden_isdir = path == '' or path.endswith('/') + + if os.path.isabs(override_with): + override_source = FSAssetSource(override_with) + if not os.path.exists(override_with): + raise ConfigurationError( + 'Cannot override asset with an absolute path that does ' + 'not exist') + override_isdir = os.path.isdir(override_with) + override_package = None + override_prefix = override_with + else: + override_package = override_with + override_prefix = '' + if ':' in override_with: + override_package, override_prefix = override_with.split(':', 1) + + __import__(override_package) + to_package = sys.modules[override_package] + override_source = PackageAssetSource(to_package, override_prefix) + + override_isdir = ( + override_prefix == '' or + override_with.endswith('/') + ) if overridden_isdir and (not override_isdir): raise ConfigurationError( @@ -255,10 +369,8 @@ class AssetsConfiguratorMixin(object): def register(): __import__(package) - __import__(override_package) from_package = sys.modules[package] - to_package = sys.modules[override_package] - override(from_package, path, to_package, override_prefix) + override(from_package, path, override_source) intr = self.introspectable( 'asset overrides', diff --git a/pyramid/tests/test_config/pkgs/asset/subpackage/templates/bar.pt b/pyramid/tests/test_config/pkgs/asset/subpackage/templates/bar.pt new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/pyramid/tests/test_config/pkgs/asset/subpackage/templates/bar.pt diff --git a/pyramid/tests/test_config/test_assets.py b/pyramid/tests/test_config/test_assets.py index 345e7f8d6..b605a602d 100644 --- a/pyramid/tests/test_config/test_assets.py +++ b/pyramid/tests/test_config/test_assets.py @@ -1,6 +1,10 @@ +import os.path import unittest from pyramid.testing import cleanUp +# we use this folder +here = os.path.dirname(os.path.abspath(__file__)) + class TestAssetsConfiguratorMixin(unittest.TestCase): def _makeOne(self, *arg, **kw): from pyramid.config import Configurator @@ -10,27 +14,31 @@ class TestAssetsConfiguratorMixin(unittest.TestCase): def test_override_asset_samename(self): from pyramid.exceptions import ConfigurationError config = self._makeOne() - self.assertRaises(ConfigurationError, config.override_asset,'a', 'a') + self.assertRaises(ConfigurationError, config.override_asset, 'a', 'a') def test_override_asset_directory_with_file(self): from pyramid.exceptions import ConfigurationError config = self._makeOne() self.assertRaises(ConfigurationError, config.override_asset, - 'a:foo/', 'a:foo.pt') + 'a:foo/', + 'pyramid.tests.test_config.pkgs.asset:foo.pt') def test_override_asset_file_with_directory(self): from pyramid.exceptions import ConfigurationError config = self._makeOne() self.assertRaises(ConfigurationError, config.override_asset, - 'a:foo.pt', 'a:foo/') + 'a:foo.pt', + 'pyramid.tests.test_config.pkgs.asset:templates/') def test_override_asset_file_with_package(self): from pyramid.exceptions import ConfigurationError config = self._makeOne() self.assertRaises(ConfigurationError, config.override_asset, - 'a:foo.pt', 'a') + 'a:foo.pt', + 'pyramid.tests.test_config.pkgs.asset') def test_override_asset_file_with_file(self): + from pyramid.config.assets import PackageAssetSource config = self._makeOne(autocommit=True) override = DummyUnderOverride() config.override_asset( @@ -41,10 +49,13 @@ class TestAssetsConfiguratorMixin(unittest.TestCase): from pyramid.tests.test_config.pkgs.asset import subpackage self.assertEqual(override.package, asset) self.assertEqual(override.path, 'templates/foo.pt') - self.assertEqual(override.override_package, subpackage) - self.assertEqual(override.override_prefix, 'templates/bar.pt') + source = override.source + self.assertTrue(isinstance(source, PackageAssetSource)) + self.assertEqual(source.package, subpackage) + self.assertEqual(source.prefix, 'templates/bar.pt') def test_override_asset_package_with_package(self): + from pyramid.config.assets import PackageAssetSource config = self._makeOne(autocommit=True) override = DummyUnderOverride() config.override_asset( @@ -55,10 +66,13 @@ class TestAssetsConfiguratorMixin(unittest.TestCase): from pyramid.tests.test_config.pkgs.asset import subpackage self.assertEqual(override.package, asset) self.assertEqual(override.path, '') - self.assertEqual(override.override_package, subpackage) - self.assertEqual(override.override_prefix, '') + source = override.source + self.assertTrue(isinstance(source, PackageAssetSource)) + self.assertEqual(source.package, subpackage) + self.assertEqual(source.prefix, '') def test_override_asset_directory_with_directory(self): + from pyramid.config.assets import PackageAssetSource config = self._makeOne(autocommit=True) override = DummyUnderOverride() config.override_asset( @@ -69,10 +83,13 @@ class TestAssetsConfiguratorMixin(unittest.TestCase): from pyramid.tests.test_config.pkgs.asset import subpackage self.assertEqual(override.package, asset) self.assertEqual(override.path, 'templates/') - self.assertEqual(override.override_package, subpackage) - self.assertEqual(override.override_prefix, 'templates/') + source = override.source + self.assertTrue(isinstance(source, PackageAssetSource)) + self.assertEqual(source.package, subpackage) + self.assertEqual(source.prefix, 'templates/') def test_override_asset_directory_with_package(self): + from pyramid.config.assets import PackageAssetSource config = self._makeOne(autocommit=True) override = DummyUnderOverride() config.override_asset( @@ -83,10 +100,13 @@ class TestAssetsConfiguratorMixin(unittest.TestCase): from pyramid.tests.test_config.pkgs.asset import subpackage self.assertEqual(override.package, asset) self.assertEqual(override.path, 'templates/') - self.assertEqual(override.override_package, subpackage) - self.assertEqual(override.override_prefix, '') + source = override.source + self.assertTrue(isinstance(source, PackageAssetSource)) + self.assertEqual(source.package, subpackage) + self.assertEqual(source.prefix, '') def test_override_asset_package_with_directory(self): + from pyramid.config.assets import PackageAssetSource config = self._makeOne(autocommit=True) override = DummyUnderOverride() config.override_asset( @@ -97,32 +117,105 @@ class TestAssetsConfiguratorMixin(unittest.TestCase): from pyramid.tests.test_config.pkgs.asset import subpackage self.assertEqual(override.package, asset) self.assertEqual(override.path, '') - self.assertEqual(override.override_package, subpackage) - self.assertEqual(override.override_prefix, 'templates/') + source = override.source + self.assertTrue(isinstance(source, PackageAssetSource)) + self.assertEqual(source.package, subpackage) + self.assertEqual(source.prefix, 'templates/') + + def test_override_asset_directory_with_absfile(self): + from pyramid.exceptions import ConfigurationError + config = self._makeOne() + self.assertRaises(ConfigurationError, config.override_asset, + 'a:foo/', + os.path.join(here, 'pkgs', 'asset', 'foo.pt')) + + def test_override_asset_file_with_absdirectory(self): + from pyramid.exceptions import ConfigurationError + config = self._makeOne() + abspath = os.path.join(here, 'pkgs', 'asset', 'subpackage', 'templates') + self.assertRaises(ConfigurationError, config.override_asset, + 'a:foo.pt', + abspath) + + def test_override_asset_file_with_missing_abspath(self): + from pyramid.exceptions import ConfigurationError + config = self._makeOne() + self.assertRaises(ConfigurationError, config.override_asset, + 'a:foo.pt', + os.path.join(here, 'wont_exist')) + + def test_override_asset_file_with_absfile(self): + from pyramid.config.assets import FSAssetSource + config = self._makeOne(autocommit=True) + override = DummyUnderOverride() + abspath = os.path.join(here, 'pkgs', 'asset', 'subpackage', + 'templates', 'bar.pt') + config.override_asset( + 'pyramid.tests.test_config.pkgs.asset:templates/foo.pt', + abspath, + _override=override) + from pyramid.tests.test_config.pkgs import asset + self.assertEqual(override.package, asset) + self.assertEqual(override.path, 'templates/foo.pt') + source = override.source + self.assertTrue(isinstance(source, FSAssetSource)) + self.assertEqual(source.prefix, abspath) + + def test_override_asset_directory_with_absdirectory(self): + from pyramid.config.assets import FSAssetSource + config = self._makeOne(autocommit=True) + override = DummyUnderOverride() + abspath = os.path.join(here, 'pkgs', 'asset', 'subpackage', 'templates') + config.override_asset( + 'pyramid.tests.test_config.pkgs.asset:templates/', + abspath, + _override=override) + from pyramid.tests.test_config.pkgs import asset + self.assertEqual(override.package, asset) + self.assertEqual(override.path, 'templates/') + source = override.source + self.assertTrue(isinstance(source, FSAssetSource)) + self.assertEqual(source.prefix, abspath) + + def test_override_asset_package_with_absdirectory(self): + from pyramid.config.assets import FSAssetSource + config = self._makeOne(autocommit=True) + override = DummyUnderOverride() + abspath = os.path.join(here, 'pkgs', 'asset', 'subpackage', 'templates') + config.override_asset( + 'pyramid.tests.test_config.pkgs.asset', + abspath, + _override=override) + from pyramid.tests.test_config.pkgs import asset + self.assertEqual(override.package, asset) + self.assertEqual(override.path, '') + source = override.source + self.assertTrue(isinstance(source, FSAssetSource)) + self.assertEqual(source.prefix, abspath) def test__override_not_yet_registered(self): from pyramid.interfaces import IPackageOverrides package = DummyPackage('package') - opackage = DummyPackage('opackage') + source = DummyAssetSource() config = self._makeOne() - config._override(package, 'path', opackage, 'oprefix', + config._override(package, 'path', source, PackageOverrides=DummyPackageOverrides) overrides = config.registry.queryUtility(IPackageOverrides, name='package') - self.assertEqual(overrides.inserted, [('path', 'opackage', 'oprefix')]) + self.assertEqual(overrides.inserted, [('path', source)]) self.assertEqual(overrides.package, package) def test__override_already_registered(self): from pyramid.interfaces import IPackageOverrides package = DummyPackage('package') - opackage = DummyPackage('opackage') + source = DummyAssetSource() overrides = DummyPackageOverrides(package) config = self._makeOne() config.registry.registerUtility(overrides, IPackageOverrides, name='package') - config._override(package, 'path', opackage, 'oprefix', + config._override(package, 'path', source, PackageOverrides=DummyPackageOverrides) - self.assertEqual(overrides.inserted, [('path', 'opackage', 'oprefix')]) + self.assertEqual(overrides.inserted, [('path', source)]) self.assertEqual(overrides.package, package) @@ -148,30 +241,24 @@ class TestOverrideProvider(unittest.TestCase): reg.registerUtility(overrides, IPackageOverrides, name=name) def test_get_resource_filename_no_overrides(self): - import os resource_name = 'test_assets.py' import pyramid.tests.test_config provider = self._makeOne(pyramid.tests.test_config) - here = os.path.dirname(os.path.abspath(__file__)) expected = os.path.join(here, resource_name) result = provider.get_resource_filename(None, resource_name) self.assertEqual(result, expected) def test_get_resource_stream_no_overrides(self): - import os resource_name = 'test_assets.py' import pyramid.tests.test_config provider = self._makeOne(pyramid.tests.test_config) - here = os.path.dirname(os.path.abspath(__file__)) with provider.get_resource_stream(None, resource_name) as result: _assertBody(result.read(), os.path.join(here, resource_name)) def test_get_resource_string_no_overrides(self): - import os resource_name = 'test_assets.py' import pyramid.tests.test_config provider = self._makeOne(pyramid.tests.test_config) - here = os.path.dirname(os.path.abspath(__file__)) result = provider.get_resource_string(None, resource_name) _assertBody(result, os.path.join(here, resource_name)) @@ -202,11 +289,9 @@ class TestOverrideProvider(unittest.TestCase): def test_get_resource_filename_override_returns_None(self): overrides = DummyOverrides(None) self._registerOverrides(overrides) - import os resource_name = 'test_assets.py' import pyramid.tests.test_config provider = self._makeOne(pyramid.tests.test_config) - here = os.path.dirname(os.path.abspath(__file__)) expected = os.path.join(here, resource_name) result = provider.get_resource_filename(None, resource_name) self.assertEqual(result, expected) @@ -214,22 +299,18 @@ class TestOverrideProvider(unittest.TestCase): def test_get_resource_stream_override_returns_None(self): overrides = DummyOverrides(None) self._registerOverrides(overrides) - import os resource_name = 'test_assets.py' import pyramid.tests.test_config provider = self._makeOne(pyramid.tests.test_config) - here = os.path.dirname(os.path.abspath(__file__)) with provider.get_resource_stream(None, resource_name) as result: _assertBody(result.read(), os.path.join(here, resource_name)) def test_get_resource_string_override_returns_None(self): overrides = DummyOverrides(None) self._registerOverrides(overrides) - import os resource_name = 'test_assets.py' import pyramid.tests.test_config provider = self._makeOne(pyramid.tests.test_config) - here = os.path.dirname(os.path.abspath(__file__)) result = provider.get_resource_string(None, resource_name) _assertBody(result, os.path.join(here, resource_name)) @@ -378,8 +459,8 @@ class TestPackageOverrides(unittest.TestCase): from pyramid.config.assets import DirectoryOverride package = DummyPackage('package') po = self._makeOne(package) - po.overrides= [None] - po.insert('foo/', 'package', 'bar/') + po.overrides = [None] + po.insert('foo/', DummyAssetSource()) self.assertEqual(len(po.overrides), 2) override = po.overrides[0] self.assertEqual(override.__class__, DirectoryOverride) @@ -388,8 +469,8 @@ class TestPackageOverrides(unittest.TestCase): from pyramid.config.assets import FileOverride package = DummyPackage('package') po = self._makeOne(package) - po.overrides= [None] - po.insert('foo.pt', 'package', 'bar.pt') + po.overrides = [None] + po.insert('foo.pt', DummyAssetSource()) self.assertEqual(len(po.overrides), 2) override = po.overrides[0] self.assertEqual(override.__class__, FileOverride) @@ -399,132 +480,137 @@ class TestPackageOverrides(unittest.TestCase): from pyramid.config.assets import DirectoryOverride package = DummyPackage('package') po = self._makeOne(package) - po.overrides= [None] - po.insert('', 'package', 'bar/') + po.overrides = [None] + source = DummyAssetSource() + po.insert('', source) self.assertEqual(len(po.overrides), 2) override = po.overrides[0] self.assertEqual(override.__class__, DirectoryOverride) - def test_search_path(self): - overrides = [ DummyOverride(None), DummyOverride(('package', 'name'))] + def test_filtered_sources(self): + overrides = [ DummyOverride(None), DummyOverride('foo')] package = DummyPackage('package') po = self._makeOne(package) - po.overrides= overrides - self.assertEqual(list(po.search_path('whatever')), - [('package', 'name')]) + po.overrides = overrides + self.assertEqual(list(po.filtered_sources('whatever')), ['foo']) def test_get_filename(self): - import os - overrides = [ DummyOverride(None), DummyOverride( - ('pyramid.tests.test_config', 'test_assets.py'))] + source = DummyAssetSource(filename='foo.pt') + overrides = [ DummyOverride(None), DummyOverride((source, ''))] package = DummyPackage('package') po = self._makeOne(package) - po.overrides= overrides - here = os.path.dirname(os.path.abspath(__file__)) - expected = os.path.join(here, 'test_assets.py') - self.assertEqual(po.get_filename('whatever'), expected) + po.overrides = overrides + result = po.get_filename('whatever') + self.assertEqual(result, 'foo.pt') + self.assertEqual(source.resource_name, '') def test_get_filename_file_doesnt_exist(self): - overrides = [ DummyOverride(None), DummyOverride( - ('pyramid.tests.test_config', 'wont_exist'))] + source = DummyAssetSource(filename=None) + overrides = [DummyOverride(None), DummyOverride((source, 'wont_exist'))] package = DummyPackage('package') po = self._makeOne(package) - po.overrides= overrides + po.overrides = overrides self.assertEqual(po.get_filename('whatever'), None) - + self.assertEqual(source.resource_name, 'wont_exist') + def test_get_stream(self): - import os - overrides = [ DummyOverride(None), DummyOverride( - ('pyramid.tests.test_config', 'test_assets.py'))] + source = DummyAssetSource(stream='a stream?') + overrides = [DummyOverride(None), DummyOverride((source, 'foo.pt'))] package = DummyPackage('package') po = self._makeOne(package) - po.overrides= overrides - here = os.path.dirname(os.path.abspath(__file__)) - with po.get_stream('whatever') as stream: - _assertBody(stream.read(), os.path.join(here, 'test_assets.py')) + po.overrides = overrides + self.assertEqual(po.get_stream('whatever'), 'a stream?') + self.assertEqual(source.resource_name, 'foo.pt') def test_get_stream_file_doesnt_exist(self): - overrides = [ DummyOverride(None), DummyOverride( - ('pyramid.tests.test_config', 'wont_exist'))] + source = DummyAssetSource(stream=None) + overrides = [DummyOverride(None), DummyOverride((source, 'wont_exist'))] package = DummyPackage('package') po = self._makeOne(package) - po.overrides= overrides + po.overrides = overrides self.assertEqual(po.get_stream('whatever'), None) + self.assertEqual(source.resource_name, 'wont_exist') def test_get_string(self): - import os - overrides = [ DummyOverride(None), DummyOverride( - ('pyramid.tests.test_config', 'test_assets.py'))] + source = DummyAssetSource(string='a string') + overrides = [DummyOverride(None), DummyOverride((source, 'foo.pt'))] package = DummyPackage('package') po = self._makeOne(package) - po.overrides= overrides - here = os.path.dirname(os.path.abspath(__file__)) - _assertBody(po.get_string('whatever'), - os.path.join(here, 'test_assets.py')) + po.overrides = overrides + self.assertEqual(po.get_string('whatever'), 'a string') + self.assertEqual(source.resource_name, 'foo.pt') def test_get_string_file_doesnt_exist(self): - overrides = [ DummyOverride(None), DummyOverride( - ('pyramid.tests.test_config', 'wont_exist'))] + source = DummyAssetSource(string=None) + overrides = [DummyOverride(None), DummyOverride((source, 'wont_exist'))] package = DummyPackage('package') po = self._makeOne(package) - po.overrides= overrides + po.overrides = overrides self.assertEqual(po.get_string('whatever'), None) + self.assertEqual(source.resource_name, 'wont_exist') def test_has_resource(self): - overrides = [ DummyOverride(None), DummyOverride( - ('pyramid.tests.test_config', 'test_assets.py'))] + source = DummyAssetSource(exists=True) + overrides = [DummyOverride(None), DummyOverride((source, 'foo.pt'))] package = DummyPackage('package') po = self._makeOne(package) - po.overrides= overrides + po.overrides = overrides self.assertEqual(po.has_resource('whatever'), True) + self.assertEqual(source.resource_name, 'foo.pt') def test_has_resource_file_doesnt_exist(self): - overrides = [ DummyOverride(None), DummyOverride( - ('pyramid.tests.test_config', 'wont_exist'))] + source = DummyAssetSource(exists=None) + overrides = [DummyOverride(None), DummyOverride((source, 'wont_exist'))] package = DummyPackage('package') po = self._makeOne(package) - po.overrides= overrides + po.overrides = overrides self.assertEqual(po.has_resource('whatever'), None) + self.assertEqual(source.resource_name, 'wont_exist') def test_isdir_false(self): - overrides = [ DummyOverride( - ('pyramid.tests.test_config', 'test_assets.py'))] + source = DummyAssetSource(isdir=False) + overrides = [DummyOverride(None), DummyOverride((source, 'foo.pt'))] package = DummyPackage('package') po = self._makeOne(package) - po.overrides= overrides + po.overrides = overrides self.assertEqual(po.isdir('whatever'), False) - + self.assertEqual(source.resource_name, 'foo.pt') + def test_isdir_true(self): - overrides = [ DummyOverride( - ('pyramid.tests.test_config', 'files'))] + source = DummyAssetSource(isdir=True) + overrides = [DummyOverride(None), DummyOverride((source, 'foo.pt'))] package = DummyPackage('package') po = self._makeOne(package) - po.overrides= overrides + po.overrides = overrides self.assertEqual(po.isdir('whatever'), True) + self.assertEqual(source.resource_name, 'foo.pt') def test_isdir_doesnt_exist(self): - overrides = [ DummyOverride(None), DummyOverride( - ('pyramid.tests.test_config', 'wont_exist'))] + source = DummyAssetSource(isdir=None) + overrides = [DummyOverride(None), DummyOverride((source, 'wont_exist'))] package = DummyPackage('package') po = self._makeOne(package) - po.overrides= overrides + po.overrides = overrides self.assertEqual(po.isdir('whatever'), None) + self.assertEqual(source.resource_name, 'wont_exist') def test_listdir(self): - overrides = [ DummyOverride( - ('pyramid.tests.test_config', 'files'))] + source = DummyAssetSource(listdir=True) + overrides = [DummyOverride(None), DummyOverride((source, 'foo.pt'))] package = DummyPackage('package') po = self._makeOne(package) - po.overrides= overrides - self.assertTrue(po.listdir('whatever')) + po.overrides = overrides + self.assertEqual(po.listdir('whatever'), True) + self.assertEqual(source.resource_name, 'foo.pt') def test_listdir_doesnt_exist(self): - overrides = [ DummyOverride(None), DummyOverride( - ('pyramid.tests.test_config', 'wont_exist'))] + source = DummyAssetSource(listdir=None) + overrides = [DummyOverride(None), DummyOverride((source, 'wont_exist'))] package = DummyPackage('package') po = self._makeOne(package) - po.overrides= overrides + po.overrides = overrides self.assertEqual(po.listdir('whatever'), None) + self.assertEqual(source.resource_name, 'wont_exist') # PEP 302 __loader__ extensions: use the "real" __loader__, if present. def test_get_data_pkg_has_no___loader__(self): @@ -570,27 +656,124 @@ class TestPackageOverrides(unittest.TestCase): def test_get_source_pkg_has___loader__(self): package = DummyPackage('package') - loader = package.__loader__ = DummyLoader() + loader = package.__loader__ = DummyLoader() po = self._makeOne(package) self.assertEqual(po.get_source('whatever'), 'def foo():\n pass') self.assertEqual(loader._got_source, 'whatever') +class AssetSourceIntegrationTests(object): + + def test_get_filename(self): + source = self._makeOne('') + self.assertEqual(source.get_filename('test_assets.py'), + os.path.join(here, 'test_assets.py')) + + def test_get_filename_with_prefix(self): + source = self._makeOne('test_assets.py') + self.assertEqual(source.get_filename(''), + os.path.join(here, 'test_assets.py')) + + def test_get_filename_file_doesnt_exist(self): + source = self._makeOne('') + self.assertEqual(source.get_filename('wont_exist'), None) + + def test_get_stream(self): + source = self._makeOne('') + with source.get_stream('test_assets.py') as stream: + _assertBody(stream.read(), os.path.join(here, 'test_assets.py')) + + def test_get_stream_with_prefix(self): + source = self._makeOne('test_assets.py') + with source.get_stream('') as stream: + _assertBody(stream.read(), os.path.join(here, 'test_assets.py')) + + def test_get_stream_file_doesnt_exist(self): + source = self._makeOne('') + self.assertEqual(source.get_stream('wont_exist'), None) + + def test_get_string(self): + source = self._makeOne('') + _assertBody(source.get_string('test_assets.py'), + os.path.join(here, 'test_assets.py')) + + def test_get_string_with_prefix(self): + source = self._makeOne('test_assets.py') + _assertBody(source.get_string(''), + os.path.join(here, 'test_assets.py')) + + def test_get_string_file_doesnt_exist(self): + source = self._makeOne('') + self.assertEqual(source.get_string('wont_exist'), None) + + def test_exists(self): + source = self._makeOne('') + self.assertEqual(source.exists('test_assets.py'), True) + + def test_exists_with_prefix(self): + source = self._makeOne('test_assets.py') + self.assertEqual(source.exists(''), True) + + def test_exists_file_doesnt_exist(self): + source = self._makeOne('') + self.assertEqual(source.exists('wont_exist'), None) + + def test_isdir_false(self): + source = self._makeOne('') + self.assertEqual(source.isdir('test_assets.py'), False) + + def test_isdir_true(self): + source = self._makeOne('') + self.assertEqual(source.isdir('files'), True) + + def test_isdir_doesnt_exist(self): + source = self._makeOne('') + self.assertEqual(source.isdir('wont_exist'), None) + + def test_listdir(self): + source = self._makeOne('') + self.assertTrue(source.listdir('files')) + + def test_listdir_doesnt_exist(self): + source = self._makeOne('') + self.assertEqual(source.listdir('wont_exist'), None) + +class TestPackageAssetSource(AssetSourceIntegrationTests, unittest.TestCase): + + def _getTargetClass(self): + from pyramid.config.assets import PackageAssetSource + return PackageAssetSource + + def _makeOne(self, prefix, package='pyramid.tests.test_config'): + klass = self._getTargetClass() + return klass(package, prefix) + +class TestFSAssetSource(AssetSourceIntegrationTests, unittest.TestCase): + def _getTargetClass(self): + from pyramid.config.assets import FSAssetSource + return FSAssetSource + + def _makeOne(self, prefix, base_prefix=here): + klass = self._getTargetClass() + return klass(os.path.join(base_prefix, prefix)) + class TestDirectoryOverride(unittest.TestCase): def _getTargetClass(self): from pyramid.config.assets import DirectoryOverride return DirectoryOverride - def _makeOne(self, path, package, prefix): + def _makeOne(self, path, source): klass = self._getTargetClass() - return klass(path, package, prefix) + return klass(path, source) def test_it_match(self): - o = self._makeOne('foo/', 'package', 'bar/') + source = DummyAssetSource() + o = self._makeOne('foo/', source) result = o('foo/something.pt') - self.assertEqual(result, ('package', 'bar/something.pt')) + self.assertEqual(result, (source, 'something.pt')) def test_it_no_match(self): - o = self._makeOne('foo/', 'package', 'bar/') + source = DummyAssetSource() + o = self._makeOne('foo/', source) result = o('baz/notfound.pt') self.assertEqual(result, None) @@ -599,17 +782,19 @@ class TestFileOverride(unittest.TestCase): from pyramid.config.assets import FileOverride return FileOverride - def _makeOne(self, path, package, prefix): + def _makeOne(self, path, source): klass = self._getTargetClass() - return klass(path, package, prefix) + return klass(path, source) def test_it_match(self): - o = self._makeOne('foo.pt', 'package', 'bar.pt') + source = DummyAssetSource() + o = self._makeOne('foo.pt', source) result = o('foo.pt') - self.assertEqual(result, ('package', 'bar.pt')) + self.assertEqual(result, (source, '')) def test_it_no_match(self): - o = self._makeOne('foo.pt', 'package', 'bar.pt') + source = DummyAssetSource() + o = self._makeOne('foo.pt', source) result = o('notfound.pt') self.assertEqual(result, None) @@ -634,8 +819,8 @@ class DummyPackageOverrides: self.package = package self.inserted = [] - def insert(self, path, package, prefix): - self.inserted.append((path, package, prefix)) + def insert(self, path, source): + self.inserted.append((path, source)) class DummyPkgResources: def __init__(self): @@ -647,6 +832,34 @@ class DummyPkgResources: class DummyPackage: def __init__(self, name): self.__name__ = name + +class DummyAssetSource: + def __init__(self, **kw): + self.kw = kw + + def get_filename(self, resource_name): + self.resource_name = resource_name + return self.kw['filename'] + + def get_stream(self, resource_name): + self.resource_name = resource_name + return self.kw['stream'] + + def get_string(self, resource_name): + self.resource_name = resource_name + return self.kw['string'] + + def exists(self, resource_name): + self.resource_name = resource_name + return self.kw['exists'] + + def isdir(self, resource_name): + self.resource_name = resource_name + return self.kw['isdir'] + + def listdir(self, resource_name): + self.resource_name = resource_name + return self.kw['listdir'] class DummyLoader: _got_data = _is_package = None @@ -664,12 +877,10 @@ class DummyLoader: return 'def foo():\n pass' class DummyUnderOverride: - def __call__(self, package, path, override_package, override_prefix, - _info=''): + def __call__(self, package, path, source, _info=''): self.package = package self.path = path - self.override_package = override_package - self.override_prefix = override_prefix + self.source = source def read_(src): with open(src, 'rb') as f: |
