Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions Doc/c-api/import.rst
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,7 @@ Importing Modules
of :class:`~importlib.machinery.SourceFileLoader` otherwise.

The module's :attr:`~module.__file__` attribute will be set to the code
object's :attr:`~codeobject.co_filename`. If applicable,
:attr:`~module.__cached__` will also be set.
object's :attr:`~codeobject.co_filename`.

This function will reload the module if it was already imported. See
:c:func:`PyImport_ReloadModule` for the intended way to reload a module.
Expand All @@ -142,10 +141,13 @@ Importing Modules
:c:func:`PyImport_ExecCodeModuleWithPathnames`.

.. versionchanged:: 3.12
The setting of :attr:`~module.__cached__` and :attr:`~module.__loader__`
The setting of ``__cached__`` and :attr:`~module.__loader__`
is deprecated. See :class:`~importlib.machinery.ModuleSpec` for
alternatives.

.. versionchanged:: 3.15
``__cached__`` is no longer set.


.. c:function:: PyObject* PyImport_ExecCodeModuleEx(const char *name, PyObject *co, const char *pathname)

Expand All @@ -157,16 +159,19 @@ Importing Modules

.. c:function:: PyObject* PyImport_ExecCodeModuleObject(PyObject *name, PyObject *co, PyObject *pathname, PyObject *cpathname)

Like :c:func:`PyImport_ExecCodeModuleEx`, but the :attr:`~module.__cached__`
attribute of the module object is set to *cpathname* if it is
non-``NULL``. Of the three functions, this is the preferred one to use.
Like :c:func:`PyImport_ExecCodeModuleEx`, but the path to any compiled file
via *cpathname* is used appropriately when non-``NULL``. Of the three
functions, this is the preferred one to use.

.. versionadded:: 3.3

.. versionchanged:: 3.12
Setting :attr:`~module.__cached__` is deprecated. See
Setting ``__cached__`` is deprecated. See
:class:`~importlib.machinery.ModuleSpec` for alternatives.

.. versionchanged:: 3.15
``__cached__`` no longer set.


.. c:function:: PyObject* PyImport_ExecCodeModuleWithPathnames(const char *name, PyObject *co, const char *pathname, const char *cpathname)

Expand Down
4 changes: 2 additions & 2 deletions Doc/deprecations/pending-removal-in-3.15.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ Pending removal in Python 3.15

* The import system:

* Setting :attr:`~module.__cached__` on a module while
* Setting ``__cached__`` on a module while
failing to set :attr:`__spec__.cached <importlib.machinery.ModuleSpec.cached>`
is deprecated. In Python 3.15, :attr:`!__cached__` will cease to be set or
is deprecated. In Python 3.15, ``__cached__`` will cease to be set or
take into consideration by the import system or standard library. (:gh:`97879`)

* Setting :attr:`~module.__package__` on a module while
Expand Down
2 changes: 1 addition & 1 deletion Doc/howto/gdb_helpers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ enabled::
at Objects/unicodeobject.c:551
#7 0x0000000000440d94 in PyUnicodeUCS2_FromString (u=0x5c2b8d "__lltrace__") at Objects/unicodeobject.c:569
#8 0x0000000000584abd in PyDict_GetItemString (v=
{'Yuck': <type at remote 0xad4730>, '__builtins__': <module at remote 0x7ffff7fd5ee8>, '__file__': 'Lib/test/crashers/nasty_eq_vs_dict.py', '__package__': None, 'y': <Yuck(i=0) at remote 0xaacd80>, 'dict': {0: 0, 1: 1, 2: 2, 3: 3}, '__cached__': None, '__name__': '__main__', 'z': <Yuck(i=0) at remote 0xaace60>, '__doc__': None}, key=
{'Yuck': <type at remote 0xad4730>, '__builtins__': <module at remote 0x7ffff7fd5ee8>, '__file__': 'Lib/test/crashers/nasty_eq_vs_dict.py', '__package__': None, 'y': <Yuck(i=0) at remote 0xaacd80>, 'dict': {0: 0, 1: 1, 2: 2, 3: 3}, '__name__': '__main__', 'z': <Yuck(i=0) at remote 0xaace60>, '__doc__': None}, key=
0x5c2b8d "__lltrace__") at Objects/dictobject.c:2171

