Marc Abramowitz
2015-02-19 e51295bee250a144adee0d31b4c6d0a62ad27770
refs
author Marc Abramowitz <marc@marc-abramowitz.com>
Thursday, February 19, 2015 22:57 +0100
committer Marc Abramowitz <marc@marc-abramowitz.com>
Friday, February 20, 2015 00:39 +0100
commite51295bee250a144adee0d31b4c6d0a62ad27770
tree c2511d563f14df7b633f3d76017d76259d7ff18c tree | zip | gz
parent 5ace6591cfb49199befc258ccb256a69c455477e view | diff
Fix asset override with package

`AssetsConfiguratorMixin.override_asset` does:

```python
__import__(override_package)
to_package = sys.modules[override_package]
override_source = PackageAssetSource(to_package, override_prefix)
```

so it's assuming that the `package` argument to `PackageAssetSource.__init__` takes a module object.

But then `PackageAssetSource` had a bunch of methods that did stuff like:

- `pkg_resources.resource_exists(self.package, path)`
- `pkg_resources.resource_filename(self.package, path)`
- `pkg_resources.resource_stream(self.package, path)`

and all these `pkg_resources` functions need their `package_or_requirement`
argument to be a **string**; not a module - see
https://pythonhosted.org/setuptools/pkg_resources.html#basic-resource-access, which says:

> the `package_or_requirement argument` may be either a Python package/module
> name (e.g. `foo.bar`) or a `Requirement` instance.

This causes errors when overriding assets -- e.g.: I am using Kotti and
Kotti has this code (https://github.com/Kotti/Kotti/blob/master/kotti/__init__.py#L251):

```python
for override in [a.strip()
for a in settings['kotti.asset_overrides'].split()
if a.strip()]:
config.override_asset(to_override='kotti', override_with=override)
```

A Kotti add-on called kotti_navigation does this
(https://github.com/Kotti/kotti_navigation/blob/master/kotti_navigation/__init__.py#L12):

```python
settings['kotti.asset_overrides'] += ' kotti_navigation:kotti-overrides/'
```

The above code is all legit as far as I can tell and it works fine in pyramid
1.5.2, but it fails with pyramid master with the following:

```pytb
File "/Users/marca/python/virtualenvs/kotti_inventorysvc/lib/python2.7/site-packages/pkg_resources.py", line 959, in resource_filename
self, resource_name
File "/Users/marca/dev/git-repos/pyramid/pyramid/config/assets.py", line 31, in get_resource_filename
filename = overrides.get_filename(resource_name)
File "/Users/marca/dev/git-repos/pyramid/pyramid/config/assets.py", line 125, in get_filename
result = source.get_filename(path)
File "/Users/marca/dev/git-repos/pyramid/pyramid/config/assets.py", line 224, in get_filename
if pkg_resources.resource_exists(self.package, path):
File "/Users/marca/python/virtualenvs/kotti_inventorysvc/lib/python2.7/site-packages/pkg_resources.py", line 948, in resource_exists
return get_provider(package_or_requirement).has_resource(resource_name)
File "/Users/marca/python/virtualenvs/kotti_inventorysvc/lib/python2.7/site-packages/pkg_resources.py", line 225, in get_provider
__import__(moduleOrReq)
TypeError: __import__() argument 1 must be string, not module
```

This was a little tricky to resolve because the `override_asset` function wants
to pass a module object to `PackageAssetSource.__init__`, but there are a
number of tests in `pyramid/tests/test_config/test_assets.py` that assume that
it takes a string. So I ended up making it legal to pass either one, so that I
don't have to change as much calling code.

See https://github.com/Kotti/kotti_navigation/issues/13
1 files modified
26 ■■■■■ changed files
pyramid/config/assets.py 26 ●●●●● diff | view | raw | blame | history