Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit dba77ef

Browse files
committed
Rely on trees for 'path' operation. Passes all but one operation.
1 parent 295c699 commit dba77ef

File tree

3 files changed

+68
-62
lines changed

3 files changed

+68
-62
lines changed

importlib_resources/_py2.py

+7-31
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
import os
22
import errno
3-
import tempfile
43

54
from . import trees
65
from ._compat import FileNotFoundError
7-
from contextlib import contextmanager
86
from importlib import import_module
97
from io import BytesIO, TextIOWrapper, open as io_open
10-
from pathlib2 import Path
118

129

1310
def _resolve(name):
@@ -96,7 +93,12 @@ def read_text(package, resource, encoding='utf-8', errors='strict'):
9693
return fp.read()
9794

9895

99-
@contextmanager
96+
def get(package, resource):
97+
resource = _normalize_path(resource)
98+
package = _get_package(package)
99+
return trees.from_package(package) / resource
100+
101+
100102
def path(package, resource):
101103
"""A context manager providing a file path object to the resource.
102104
@@ -106,33 +108,7 @@ def path(package, resource):
106108
raised if the file was deleted prior to the context manager
107109
exiting).
108110
"""
109-
resource = _normalize_path(resource)
110-
package = _get_package(package)
111-
package_directory = Path(package.__file__).parent
112-
file_path = package_directory / resource
113-
# If the file actually exists on the file system, just return it.
114-
if file_path.exists():
115-
yield file_path
116-
return
117-
118-
# Otherwise, it's probably in a zip file, so we need to create a temporary
119-
# file and copy the contents into that file, hence the contextmanager to
120-
# clean up the temp file resource.
121-
with open_binary(package, resource) as fp:
122-
data = fp.read()
123-
# Not using tempfile.NamedTemporaryFile as it leads to deeper 'try'
124-
# blocks due to the need to close the temporary file to work on Windows
125-
# properly.
126-
fd, raw_path = tempfile.mkstemp()
127-
try:
128-
os.write(fd, data)
129-
os.close(fd)
130-
yield Path(raw_path)
131-
finally:
132-
try:
133-
os.remove(raw_path)
134-
except FileNotFoundError:
135-
pass
111+
return trees.as_file(get(package, resource))
136112

137113

138114
def is_resource(package, name):

importlib_resources/_py3.py

+14-30
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import os
22
import sys
3-
import tempfile
43

54
from . import abc as resources_abc
65
from . import trees
@@ -130,6 +129,15 @@ def read_text(package: Package,
130129
return fp.read()
131130

132131

132+
def get(package: Package, resource: Resource) -> trees.Traversable:
133+
"""
134+
Get a Traversable resource from a package
135+
"""
136+
resource = _normalize_path(resource)
137+
package = _get_package(package)
138+
return trees.from_package(package) / resource
139+
140+
133141
@contextmanager
134142
def path(package: Package, resource: Resource) -> Iterator[Path]:
135143
"""A context manager providing a file path object to the resource.
@@ -140,38 +148,14 @@ def path(package: Package, resource: Resource) -> Iterator[Path]:
140148
raised if the file was deleted prior to the context manager
141149
exiting).
142150
"""
143-
resource = _normalize_path(resource)
144-
package = _get_package(package)
145-
reader = _get_resource_reader(package)
151+
norm_resource = _normalize_path(resource)
152+
reader = _get_resource_reader(_get_package(package))
146153
if reader is not None:
147154
with suppress(FileNotFoundError):
148-
yield Path(reader.resource_path(resource))
155+
yield Path(reader.resource_path(norm_resource))
149156
return
150-
# Fall-through for both the lack of resource_path() *and* if
151-
# resource_path() raises FileNotFoundError.
152-
package_directory = Path(package.__spec__.origin).parent
153-
file_path = package_directory / resource
154-
# If the file actually exists on the file system, just return it.
155-
if file_path.exists():
156-
yield file_path
157-
return
158-
159-
# Otherwise, it's probably in a zip file, so we need to create a temporary
160-
# file and copy the contents into that file, hence the contextmanager to
161-
# clean up the temp file resource.
162-
with open_binary(package, resource) as fp:
163-
data = fp.read()
164-
# Not using tempfile.NamedTemporaryFile as it leads to deeper 'try'
165-
# blocks due to the need to close the temporary file to work on
166-
# Windows properly.
167-
fd, raw_path = tempfile.mkstemp()
168-
try:
169-
os.write(fd, data)
170-
os.close(fd)
171-
yield Path(raw_path)
172-
finally:
173-
with suppress(FileNotFoundError):
174-
os.remove(raw_path)
157+
with trees.as_file(get(package, resource)) as res:
158+
yield res
175159

176160

177161
def is_resource(package: Package, name: str) -> bool:

importlib_resources/trees.py

+47-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
from __future__ import absolute_import
22

3+
import os
34
import abc
45
import zipp
6+
import tempfile
7+
import contextlib
58

6-
from ._compat import ABC, Path, package_spec
9+
from ._compat import ABC, Path, package_spec, FileNotFoundError
710

811

912
class Traversable(ABC):
@@ -49,3 +52,46 @@ def from_package(package):
4952
except Exception:
5053
pass
5154
return package_directory
55+
56+
57+
@contextlib.contextmanager
58+
def _zip_path_as_file(path):
59+
# Not using tempfile.NamedTemporaryFile as it leads to deeper 'try'
60+
# blocks due to the need to close the temporary file to work on Windows
61+
# properly.
62+
fd, raw_path = tempfile.mkstemp()
63+
try:
64+
os.write(fd, path.read_bytes())
65+
os.close(fd)
66+
yield Path(raw_path)
67+
finally:
68+
try:
69+
os.remove(raw_path)
70+
except FileNotFoundError:
71+
pass
72+
73+
74+
@contextlib.contextmanager
75+
def _local_path_as_file(path):
76+
"""
77+
Degenerate wrapper for pathlib.Path objects
78+
"""
79+
yield path
80+
81+
82+
@contextlib.contextmanager
83+
def as_file(path):
84+
"""
85+
Given a path-like object, return that object as a
86+
path on the local file system in a context manager.
87+
"""
88+
if not path.is_file():
89+
raise FileNotFoundError(path)
90+
# todo: consider using functools.singledispatch
91+
wrapper = (
92+
_zip_path_as_file
93+
if isinstance(path, zipp.Path)
94+
else _local_path_as_file
95+
)
96+
with wrapper(path) as local:
97+
yield local

0 commit comments

Comments
 (0)