Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 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
5 changes: 2 additions & 3 deletions Doc/c-api/extension-modules.rst
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,8 @@ The process of creating an extension module follows several phases:
- By default, Python itself then creates the module object -- that is, it does
the equivalent of calling :py:meth:`~object.__new__` when creating an object.
This step can be overridden using the :c:data:`Py_mod_create` slot.
- Python sets initial module attributes like :attr:`~module.__package__` and
:attr:`~module.__loader__`, and inserts the module object into
:py:attr:`sys.modules`.
- Python sets initial module attributes like :attr:`~module.__spec__`, and
inserts the module object into :py:attr:`sys.modules`.
- Afterwards, the module object is initialized in an extension-specific way
-- the equivalent of :py:meth:`~object.__init__` when creating an object,
or of executing top-level code in a Python-language module.
Expand Down
12 changes: 7 additions & 5 deletions Doc/c-api/module.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,13 @@ Module Objects
single: __name__ (module attribute)
single: __doc__ (module attribute)
single: __file__ (module attribute)
single: __package__ (module attribute)
single: __loader__ (module attribute)
Return a new module object with :attr:`module.__name__` set to *name*.
The module's :attr:`!__name__`, :attr:`~module.__doc__`,
:attr:`~module.__package__` and :attr:`~module.__loader__` attributes are
filled in (all but :attr:`!__name__` are set to ``None``). The caller is
responsible for setting a :attr:`~module.__file__` attribute.
The module's :attr:`!__name__`, :attr:`~module.__doc__`, and
:attr:`~module.__loader__` attributes are filled in (all but
:attr:`!__name__` are set to ``None``). The caller is responsible for
setting a :attr:`~module.__file__` attribute.
Return ``NULL`` with an exception set on error.
Expand All @@ -50,6 +49,9 @@ Module Objects
:attr:`~module.__package__` and :attr:`~module.__loader__` are now set to
``None``.
.. versionchanged:: 3.15
:attr:`~module.__package__` is no longer set.
.. c:function:: PyObject* PyModule_New(const char *name)
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 @@ -10,8 +10,8 @@ Pending removal in Python 3.15

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

* :mod:`ctypes`:

Expand Down
8 changes: 3 additions & 5 deletions 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', '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=
0x5c2b8d "__lltrace__") at Objects/dictobject.c:2171

Notice how the dictionary argument to ``PyDict_GetItemString`` is displayed
Expand All @@ -148,8 +148,7 @@ cast the value to a pointer of the appropriate type. For example::

(gdb) p globals
$1 = {'__builtins__': <module at remote 0x7ffff7fb1868>, '__name__':
'__main__', 'ctypes': <module at remote 0x7ffff7f14360>, '__doc__': None,
'__package__': None}
'__main__', 'ctypes': <module at remote 0x7ffff7f14360>, '__doc__': None}

(gdb) p *(PyDictObject*)globals
$2 = {ob_refcnt = 3, ob_type = 0x3dbdf85820, ma_fill = 5, ma_used = 5,
Expand All @@ -162,8 +161,7 @@ cast the value to a pointer of the appropriate type. For example::
{me_hash = -9177857982131165996, me_key = 'ctypes',
me_value = <module at remote 0x7ffff7f14360>},
{me_hash = -8518757509529533123, me_key = '__doc__', me_value = None},
{me_hash = 0, me_key = 0x0, me_value = 0x0}, {
me_hash = 6614918939584953775, me_key = '__package__', me_value = None}}}
{me_hash = 0, me_key = 0x0, me_value = 0x0}}}

Note that the pretty-printers do not actually call ``repr()``.
For basic types, they try to match its result closely.
Expand Down
4 changes: 2 additions & 2 deletions Doc/library/importlib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,6 @@ ABC hierarchy::
- :attr:`module.__file__`
- :attr:`module.__cached__` *(deprecated)*
- :attr:`module.__path__`
- :attr:`module.__package__` *(deprecated)*
- :attr:`module.__loader__` *(deprecated)*

When :meth:`exec_module` is available then backwards-compatible
Expand Down Expand Up @@ -1271,7 +1270,8 @@ find and load modules.

(Read-only) The fully qualified name of the package the module is in (or the
empty string for a top-level module).
See :attr:`module.__package__`.
See :attr:`module.__package__` for an optional way to override using
this attribute by the import system.
If the module is a package then this is the same as :attr:`name`.

.. attribute:: has_location
Expand Down
30 changes: 18 additions & 12 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.)
``__cached__``, and ``__loader__`` 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__``, ``__cached__``, and ``__loader__`` 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
``__package__`` 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.)
``__cached__``, and ``__loader__`` 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
``__package__`` will all be set to :const:`None`.
*file_path*, and ``__spec__``, ``__cached__``, and ``__loader__`` 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__``, ``__cached__``, and ``__loader__`` 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
``__package__`` is no longer set.

