Skip to content

Add default_role for Sphinx. #571

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

Merged
merged 13 commits into from
Sep 9, 2019
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
2 changes: 1 addition & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ Changes:
`#128 <https://github.com/python-attrs/attrs/pull/128>`_
- ``__attrs_post_init__()`` is now run if validation is disabled.
`#130 <https://github.com/python-attrs/attrs/pull/130>`_
- Added ``attr.validators.in_(options)`` that, given the allowed `options`, checks whether the attribute value is in it.
- Added ``attr.validators.in_(options)`` that, given the allowed ``options``, checks whether the attribute value is in it.
This can be used to check constants, enums, mappings, etc.
`#181 <https://github.com/python-attrs/attrs/pull/181>`_
- Added ``attr.validators.and_()`` that composes multiple validators into one.
Expand Down
17 changes: 8 additions & 9 deletions docs/api.rst
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
.. _api:

API Reference
=============

.. currentmodule:: attr

``attrs`` works by decorating a class using :func:`attr.s` and then optionally defining attributes on the class using :func:`attr.ib`.
``attrs`` works by decorating a class using `attr.s` and then optionally defining attributes on the class using `attr.ib`.

.. note::

When this documentation speaks about "``attrs`` attributes" it means those attributes that are defined using :func:`attr.ib` in the class body.
When this documentation speaks about "``attrs`` attributes" it means those attributes that are defined using `attr.ib` in the class body.

What follows is the API explanation, if you'd like a more hands-on introduction, have a look at :doc:`examples`.
What follows is the API explanation, if you'd like a more hands-on introduction, have a look at `examples`.



Expand Down Expand Up @@ -64,7 +62,7 @@ Core

``attrs`` also comes with a serious business alias ``attr.attrib``.

The object returned by :func:`attr.ib` also allows for setting the default and the validator using decorators:
The object returned by `attr.ib` also allows for setting the default and the validator using decorators:

.. doctest::

Expand All @@ -90,7 +88,7 @@ Core

Instances of this class are frequently used for introspection purposes like:

- :func:`fields` returns a tuple of them.
- `fields` returns a tuple of them.
- Validators get them passed as the first argument.

.. warning::
Expand Down Expand Up @@ -148,6 +146,7 @@ Core
.. autoexception:: attr.exceptions.NotAnAttrsClassError
.. autoexception:: attr.exceptions.DefaultAlreadySetError
.. autoexception:: attr.exceptions.UnannotatedAttributeError
.. autoexception:: attr.exceptions.NotCallableError

For example::

Expand Down Expand Up @@ -247,7 +246,7 @@ Helpers

.. autofunction:: attr.filters.exclude

See :ref:`asdict` for examples.
See :func:`asdict` for examples.

.. autofunction:: attr.evolve

Expand Down Expand Up @@ -357,7 +356,7 @@ Validators

.. autofunction:: attr.validators.and_

For convenience, it's also possible to pass a list to :func:`attr.ib`'s validator argument.
For convenience, it's also possible to pass a list to `attr.ib`'s validator argument.

Thus the following two statements are equivalent::

Expand Down
4 changes: 2 additions & 2 deletions docs/backward-compatibility.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ Backward Compatibility
``attrs`` has a very strong backward compatibility policy that is inspired by the policy of the `Twisted framework <https://twistedmatrix.com/trac/wiki/CompatibilityPolicy>`_.

Put simply, you shouldn't ever be afraid to upgrade ``attrs`` if you're only using its public APIs.
If there will ever be a need to break compatibility, it will be announced in the :doc:`changelog` and raise a ``DeprecationWarning`` for a year (if possible) before it's finally really broken.
If there will ever be a need to break compatibility, it will be announced in the `changelog` and raise a ``DeprecationWarning`` for a year (if possible) before it's finally really broken.


.. _exemption:

.. warning::

The structure of the :class:`attr.Attribute` class is exempt from this rule.
The structure of the `attr.Attribute` class is exempt from this rule.
It *will* change in the future, but since it should be considered read-only, that shouldn't matter.

However if you intend to build extensions on top of ``attrs`` you have to anticipate that.
18 changes: 17 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ def find_version(*file_paths):

