8000 Merge branch 'renames' into 'master' · jaraco/cpython@8d6e24d · GitHub
[go: up one dir, main page]

Skip to content

Commit 8d6e24d

Browse files
committed
Merge branch 'renames' into 'master'
"filename" -> "resource" Closes python#33 See merge request python-devs/importlib_resources!39
2 parents 5d53bf9 + 2249ef8 commit 8d6e24d

File tree

5 files changed

+105
-206
lines changed

5 files changed

+105
-206
lines changed

README.rst

Lines changed: 12 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -1,118 +1,13 @@
1-
``importlib.resources``
2-
=======================
3-
This repository is to house the design and implementation of a planned
4-
``importlib.resources`` module for Python's stdlib -- aiming for
5-
Python 3.7 -- along with a backport to target Python 3.4 - 3.6.
6-
7-
The key goal of this module is to replace
8-
`pkg_resources <https://setuptools.readthedocs.io/en/latest/pkg_resources.html>`_
9-
with a solution in Python's stdlib that relies on well-defined APIs.
10-
This should not only make reading resources included in packages easier,
11-
but have the semantics be stable and consistent.
12-
13-
Goals
14-
-----
15-
< 8000 /td>
16-
- Provide a reasonable replacement for ``pkg_resources.resource_stream()``
17-
- Provide a reasonable replacement for ``pkg_resources.resource_string()``
18-
- Provide a reasonable replacement for ``pkg_resources.resource_filename()``
19-
- Define an ABC for loaders to implement for reading resources
20-
- Implement this in the stdlib for Python 3.7
21-
- Implement a package for PyPI which will work on Python >=3.4
22-
23-
Non-goals
24-
---------
25-
- Replace all of ``pkg_resources``
26-
- For what is replaced in ``pkg_resources``, provide an **exact**
27-
replacement
28-
29-
Design
30-
======
31-
Low-level
32-
---------
33-
For `importlib.abc <https://docs.python.org/3/library/importlib.html#module-importlib.abc>`_::
34-
35-
import abc
36-
from typing.io import BinaryIO
37-
38-
39-
class ResourceReader(abc.ABC):
40-
41-
def open_resource(self, path: str) -> BinaryIO:
42-
"""Return a file-like object opened for binary reading.
43-
44-
The 'path' argument is expected to represent only a file name.
45-
If the resource cannot be found, FileNotFoundError is raised.
46-
"""
47-
raise FileNotFoundError
48-
49-
def resource_path(self, path: str) -> str:
50-
"""Return the file system path to the specified resource.
51-
52-
53-
The 'path' argument is expected to represent only a file name.
54-
If the resource does not exist on the file system, raise
55-
FileNotFoundError.
56-
"""
57-
raise FileNotFoundError
58-
59-
High-level
60-
----------
61-
For ``importlib.resources``::
62-
63-
import pathlib
64-
import types
65-
from typing import ContextManager, Union
66-
from typing.io import BinaryIO
1+
=========================
2+
``importlib.resources``
3+
=========================
674

68-
69-
Package = Union[str, types.ModuleType]
70-
FileName = Union[str, os.PathLike]
71-
72-
73-
def open(package: Package, file_name: FileName) -> BinaryIO:
74-
"""Return a file-like object opened for binary-reading of the resource."""
75-
...
76-
77-
78-
def read(package: Package, file_name: FileName, encoding: str = "utf-8",
79-
errors: str = "strict") -> str:
80-
"""Return the decoded string of the resource.
81-
82-
The decoding-related arguments have the same semantics as those of
83-
bytes.decode().
84-
"""
85-
...
86-
87-
88-
@contextlib.contextmanager
89-
def path(package: Package, file_name: FileName) -> ContextManager[pathlib.Path]:
90-
"""A context manager providing a file path object to the resource.
91-
92-
If the resource does not already exist on its own on the file system,
93-
a temporary file will be created. If the file was created, the file
94-
will be deleted upon exiting the context manager (no exception is
95-
raised if the file was deleted prior to the context manager
96-
exiting).
97-
"""
98-
...
99-
100-
If *package* is an actual package, it is used directly. Otherwise the
101-
argument is used in calling ``importlib.import_module()``. The found
102-
package is expected to be an actual package, otherwise ``TypeError`` is
103-
raised.
104-
105-
For the *file_name* argument, it is expected to be only a file name
106-
with no other path parts. If any parts beyond a file name are found, a
107-
``ValueError`` will be raised. The expectation is that all data files
108-
will exist within a directory that can be imported by Python as a
109-
package.
110-
111-
All functions raise ``FileNotFoundError`` if the resource does not exist
112-
or cannot be found.
113-
114-
115-
Issues
116-
======
117-
Please see the
118-
`issue tracker <https://github.com/brettcannon/importlib_resources/issues>`_.
5+
This repository is to house the design and implementation of a planned
6+
``importlib.resources`` module for Python's stdlib -- aiming for Python 3.7 --
7+
along with a backport to target Python 2.7, and 3.4 - 3.6.
8+
9+
The key goal of this module is to replace parts of `pkg_resources
10+
<https://setuptools.readthedocs.io/en/latest/pkg_resources.html>`_ with a
11+
solution in Python's stdlib that relies on well-defined APIs. This should not
12+
only make reading resources included in packages easier, but have the
13+
semantics be stable and consistent.

