Name | acres JSON |
Version |
0.2.0
JSON |
| download |
home_page | None |
Summary | Access resources on your terms |
upload_time | 2024-12-09 21:26:50 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.8 |
license | Apache-2.0 |
keywords |
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# Acres: Access resources on your terms
[](https://pypi.python.org/project/acres/)
[](https://codecov.io/github/nipreps/acres)
This module provides simple, consistent access to package resources.
```python
from acres import Loader
loader = Loader(somepkg)
res_text = loader.readable('data/some_resource.txt').read_text()
res_bytes = loader.readable('data/another_resource.bin').read_bytes()
with loader.as_path('data') as data_dir:
# data_dir is a pathlib.Path until the "with" scope closes
resource_path = loader.cached('data/another_resource.bin')
# The path pointed to by resource_path will exist until interpreter exit
```
## Module loader
The primary use case for `acres.Loader` is to allow a directory module to provide access
to its resources.
Suppose you have a module structure:
```
src/
mypkg/
data/
resourceDir/
...
__init__.py
resource.ext
__init__.py
...
```
In `src/mypkg/data/__init__.py`, add:
```python
'''Data package
.. autofunction:: load_resource
.. automethod:: load_resource.readable
.. automethod:: load_resource.as_path
.. automethod:: load_resource.cached
'''
from acres import Loader
load_resource = Loader(__spec__.name)
```
`mypkg.data.load_resource()` is now a function that will return a `Path` to a
resource that is guaranteed to exist until interpreter exit:
```python
from mypkg.data import load_resource
resource_file: Path = load_resource('resource.ext')
```
For additional control, you can use `load_resource.readable()` to return a `Path`-like
object that implements `.read_text()` and `.read_bytes()`:
```python
resource_contents: bytes = load_resource.readable('resource.ext').read_bytes()
```
Or a context manager with a limited lifetime:
```python
with load_resource.as_path('resourceDir') as resource_dir:
# Work with the contents of `resource_dir` as a `Path`
# Outside the `with` block, `resource_dir` may no longer point to an existing path.
```
Note that `load_resource()` is a shorthand for `load_resource.cached()`,
whose explicitness might be more to your taste.
### The `__spec__.name` anchor
Previous versions recommended using `Loader(__package__)`.
Before Python 3.10, `__package__` might be `None` during a [zipimport][],
and `__package__` has been deprecated in Python 3.13, to be removed in 3.15.
[`__spec__.parent`][ModuleSpec.parent] is an exact equivalent for `__package__`,
but for `__init__.py` files, [`__spec__.name`][ModuleSpec.name] is equivalent.
`__spec__.name` is also guaranteed to be a string and not `None`,
which lets it play nicely with type checkers.
## Interpreter-scoped resources, locally scoped loaders
`Loader.cached` uses a global cache. This ensures that cached files do not get
unloaded if a `Loader()` instance is garbage collected, and it also ensures that
instances created cheaply and garbage collected when out of scope.
## Why acres?
`importlib.resources` provides a simple, composable interface, using the
`files()` and `as_file()` functions:
```python
from importlib.resources import files, as_file
with as_file(files(my_module) / 'data' / 'resource.ext') as resource_path:
# Interact with resource_path as a pathlib.Path
# resource_path *may* no longer exist
```
`files()` returns a [Traversable][] object, which is similar to a [pathlib.Path][],
except that the object may not actually exist, so `os` functions may not work
correctly on it. `as_files()` turns a `Traversable` into a `Path` that exists on
the filesystem for the duration of the `with` block.
To make matters more complicated, if a package is unpacked on the filesystem,
`files()` returns an actual `Path` object. It is therefore easy to miss bugs
where a true `Path` is always needed but a `Traversable` may be returned when
the package is zipped.
Finally, the scoping of `as_files()` is frequently inconvenient. If you pass a
`Path` to an object inside an `as_files()` context, but the resource access is
deferred, the `Path` may point to a nonexistent file or directory. Again,
this bug will only exhibit when the package is zipped.
`acres.Loader` aims to clearly delineate the scopes and capabilities of
the accessed resources, including providing an interpreter-lifetime scope.
[Traversable]: https://docs.python.org/3/library/importlib.resources.abc.html#importlib.resources.abc.Traversable
[pathlib.Path]: https://docs.python.org/3/library/pathlib.html#pathlib.Path
[ModuleSpec.name]: https://docs.python.org/3/library/importlib.html#importlib.machinery.ModuleSpec.name
[ModuleSpec.parent]: https://docs.python.org/3/library/importlib.html#importlib.machinery.ModuleSpec.parent
Raw data
{
"_id": null,
"home_page": null,
"name": "acres",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": null,
"author": null,
"author_email": "The NiPreps Developers <nipreps@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/b8/f4/eb4f59db413f28b11cfefa3cc4d0a47b2703dd31d95b4088d7e532639326/acres-0.2.0.tar.gz",
"platform": null,
"description": "# Acres: Access resources on your terms\n\n[](https://pypi.python.org/project/acres/)\n[](https://codecov.io/github/nipreps/acres)\n\nThis module provides simple, consistent access to package resources.\n\n```python\nfrom acres import Loader\n\nloader = Loader(somepkg)\n\nres_text = loader.readable('data/some_resource.txt').read_text()\nres_bytes = loader.readable('data/another_resource.bin').read_bytes()\n\nwith loader.as_path('data') as data_dir:\n # data_dir is a pathlib.Path until the \"with\" scope closes\n\nresource_path = loader.cached('data/another_resource.bin')\n# The path pointed to by resource_path will exist until interpreter exit\n```\n\n## Module loader\n\nThe primary use case for `acres.Loader` is to allow a directory module to provide access\nto its resources.\n\nSuppose you have a module structure:\n\n```\nsrc/\n mypkg/\n data/\n resourceDir/\n ...\n __init__.py\n resource.ext\n __init__.py\n ...\n```\n\nIn `src/mypkg/data/__init__.py`, add:\n\n```python\n'''Data package\n\n.. autofunction:: load_resource\n\n.. automethod:: load_resource.readable\n\n.. automethod:: load_resource.as_path\n\n.. automethod:: load_resource.cached\n'''\n\nfrom acres import Loader\n\nload_resource = Loader(__spec__.name)\n```\n\n`mypkg.data.load_resource()` is now a function that will return a `Path` to a\nresource that is guaranteed to exist until interpreter exit:\n\n```python\nfrom mypkg.data import load_resource\n\nresource_file: Path = load_resource('resource.ext')\n```\n\nFor additional control, you can use `load_resource.readable()` to return a `Path`-like\nobject that implements `.read_text()` and `.read_bytes()`:\n\n```python\nresource_contents: bytes = load_resource.readable('resource.ext').read_bytes()\n```\n\nOr a context manager with a limited lifetime:\n\n```python\nwith load_resource.as_path('resourceDir') as resource_dir:\n # Work with the contents of `resource_dir` as a `Path`\n\n# Outside the `with` block, `resource_dir` may no longer point to an existing path.\n```\n\nNote that `load_resource()` is a shorthand for `load_resource.cached()`,\nwhose explicitness might be more to your taste.\n\n### The `__spec__.name` anchor\n\nPrevious versions recommended using `Loader(__package__)`.\nBefore Python 3.10, `__package__` might be `None` during a [zipimport][],\nand `__package__` has been deprecated in Python 3.13, to be removed in 3.15.\n\n[`__spec__.parent`][ModuleSpec.parent] is an exact equivalent for `__package__`,\nbut for `__init__.py` files, [`__spec__.name`][ModuleSpec.name] is equivalent.\n`__spec__.name` is also guaranteed to be a string and not `None`,\nwhich lets it play nicely with type checkers.\n\n## Interpreter-scoped resources, locally scoped loaders\n\n`Loader.cached` uses a global cache. This ensures that cached files do not get\nunloaded if a `Loader()` instance is garbage collected, and it also ensures that\ninstances created cheaply and garbage collected when out of scope.\n\n## Why acres?\n\n`importlib.resources` provides a simple, composable interface, using the\n`files()` and `as_file()` functions:\n\n```python\nfrom importlib.resources import files, as_file\n\nwith as_file(files(my_module) / 'data' / 'resource.ext') as resource_path:\n # Interact with resource_path as a pathlib.Path\n\n# resource_path *may* no longer exist\n```\n\n`files()` returns a [Traversable][] object, which is similar to a [pathlib.Path][],\nexcept that the object may not actually exist, so `os` functions may not work\ncorrectly on it. `as_files()` turns a `Traversable` into a `Path` that exists on\nthe filesystem for the duration of the `with` block.\n\nTo make matters more complicated, if a package is unpacked on the filesystem,\n`files()` returns an actual `Path` object. It is therefore easy to miss bugs\nwhere a true `Path` is always needed but a `Traversable` may be returned when\nthe package is zipped.\n\nFinally, the scoping of `as_files()` is frequently inconvenient. If you pass a\n`Path` to an object inside an `as_files()` context, but the resource access is\ndeferred, the `Path` may point to a nonexistent file or directory. Again,\nthis bug will only exhibit when the package is zipped.\n\n`acres.Loader` aims to clearly delineate the scopes and capabilities of\nthe accessed resources, including providing an interpreter-lifetime scope.\n\n[Traversable]: https://docs.python.org/3/library/importlib.resources.abc.html#importlib.resources.abc.Traversable\n[pathlib.Path]: https://docs.python.org/3/library/pathlib.html#pathlib.Path\n[ModuleSpec.name]: https://docs.python.org/3/library/importlib.html#importlib.machinery.ModuleSpec.name\n[ModuleSpec.parent]: https://docs.python.org/3/library/importlib.html#importlib.machinery.ModuleSpec.parent\n",
"bugtrack_url": null,
"license": "Apache-2.0",
"summary": "Access resources on your terms",
"version": "0.2.0",
"project_urls": null,
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "47eb3e0b3e1182d46aaa7518a4afbb9488f9c907dc2c63cb21818625de3431fd",
"md5": "77303bb57c67df15e4a790ef9966d680",
"sha256": "1cadf56a1b7ce0d659c3fcf3e5952ae608e75e72187c61c3f802f9d459a909ba"
},
"downloads": -1,
"filename": "acres-0.2.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "77303bb57c67df15e4a790ef9966d680",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 10344,
"upload_time": "2024-12-09T21:26:48",
"upload_time_iso_8601": "2024-12-09T21:26:48.554583Z",
"url": "https://files.pythonhosted.org/packages/47/eb/3e0b3e1182d46aaa7518a4afbb9488f9c907dc2c63cb21818625de3431fd/acres-0.2.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "b8f4eb4f59db413f28b11cfefa3cc4d0a47b2703dd31d95b4088d7e532639326",
"md5": "f35922152ecae65227c95bea6d55f55e",
"sha256": "21fb0d1d164d91737051cfad172f45a81b3a2a90d13082a34c5297fdbb4f7db8"
},
"downloads": -1,
"filename": "acres-0.2.0.tar.gz",
"has_sig": false,
"md5_digest": "f35922152ecae65227c95bea6d55f55e",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 10571,
"upload_time": "2024-12-09T21:26:50",
"upload_time_iso_8601": "2024-12-09T21:26:50.260182Z",
"url": "https://files.pythonhosted.org/packages/b8/f4/eb4f59db413f28b11cfefa3cc4d0a47b2703dd31d95b4088d7e532639326/acres-0.2.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-12-09 21:26:50",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"lcname": "acres"
}