# -- General configuration ------------------------------------------------

# In nitpick mode (-n), still ignore any of the following "broken" references
# to non-types.
nitpick_ignore = [
("py:class", "Any value"),
("py:class", "callable"),
("py:class", "callables"),
("py:class", "tuple of types"),
]

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
Expand Down Expand Up @@ -68,6 +77,10 @@ def find_version(*file_paths):
# directories to ignore when looking for source files.
exclude_patterns = ["_build"]

# The reST default role (used for this markup: `text`) to use for all
# documents.
default_role = "any"

# If true, '()' will be appended to :func: etc. cross-reference text.
add_function_parentheses = True

Expand Down Expand Up @@ -154,7 +167,10 @@ def find_version(*file_paths):
)
]

intersphinx_mapping = {"https://docs.python.org/3": None}
intersphinx_mapping = {
"https://docs.python.org/3": None,
"https://zopeinterface.readthedocs.io/en/latest/": None,
}

# Allow non-local URIs so we can have images in CHANGELOG etc.
suppress_warnings = ["image.nonlocal_uri"]
28 changes: 13 additions & 15 deletions docs/examples.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
.. _examples:

``attrs`` by Example
====================

Expand Down Expand Up @@ -217,15 +215,15 @@ If you don't set ``kw_only=True``, then there's is no valid attribute ordering a
Converting to Collections Types
-------------------------------

When you have a class with data, it often is very convenient to transform that class into a :class:`dict` (for example if you want to serialize it to JSON):
When you have a class with data, it often is very convenient to transform that class into a `dict` (for example if you want to serialize it to JSON):

.. doctest::

>>> attr.asdict(Coordinates(x=1, y=2))
{'x': 1, 'y': 2}

Some fields cannot or should not be transformed.
For that, :func:`attr.asdict` offers a callback that decides whether an attribute should be included:
For that, `attr.asdict` offers a callback that decides whether an attribute should be included:

.. doctest::

Expand All @@ -241,7 +239,7 @@ For that, :func:`attr.asdict` offers a callback that decides whether an attribut
... filter=lambda attr, value: attr.name != "password")
{'users': [{'email': '[email protected]'}, {'email': '[email protected]'}]}

For the common case where you want to :func:`include <attr.filters.include>` or :func:`exclude <attr.filters.exclude>` certain types or attributes, ``attrs`` ships with a few helpers:
For the common case where you want to `include <attr.filters.include>` or `exclude <attr.filters.exclude>` certain types or attributes, ``attrs`` ships with a few helpers:

.. doctest::

Expand Down Expand Up @@ -426,7 +424,7 @@ You can use a decorator:
ValueError: value out of bounds


``attrs`` ships with a bunch of validators, make sure to :ref:`check them out <api_validators>` before writing your own:
``attrs`` ships with a bunch of validators, make sure to `check them out <api_validators>` before writing your own:

.. doctest::

Expand All @@ -440,7 +438,7 @@ You can use a decorator:
...
TypeError: ("'x' must be <type 'int'> (got '42' that is a <type 'str'>).", Attribute(name='x', default=NOTHING, factory=NOTHING, validator=<instance_of validator for type <type 'int'>>, type=None, kw_only=False), <type 'int'>, '42')

Check out :ref:`validators` for more details.
Check out `validators` for more details.


Conversion
Expand All @@ -458,7 +456,7 @@ This can be useful for doing type-conversions on values that you don't want to f
>>> o.x
1

Check out :ref:`converters` for more details.
Check out `converters` for more details.


.. _metadata:
Expand All @@ -481,13 +479,13 @@ All ``attrs`` attributes may include arbitrary metadata in the form of a read-on
Metadata is not used by ``attrs``, and is meant to enable rich functionality in third-party libraries.
The metadata dictionary follows the normal dictionary rules: keys need to be hashable, and both keys and values are recommended to be immutable.

If you're the author of a third-party library with ``attrs`` integration, please see :ref:`Extending Metadata <extending_metadata>`.
If you're the author of a third-party library with ``attrs`` integration, please see `Extending Metadata <extending_metadata>`.


Types
-----