importlib_reso F438 urces/_py2.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,14 @@ def _normalize_path(path):
3434
return file_name
3535

3636

37-
def open(package, file_name, encoding=None, errors=None):
37+
def open(package, resource, encoding=None, errors=None):
3838
"""Return a file-like object opened for reading of the resource."""
39-
file_name = _normalize_path(file_name)
39+
resource = _normalize_path(resource)
4040
package = _get_package(package)
4141
# Using pathlib doesn't work well here due to the lack of 'strict' argument
4242
# for pathlib.Path.resolve() prior to Python 3.6.
4343
package_path = os.path.dirname(package.__file__)
44-
relative_path = os.path.join(package_path, file_name)
44+
relative_path = os.path.join(package_path, resource)
4545
full_path = os.path.abspath(relative_path)
4646
if encoding is None:
4747
args = dict(mode='rb')
@@ -63,30 +63,30 @@ def open(package, file_name, encoding=None, errors=None):
6363
except (IOError, AttributeError):
6464
package_name = package.__name__
6565
message = '{!r} resource not found in {!r}'.format(
66-
file_name, package_name)
66+
resource, package_name)
6767
raise FileNotFoundError(message)
6868
else:
6969
return _wrap_file(BytesIO(data), encoding, errors)
7070

7171

72-
def read(package, file_name, encoding='utf-8', errors='strict'):
72+
def read(package, resource, encoding='utf-8', errors='strict'):
7373
"""Return the decoded string of the resource.
7474
7575
The decoding-related arguments have the same semantics as those of
7676
bytes.decode().
7777
"""
78-
file_name = _normalize_path(file_name)
78+
resource = _normalize_path(resource)
7979
package = _get_package(package)
8080
# Note this is **not** builtins.open()!
81-
with open(package, file_name) as binary_file:
81+
with open(package, resource) as binary_file:
8282
contents = binary_file.read()
8383
if encoding is None:
8484
return contents
8585
return contents.decode(encoding=encoding, errors=errors)
8686

8787

8888
@contextmanager
89-
def path(package, file_name):
89+
def path(package, resource):
9090
"""A context manager providing a file path object to the resource.
9191
9292
If the resource does not already exist on its own on the file system,
@@ -95,10 +95,10 @@ def path(package, file_name):
9595
raised if the file was deleted prior to the context manager
9696
exiting).
9797
"""
98-
file_name = _normalize_path(file_name)
98+
resource = _normalize_path(resource)
9999
package = _get_package(package)
100100
package_directory = Path(package.__file__).parent
101-
file_path = package_directory / file_name
101+
file_path = package_directory / resource
102102
# If the file actually exists on the file system, just return it.
103103
# Otherwise, it's probably in a zip file, so we need to create a temporary
104104
# file and copy the contents into that file, hence the contextmanager to
@@ -107,7 +107,7 @@ def path(package, file_name):
107107
yield file_path
108108
else:
109109
# Note this is **not** builtins.open()!
110-
with open(package, file_name) as fileobj:
110+
with open(package, resource) as fileobj:
111111
data = fileobj.read()
112112
# Not using tempfile.NamedTemporaryFile as it leads to deeper 'try'
113113
# blocks due to the need to close the temporary file to work on Windows
@@ -124,13 +124,13 @@ def path(package, file_name):
124124
pass
125125

126126

127-
def is_resource(package, file_name):
128-
"""True if file_name is a resource inside package.
127+
def is_resource(package, name):
128+
"""True if name is a resource inside package.
129129
130130
Directories are *not* resources.
131131
"""
132132
package = _get_package(package)
133-
_normalize_path(file_name)
133+
_normalize_path(name)
134134
try:
135135
package_contents = set(contents(package))
136136
except OSError as error:
@@ -142,12 +142,12 @@ def is_resource(package, file_name):
142142
# worth it.
143143
raise # pragma: ge3
144144
return False
145-
if file_name not in package_contents:
145+
if name not in package_contents:
146146
return False
147147
# Just because the given file_name lives as an entry in the package's
148148
# contents doesn't necessarily mean it's a resource. Directories are not
149149
# resources, so let's try to find out if it's a directory or not.
150-
path = Path(package.__file__).parent / file_name
150+
path = Path(package.__file__).parent / name
151151
if path.is_file():
152152
return True
153153
if path.is_dir():
@@ -161,7 +161,7 @@ def is_resource(package, file_name):
161161
with ZipFile(archive_path) as zf:
162162
toc = zf.namelist()
163163
relpath = package_directory.relative_to(archive_path)
164-
candidate_path = relpath / file_name
164+
candidate_path = relpath / name
165165
for entry in toc: # pragma: nobranch
166166
try:
167167
relative_to_candidate = Path(entry).relative_to(candidate_path)

0 commit comments

Comments
 (0)
0