Skip to content

Commit 6b83a72

Browse files
committed
Only accept a file name
Closes python#8
1 parent 1143d03 commit 6b83a72

File tree

1 file changed

+16
-19
lines changed

1 file changed

+16
-19
lines changed

README.md

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ from typing.io import BinaryIO
6464

6565

6666
Package = Union[str, types.ModuleType]
67-
Path = Union[str, os.PathLike]
67+
FileName = Union[str, os.PathLike]
6868

6969

7070
def _get_package(package):
@@ -82,35 +82,34 @@ def _get_package(package):
8282

8383

8484
def _normalize_path(path):
85-
if os.path.isabs(path):
86-
raise ValueError(f"{path!r} is absolute")
87-
normalized_path = os.path.normpath(path)
88-
if normalized_path.startswith(".."):
89-
raise ValueError(f"{path!r} attempts to traverse past package")
85+
directory, file_name = os.path.split(path)
86+
if directory:
87+
raise ValueError(f"{path!r} is not just a file name")
9088
else:
91-
return normalized_path
89+
return file_name
9290

9391

94-
def open(module_name: Package, path: Path) -> BinaryIO:
92+
def open(module_name: Package, file_name: FileName) -> BinaryIO:
9593
"""Return a file-like object opened for binary-reading of the resource."""
96-
normalized_path = _normalize_path(path)
94+
normalized_path = _normalize_path(file_name)
9795
module = _get_package(module_name)
9896
return module.__spec__.loader.open_resource(normalized_path)
9997

10098

101-
def read(module_name: Package, path: Path, encoding: str = "utf-8",
99+
def read(module_name: Package, file_name: FileName, encoding: str = "utf-8",
102100
errors: str = "strict") -> str:
103101
"""Return the decoded string of the resource.
104102
105103
The decoding-related arguments have the same semantics as those of
106104
bytes.decode().
107105
"""
108-
with open(module_name, path) as file:
106+
# Note this is **not** builtins.open()!
107+
with open(module_name, file_name) as file:
109108
return file.read().decode(encoding=encoding, errors=errors)
110109

111110

112111
@contextlib.contextmanager
113-
def path(module_name: Package, path: Path) -> Iterator[pathlib.Path]:
112+
def path(module_name: Package, file_name: FileName) -> Iterator[pathlib.Path]:
114113
"""A context manager providing a file path object to the resource.
115114
116115
If the resource does not already exist on its own on the file system,
@@ -119,7 +118,7 @@ def path(module_name: Package, path: Path) -> Iterator[pathlib.Path]:
119118
raised if the file was deleted prior to the context manager
120119
exiting).
121120
"""
122-
normalized_path = _normalize_path(path)
121+
normalized_path = _normalize_path(file_name)
123122
module = _get_package(module_name)
124123
try:
125124
yield pathlib.Path(module.__spec__.resource_path(normalized_path))
@@ -143,12 +142,10 @@ side-effect of the call. The specified module is expected to be a
143142
package, otherwise `TypeError` is raised. The module is expected to
144143
have a loader specified on `__spec__.loader` which
145144

146-
For the *path* argument, it is expected to be a relative path. If
147-
there are implicit references to the parent directory (i.e. `..`), they
148-
will be resolved. If the normalized, relative path attempts to reference
149-
beyond the location of the specified module, a `ValueError` will be
150-
raised. The provided path is expected to be UNIX-style (i.e. to use
151-
`/` as its path separator). Bytes-based paths are not supported.
145+
For the *file_name* argument, it is expected to be only a file name with
146+
no other path parts. If any parts beyond a file name are found, a `ValueError`
147+
will be raised. The expectation is that all data files will exist within
148+
a directory that can be imported by Python as a package.
152149

153150
All functions raise `FileNotFoundError` if the resource does not exist.
154151

0 commit comments

Comments
 (0)