``attrs`` also allows you to associate a type with an attribute using either the *type* argument to :func:`attr.ib` or -- as of Python 3.6 -- using `PEP 526 <https://www.python.org/dev/peps/pep-0526/>`_-annotations:
``attrs`` also allows you to associate a type with an attribute using either the *type* argument to `attr.ib` or -- as of Python 3.6 -- using `PEP 526 <https://www.python.org/dev/peps/pep-0526/>`_-annotations:


.. doctest::
Expand All @@ -501,7 +499,7 @@ Types
>>> attr.fields(C).y.type
<class 'int'>

If you don't mind annotating *all* attributes, you can even drop the :func:`attr.ib` and assign default values instead:
If you don't mind annotating *all* attributes, you can even drop the `attr.ib` and assign default values instead:

.. doctest::

Expand Down Expand Up @@ -572,11 +570,11 @@ If you'd like to enforce it, ``attrs`` will try to help:
>>> i.x
1

Please note that true immutability is impossible in Python but it will :ref:`get <how-frozen>` you 99% there.
Please note that true immutability is impossible in Python but it will `get <how-frozen>` you 99% there.
By themselves, immutable classes are useful for long-lived objects that should never change; like configurations for example.

In order to use them in regular program flow, you'll need a way to easily create new instances with changed attributes.
In Clojure that function is called `assoc <https://clojuredocs.org/clojure.core/assoc>`_ and ``attrs`` shamelessly imitates it: :func:`attr.evolve`:
In Clojure that function is called `assoc <https://clojuredocs.org/clojure.core/assoc>`_ and ``attrs`` shamelessly imitates it: `attr.evolve`:

.. doctest::

Expand All @@ -598,7 +596,7 @@ Other Goodies
-------------

Sometimes you may want to create a class programmatically.
``attrs`` won't let you down and gives you :func:`attr.make_class` :
``attrs`` won't let you down and gives you `attr.make_class` :

.. doctest::

Expand All @@ -625,7 +623,7 @@ You can still have power over the attributes if you pass a dictionary of name: `
>>> i.y
[]

If you need to dynamically make a class with :func:`attr.make_class` and it needs to be a subclass of something else than ``object``, use the ``bases`` argument:
If you need to dynamically make a class with `attr.make_class` and it needs to be a subclass of something else than ``object``, use the ``bases`` argument:

.. doctest::

Expand Down
8 changes: 3 additions & 5 deletions docs/extending.rst
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
.. _extending:

Extending
=========

Each ``attrs``-decorated class has a ``__attrs_attrs__`` class attribute.
It is a tuple of :class:`attr.Attribute` carrying meta-data about each attribute.
It is a tuple of `attr.Attribute` carrying meta-data about each attribute.

So it is fairly simple to build your own decorators on top of ``attrs``:

Expand All @@ -23,7 +21,7 @@ So it is fairly simple to build your own decorators on top of ``attrs``:

.. warning::

The :func:`attr.s` decorator **must** be applied first because it puts ``__attrs_attrs__`` in place!
The `attr.s` decorator **must** be applied first because it puts ``__attrs_attrs__`` in place!
That means that is has to come *after* your decorator because::

@a
Expand Down Expand Up @@ -53,7 +51,7 @@ Types
``attrs`` offers two ways of attaching type information to attributes:

- `PEP 526 <https://www.python.org/dev/peps/pep-0526/>`_ annotations on Python 3.6 and later,
- and the *type* argument to :func:`attr.ib`.
- and the *type* argument to `attr.ib`.

This information is available to you:

Expand Down
4 changes: 2 additions & 2 deletions docs/glossary.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ Glossary
- Slotted classes can inherit from other classes just like non-slotted classes, but some of the benefits of slotted classes are lost if you do that.
If you must inherit from other classes, try to inherit only from other slotted classes.

- Slotted classes must implement :meth:`__getstate__ <object.__getstate__>` and :meth:`__setstate__ <object.__setstate__>` to be serializable with :mod:`pickle` protocol 0 and 1.
- Slotted classes must implement :meth:`__getstate__ <object.__getstate__>` and :meth:`__setstate__ <object.__setstate__>` to be serializable with `pickle` protocol 0 and 1.
Therefore, ``attrs`` creates these methods automatically for ``slots=True`` classes (Python 2 uses protocol 0 by default).