Notice how the dictionary argument to ``PyDict_GetItemString`` is displayed
Expand Down
2 changes: 1 addition & 1 deletion Doc/library/functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ are always available. They are listed here in alphabetical order.
>>> dir() # show the names in the module namespace # doctest: +SKIP
['__builtins__', '__name__', 'struct']
>>> dir(struct) # show the names in the struct module # doctest: +SKIP
['Struct', '__all__', '__builtins__', '__cached__', '__doc__', '__file__',
['Struct', '__all__', '__builtins__', '__doc__', '__file__',
'__initializing__', '__loader__', '__name__', '__package__',
'_clearcache', 'calcsize', 'error', 'pack', 'pack_into',
'unpack', 'unpack_from']
Expand Down
4 changes: 1 addition & 3 deletions Doc/library/importlib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,6 @@ ABC hierarchy::

- :attr:`module.__name__`
- :attr:`module.__file__`
- :attr:`module.__cached__` *(deprecated)*
- :attr:`module.__path__`
- :attr:`module.__package__` *(deprecated)*
- :attr:`module.__loader__` *(deprecated)*
Expand Down Expand Up @@ -1262,8 +1261,7 @@ find and load modules.

.. attribute:: cached

The filename of a compiled version of the module's code
(see :attr:`module.__cached__`).
The filename of a compiled version of the module's code.
The :term:`finder` should always set this attribute but it may be ``None``
for modules that do not need compiled code stored.

Expand Down
28 changes: 17 additions & 11 deletions Doc/library/runpy.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ The :mod:`runpy` module provides two functions:
overridden by :func:`run_module`.

The special global variables ``__name__``, ``__spec__``, ``__file__``,
``__cached__``, ``__loader__`` and ``__package__`` are set in the globals
dictionary before the module code is executed. (Note that this is a
minimal set of variables - other variables may be set implicitly as an
interpreter implementation detail.)
``__loader__`` and ``__package__`` are set in the globals dictionary before
the module code is executed. (Note that this is a minimal set of variables -
other variables may be set implicitly as an interpreter implementation
detail.)

``__name__`` is set to *run_name* if this optional argument is not
:const:`None`, to ``mod_name + '.__main__'`` if the named module is a
Expand All @@ -63,7 +63,7 @@ The :mod:`runpy` module provides two functions:
module (that is, ``__spec__.name`` will always be *mod_name* or
``mod_name + '.__main__'``, never *run_name*).

``__file__``, ``__cached__``, ``__loader__`` and ``__package__`` are
``__file__``, ``__loader__`` and ``__package__`` are
:ref:`set as normal <import-mod-attrs>` based on the module spec.

If the argument *alter_sys* is supplied and evaluates to :const:`True`,
Expand Down Expand Up @@ -98,6 +98,9 @@ The :mod:`runpy` module provides two functions:
``__package__`` are deprecated. See
:class:`~importlib.machinery.ModuleSpec` for alternatives.

.. versionchanged:: 3.15
``__cached__`` is no longer set.

.. function:: run_path(path_name, init_globals=None, run_name=None)

.. index::
Expand Down Expand Up @@ -125,23 +128,23 @@ The :mod:`runpy` module provides two functions:
overridden by :func:`run_path`.

The special global variables ``__name__``, ``__spec__``, ``__file__``,
``__cached__``, ``__loader__`` and ``__package__`` are set in the globals
dictionary before the module code is executed. (Note that this is a
minimal set of variables - other variables may be set implicitly as an
interpreter implementation detail.)
``__loader__`` and ``__package__`` are set in the globals dictionary before
the module code is executed. (Note that this is a minimal set of variables -
other variables may be set implicitly as an interpreter implementation
detail.)

``__name__`` is set to *run_name* if this optional argument is not
:const:`None` and to ``'<run_path>'`` otherwise.

If *file_path* directly references a script file (whether as source
or as precompiled byte code), then ``__file__`` will be set to
*file_path*, and ``__spec__``, ``__cached__``, ``__loader__`` and
*file_path*, and ``__spec__``, ``__loader__`` and
``__package__`` will all be set to :const:`None`.

If *file_path* is a reference to a valid :data:`sys.path` entry, then
``__spec__`` will be set appropriately for the imported :mod:`__main__`
module (that is, ``__spec__.name`` will always be ``__main__``).
``__file__``, ``__cached__``, ``__loader__`` and ``__package__`` will be
``__file__``, ``__loader__`` and ``__package__`` will be
:ref:`set as normal <import-mod-attrs>` based on the module spec.

A number of alterations are also made to the :mod:`sys` module. Firstly,
Expand Down Expand Up @@ -173,6 +176,9 @@ The :mod:`runpy` module provides two functions:
The setting of ``__cached__``, ``__loader__``, and
``__package__`` are deprecated.

.. versionchanged:: 3.15
``__cached__`` is no longer set.

.. seealso::

:pep:`338` -- Executing modules as scripts
Expand Down
38 changes: 11 additions & 27 deletions Doc/reference/datamodel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -895,7 +895,6 @@ Attribute assignment updates the module's namespace dictionary, e.g.,
single: __loader__ (module attribute)
single: __path__ (module attribute)
single: __file__ (module attribute)
single: __cached__ (module attribute)
single: __doc__ (module attribute)
single: __annotations__ (module attribute)
single: __annotate__ (module attribute)
Expand Down Expand Up @@ -1044,43 +1043,28 @@ this approach.
instead of :attr:`!module.__path__`.

.. attribute:: module.__file__
.. attribute:: module.__cached__

:attr:`!__file__` and :attr:`!__cached__` are both optional attributes that
:attr:`!__file__` is an optional attribute that
may or may not be set. Both attributes should be a :class:`str` when they
are available.

:attr:`!__file__` indicates the pathname of the file from which the module
was loaded (if loaded from a file), or the pathname of the shared library
file for extension modules loaded dynamically from a shared library.
It might be missing for certain types of modules, such as C modules that are
statically linked into the interpreter, and the
An optional attribute, :attr:`!__file__` indicates the pathname of the file
from which the module was loaded (if loaded from a file), or the pathname of
the shared library file for extension modules loaded dynamically from a
shared library. It might be missing for certain types of modules, such as C
modules that are statically linked into the interpreter, and the
:ref:`import system <importsystem>` may opt to leave it unset if it
has no semantic meaning (for example, a module loaded from a database).

If :attr:`!__file__` is set then the :attr:`!__cached__` attribute might
also be set, which is the path to any compiled version of
the code (for example, a byte-compiled file). The file does not need to exist
to set this attribute; the path can simply point to where the
compiled file *would* exist (see :pep:`3147`).

Note that :attr:`!__cached__` may be set even if :attr:`!__file__` is not
set. However, that scenario is quite atypical. Ultimately, the
:term:`loader` is what makes use of the module spec provided by the
:term:`finder` (from which :attr:`!__file__` and :attr:`!__cached__` are
derived). So if a loader can load from a cached module but otherwise does
not load from a file, that atypical scenario may be appropriate.

It is **strongly** recommended that you use
:attr:`module.__spec__.cached <importlib.machinery.ModuleSpec.cached>`
instead of :attr:`!module.__cached__`.

.. deprecated-removed:: 3.13 3.15
Setting :attr:`!__cached__` on a module while failing to set
Setting ``__cached__`` on a module while failing to set
:attr:`!__spec__.cached` is deprecated. In Python 3.15,
:attr:`!__cached__` will cease to be set or taken into consideration by
``__cached__`` will cease to be set or taken into consideration by
the import system or standard library.

.. versionchanged:: 3.15
``__cached__`` is no longer set.

Other writable attributes on module objects
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down
2 changes: 1 addition & 1 deletion Doc/whatsnew/3.12.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1337,7 +1337,7 @@ Deprecated
it was :exc:`ImportWarning`).
(Contributed by Brett Cannon in :gh:`65961`.)

