Skip to content

Commit 99945c6

Browse files
authored
bpo-46109: Separate out files relating to importlib.resources (GH-30160)
* Separate out files relating to importlib.resources * Update Introduction to direct readers to the submodule documentation. * Create separate file for abcs relating to resources. * Move abc docs back to where they were.
1 parent e712a5b commit 99945c6

File tree

5 files changed

+586
-573
lines changed

5 files changed

+586
-573
lines changed
Lines changed: 385 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,385 @@
1+
.. class:: ResourceReader
2+
3+
*Superseded by TraversableResources*
4+
5+
An :term:`abstract base class` to provide the ability to read
6+
*resources*.
7+
8+
From the perspective of this ABC, a *resource* is a binary
9+
artifact that is shipped within a package. Typically this is
10+
something like a data file that lives next to the ``__init__.py``
11+
file of the package. The purpose of this class is to help abstract
12+
out the accessing of such data files so that it does not matter if
13+
the package and its data file(s) are stored in a e.g. zip file
14+
versus on the file system.
15+
16+
For any of methods of this class, a *resource* argument is
17+
expected to be a :term:`path-like object` which represents
18+
conceptually just a file name. This means that no subdirectory
19+
paths should be included in the *resource* argument. This is
20+
because the location of the package the reader is for, acts as the
21+
"directory". Hence the metaphor for directories and file
22+
names is packages and resources, respectively. This is also why
23+
instances of this class are expected to directly correlate to
24+
a specific package (instead of potentially representing multiple
25+
packages or a module).
26+
27+
Loaders that wish to support resource reading are expected to
28+
provide a method called ``get_resource_reader(fullname)`` which
29+
returns an object implementing this ABC's interface. If the module
30+
specified by fullname is not a package, this method should return
31+
:const:`None`. An object compatible with this ABC should only be
32+
returned when the specified module is a package.
33+
34+
.. versionadded:: 3.7
35+
36+
.. abstractmethod:: open_resource(resource)
37+
38+
Returns an opened, :term:`file-like object` for binary reading
39+
of the *resource*.
40+
41+
If the resource cannot be found, :exc:`FileNotFoundError` is
42+
raised.
43+
44+
.. abstractmethod:: resource_path(resource)
45+
46+
Returns the file system path to the *resource*.
47+
48+
If the resource does not concretely exist on the file system,
49+
raise :exc:`FileNotFoundError`.
50+
51+
.. abstractmethod:: is_resource(name)
52+
53+
Returns ``True`` if the named *name* is considered a resource.
54+
:exc:`FileNotFoundError` is raised if *name* does not exist.
55+
56+
.. abstractmethod:: contents()
57+
58+
Returns an :term:`iterable` of strings over the contents of
59+
the package. Do note that it is not required that all names
60+
returned by the iterator be actual resources, e.g. it is
61+
acceptable to return names for which :meth:`is_resource` would
62+
be false.
63+
64+
Allowing non-resource names to be returned is to allow for
65+
situations where how a package and its resources are stored
66+
are known a priori and the non-resource names would be useful.
67+
For instance, returning subdirectory names is allowed so that
68+
when it is known that the package and resources are stored on
69+
the file system then those subdirectory names can be used
70+
directly.
71+
72+
The abstract method returns an iterable of no items.
73+
74+
75+
.. class:: ResourceLoader
76+
77+
An abstract base class for a :term:`loader` which implements the optional
78+
:pep:`302` protocol for loading arbitrary resources from the storage
79+
back-end.
80+
81+
.. deprecated:: 3.7
82+
This ABC is deprecated in favour of supporting resource loading
83+
through :class:`importlib.abc.ResourceReader`.
84+
85+
.. abstractmethod:: get_data(path)
86+
87+
An abstract method to return the bytes for the data located at *path*.
88+
Loaders that have a file-like storage back-end
89+
that allows storing arbitrary data
90+
can implement this abstract method to give direct access
91+
to the data stored. :exc:`OSError` is to be raised if the *path* cannot
92+
be found. The *path* is expected to be constructed using a module's
93+
:attr:`__file__` attribute or an item from a package's :attr:`__path__`.
94+
95+
.. versionchanged:: 3.4
96+
Raises :exc:`OSError` instead of :exc:`NotImplementedError`.
97+
98+
99+
.. class:: InspectLoader
100+
101+
An abstract base class for a :term:`loader` which implements the optional
102+
:pep:`302` protocol for loaders that inspect modules.
103+
104+
.. method:: get_code(fullname)
105+
106+
Return the code object for a module, or ``None`` if the module does not
107+
have a code object (as would be the case, for example, for a built-in
108+
module). Raise an :exc:`ImportError` if loader cannot find the
109+
requested module.
110+
111+
.. note::
112+
While the method has a default implementation, it is suggested that
113+
it be overridden if possible for performance.
114+
115+
.. index::
116+
single: universal newlines; importlib.abc.InspectLoader.get_source method
117+
118+
.. versionchanged:: 3.4
119+
No longer abstract and a concrete implementation is provided.
120+
121+
.. abstractmethod:: get_source(fullname)
122+
123+
An abstract method to return the source of a module. It is returned as
124+
a text string using :term:`universal newlines`, translating all
125+
recognized line separators into ``'\n'`` characters. Returns ``None``
126+
if no source is available (e.g. a built-in module). Raises
127+
:exc:`ImportError` if the loader cannot find the module specified.
128+
129+
.. versionchanged:: 3.4
130+
Raises :exc:`ImportError` instead of :exc:`NotImplementedError`.
131+
132+
.. method:: is_package(fullname)
133+
134+
An optional method to return a true value if the module is a package, a
135+
false value otherwise. :exc:`ImportError` is raised if the
136+
:term:`loader` cannot find the module.
137+
138+
.. versionchanged:: 3.4
139+
Raises :exc:`ImportError` instead of :exc:`NotImplementedError`.
140+
141+
.. staticmethod:: source_to_code(data, path='<string>')
142+
143+
Create a code object from Python source.
144+
145+
The *data* argument can be whatever the :func:`compile` function
146+
supports (i.e. string or bytes). The *path* argument should be
147+
the "path" to where the source code originated from, which can be an
148+
abstract concept (e.g. location in a zip file).
149+
150+
With the subsequent code object one can execute it in a module by
151+
running ``exec(code, module.__dict__)``.
152+
153+
.. versionadded:: 3.4
154+
155+
.. versionchanged:: 3.5
156+
Made the method static.
157+
158+
.. method:: exec_module(module)
159+
160+
Implementation of :meth:`Loader.exec_module`.
161+
162+
.. versionadded:: 3.4
163+
164+
.. method:: load_module(fullname)
165+
166+
Implementation of :meth:`Loader.load_module`.
167+
168+
.. deprecated:: 3.4
169+
use :meth:`exec_module` instead.
170+
171+
172+
.. class:: ExecutionLoader
173+
174+
An abstract base class which inherits from :class:`InspectLoader` that,
175+
when implemented, helps a module to be executed as a script. The ABC
176+
represents an optional :pep:`302` protocol.
177+
178+
.. abstractmethod:: get_filename(fullname)
179+
180+
An abstract method that is to return the value of :attr:`__file__` for
181+
the specified module. If no path is available, :exc:`ImportError` is
182+
raised.
183+
184+
If source code is available, then the method should return the path to
185+
the source file, regardless of whether a bytecode was used to load the
186+
module.
187+
188+
.. versionchanged:: 3.4
189+
Raises :exc:`ImportError` instead of :exc:`NotImplementedError`.
190+
191+
192+
.. class:: FileLoader(fullname, path)
193+
194+
An abstract base class which inherits from :class:`ResourceLoader` and
195+
:class:`ExecutionLoader`, providing concrete implementations of
196+
:meth:`ResourceLoader.get_data` and :meth:`ExecutionLoader.get_filename`.
197+
198+
The *fullname* argument is a fully resolved name of the module the loader is
199+
to handle. The *path* argument is the path to the file for the module.
200+
201+
.. versionadded:: 3.3
202+
203+
.. attribute:: name
204+
205+
The name of the module the loader can handle.
206+
207+
.. attribute:: path
208+
209+
Path to the file of the module.
210+
211+
.. method:: load_module(fullname)
212+
213+
Calls super's ``load_module()``.
214+
215+
.. deprecated:: 3.4
216+
Use :meth:`Loader.exec_module` instead.
217+
218+
.. abstractmethod:: get_filename(fullname)
219+
220+
Returns :attr:`path`.
221+
222+
.. abstractmethod:: get_data(path)
223+
224+
Reads *path* as a binary file and returns the bytes from it.
225+
226+
227+
.. class:: SourceLoader
228+
229+
An abstract base class for implementing source (and optionally bytecode)
230+
file loading. The class inherits from both :class:`ResourceLoader` and
231+
:class:`ExecutionLoader`, requiring the implementation of:
232+
233+
* :meth:`ResourceLoader.get_data`
234+
* :meth:`ExecutionLoader.get_filename`
235+
Should only return the path to the source file; sourceless
236+
loading is not supported.
237+
238+
The abstract methods defined by this class are to add optional bytecode
239+
file support. Not implementing these optional methods (or causing them to
240+
raise :exc:`NotImplementedError`) causes the loader to
241+
only work with source code. Implementing the methods allows the loader to
242+
work with source *and* bytecode files; it does not allow for *sourceless*
243+
loading where only bytecode is provided. Bytecode files are an
244+
optimization to speed up loading by removing the parsing step of Python's
245+
compiler, and so no bytecode-specific API is exposed.
246+
247+
.. method:: path_stats(path)
248+
249+
Optional abstract method which returns a :class:`dict` containing
250+
metadata about the specified path. Supported dictionary keys are:
251+
252+
- ``'mtime'`` (mandatory): an integer or floating-point number
253+
representing the modification time of the source code;
254+
- ``'size'`` (optional): the size in bytes of the source code.
255+
256+
Any other keys in the dictionary are ignored, to allow for future
257+
extensions. If the path cannot be handled, :exc:`OSError` is raised.
258+
259+
.. versionadded:: 3.3
260+
261+
.. versionchanged:: 3.4
262+
Raise :exc:`OSError` instead of :exc:`NotImplementedError`.
263+
264+
.. method:: path_mtime(path)
265+
266+
Optional abstract method which returns the modification time for the
267+
specified path.
268+
269+
.. deprecated:: 3.3
270+
This method is deprecated in favour of :meth:`path_stats`. You don't
271+
have to implement it, but it is still available for compatibility
272+
purposes. Raise :exc:`OSError` if the path cannot be handled.
273+
274+
.. versionchanged:: 3.4
275+
Raise :exc:`OSError` instead of :exc:`NotImplementedError`.
276+
277+
.. method:: set_data(path, data)
278+
279+
Optional abstract method which writes the specified bytes to a file
280+
path. Any intermediate directories which do not exist are to be created
281+
automatically.
282+
283+
When writing to the path fails because the path is read-only
284+
(:attr:`errno.EACCES`/:exc:`PermissionError`), do not propagate the
285+
exception.
286+
287+
.. versionchanged:: 3.4
288+
No longer raises :exc:`NotImplementedError` when called.
289+
290+
.. method:: get_code(fullname)
291+
292+
Concrete implementation of :meth:`InspectLoader.get_code`.
293+
294+
.. method:: exec_module(module)
295+
296+
Concrete implementation of :meth:`Loader.exec_module`.
297+
298+
.. versionadded:: 3.4
299+
300+
.. method:: load_module(fullname)
301+
302+
Concrete implementation of :meth:`Loader.load_module`.
303+
304+
.. deprecated:: 3.4
305+
Use :meth:`exec_module` instead.
306+
307+
.. method:: get_source(fullname)
308+
309+
Concrete implementation of :meth:`InspectLoader.get_source`.
310+
311+
.. method:: is_package(fullname)
312+
313+
Concrete implementation of :meth:`InspectLoader.is_package`. A module
314+
is determined to be a package if its file path (as provided by
315+
:meth:`ExecutionLoader.get_filename`) is a file named
316+
``__init__`` when the file extension is removed **and** the module name
317+
itself does not end in ``__init__``.
318+
319+
320+
.. class:: Traversable
321+
322+
An object with a subset of pathlib.Path methods suitable for
323+
traversing directories and opening files.
324+
325+
.. versionadded:: 3.9
326+
327+
.. attribute:: name
328+
329+
Abstract. The base name of this object without any parent references.
330+
331+
.. abstractmethod:: iterdir()
332+
333+
Yield Traversable objects in self.
334+
335+
.. abstractmethod:: is_dir()
336+
337+
Return True if self is a directory.
338+
339+
.. abstractmethod:: is_file()
340+
341+
Return True if self is a file.
342+
343+
.. abstractmethod:: joinpath(child)
344+
345+
Return Traversable child in self.
346+
347+
.. abstractmethod:: __truediv__(child)
348+
349+
Return Traversable child in self.
350+
351+
.. abstractmethod:: open(mode='r', *args, **kwargs)
352+
353+
*mode* may be 'r' or 'rb' to open as text or binary. Return a handle
354+
suitable for reading (same as :attr:`pathlib.Path.open`).
355+
356+
When opening as text, accepts encoding parameters such as those
357+
accepted by :attr:`io.TextIOWrapper`.
358+
359+
.. method:: read_bytes()
360+
361+
Read contents of self as bytes.
362+
363+
.. method:: read_text(encoding=None)
364+
365+
Read contents of self as text.
366+
367+
368+
.. class:: TraversableResources
369+
370+
An abstract base class for resource readers capable of serving
371+
the :meth:`importlib.resources.files` interface. Subclasses
372+
:class:`importlib.abc.ResourceReader` and provides
373+
concrete implementations of the :class:`importlib.abc.ResourceReader`'s
374+
abstract methods. Therefore, any loader supplying
375+
:class:`importlib.abc.TraversableReader` also supplies ResourceReader.
376+
377+
Loaders that wish to support resource reading are expected to
378+
implement this interface.
379+
380+
.. versionadded:: 3.9
381+
382+
.. abstractmethod:: files()
383+
384+
Returns a :class:`importlib.abc.Traversable` object for the loaded
385+
package.

0 commit comments

Comments
 (0)