Skip to content

Commit 3e9cda3

Browse files
authored
Add API documentation (python#34)
API documentation. Closes python#16
1 parent a7e8a66 commit 3e9cda3

File tree

5 files changed

+132
-21
lines changed

5 files changed

+132
-21
lines changed

importlib_resources/docs/api.rst

+107
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
=========================
2+
importlib_resources API
3+
=========================
4+
5+
``importlib_resources`` exposes a small number of functions, and it references
6+
a limited number of types, both as arguments to functions and as return types.
7+
8+
9+
Types
10+
=====
11+
12+
.. py:class:: Package
13+
14+
``Package`` types are defined as ``Union[ModuleType, str]``. This means
15+
that where the function describes accepting a ``Package``, you can pass in
16+
either a module or a string. Note that in Python 2, the module object
17+
*must* have a ``__path__`` attribute, while in Python 3, the module object
18+
must have a resolvable ``__spec__.submodule_search_locations`` that is not
19+
``None``.
20+
21+
.. py:class:: FileName
22+
23+
This type describes the resource names passed into the various functions
24+
in this package. For Python 3.6 and later, this is defined as
25+
``Union[str, os.PathLike]``. For earlier versions (which don't have
26+
``os.PathLike``), this is defined as ``str``.
27+
28+
29+
Functions
30+
=========
31+
32+
.. py:function:: importlib_resources.open(package, file_name, encoding=None, errors=None)
33+
34+
Open for reading the resource named ``file_name`` within the ``package``
35+
package. By default, the resource is opened for reading in binary mode.
36+
With a non-``None`` ``encoding`` argument, the resource is opened in text
37+
mode, with ``errors`` having the same meaning as for built-in
38+
:py:func:`open`.
39+
40+
:param package: A package name or module object. See above for the API
41+
that such module objects must support.
42+
:type package: ``Package``
43+
:param file_name: The name of the resource to open within ``package``.
44+
``file_name`` may not contain path separators and it may
45+
not have sub-resources (i.e. it cannot be a directory).
46+
:type file_name: ``FileName``
47+
:param encoding: When ``None``, the resource is opened in binary mode.
48+
When an encoding is given, the resource is opened in text
49+
mode. ``encoding`` has the same meaning as with
50+
:py:func:`open`.
51+
:type encoding: str
52+
:param errors: This parameter is ignored when ``encoding`` is ``None``.
53+
Otherwise it has the same meaning as with :py:func:`open`.
54+
:type errors: str
55+
:returns: an I/O stream open for reading.
56+
:rtype: ``typing.IO``
57+
58+
59+
.. py:function:: importlib_resources.read(package, file_name, encoding='utf-8', errors='strict')
60+
61+
Read and return the contents of the resource named ``file_name`` within
62+
the ``package`` package. By default, the contents are read in UTF-8 and
63+
returned as a ``str`` (in Python 3 - ``unicode`` in Python 2). With
64+
``encoding`` set to ``None``, the resource contents are read in binary
65+
mode and returned as ``bytes``.
66+
67+
:param package: A package name or module object. See above for the API
68+
that such module objects must support.
69+
:type package: ``Package``
70+
:param file_name: The name of the resource to read within ``package``.
71+
``file_name`` may not contain path separators and it may
72+
not have sub-resources (i.e. it cannot be a directory).
73+
:type file_name: ``FileName``
74+
:param encoding: When ``None``, the resource is read in binary mode.
75+
When an encoding is given, the resource is read in text
76+
mode. ``encoding`` has the same meaning as with
77+
:py:func:`open`.
78+
:type encoding: str
79+
:param errors: This parameter is ignored when ``encoding`` is ``None``.
80+
Otherwise it has the same meaning as with :py:func:`open`.
81+
:type errors: str
82+
:returns: the contents of the resource.
83+
:rtype: ``bytes`` or ``str``
84+
85+
.. py:function:: importlib_resources.path(package, file_name)
86+
87+
Return the path to the resource as an actual file system path. This
88+
function returns a `context manager`_ for use in a ``with``-statement.
89+
The context manager provides a :py:class:`pathlib.Path` object.
90+
91+
Exiting the context manager cleans up any temporary file created when the
92+
resource needs to be extracted from e.g. a zip file.
93+
94+
:param package: A package name or module object. See above for the API
95+
that such module objects must support.
96+
:type package: ``Package``
97+
:param file_name: The name of the resource to read within ``package``.
98+
``file_name`` may not contain path separators and it may
99+
not have sub-resources (i.e. it cannot be a directory).
100+
:type file_name: ``FileName``
101+
:returns: A context manager for use in a ``with``-statement. Entering
102+
the context manager provides a :py:class:`pathlib.Path`
103+
object.
104+
:rtype: context manager providing a :py:class:`pathlib.Path` object
105+
106+
107+
.. _`context manager`: https://docs.python.org/3/library/stdtypes.html#typecontextmanager

importlib_resources/docs/conf.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -176,5 +176,5 @@
176176

177177
# Example configuration for intersphinx: refer to the Python standard library.
178178
intersphinx_mapping = {
179-
'py': ('https://docs.python.org/3/', None),
179+
'python': ('https://docs.python.org/3', None),
180180
}

importlib_resources/docs/index.rst

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ standard library as ``importlib.resources``. Its API is currently
1818
`provisional`_.
1919

2020
This documentation includes a general :ref:`usage <using>` guide and a
21-
:ref:`migration` guide for projects which want to adopt
21+
:ref:`migration <migration>` guide for projects that want to adopt
2222
``importlib_resources`` instead of ``pkg_resources``.
2323

2424

@@ -28,6 +28,7 @@ This documentation includes a general :ref:`usage <using>` guide and a
2828

2929
using.rst
3030
migration.rst
31+
api.rst
3132

3233

3334
Indices and tables

importlib_resources/docs/migration.rst

+5-5
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ access`_ APIs:
1717

1818
Keep in mind that ``pkg_resources`` defines *resources* to include
1919
directories. ``importlib_resources`` does not treat directories as resources;
20-
since only file are allowed as resources, file names in the
20+
since only files are allowed as resources, file names in the
2121
``importlib_resources`` API may *not* include path separators (e.g. slashes).
2222

2323

@@ -29,7 +29,7 @@ guarantees that the return value names a file on the file system. This means
2929
that if the resource is in a zip file, ``pkg_resources()`` will extract the
3030
file and return the name of the temporary file it created. The problem is
3131
that ``pkg_resources()`` also *implicitly* cleans up this temporary file,
32-
without control or its lifetime by the programmer.
32+
without control over its lifetime by the programmer.
3333

3434
``importlib_resources`` takes a different approach. Its equivalent API is the
3535
``path()`` function, which returns a context manager providing a
@@ -45,10 +45,10 @@ Here's an example from ``pkg_resources()``::
4545
The best way to convert this is with the following idiom::
4646

4747
with importlib_resources.path('my.package', 'resource.dat') as path:
48-
# Do something with path. After the with-state exits, any temporary
49-
# file created will be immediately cleaned up.
48+
# Do something with path. After the with-statement exits, any
49+
# temporary file created will be immediately cleaned up.
5050

51-
That's all fine is you only need the file temporarily, but what if you need it
51+
That's all fine if you only need the file temporarily, but what if you need it
5252
to stick around for a while? One way of doing this is to use an
5353
:py:class:`contextlib.ExitStack` instance and manage the resource explicitly::
5454

importlib_resources/docs/using.rst

+17-14
Original file line numberDiff line numberDiff line change
@@ -18,31 +18,34 @@ Your test could read the data file by doing something like::
1818
eml = fp.read()
1919

2020
But there's a problem with this! The use of ``__file__`` doesn't work if your
21-
package lives inside a zip file, since in that case, this code does not live
22-
on the file system.
21+
package lives inside a zip file, since in that case this code does not live on
22+
the file system.
2323

2424
You could use the `pkg_resources API`_ like so::
2525

2626
# In Python 3, resource_string() actually returns bytes!
2727
from pkg_resources import resource_string as resource_bytes
2828
eml = resource_bytes('email.tests.data', 'message.eml').decode('utf-8')
2929

30-
This requires you to make both ``email/tests`` and ``email/tests/data`` to be
31-
Python packages, by placing empty ``__init__.py`` files in those directories.
30+
This requires you to make Python packages of both ``email/tests`` and
31+
``email/tests/data``, by placing an empty ``__init__.py`` files in each of
32+
those directories.
33+
3234
**This is a requirement for ``importlib_resources`` too!**
3335

34-
The problem with this is that, depending on the structure of your package,
35-
``pkg_resources`` can be very inefficient even to just import.
36-
``pkg_resources`` is a sort of grab-bag of APIs and functionalities, and to
37-
support all of this, it sometimes has to do a ton of work at import time,
38-
e.g. to scan every package on your ``sys.path``. This can have a serious
39-
negative impact on things like command line startup time for Python implement
40-
commands.
36+
The problem with the ``pkg_resources`` approach is that, depending on the
37+
structure of your package, ``pkg_resources`` can be very inefficient even to
38+
just import. ``pkg_resources`` is a sort of grab-bag of APIs and
39+
functionalities, and to support all of this, it sometimes has to do a ton of
40+
work at import time, e.g. to scan every package on your ``sys.path``. This
41+
can have a serious negative impact on things like command line startup time
42+
for Python implement commands.
4143

4244
``importlib_resources`` solves this by being built entirely on the back of the
43-
stdlib :py:mod:`importlib`. This makes it very fast, by taking advantage of
44-
all the efficiencies in Python's import system. The equivalent code using
45-
``importlib_resources`` would look like::
45+
stdlib :py:mod:`importlib`. By taking advantage of all the efficiencies in
46+
Python's import system, and the fact that it's built into Python, using
47+
``importlib_resources`` can be much more performant. The equivalent code
48+
using ``importlib_resources`` would look like::
4649

4750
from importlib_resources import read
4851
# Reads contents with UTF-8 encoding and returns str.

0 commit comments

Comments
 (0)