* Setting :attr:`~module.__package__` or :attr:`~module.__cached__` on a
* Setting :attr:`~module.__package__` or ``__cached__`` on a
module is deprecated, and will cease to be set or taken into consideration by
the import system in Python 3.14. (Contributed by Brett Cannon in :gh:`65961`.)

Expand Down
2 changes: 1 addition & 1 deletion Doc/whatsnew/3.2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ cluttering source directories, the *pyc* files are now collected in a
Aside from the filenames and target directories, the new scheme has a few
aspects that are visible to the programmer:

* Imported modules now have a :attr:`~module.__cached__` attribute which stores
* Imported modules now have a ``__cached__`` attribute which stores
the name of the actual file that was imported:

>>> import collections
Expand Down
17 changes: 3 additions & 14 deletions Lib/importlib/_bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -583,8 +583,7 @@ class ModuleSpec:
`has_location` indicates that a spec's "origin" reflects a location.
When this is True, `__file__` attribute of the module is set.

`cached` is the location of the cached bytecode file, if any. It
corresponds to the `__cached__` attribute.
`cached` is the location of the cached bytecode file, if any.

`submodule_search_locations` is the sequence of path entries to
search when importing submodules. If set, is_package should be
Expand Down Expand Up @@ -717,18 +716,14 @@ def _spec_from_module(module, loader=None, origin=None):
origin = getattr(loader, '_ORIGIN', None)
if not origin and location is not None:
origin = location
try:
cached = module.__cached__
except AttributeError:
cached = None
try:
submodule_search_locations = list(module.__path__)
except AttributeError:
submodule_search_locations = None