.. note::

If the ``@attr.s(slots=True)`` decorated class already implements the :meth:`__getstate__ <object.__getstate__>` and :meth:`__setstate__ <object.__setstate__>` methods, they will be *overridden* by ``attrs`` autogenerated implementation.

Also, `think twice <https://www.youtube.com/watch?v=7KnfGDajDQw>`_ before using :mod:`pickle`.
Also, `think twice <https://www.youtube.com/watch?v=7KnfGDajDQw>`_ before using `pickle`.

- Slotted classes are weak-referenceable by default.
This can be disabled in CPython by passing ``weakref_slot=False`` to ``@attr.s`` [#pypyweakref]_.
Expand Down
8 changes: 4 additions & 4 deletions docs/hashing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@ Hash Method Generation
Setting ``hash`` yourself can have unexpected consequences so we recommend to tinker with it only if you know exactly what you're doing.

Under certain circumstances, it's necessary for objects to be *hashable*.
For example if you want to put them into a :class:`set` or if you want to use them as keys in a :class:`dict`.
For example if you want to put them into a `set` or if you want to use them as keys in a `dict`.

The *hash* of an object is an integer that represents the contents of an object.
It can be obtained by calling :func:`hash` on an object and is implemented by writing a ``__hash__`` method for your class.
It can be obtained by calling `hash` on an object and is implemented by writing a ``__hash__`` method for your class.

``attrs`` will happily write a ``__hash__`` method for you [#fn1]_, however it will *not* do so by default.
Because according to the definition_ from the official Python docs, the returned hash has to fulfill certain constraints:

#. Two objects that are equal, **must** have the same hash.
This means that if ``x == y``, it *must* follow that ``hash(x) == hash(y)``.

By default, Python classes are compared *and* hashed by their :func:`id`.
By default, Python classes are compared *and* hashed by their `id`.
That means that every instance of a class has a different hash, no matter what attributes it carries.

It follows that the moment you (or ``attrs``) change the way equality is handled by implementing ``__eq__`` which is based on attribute values, this constraint is broken.
Expand Down Expand Up @@ -65,7 +65,7 @@ For a more thorough explanation of this topic, please refer to this blog post: `

Hashing and Mutability
----------------------
Changing any field involved in hash code computation after the first call to `__hash__` (typically this would be after its insertion into a hash-based collection) can result in silent bugs.
Changing any field involved in hash code computation after the first call to ``__hash__`` (typically this would be after its insertion into a hash-based collection) can result in silent bugs.
Therefore, it is strongly recommended that hashable classes be ``frozen.``
Beware, however, that this is not a complete guarantee of safety:
if a field points to an object and that object is mutated, the hash code may change, but ``frozen`` will not protect you.
Expand Down
4 changes: 2 additions & 2 deletions docs/how-does-it-work.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ No magic, no meta programming, no expensive introspection at runtime.

Everything until this point happens exactly *once* when the class is defined.
As soon as a class is done, it's done.
And it's just a regular Python class like any other, except for a single ``__attrs_attrs__`` attribute that can be used for introspection or for writing your own tools and decorators on top of ``attrs`` (like :func:`attr.asdict`).
And it's just a regular Python class like any other, except for a single ``__attrs_attrs__`` attribute that can be used for introspection or for writing your own tools and decorators on top of ``attrs`` (like `attr.asdict`).

And once you start instantiating your classes, ``attrs`` is out of your way completely.

Expand All @@ -51,7 +51,7 @@ This **static** approach was very much a design goal of ``attrs`` and what I str
Immutability
------------

In order to give you immutability, ``attrs`` will attach a ``__setattr__`` method to your class that raises a :exc:`attr.exceptions.FrozenInstanceError` whenever anyone tries to set an attribute.
In order to give you immutability, ``attrs`` will attach a ``__setattr__`` method to your class that raises a `attr.exceptions.FrozenInstanceError` whenever anyone tries to set an attribute.

Depending on whether a class is a dict class or a slotted class, ``attrs`` uses a different technique to circumvent that limitation in the ``__init__`` method.

Expand Down
Loading