Skip to content
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

[3.12] gh-101100: Fix sphinx warnings in howto/* (GH-127084) #127311

Merged
merged 1 commit into from
Nov 27, 2024
Merged
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
100 changes: 50 additions & 50 deletions Doc/howto/descriptor.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ add new capabilities one by one.
Simple example: A descriptor that returns a constant
----------------------------------------------------

The :class:`Ten` class is a descriptor whose :meth:`__get__` method always
The :class:`!Ten` class is a descriptor whose :meth:`~object.__get__` method always
returns the constant ``10``:

.. testcode::
Expand Down Expand Up @@ -120,10 +120,10 @@ different, updated answers each time::
2

Besides showing how descriptors can run computations, this example also
reveals the purpose of the parameters to :meth:`__get__`. The *self*
reveals the purpose of the parameters to :meth:`~object.__get__`. The *self*
parameter is *size*, an instance of *DirectorySize*. The *obj* parameter is
either *g* or *s*, an instance of *Directory*. It is the *obj* parameter that
lets the :meth:`__get__` method learn the target directory. The *objtype*
lets the :meth:`~object.__get__` method learn the target directory. The *objtype*
parameter is the class *Directory*.


Expand All @@ -133,7 +133,7 @@ Managed attributes
A popular use for descriptors is managing access to instance data. The
descriptor is assigned to a public attribute in the class dictionary while the
actual data is stored as a private attribute in the instance dictionary. The
descriptor's :meth:`__get__` and :meth:`__set__` methods are triggered when
descriptor's :meth:`~object.__get__` and :meth:`~object.__set__` methods are triggered when
the public attribute is accessed.

In the following example, *age* is the public attribute and *_age* is the
Expand Down Expand Up @@ -215,9 +215,9 @@ Customized names
When a class uses descriptors, it can inform each descriptor about which
variable name was used.

In this example, the :class:`Person` class has two descriptor instances,
*name* and *age*. When the :class:`Person` class is defined, it makes a
callback to :meth:`__set_name__` in *LoggedAccess* so that the field names can
In this example, the :class:`!Person` class has two descriptor instances,
*name* and *age*. When the :class:`!Person` class is defined, it makes a
callback to :meth:`~object.__set_name__` in *LoggedAccess* so that the field names can
be recorded, giving each descriptor its own *public_name* and *private_name*:

.. testcode::
Expand Down Expand Up @@ -253,8 +253,8 @@ be recorded, giving each descriptor its own *public_name* and *private_name*:
def birthday(self):
self.age += 1

An interactive session shows that the :class:`Person` class has called
:meth:`__set_name__` so that the field names would be recorded. Here
An interactive session shows that the :class:`!Person` class has called
:meth:`~object.__set_name__` so that the field names would be recorded. Here
we call :func:`vars` to look up the descriptor without triggering it:

.. doctest::
Expand Down Expand Up @@ -294,10 +294,10 @@ The two *Person* instances contain only the private names:
Closing thoughts
----------------

A :term:`descriptor` is what we call any object that defines :meth:`__get__`,
:meth:`__set__`, or :meth:`__delete__`.
A :term:`descriptor` is what we call any object that defines :meth:`~object.__get__`,
:meth:`~object.__set__`, or :meth:`~object.__delete__`.

Optionally, descriptors can have a :meth:`__set_name__` method. This is only
Optionally, descriptors can have a :meth:`~object.__set_name__` method. This is only
used in cases where a descriptor needs to know either the class where it was
created or the name of class variable it was assigned to. (This method, if
present, is called even if the class is not a descriptor.)
Expand Down Expand Up @@ -337,7 +337,7 @@ any data, it verifies that the new value meets various type and range
restrictions. If those restrictions aren't met, it raises an exception to
prevent data corruption at its source.

This :class:`Validator` class is both an :term:`abstract base class` and a
This :class:`!Validator` class is both an :term:`abstract base class` and a
managed attribute descriptor:

.. testcode::
Expand All @@ -360,22 +360,22 @@ managed attribute descriptor:
def validate(self, value):
pass

Custom validators need to inherit from :class:`Validator` and must supply a
:meth:`validate` method to test various restrictions as needed.
Custom validators need to inherit from :class:`!Validator` and must supply a
:meth:`!validate` method to test various restrictions as needed.


Custom validators
-----------------

Here are three practical data validation utilities:

1) :class:`OneOf` verifies that a value is one of a restricted set of options.
1) :class:`!OneOf` verifies that a value is one of a restricted set of options.

2) :class:`Number` verifies that a value is either an :class:`int` or
2) :class:`!Number` verifies that a value is either an :class:`int` or
:class:`float`. Optionally, it verifies that a value is between a given
minimum or maximum.

3) :class:`String` verifies that a value is a :class:`str`. Optionally, it
3) :class:`!String` verifies that a value is a :class:`str`. Optionally, it
validates a given minimum or maximum length. It can validate a
user-defined `predicate
<https://en.wikipedia.org/wiki/Predicate_(mathematical_logic)>`_ as well.
Expand Down Expand Up @@ -498,8 +498,8 @@ Definition and introduction
---------------------------

In general, a descriptor is an attribute value that has one of the methods in
the descriptor protocol. Those methods are :meth:`__get__`, :meth:`__set__`,
and :meth:`__delete__`. If any of those methods are defined for an
the descriptor protocol. Those methods are :meth:`~object.__get__`, :meth:`~object.__set__`,
and :meth:`~object.__delete__`. If any of those methods are defined for an
attribute, it is said to be a :term:`descriptor`.

The default behavior for attribute access is to get, set, or delete the
Expand Down Expand Up @@ -531,8 +531,8 @@ That is all there is to it. Define any of these methods and an object is
considered a descriptor and can override default behavior upon being looked up
as an attribute.

If an object defines :meth:`__set__` or :meth:`__delete__`, it is considered
a data descriptor. Descriptors that only define :meth:`__get__` are called
If an object defines :meth:`~object.__set__` or :meth:`~object.__delete__`, it is considered
a data descriptor. Descriptors that only define :meth:`~object.__get__` are called
non-data descriptors (they are often used for methods but other uses are
possible).

Expand All @@ -542,9 +542,9 @@ has an entry with the same name as a data descriptor, the data descriptor
takes precedence. If an instance's dictionary has an entry with the same
name as a non-data descriptor, the dictionary entry takes precedence.

To make a read-only data descriptor, define both :meth:`__get__` and
:meth:`__set__` with the :meth:`__set__` raising an :exc:`AttributeError` when
called. Defining the :meth:`__set__` method with an exception raising
To make a read-only data descriptor, define both :meth:`~object.__get__` and
:meth:`~object.__set__` with the :meth:`~object.__set__` raising an :exc:`AttributeError` when
called. Defining the :meth:`~object.__set__` method with an exception raising
placeholder is enough to make it a data descriptor.


Expand All @@ -571,7 +571,7 @@ Invocation from an instance

Instance lookup scans through a chain of namespaces giving data descriptors
the highest priority, followed by instance variables, then non-data
descriptors, then class variables, and lastly :meth:`__getattr__` if it is
descriptors, then class variables, and lastly :meth:`~object.__getattr__` if it is
provided.

If a descriptor is found for ``a.x``, then it is invoked with:
Expand Down Expand Up @@ -716,12 +716,12 @@ a pure Python equivalent:
>>> object_getattribute(u2, 'x') == u2.x == (D1, u2, U2)
True

Note, there is no :meth:`__getattr__` hook in the :meth:`__getattribute__`
code. That is why calling :meth:`__getattribute__` directly or with
``super().__getattribute__`` will bypass :meth:`__getattr__` entirely.
Note, there is no :meth:`~object.__getattr__` hook in the :meth:`~object.__getattribute__`
code. That is why calling :meth:`~object.__getattribute__` directly or with
``super().__getattribute__`` will bypass :meth:`~object.__getattr__` entirely.

Instead, it is the dot operator and the :func:`getattr` function that are
responsible for invoking :meth:`__getattr__` whenever :meth:`__getattribute__`
responsible for invoking :meth:`~object.__getattr__` whenever :meth:`~object.__getattribute__`
raises an :exc:`AttributeError`. Their logic is encapsulated in a helper
function:

Expand Down Expand Up @@ -773,8 +773,8 @@ Invocation from a class
-----------------------

The logic for a dotted lookup such as ``A.x`` is in
:meth:`type.__getattribute__`. The steps are similar to those for
:meth:`object.__getattribute__` but the instance dictionary lookup is replaced
:meth:`!type.__getattribute__`. The steps are similar to those for
:meth:`!object.__getattribute__` but the instance dictionary lookup is replaced
by a search through the class's :term:`method resolution order`.

If a descriptor is found, it is invoked with ``desc.__get__(None, A)``.
Expand All @@ -786,7 +786,7 @@ The full C implementation can be found in :c:func:`!type_getattro` and
Invocation from super
---------------------

The logic for super's dotted lookup is in the :meth:`__getattribute__` method for
The logic for super's dotted lookup is in the :meth:`~object.__getattribute__` method for
object returned by :func:`super`.

A dotted lookup such as ``super(A, obj).m`` searches ``obj.__class__.__mro__``
Expand All @@ -803,21 +803,21 @@ The full C implementation can be found in :c:func:`!super_getattro` in
Summary of invocation logic
---------------------------

The mechanism for descriptors is embedded in the :meth:`__getattribute__`
The mechanism for descriptors is embedded in the :meth:`~object.__getattribute__`
methods for :class:`object`, :class:`type`, and :func:`super`.

The important points to remember are:

* Descriptors are invoked by the :meth:`__getattribute__` method.
* Descriptors are invoked by the :meth:`~object.__getattribute__` method.

* Classes inherit this machinery from :class:`object`, :class:`type`, or
:func:`super`.

* Overriding :meth:`__getattribute__` prevents automatic descriptor calls
* Overriding :meth:`~object.__getattribute__` prevents automatic descriptor calls
because all the descriptor logic is in that method.

* :meth:`object.__getattribute__` and :meth:`type.__getattribute__` make
different calls to :meth:`__get__`. The first includes the instance and may
* :meth:`!object.__getattribute__` and :meth:`!type.__getattribute__` make
different calls to :meth:`~object.__get__`. The first includes the instance and may
include the class. The second puts in ``None`` for the instance and always
includes the class.

Expand All @@ -832,16 +832,16 @@ Automatic name notification
Sometimes it is desirable for a descriptor to know what class variable name it
was assigned to. When a new class is created, the :class:`type` metaclass
scans the dictionary of the new class. If any of the entries are descriptors
and if they define :meth:`__set_name__`, that method is called with two
and if they define :meth:`~object.__set_name__`, that method is called with two
arguments. The *owner* is the class where the descriptor is used, and the
*name* is the class variable the descriptor was assigned to.

The implementation details are in :c:func:`!type_new` and
:c:func:`!set_names` in :source:`Objects/typeobject.c`.

Since the update logic is in :meth:`type.__new__`, notifications only take
Since the update logic is in :meth:`!type.__new__`, notifications only take
place at the time of class creation. If descriptors are added to the class
afterwards, :meth:`__set_name__` will need to be called manually.
afterwards, :meth:`~object.__set_name__` will need to be called manually.


ORM example
Expand Down Expand Up @@ -870,7 +870,7 @@ care of lookups or updates:
conn.execute(self.store, [value, obj.key])
conn.commit()

We can use the :class:`Field` class to define `models
We can use the :class:`!Field` class to define `models
<https://en.wikipedia.org/wiki/Database_model>`_ that describe the schema for
each table in a database:

Expand Down Expand Up @@ -1150,7 +1150,7 @@ to wrap access to the value attribute in a property data descriptor:
self.recalc()
return self._value

Either the built-in :func:`property` or our :func:`Property` equivalent would
Either the built-in :func:`property` or our :func:`!Property` equivalent would
work in this example.


Expand Down Expand Up @@ -1183,7 +1183,7 @@ roughly equivalent to:
return func(obj, *args, **kwargs)

To support automatic creation of methods, functions include the
:meth:`__get__` method for binding methods during attribute access. This
:meth:`~object.__get__` method for binding methods during attribute access. This
means that functions are non-data descriptors that return bound methods
during dotted lookup from an instance. Here's how it works:

Expand Down Expand Up @@ -1215,19 +1215,19 @@ The function has a :term:`qualified name` attribute to support introspection:
'D.f'

Accessing the function through the class dictionary does not invoke
:meth:`__get__`. Instead, it just returns the underlying function object::
:meth:`~object.__get__`. Instead, it just returns the underlying function object::

>>> D.__dict__['f']
<function D.f at 0x00C45070>

Dotted access from a class calls :meth:`__get__` which just returns the
Dotted access from a class calls :meth:`~object.__get__` which just returns the
underlying function unchanged::

>>> D.f
<function D.f at 0x00C45070>

The interesting behavior occurs during dotted access from an instance. The
dotted lookup calls :meth:`__get__` which returns a bound method object::
dotted lookup calls :meth:`~object.__get__` which returns a bound method object::

>>> d = D()
>>> d.f
Expand All @@ -1252,7 +1252,7 @@ Kinds of methods
Non-data descriptors provide a simple mechanism for variations on the usual
patterns of binding functions into methods.

To recap, functions have a :meth:`__get__` method so that they can be converted
To recap, functions have a :meth:`~object.__get__` method so that they can be converted
to a method when accessed as attributes. The non-data descriptor transforms an
``obj.f(*args)`` call into ``f(obj, *args)``. Calling ``cls.f(*args)``
becomes ``f(*args)``.
Expand Down Expand Up @@ -1682,7 +1682,7 @@ by member descriptors:
'Emulate member_repr() in Objects/descrobject.c'
return f'<Member {self.name!r} of {self.clsname!r}>'

The :meth:`type.__new__` method takes care of adding member objects to class
The :meth:`!type.__new__` method takes care of adding member objects to class
variables:

.. testcode::
Expand Down Expand Up @@ -1733,7 +1733,7 @@ Python:
)
super().__delattr__(name)

To use the simulation in a real class, just inherit from :class:`Object` and
To use the simulation in a real class, just inherit from :class:`!Object` and
set the :term:`metaclass` to :class:`Type`:

.. testcode::
Expand Down
Loading
Loading