spec = ModuleSpec(name, loader, origin=origin)
spec._set_fileattr = False if location is None else (origin == location)
spec.cached = cached
spec.cached = None
spec.submodule_search_locations = submodule_search_locations
return spec

Expand Down Expand Up @@ -789,20 +784,14 @@ def _init_module_attrs(spec, module, *, override=False):
module.__path__ = spec.submodule_search_locations
except AttributeError:
pass
# __file__/__cached__
# __file__
if spec.has_location:
if override or getattr(module, '__file__', None) is None:
try:
module.__file__ = spec.origin
except AttributeError:
pass

if override or getattr(module, '__cached__', None) is None:
if spec.cached is not None:
try:
module.__cached__ = spec.cached
except AttributeError:
pass
return module


Expand Down
1 change: 0 additions & 1 deletion Lib/importlib/_bootstrap_external.py
Original file line number Diff line number Diff line change
Expand Up @@ -1543,7 +1543,6 @@ def _fix_up_module(ns, name, pathname, cpathname=None):
ns['__spec__'] = spec
ns['__loader__'] = loader
ns['__file__'] = pathname
ns['__cached__'] = cpathname
except Exception:
# Not important enough to report.
pass
Expand Down
12 changes: 6 additions & 6 deletions Lib/inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -3408,20 +3408,20 @@ def _main():
sys.exit(1)

if args.details:
print('Target: {}'.format(target))
print('Origin: {}'.format(getsourcefile(module)))
print('Cached: {}'.format(module.__cached__))
print(f'Target: {target}')
print(f'Origin: {getsourcefile(module)}')
print(f'Cached: {module.__spec__.cached}')
if obj is module:
print('Loader: {}'.format(repr(module.__loader__)))
print(f'Loader: {module.__loader__!r}')
if hasattr(module, '__path__'):
print('Submodule search path: {}'.format(module.__path__))
print(f'Submodule search path: {module.__path__}')
else:
try:
__, lineno = findsource(obj)
except Exception:
pass
else:
print('Line: {}'.format(lineno))
print(f'Line: {lineno}')

print()
else:
Expand Down
1 change: 0 additions & 1 deletion Lib/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,6 @@ def main():
'__file__': spec.origin,
'__name__': spec.name,
'__package__': None,
'__cached__': None,
}
try:
runctx(code, globs, None, options.outfile, options.sort)
Expand Down
1 change: 0 additions & 1 deletion Lib/profiling/tracing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,6 @@ def main():
'__file__': spec.origin,
'__name__': spec.name,
'__package__': None,
'__cached__': None,
})

try:
Expand Down
12 changes: 6 additions & 6 deletions Lib/pydoc.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,12 +241,12 @@ def visiblename(name, all=None, obj=None):
"""Decide whether to show documentation on a variable."""
# Certain special names are redundant or internal.
# XXX Remove __initializing__?
if name in {'__author__', '__builtins__', '__cached__', '__credits__',
'__date__', '__doc__', '__file__', '__spec__',
'__loader__', '__module__', '__name__', '__package__',
'__path__', '__qualname__', '__slots__', '__version__',
'__static_attributes__', '__firstlineno__',
'__annotate_func__', '__annotations_cache__'}:
if name in {'__author__', '__builtins__', '__credits__', '__date__',
'__doc__', '__file__', '__spec__', '__loader__', '__module__',
'__name__', '__package__', '__path__', '__qualname__',
'__slots__', '__version__', '__static_attributes__',
'__firstlineno__', '__annotate_func__',
'__annotations_cache__'}:
return 0
# Private names are hidden, but special names are displayed.
if name.startswith('__') and name.endswith('__'): return 1
Expand Down
2 changes: 0 additions & 2 deletions Lib/runpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ def _run_code(code, run_globals, init_globals=None,
pkg_name = mod_spec.parent
run_globals.update(__name__ = mod_name,
__file__ = fname,
__cached__ = cached,
__doc__ = None,
__loader__ = loader,
__package__ = pkg_name,
Expand Down Expand Up @@ -180,7 +179,6 @@ def _run_module_as_main(mod_name, alter_argv=True):
At the very least, these variables in __main__ will be overwritten:
__name__
__file__
__cached__
__loader__
__package__
"""
Expand Down
Loading
Loading