.. seealso::

:pep:`338` -- Executing modules as scripts
Expand Down
17 changes: 6 additions & 11 deletions Doc/reference/datamodel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -960,25 +960,21 @@ this approach.

.. attribute:: module.__package__

The :term:`package` a module belongs to.
An optional attribute that states what :term:`package` a module belongs to.

If the module is top-level (that is, not a part of any specific package)
then the attribute should be set to ``''`` (the empty string). Otherwise,
it should be set to the name of the module's package (which can be equal to
:attr:`module.__name__` if the module itself is a package). See :pep:`366`
for further details.

This attribute is used instead of :attr:`~module.__name__` to calculate
explicit relative imports for main modules. It defaults to ``None`` for
modules created dynamically using the :class:`types.ModuleType` constructor;
use :func:`importlib.util.module_from_spec` instead to ensure the attribute
is set to a :class:`str`.
When set, this attribute is used instead of :attr:`~module.__spec__` or
:attr:`~module.__name__` to calculate explicit relative imports for main
modules.

It is **strongly** recommended that you use
:attr:`module.__spec__.parent <importlib.machinery.ModuleSpec.parent>`
instead of :attr:`!module.__package__`. :attr:`__package__` is now only used
as a fallback if :attr:`!__spec__.parent` is not set, and this fallback
path is deprecated.
instead of :attr:`!module.__package__`.

.. versionchanged:: 3.4
This attribute now defaults to ``None`` for modules created dynamically
Expand All @@ -1001,8 +997,7 @@ this approach.
falling back to :attr:`!__package__` during import resolution.

.. deprecated-removed:: 3.13 3.15
:attr:`!__package__` will cease to be set or taken into consideration
by the import system or standard library.
:attr:`!__package__` is no longer set.

.. attribute:: module.__loader__

Expand Down
2 changes: 1 addition & 1 deletion Doc/tutorial/inputoutput.rst
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ This is particularly useful in combination with the built-in function
>>> table = {k: str(v) for k, v in vars().items()}
>>> message = " ".join([f'{k}: ' + '{' + k +'};' for k in table.keys()])
>>> print(message.format(**table))
__name__: __main__; __doc__: None; __package__: None; __loader__: ...
__name__: __main__; __doc__: None; __loader__: ...

As an example, the following lines produce a tidily aligned
set of columns giving integers and their squares and cubes::
Expand Down
4 changes: 2 additions & 2 deletions Doc/tutorial/modules.rst
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ defines. It returns a sorted list of strings::
['__name__', 'fib', 'fib2']
>>> dir(sys) # doctest: +NORMALIZE_WHITESPACE
['__breakpointhook__', '__displayhook__', '__doc__', '__excepthook__',
'__interactivehook__', '__loader__', '__name__', '__package__', '__spec__',
'__interactivehook__', '__loader__', '__name__', '__spec__',
'__stderr__', '__stdin__', '__stdout__', '__unraisablehook__',
'_clear_type_cache', '_current_frames', '_debugmallocstats', '_framework',
'_getframe', '_git', '_home', '_xoptions', 'abiflags', 'addaudithook',
Expand Down Expand Up @@ -373,7 +373,7 @@ want a list of those, they are defined in the standard module
'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError',
'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning',
'ValueError', 'Warning', 'ZeroDivisionError', '_', '__build_class__',
'__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs',
'__debug__', '__doc__', '__import__', '__name__', 'abs',
'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable',
'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits',
'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit',
Expand Down
7 changes: 4 additions & 3 deletions Lib/_pyrepl/_module_completer.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@


def make_default_module_completer() -> ModuleCompleter:
# Inside pyrepl, __package__ is set to None by default
return ModuleCompleter(namespace={'__package__': None})
return ModuleCompleter()


class ModuleCompleter:
Expand Down Expand Up @@ -102,7 +101,9 @@ def _find_modules(self, path: str, prefix: str) -> list[str]:

if path.startswith('.'):
# Convert relative path to absolute path
package = self.namespace.get('__package__', '')
if not (package := self.namespace.get('__package__', '')):
if spec := self.namespace.get('__spec__'):
package = spec.parent or ''
path = self.resolve_relative_name(path, package) # type: ignore[assignment]
if path is None:
return []
Expand Down
2 changes: 1 addition & 1 deletion Lib/asyncio/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ def interrupt(self) -> None:
asyncio.set_event_loop(loop)

repl_locals = {'asyncio': asyncio}
for key in {'__name__', '__package__',
for key in {'__name__',
'__loader__', '__spec__',
'__builtins__', '__file__'}:
repl_locals[key] = locals()[key]
Expand Down
2 changes: 1 addition & 1 deletion Lib/asyncio/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@


# Name the logger after the package.
logger = logging.getLogger(__package__)
logger = logging.getLogger(__spec__.parent)
2 changes: 1 addition & 1 deletion Lib/idlelib/editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -1154,7 +1154,7 @@ def load_extension(self, name):
fname = self.extfiles.get(name, name)
try:
try:
mod = importlib.import_module('.' + fname, package=__package__)
mod = importlib.import_module('.' + fname, package=__spec__.parent)
except (ImportError, TypeError):
mod = importlib.import_module(fname)
except ImportError:
Expand Down
2 changes: 0 additions & 2 deletions Lib/importlib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
# importlib._bootstrap is the built-in import, ensure we don't create
# a second copy of the module.
_bootstrap.__name__ = 'importlib._bootstrap'
_bootstrap.__package__ = 'importlib'
try:
_bootstrap.__file__ = __file__.replace('__init__.py', '_bootstrap.py')
except NameError:
Expand All @@ -38,7 +37,6 @@
_bootstrap._bootstrap_external = _bootstrap_external
else:
_bootstrap_external.__name__ = 'importlib._bootstrap_external'
_bootstrap_external.__package__ = 'importlib'
try:
_bootstrap_external.__file__ = __file__.replace('__init__.py', '_bootstrap_external.py')
except NameError:
Expand Down
36 changes: 5 additions & 31 deletions Lib/importlib/_bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -770,12 +770,6 @@ def _init_module_attrs(spec, module, *, override=False):
module.__loader__ = loader
except AttributeError:
pass
# __package__
if override or getattr(module, '__package__', None) is None:
try:
module.__package__ = spec.parent
except AttributeError:
pass
# __spec__
try:
module.__spec__ = spec
Expand Down Expand Up @@ -894,16 +888,6 @@ def _load_backward_compatible(spec):
module.__loader__ = spec.loader
except AttributeError:
pass
if getattr(module, '__package__', None) is None:
try:
# Since module.__path__ may not line up with
# spec.submodule_search_paths, we can't necessarily rely
# on spec.parent here.
module.__package__ = module.__name__
if not hasattr(module, '__path__'):
module.__package__ = spec.name.rpartition('.')[0]
except AttributeError:
pass
if getattr(module, '__spec__', None) is None:
try:
module.__spec__ = spec
Expand Down Expand Up @@ -1295,7 +1279,7 @@ def _sanity_check(name, package, level):
raise ValueError('level must be >= 0')
if level > 0:
if not isinstance(package, str):
raise TypeError('__package__ not set to a string')
raise TypeError('__package__ or __spec__.parent not set to a string')
elif not package:
raise ImportError('attempted relative import with no known parent '
'package')
Expand Down Expand Up @@ -1396,8 +1380,7 @@ def _gcd_import(name, package=None, level=0):
being made from, and the level adjustment.

This function represents the greatest common denominator of functionality
between import_module and __import__. This includes setting __package__ if
the loader did not.
between import_module and __import__.

"""
_sanity_check(name, package, level)
Expand Down Expand Up @@ -1443,20 +1426,11 @@ def _handle_fromlist(module, fromlist, import_, *, recursive=False):
return module


def _calc___package__(globals):
"""Calculate what __package__ should be.

__package__ is not guaranteed to be defined or could be set to None
to represent that its proper value is unknown.

"""
def _calc_package(globals):
"""Calculate what the containing package is."""
package = globals.get('__package__')
spec = globals.get('__spec__')
if package is not None:
if spec is not None and package != spec.parent:
_warnings.warn("__package__ != __spec__.parent "
f"({package!r} != {spec.parent!r})",
DeprecationWarning, stacklevel=3)
return package
elif spec is not None:
return spec.parent
Expand Down Expand Up @@ -1485,7 +1459,7 @@ def __import__(name, globals=None, locals=None, fromlist=(), level=0):
module = _gcd_import(name)
else:
globals_ = globals if globals is not None else {}
package = _calc___package__(globals_)
package = _calc_package(globals_)
module = _gcd_import(name, package, level)
if not fromlist:
# Return up to the first dot in 'name'. This is complicated by the fact
Expand Down
2 changes: 0 additions & 2 deletions Lib/pdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,6 @@ def namespace(self):
return dict(
__name__='__main__',
__file__=os.path.normcase(os.path.abspath(self.filename)),
__package__=self._spec.parent,
__loader__=self._spec.loader,
__spec__=self._spec,
__builtins__=__builtins__,
Expand Down Expand Up @@ -288,7 +287,6 @@ def namespace(self):
return dict(
__name__='__main__',
__file__=os.path.normcase(os.path.abspath(self.filename)),
__package__=self._spec.parent,
__loader__=self._spec.loader,
__spec__=self._spec,
__builtins__=__builtins__,
Expand Down
Loading
Loading