GeezerVison is showing github.com — PEP 737: gh-111696: Add type.__fully_qualified_name__ attribute by vstinner · Pull Request #112133 · python/cpython
PEP 737: gh-111696: Add type.__fully_qualified_name__ attribute
#112133
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and
privacy statement . We’ll occasionally send you account related emails.
Already on GitHub?
Sign in
to your account
Uh oh!
There was an error while loading. Please reload this page.
Show file tree
Hide file tree
Changes from all commits
Commits
File filter
Filter by extension
.c
(2)
.h
(1)
.py
(22)
.rst
(17)
All 4 file types selected
Viewed files
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Hide whitespace
Diff view
Hide whitespace
There are no files selected for viewing
Original file line number
Diff line number
Diff line change
Expand Up
@@ -185,6 +185,14 @@ Type Objects
.. versionadded:: 3.11
.. c:function:: PyObject* PyType_GetFullyQualifiedName(PyTypeObject *type)
Return the type's :term:`fully qualified name`. Equivalent to getting the
type's :attr:`__fully_qualified_name__ <class.__fully_qualified_name__>`
attribute.
.. versionadded:: 3.13
.. c:function:: void* PyType_GetSlot(PyTypeObject *type, int slot)
Return the function pointer stored in the given slot. If the
Expand Down
Original file line number
Diff line number
Diff line change
Expand Up
@@ -435,6 +435,25 @@ Glossary
division. Note that ``(-11) // 4`` is ``-3`` because that is ``-2.75``
rounded *downward*. See :pep:`238`.
fully qualified name
The fully qualified name is the entire dotted path to a class or a
module.
The :attr:`class.__fully_qualified_name__` attribute includes the module
name, except for built-in classes. Example::
>>> import collections
>>> collections.OrderedDict.__fully_qualified_name__
'collections.OrderedDict'
When used to refer to modules, the *fully qualified name* means the
entire dotted path to the module, including any parent packages,
e.g. ``email.mime.text``::
>>> import email.mime.text
>>> email.mime.text.__name__
'email.mime.text'
function
A series of statements which returns some value to a caller. It can also
be passed zero or more :term:`arguments <argument>` which may be used in
Expand Down
Original file line number
Diff line number
Diff line change
Expand Up
@@ -587,13 +587,13 @@ doctest decides whether actual output matches an example's expected output:
.. data:: IGNORE_EXCEPTION_DETAIL
When specified, doctests expecting exceptions pass so long as an exception
of the expected type is raised, even if the details
(message and fully qualified exception name) don't match.
of the expected type is raised, even if the details (message and
:term:` fully qualified exception name <fully qualified name>` ) don't match.
For example, an example expecting ``ValueError: 42`` will pass if the actual
exception raised is ``ValueError: 3*14``, but will fail if, say, a
:exc:`TypeError` is raised instead.
It will also ignore any fully qualified name included before the
It will also ignore any :term:` fully qualified name` included before the
exception class, which can vary between implementations and versions
of Python and the code/libraries in use.
Hence, all three of these variations will work with the flag specified:
Expand Down
Original file line number
Diff line number
Diff line change
Expand Up
@@ -56,8 +56,8 @@
found:
* the type itself (``typ``)
* the type's fully qualified name (``typ.__module__ + '.' +
typ.__qualname__` `).
* the type's :term:` fully qualified name`
(:attr:` typ.__fully_qualified_name__ <class.__fully_qualified_name__> `).
* the type's qualname (``typ.__qualname__``)
* the type's name (``typ.__name__``).
Expand Down
Original file line number
Diff line number
Diff line change
Expand Up
@@ -356,7 +356,7 @@ ABC hierarchy::
reloaded):
- :attr:`__name__`
The module's fully qualified name.
The module's :term:` fully qualified name` .
It is ``'__main__'`` for an executed module.
- :attr:`__file__`
Expand All
@@ -377,8 +377,8 @@ ABC hierarchy::
as an indicator that the module is a package.
- :attr:`__package__`
The fully qualified name of the package the module is in (or the
empty string for a top-level module).
The :term:` fully qualified name` of the package the module is in
(or the empty string for a top-level module).
If the module is a package then this is the same as :attr:`__name__`.
- :attr:`__loader__`
Expand Down
Expand Up
@@ -1181,7 +1181,7 @@ find and load modules.
(:attr:`__name__`)
The module's fully qualified name.
The module's :term:` fully qualified name` .
The :term:`finder` should always set this attribute to a non-empty string.
.. attribute:: loader
Expand Down
Expand Up
@@ -1230,8 +1230,8 @@ find and load modules.
(:attr:`__package__`)
(Read-only) The fully qualified name of the package the module is in (or the
empty string for a top-level module).
(Read-only) The :term:` fully qualified name` of the package the module is in
(or the empty string for a top-level module).
If the module is a package then this is the same as :attr:`name`.
.. attribute:: has_location
Expand Down
Original file line number
Diff line number
Diff line change
Expand Up
@@ -182,7 +182,7 @@ attributes (see :ref:`import-mod-attrs` for module attributes):
| | co_name | name with which this code |
| | | object was defined |
+-----------+-------------------+---------------------------+
| | co_qualname | fully qualified name with |
| | co_qualname | qualified name with |
| | | which this code object |
| | | was defined |
+-----------+-------------------+---------------------------+
Expand Down
Original file line number
Diff line number
Diff line change
Expand Up
@@ -286,7 +286,7 @@ otherwise, the context is used to determine what to instantiate.
The configuring dict is searched for the following keys:
* ``class`` (mandatory). This is the fully qualified name of the
* ``class`` (mandatory). This is the :term:` fully qualified name` of the
handler class.
* ``level`` (optional). The level of the handler.
Expand Down
Original file line number
Diff line number
Diff line change
Expand Up
@@ -525,7 +525,7 @@ the function's code, nor any of its function attributes are pickled. Thus the
defining module must be importable in the unpickling environment, and the module
must contain the named object, otherwise an exception will be raised. [#]_
Similarly, classes are pickled by fully qualified name, so the same restrictions in
Similarly, classes are pickled by :term:` fully qualified name` , so the same restrictions in
the unpickling environment apply. Note that none of the class's code or data is
pickled, so in the following example the class attribute ``attr`` is not
restored in the unpickling environment::
Expand Down
Original file line number
Diff line number
Diff line change
Expand Up
@@ -5496,6 +5496,15 @@ types, where they are relevant. Some of these are not reported by the
.. versionadded:: 3.3
.. attribute:: class.__fully_qualified_name__
Comment thread
vstinner marked this conversation as resolved.
Resolved
Uh oh!
There was an error while loading. Please reload this page.
The :term:`fully qualified name` of the class instance:
``f"{class.__module__}.{class.__qualname__}"``, or ``class.__qualname__`` if
``class.__module__`` is not a string or is equal to ``"builtins"``.
.. versionadded:: 3.13
.. attribute:: definition.__type_params__
The :ref:`type parameters <type-params>` of generic classes, functions,
Expand Down
Original file line number
Diff line number
Diff line change
Expand Up
@@ -234,8 +234,8 @@ Command-line options
test name using :meth:`fnmatch.fnmatchcase`; otherwise simple case-sensitive
substring matching is used.
Patterns are matched against the fully qualified test method name as
imported by the test loader.
Patterns are matched against the :term:` fully qualified test method name
<fully qualified name>` as imported by the test loader.
For example, ``-k foo`` matches ``foo_tests.SomeTest.test_something``,
``bar_tests.SomeTest.test_foo``, but not ``bar_tests.FooTest.test_something``.
Expand Down
Original file line number
Diff line number
Diff line change
Expand Up
@@ -163,7 +163,8 @@ the disposition of the match. Each entry is a tuple of the form (*action*,
category must be a subclass in order to match.
* *module* is a string containing a regular expression that the start of the
fully qualified module name must match, case-sensitively. In :option:`-W` and
:term:`fully qualified module name <fully qualified name>` must match,
case-sensitively. In :option:`-W` and
:envvar:`PYTHONWARNINGS`, *module* is a literal string that the
fully qualified module name must be equal to (case-sensitively), ignoring any
whitespace at the start or end of *module*.
Expand Down
Original file line number
Diff line number
Diff line change
Expand Up
@@ -1076,7 +1076,7 @@ indirectly) to mutable objects.
single: co_qualname (code object attribute)
Special read-only attributes: :attr:`co_name` gives the function name;
:attr:`co_qualname` gives the fully qualified function name;
:attr:`co_qualname` gives the qualified function name;
:attr:`co_argcount` is the total number of positional arguments
(including positional-only arguments and arguments with default values);
:attr:`co_posonlyargcount` is the number of positional-only arguments
Expand Down
Original file line number
Diff line number
Diff line change
Expand Up
@@ -157,8 +157,8 @@ See also :pep:`420` for the namespace package specification.
Searching
=========
To begin the search, Python needs the :term:`fully qualified <qualified name> `
name of the module (or package, but for the purposes of this discussion, the
To begin the search, Python needs the :term:`fully qualified name`
of the module (or package, but for the purposes of this discussion, the
difference is immaterial) being imported. This name may come from various
arguments to the :keyword:`import` statement, or from the parameters to the
:func:`importlib.import_module` or :func:`__import__` functions.
Expand Down
Expand Up
@@ -547,7 +547,7 @@ listed below.
.. attribute:: __name__
The ``__name__`` attribute must be set to the fully qualified name of
The ``__name__`` attribute must be set to the :term:` fully qualified name` of
the module. This name is used to uniquely identify the module in
the import system.
Expand Down
Expand Up
@@ -885,7 +885,7 @@ contribute portions to namespace packages, path entry finders must implement
the :meth:`~importlib.abc.PathEntryFinder.find_spec` method.
:meth:`~importlib.abc.PathEntryFinder.find_spec` takes two arguments: the
fully qualified name of the module being imported, and the (optional) target
:term:` fully qualified name` of the module being imported, and the (optional) target
module. ``find_spec()`` returns a fully populated spec for the module.
This spec will always have "loader" set (with one exception).
Expand All
@@ -905,7 +905,7 @@ a list containing the portion.
implemented on the path entry finder, the legacy methods are ignored.
:meth:`!find_loader` takes one argument, the
fully qualified name of the module being imported. ``find_loader()``
:term:` fully qualified name` of the module being imported. ``find_loader()``
returns a 2-tuple where the first item is the loader and the second item
is a namespace :term:`portion`.
Expand Down
Original file line number
Diff line number
Diff line change
Expand Up
@@ -464,8 +464,8 @@ Miscellaneous options
whether the actual warning category of the message is a subclass of the
specified warning category.
The *module* field matches the ( fully qualified) module name; this match is
case-sensitive.
The *module* field matches the :term:` fully qualified module name <fully
qualified name>`; this match is case-sensitive.
The *lineno* field matches the line number, where zero matches all line
numbers and is thus equivalent to an omitted line number.
Expand Down
Original file line number
Diff line number
Diff line change
Expand Up
@@ -125,6 +125,11 @@ Other Language Changes
equivalent of the :option:`-X frozen_modules <-X>` command-line option.
(Contributed by Yilei Yang in :gh:`111374`.)
* Add the :attr:`__fully_qualified_name__ <class.__fully_qualified_name__>`
read-only attribute to types: the :term:`fully qualified name` of the type.
(Contributed by Victor Stinner in :gh:`111696`.)
New Modules
===========
Expand Down
Expand Up
@@ -1181,6 +1186,11 @@ New Features
:exc:`KeyError` if the key missing.
(Contributed by Stefan Behnel and Victor Stinner in :gh:`111262`.)
* Add :c:func:`PyType_GetFullyQualifiedName` function: get the type's
:term:`fully qualified name`. It is equivalent to getting the type's
:attr:`__fully_qualified_name__ <class.__fully_qualified_name__>` attribute.
(Contributed by Victor Stinner in :gh:`111696`.)
Porting to Python 3.13
----------------------
Expand Down
Original file line number
Diff line number
Diff line change
Expand Up
@@ -271,6 +271,7 @@ PyAPI_FUNC(const char *) _PyType_Name(PyTypeObject *);
PyAPI_FUNC(PyObject *) _PyType_Lookup(PyTypeObject *, PyObject *);
PyAPI_FUNC(PyObject *) PyType_GetModuleByDef(PyTypeObject *, PyModuleDef *);
PyAPI_FUNC(PyObject *) PyType_GetDict(PyTypeObject *);
PyAPI_FUNC(PyObject *) PyType_GetFullyQualifiedName(PyTypeObject *);
PyAPI_FUNC(int) PyObject_Print(PyObject *, FILE *, int);
PyAPI_FUNC(void) _Py_BreakPoint(void);
Expand Down
Original file line number
Diff line number
Diff line change
Expand Up
@@ -528,9 +528,7 @@ def _type_repr(obj):
(Keep this roughly in sync with the typing version.)
"""
if isinstance(obj, type):
if obj.__module__ == 'builtins':
return obj.__qualname__
return f'{obj.__module__}.{obj.__qualname__}'
return obj.__fully_qualified_name__
if obj is Ellipsis:
return '...'
if isinstance(obj, FunctionType):
Expand Down
Original file line number
Diff line number
Diff line change
Expand Up
@@ -71,7 +71,7 @@ def register(cls, subclass):
def _dump_registry(cls, file=None):
"""Debug helper to print the ABC registry."""
print(f"Class: {cls.__module__}.{cls.__qualname__ }", file=file)
print(f"Class: {cls.__fully_qualified_name__ }", file=file)
print(f"Inv. counter: {get_cache_token()}", file=file)
for name in cls.__dict__:
if name.startswith("_abc_"):
Expand Down
Original file line number
Diff line number
Diff line change
Expand Up
@@ -124,7 +124,7 @@ def __subclasscheck__(cls, subclass):
def _dump_registry(cls, file=None):
"""Debug helper to print the ABC registry."""
print(f"Class: {cls.__module__}.{cls.__qualname__ }", file=file)
print(f"Class: {cls.__fully_qualified_name__ }", file=file)
print(f"Inv. counter: {get_cache_token()}", file=file)
(_abc_registry, _abc_cache, _abc_negative_cache,
_abc_negative_cache_version) = _get_dump(cls)
Expand Down
Original file line number
Diff line number
Diff line change
Expand Up
@@ -107,8 +107,8 @@ def __new__(cls, encode, decode, streamreader=None, streamwriter=None,
return self
def __repr__(self):
return "<%s.%s object for encoding %s at %#x>" % \
(self.__class__.__module__, self.__class__.__qualname__ ,
return "<%s object for encoding %s at %#x>" % \
(self.__class__.__fully_qualified_name__ ,
self.name, id(self))
def __getnewargs__(self):
Expand Down
Original file line number
Diff line number
Diff line change
Expand Up
@@ -525,7 +525,7 @@ def enter_context(self, cm):
_enter = cls.__enter__
_exit = cls.__exit__
except AttributeError:
raise TypeError(f"'{cls.__module__}.{cls.__qualname__ }' object does "
raise TypeError(f"'{cls.__fully_qualified_name__ }' object does "
f"not support the context manager protocol") from None
result = _enter(cm)
self._push_cm_exit(cm, _exit)
Expand Down
Expand Up
@@ -662,7 +662,7 @@ async def enter_async_context(self, cm):
_enter = cls.__aenter__
_exit = cls.__aexit__
except AttributeError:
raise TypeError(f"'{cls.__module__}.{cls.__qualname__ }' object does "
raise TypeError(f"'{cls.__fully_qualified_name__ }' object does "
f"not support the asynchronous context manager protocol"
) from None
result = await _enter(cm)
Expand Down
Original file line number
Diff line number
Diff line change
Expand Up
@@ -1401,7 +1401,7 @@ def __run(self, test, compileflags, out):
# They start with `SyntaxError:` (or any other class name)
exception_line_prefixes = (
f"{exception[0].__qualname__}:",
f"{exception[0].__module__}.{exception[0].__qualname__ }:",
f"{exception[0].__fully_qualified_name__ }:",
)
exc_msg_index = next(
index
Expand Down
Original file line number
Diff line number
Diff line change
Expand Up
@@ -1501,9 +1501,9 @@ def repl(match):
if isinstance(annotation, types.GenericAlias):
return str(annotation)
if isinstance(annotation, type):
if annotation.__module__ in ('builtins', base_module) :
if annotation.__module__ == base_module:
return annotation.__qualname__
return annotation.__module__+'.'+annotation.__qualname__
return annotation.__fully_qualified_name__
return repr(annotation)
def formatannotationrelativeto(object):
Expand Down
Original file line number
Diff line number
Diff line change
Expand Up
@@ -272,7 +272,7 @@ def __del__(self, _warn=warnings.warn, RUN=RUN):
def __repr__(self):
cls = self.__class__
return (f'<{cls.__module__}.{cls.__qualname__ } '
return (f'<{cls.__fully_qualified_name__ } '
f'state={self._state} '
f'pool_size={len(self._pool)}>')
Expand Down
Original file line number
Diff line number
Diff line change
Expand Up
@@ -1726,7 +1726,7 @@ def do_whatis(self, arg):
return
# Is it a class?
if value.__class__ is type:
self.message('Class %s.%s' % ( value.__module__, value.__qualname__) )
self.message(f 'Class { value.__fully_qualified_name__}' )
return
# None of the above...
self.message(type(value))
Expand Down
Original file line number
Diff line number
Diff line change
Expand Up
@@ -256,7 +256,7 @@ def __init__(self, sock=None, map=None):
self.socket = None
def __repr__(self):
status = [self.__class__.__module__+"."+self.__class__.__qualname__ ]
status = [self.__class__.__fully_qualified_name__ ]
if self.accepting and self.addr:
status.append('listening')
elif self.connected:
Expand Down
Loading
Oops, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.