acres


Nameacres JSON
Version 0.2.0 PyPI version JSON
download
home_pageNone
SummaryAccess resources on your terms
upload_time2024-12-09 21:26:50
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseApache-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

[![PyPI release](https://img.shields.io/pypi/v/acres.svg)](https://pypi.python.org/project/acres/)
[![Codecov Coverage report](https://codecov.io/github/nipreps/acres/graph/badge.svg?token=jVfxERJR5k)](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[![PyPI release](https://img.shields.io/pypi/v/acres.svg)](https://pypi.python.org/project/acres/)\n[![Codecov Coverage report](https://codecov.io/github/nipreps/acres/graph/badge.svg?token=jVfxERJR5k)](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"
}
        
Elapsed time: 0.47544s