pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/python/cpython/commit/e712a5b277866a71c195f38c1b5d87d9126dba3e

bpo-46118: Move importlib.resources to its own package. (#30176) · python/cpython@e712a5b · GitHub
Skip to content

Commit e712a5b

Browse files
authored
bpo-46118: Move importlib.resources to its own package. (#30176)
* bpo-46118: Move importlib.resources to its own package. * Expand compatibility shims with documentation and explicit imports.
1 parent 2cf7d02 commit e712a5b

13 files changed

Lines changed: 409 additions & 368 deletions

File tree

Lib/importlib/abc.py

Lines changed: 13 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,19 @@
1414
from ._abc import Loader
1515
import abc
1616
import warnings
17-
from typing import BinaryIO, Iterable, Text
18-
from typing import Protocol, runtime_checkable
17+
18+
# for compatibility with Python 3.10
19+
from .resources.abc import ResourceReader, Traversable, TraversableResources
20+
21+
22+
__all__ = [
23+
'Loader', 'Finder', 'MetaPathFinder', 'PathEntryFinder',
24+
'ResourceLoader', 'InspectLoader', 'ExecutionLoader',
25+
'FileLoader', 'SourceLoader',
26+
27+
# for compatibility with Python 3.10
28+
'ResourceReader', 'Traversable', 'TraversableResources',
29+
]
1930

2031

2132
def _register(abstract_cls, *classes):
@@ -307,136 +318,3 @@ def set_data(self, path, data):
307318
"""
308319

309320
_register(SourceLoader, machinery.SourceFileLoader)
310-
311-
312-
class ResourceReader(metaclass=abc.ABCMeta):
313-
"""Abstract base class for loaders to provide resource reading support."""
314-
315-
@abc.abstractmethod
316-
def open_resource(self, resource: Text) -> BinaryIO:
317-
"""Return an opened, file-like object for binary reading.
318-
319-
The 'resource' argument is expected to represent only a file name.
320-
If the resource cannot be found, FileNotFoundError is raised.
321-
"""
322-
# This deliberately raises FileNotFoundError instead of
323-
# NotImplementedError so that if this method is accidentally called,
324-
# it'll still do the right thing.
325-
raise FileNotFoundError
326-
327-
@abc.abstractmethod
328-
def resource_path(self, resource: Text) -> Text:
329-
"""Return the file system path to the specified resource.
330-
331-
The 'resource' argument is expected to represent only a file name.
332-
If the resource does not exist on the file system, raise
333-
FileNotFoundError.
334-
"""
335-
# This deliberately raises FileNotFoundError instead of
336-
# NotImplementedError so that if this method is accidentally called,
337-
# it'll still do the right thing.
338-
raise FileNotFoundError
339-
340-
@abc.abstractmethod
341-
def is_resource(self, path: Text) -> bool:
342-
"""Return True if the named 'path' is a resource.
343-
344-
Files are resources, directories are not.
345-
"""
346-
raise FileNotFoundError
347-
348-
@abc.abstractmethod
349-
def contents(self) -> Iterable[str]:
350-
"""Return an iterable of entries in `package`."""
351-
raise FileNotFoundError
352-
353-
354-
@runtime_checkable
355-
class Traversable(Protocol):
356-
"""
357-
An object with a subset of pathlib.Path methods suitable for
358-
traversing directories and opening files.
359-
"""
360-
361-
@abc.abstractmethod
362-
def iterdir(self):
363-
"""
364-
Yield Traversable objects in self
365-
"""
366-
367-
def read_bytes(self):
368-
"""
369-
Read contents of self as bytes
370-
"""
371-
with self.open('rb') as strm:
372-
return strm.read()
373-
374-
def read_text(self, encoding=None):
375-
"""
376-
Read contents of self as text
377-
"""
378-
with self.open(encoding=encoding) as strm:
379-
return strm.read()
380-
381-
@abc.abstractmethod
382-
def is_dir(self) -> bool:
383-
"""
384-
Return True if self is a directory
385-
"""
386-
387-
@abc.abstractmethod
388-
def is_file(self) -> bool:
389-
"""
390-
Return True if self is a file
391-
"""
392-
393-
@abc.abstractmethod
394-
def joinpath(self, child):
395-
"""
396-
Return Traversable child in self
397-
"""
398-
399-
def __truediv__(self, child):
400-
"""
401-
Return Traversable child in self
402-
"""
403-
return self.joinpath(child)
404-
405-
@abc.abstractmethod
406-
def open(self, mode='r', *args, **kwargs):
407-
"""
408-
mode may be 'r' or 'rb' to open as text or binary. Return a handle
409-
suitable for reading (same as pathlib.Path.open).
410-
411-
When opening as text, accepts encoding parameters such as those
412-
accepted by io.TextIOWrapper.
413-
"""
414-
415-
@abc.abstractproperty
416-
def name(self) -> str:
417-
"""
418-
The base name of this object without any parent references.
419-
"""
420-
421-
422-
class TraversableResources(ResourceReader):
423-
"""
424-
The required interface for providing traversable
425-
resources.
426-
"""
427-
428-
@abc.abstractmethod
429-
def files(self):
430-
"""Return a Traversable object for the loaded package."""
431-
432-
def open_resource(self, resource):
433-
return self.files().joinpath(resource).open('rb')
434-
435-
def resource_path(self, resource):
436-
raise FileNotFoundError(resource)
437-
438-
def is_resource(self, path):
439-
return self.files().joinpath(path).is_file()
440-
441-
def contents(self):
442-
return (item.name for item in self.files().iterdir())

Lib/importlib/readers.py

Lines changed: 9 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -1,122 +1,12 @@
1-
import collections
2-
import operator
3-
import pathlib
4-
import zipfile
1+
"""
2+
Compatibility shim for .resources.readers as found on Python 3.10.
53
6-
from . import abc
4+
Consumers that can rely on Python 3.11 should use the other
5+
module directly.
6+
"""
77

8-
from ._itertools import unique_everseen
8+
from .resources.readers import (
9+
FileReader, ZipReader, MultiplexedPath, NamespaceReader,
10+
)
911

10-
11-
def remove_duplicates(items):
12-
return iter(collections.OrderedDict.fromkeys(items))
13-
14-
15-
class FileReader(abc.TraversableResources):
16-
def __init__(self, loader):
17-
self.path = pathlib.Path(loader.path).parent
18-
19-
def resource_path(self, resource):
20-
"""
21-
Return the file system path to prevent
22-
`resources.path()` from creating a temporary
23-
copy.
24-
"""
25-
return str(self.path.joinpath(resource))
26-
27-
def files(self):
28-
return self.path
29-
30-
31-
class ZipReader(abc.TraversableResources):
32-
def __init__(self, loader, module):
33-
_, _, name = module.rpartition('.')
34-
self.prefix = loader.prefix.replace('\\', '/') + name + '/'
35-
self.archive = loader.archive
36-
37-
def open_resource(self, resource):
38-
try:
39-
return super().open_resource(resource)
40-
except KeyError as exc:
41-
raise FileNotFoundError(exc.args[0])
42-
43-
def is_resource(self, path):
44-
# workaround for `zipfile.Path.is_file` returning true
45-
# for non-existent paths.
46-
target = self.files().joinpath(path)
47-
return target.is_file() and target.exists()
48-
49-
def files(self):
50-
return zipfile.Path(self.archive, self.prefix)
51-
52-
53-
class MultiplexedPath(abc.Traversable):
54-
"""
55-
Given a series of Traversable objects, implement a merged
56-
version of the interface across all objects. Useful for
57-
namespace packages which may be multihomed at a single
58-
name.
59-
"""
60-
61-
def __init__(self, *paths):
62-
self._paths = list(map(pathlib.Path, remove_duplicates(paths)))
63-
if not self._paths:
64-
message = 'MultiplexedPath must contain at least one path'
65-
raise FileNotFoundError(message)
66-
if not all(path.is_dir() for path in self._paths):
67-
raise NotADirectoryError('MultiplexedPath only supports directories')
68-
69-
def iterdir(self):
70-
files = (file for path in self._paths for file in path.iterdir())
71-
return unique_everseen(files, key=operator.attrgetter('name'))
72-
73-
def read_bytes(self):
74-
raise FileNotFoundError(f'{self} is not a file')
75-
76-
def read_text(self, *args, **kwargs):
77-
raise FileNotFoundError(f'{self} is not a file')
78-
79-
def is_dir(self):
80-
return True
81-
82-
def is_file(self):
83-
return False
84-
85-
def joinpath(self, child):
86-
# first try to find child in current paths
87-
for file in self.iterdir():
88-
if file.name == child:
89-
return file
90-
# if it does not exist, construct it with the first path
91-
return self._paths[0] / child
92-
93-
__truediv__ = joinpath
94-
95-
def open(self, *args, **kwargs):
96-
raise FileNotFoundError(f'{self} is not a file')
97-
98-
@property
99-
def name(self):
100-
return self._paths[0].name
101-
102-
def __repr__(self):
103-
paths = ', '.join(f"'{path}'" for path in self._paths)
104-
return f'MultiplexedPath({paths})'
105-
106-
107-
class NamespaceReader(abc.TraversableResources):
108-
def __init__(self, namespace_path):
109-
if 'NamespacePath' not in str(namespace_path):
110-
raise ValueError('Invalid path')
111-
self.path = MultiplexedPath(*list(namespace_path))
112-
113-
def resource_path(self, resource):
114-
"""
115-
Return the file system path to prevent
116-
`resources.path()` from creating a temporary
117-
copy.
118-
"""
119-
return str(self.path.joinpath(resource))
120-
121-
def files(self):
122-
return self.path
12+
__all__ = ['FileReader', 'ZipReader', 'MultiplexedPath', 'NamespaceReader']
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
Resource,
1818
)
1919

20-
from importlib.abc import ResourceReader
20+
from .abc import ResourceReader
2121

2222

2323
__all__ = [

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy