diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 0cd0ff17..cf1f8d77 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -164,16 +164,26 @@ You will find the built documentation in `docs/_build/html`. - If you add a new feature, demonstrate its awesomeness on the [examples page](https://github.com/python-attrs/attrs/blob/main/docs/examples.md)! -- For docstrings, we follow [PEP 257](https://peps.python.org/pep-0257/) and use the `"""`-on-separate-lines style: +- For docstrings, we follow [PEP 257](https://peps.python.org/pep-0257/), use the `"""`-on-separate-lines style, and [Napoleon](https://www.sphinx-doc.org/en/master/usage/extensions/napoleon.html)-style API documentation: ```python - def func(x): + def func(x: str, y: int) -> str: """ Do something. - :param str x: A very important parameter. + Args: + x: A very important argument. - :rtype: str + y: + Another very important argument, but its description is so long + that it doesn't fit on one line. So, we start the whole block on a + fresh new line to keep the block together. + + Returns: + str: The result of doing something. + + Raises: + ValueError: When an invalid value is passed. """ ``` diff --git a/docs/conf.py b/docs/conf.py index f166eb5c..45a681a0 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -46,6 +46,7 @@ nitpick_ignore = [ # ones. extensions = [ "myst_parser", + "sphinx.ext.napoleon", "sphinx.ext.autodoc", "sphinx.ext.doctest", "sphinx.ext.intersphinx", diff --git a/src/attr/_cmp.py b/src/attr/_cmp.py index 1c4cce65..f367bb3a 100644 --- a/src/attr/_cmp.py +++ b/src/attr/_cmp.py @@ -26,21 +26,31 @@ def cmp_using( The resulting class will have a full set of ordering methods if at least one of ``{lt, le, gt, ge}`` and ``eq`` are provided. - :param typing.Callable | None eq: Callable used to evaluate equality of two - objects. - :param typing.Callable | None lt: Callable used to evaluate whether one - object is less than another object. - :param typing.Callable | None le: Callable used to evaluate whether one - object is less than or equal to another object. - :param typing.Callable | None gt: Callable used to evaluate whether one - object is greater than another object. - :param typing.Callable | None ge: Callable used to evaluate whether one - object is greater than or equal to another object. + Args: + eq (typing.Callable | None): + Callable used to evaluate equality of two objects. - :param bool require_same_type: When `True`, equality and ordering methods - will return `NotImplemented` if objects are not of the same type. + lt (typing.Callable | None): + Callable used to evaluate whether one object is less than another + object. - :param str | None class_name: Name of class. Defaults to "Comparable". + le (typing.Callable | None): + Callable used to evaluate whether one object is less than or equal + to another object. + + gt (typing.Callable | None): + Callable used to evaluate whether one object is greater than + another object. + + ge (typing.Callable | None): + Callable used to evaluate whether one object is greater than or + equal to another object. + + require_same_type (bool): + When `True`, equality and ordering methods will return + `NotImplemented` if objects are not of the same type. + + class_name (str | None): Name of class. Defaults to "Comparable". See `comparison` for more details. diff --git a/src/attr/_funcs.py b/src/attr/_funcs.py index 29e86607..6bdaaf71 100644 --- a/src/attr/_funcs.py +++ b/src/attr/_funcs.py @@ -21,33 +21,44 @@ def asdict( Optionally recurse into other *attrs*-decorated classes. - :param inst: Instance of an *attrs*-decorated class. - :param bool recurse: Recurse into classes that are also *attrs*-decorated. - :param ~typing.Callable filter: A callable whose return code determines - whether an attribute or element is included (`True`) or dropped - (`False`). Is called with the `attrs.Attribute` as the first argument - and the value as the second argument. - :param ~typing.Callable dict_factory: A callable to produce dictionaries - from. For example, to produce ordered dictionaries instead of normal - Python dictionaries, pass in ``collections.OrderedDict``. - :param bool retain_collection_types: Do not convert to `list` when - encountering an attribute whose type is `tuple` or `set`. Only - meaningful if *recurse* is `True`. - :param typing.Callable | None value_serializer: A hook that is called for - every attribute or dict key/value. It receives the current instance, - field and value and must return the (updated) value. The hook is run - *after* the optional *filter* has been applied. + Args: + inst: Instance of an *attrs*-decorated class. - :rtype: return type of *dict_factory* + recurse (bool): Recurse into classes that are also *attrs*-decorated. - :raise attrs.exceptions.NotAnAttrsClassError: If *cls* is not an *attrs* - class. + filter (~typing.Callable): + A callable whose return code determines whether an attribute or + element is included (`True`) or dropped (`False`). Is called with + the `attrs.Attribute` as the first argument and the value as the + second argument. + + dict_factory (~typing.Callable): + A callable to produce dictionaries from. For example, to produce + ordered dictionaries instead of normal Python dictionaries, pass in + ``collections.OrderedDict``. + + retain_collection_types (bool): + Do not convert to `list` when encountering an attribute whose type + is `tuple` or `set`. Only meaningful if *recurse* is `True`. + + value_serializer (typing.Callable | None): + A hook that is called for every attribute or dict key/value. It + receives the current instance, field and value and must return the + (updated) value. The hook is run *after* the optional *filter* has + been applied. + + Returns: + Return type of *dict_factory*. + + Raises: + attrs.exceptions.NotAnAttrsClassError: + If *cls* is not an *attrs* class. .. versionadded:: 16.0.0 *dict_factory* .. versionadded:: 16.1.0 *retain_collection_types* .. versionadded:: 20.3.0 *value_serializer* - .. versionadded:: 21.3.0 If a dict has a collection for a key, it is - serialized as a tuple. + .. versionadded:: 21.3.0 + If a dict has a collection for a key, it is serialized as a tuple. """ attrs = fields(inst.__class__) rv = dict_factory() @@ -205,22 +216,33 @@ def astuple( Optionally recurse into other *attrs*-decorated classes. - :param inst: Instance of an *attrs*-decorated class. - :param bool recurse: Recurse into classes that are also *attrs*-decorated. - :param ~typing.Callable filter: A callable whose return code determines - whether an attribute or element is included (`True`) or dropped - (`False`). Is called with the `attrs.Attribute` as the first argument - and the value as the second argument. - :param ~typing.Callable tuple_factory: A callable to produce tuples from. - For example, to produce lists instead of tuples. - :param bool retain_collection_types: Do not convert to `list` or `dict` - when encountering an attribute which type is `tuple`, `dict` or `set`. - Only meaningful if *recurse* is `True`. + Args: + inst: Instance of an *attrs*-decorated class. - :rtype: return type of *tuple_factory* + recurse (bool): + Recurse into classes that are also *attrs*-decorated. - :raise attrs.exceptions.NotAnAttrsClassError: If *cls* is not an *attrs* - class. + filter (~typing.Callable): + A callable whose return code determines whether an attribute or + element is included (`True`) or dropped (`False`). Is called with + the `attrs.Attribute` as the first argument and the value as the + second argument. + + tuple_factory (~typing.Callable): + A callable to produce tuples from. For example, to produce lists + instead of tuples. + + retain_collection_types (bool): + Do not convert to `list` or `dict` when encountering an attribute + which type is `tuple`, `dict` or `set`. Only meaningful if + *recurse* is `True`. + + Returns: + Return type of *tuple_factory* + + Raises: + attrs.exceptions.NotAnAttrsClassError: + If *cls* is not an *attrs* class. .. versionadded:: 16.2.0 """ @@ -305,10 +327,14 @@ def has(cls): """ Check whether *cls* is a class with *attrs* attributes. - :param type cls: Class to introspect. - :raise TypeError: If *cls* is not a class. + Args: + cls (type): Class to introspect. - :rtype: bool + Raises: + TypeError: If *cls* is not a class. + + Returns: + bool: """ attrs = getattr(cls, "__attrs_attrs__", None) if attrs is not None: @@ -337,20 +363,25 @@ def assoc(inst, **changes): .. _`edge cases`: https://github.com/python-attrs/attrs/issues/251 - :param inst: Instance of a class with *attrs* attributes. - :param changes: Keyword changes in the new copy. + Args: + inst: Instance of a class with *attrs* attributes. - :return: A copy of inst with *changes* incorporated. + changes: Keyword changes in the new copy. - :raise attrs.exceptions.AttrsAttributeNotFoundError: If *attr_name* - couldn't be found on *cls*. - :raise attrs.exceptions.NotAnAttrsClassError: If *cls* is not an *attrs* - class. + Returns: + A copy of inst with *changes* incorporated. + + Raises: + attrs.exceptions.AttrsAttributeNotFoundError: + If *attr_name* couldn't be found on *cls*. + + attrs.exceptions.NotAnAttrsClassError: + If *cls* is not an *attrs* class. .. deprecated:: 17.1.0 - Use `attrs.evolve` instead if you can. - This function will not be removed du to the slightly different approach - compared to `attrs.evolve`. + Use `attrs.evolve` instead if you can. This function will not be + removed du to the slightly different approach compared to + `attrs.evolve`, though. """ new = copy.copy(inst) attrs = fields(inst.__class__) @@ -368,16 +399,24 @@ def evolve(*args, **changes): Create a new instance, based on the first positional argument with *changes* applied. - :param inst: Instance of a class with *attrs* attributes. *inst* must be - passed as a positional argument. - :param changes: Keyword changes in the new copy. + Args: - :return: A copy of inst with *changes* incorporated. + inst: + Instance of a class with *attrs* attributes. *inst* must be passed + as a positional argument. - :raise TypeError: If *attr_name* couldn't be found in the class - ``__init__``. - :raise attrs.exceptions.NotAnAttrsClassError: If *cls* is not an *attrs* - class. + changes: + Keyword changes in the new copy. + + Returns: + A copy of inst with *changes* incorporated. + + Raises: + TypeError: + If *attr_name* couldn't be found in the class ``__init__``. + + attrs.exceptions.NotAnAttrsClassError: + If *cls* is not an *attrs* class. .. versionadded:: 17.1.0 .. deprecated:: 23.1.0 @@ -425,25 +464,36 @@ def resolve_types( other dictionaries in which to look up these names. See the docs of `typing.get_type_hints` for more details. - :param type cls: Class to resolve. - :param dict | None globalns: Dictionary containing global variables. - :param dict | None localns: Dictionary containing local variables. - :param list | None attribs: List of attribs for the given class. This is - necessary when calling from inside a ``field_transformer`` since *cls* - is not an *attrs* class yet. - :param bool include_extras: Resolve more accurately, if possible. Pass - ``include_extras`` to ``typing.get_hints``, if supported by the typing - module. On supported Python versions (3.9+), this resolves the types - more accurately. + Args: + cls (type): Class to resolve. - :raise TypeError: If *cls* is not a class. - :raise attrs.exceptions.NotAnAttrsClassError: If *cls* is not an *attrs* - class and you didn't pass any attribs. - :raise NameError: If types cannot be resolved because of missing variables. + globalns (dict | None): Dictionary containing global variables. - :returns: *cls* so you can use this function also as a class decorator. - Please note that you have to apply it **after** `attrs.define`. That - means the decorator has to come in the line **before** `attrs.define`. + localns (dict | None): Dictionary containing local variables. + + attribs (list | None): + List of attribs for the given class. This is necessary when calling + from inside a ``field_transformer`` since *cls* is not an *attrs* + class yet. + + include_extras (bool): + Resolve more accurately, if possible. Pass ``include_extras`` to + ``typing.get_hints``, if supported by the typing module. On + supported Python versions (3.9+), this resolves the types more + accurately. + + Raises: + TypeError: If *cls* is not a class. + + attrs.exceptions.NotAnAttrsClassError: + If *cls* is not an *attrs* class and you didn't pass any attribs. + + NameError: If types cannot be resolved because of missing variables. + + Returns: + *cls* so you can use this function also as a class decorator. Please + note that you have to apply it **after** `attrs.define`. That means the + decorator has to come in the line **before** `attrs.define`. .. versionadded:: 20.1.0 .. versionadded:: 21.1.0 *attribs* diff --git a/src/attr/_make.py b/src/attr/_make.py index 89c2d569..e437e62e 100644 --- a/src/attr/_make.py +++ b/src/attr/_make.py @@ -123,114 +123,134 @@ def attrib( Please consider using `attrs.field` in new code (``attr.ib`` will *never* go away, though). - :param default: A value that is used if an *attrs*-generated ``__init__`` - is used and no value is passed while instantiating or the attribute is - excluded using ``init=False``. + Args: + default: + A value that is used if an *attrs*-generated ``__init__`` is used + and no value is passed while instantiating or the attribute is + excluded using ``init=False``. - If the value is an instance of `attrs.Factory`, its callable will be - used to construct a new value (useful for mutable data types like lists - or dicts). + If the value is an instance of `attrs.Factory`, its callable will + be used to construct a new value (useful for mutable data types + like lists or dicts). - If a default is not set (or set manually to `attrs.NOTHING`), a value - *must* be supplied when instantiating; otherwise a `TypeError` will be - raised. + If a default is not set (or set manually to `attrs.NOTHING`), a + value *must* be supplied when instantiating; otherwise a + `TypeError` will be raised. - The default can also be set using decorator notation as shown below. + The default can also be set using decorator notation as shown + below. - .. seealso:: `defaults` + .. seealso:: `defaults` - :param ~typing.Callable factory: Syntactic sugar for - ``default=attr.Factory(factory)``. + factory (~typing.Callable): + Syntactic sugar for ``default=attr.Factory(factory)``. - :param ~typing.Callable | list[~typing.Callable] validator: Callable that - is called by *attrs*-generated ``__init__`` methods after the instance - has been initialized. They receive the initialized instance, the - :func:`~attrs.Attribute`, and the passed value. + validator (~typing.Callable | list[~typing.Callable]): + Callable that is called by *attrs*-generated ``__init__`` methods + after the instance has been initialized. They receive the + initialized instance, the :func:`~attrs.Attribute`, and the passed + value. - The return value is *not* inspected so the validator has to throw an - exception itself. + The return value is *not* inspected so the validator has to throw + an exception itself. - If a `list` is passed, its items are treated as validators and must all - pass. + If a `list` is passed, its items are treated as validators and must + all pass. - Validators can be globally disabled and re-enabled using - `attrs.validators.get_disabled` / `attrs.validators.set_disabled`. + Validators can be globally disabled and re-enabled using + `attrs.validators.get_disabled` / `attrs.validators.set_disabled`. - The validator can also be set using decorator notation as shown below. + The validator can also be set using decorator notation as shown + below. - .. seealso:: :ref:`validators` + .. seealso:: :ref:`validators` - :param bool | ~typing.Callable repr: Include this attribute in the - generated ``__repr__`` method. If `True`, include the attribute; if - `False`, omit it. By default, the built-in ``repr()`` function is used. - To override how the attribute value is formatted, pass a ``callable`` - that takes a single value and returns a string. Note that the resulting - string is used as-is, which means it will be used directly *instead* of - calling ``repr()`` (the default). + repr (bool | ~typing.Callable): + Include this attribute in the generated ``__repr__`` method. If + `True`, include the attribute; if `False`, omit it. By default, the + built-in ``repr()`` function is used. To override how the attribute + value is formatted, pass a ``callable`` that takes a single value + and returns a string. Note that the resulting string is used as-is, + which means it will be used directly *instead* of calling + ``repr()`` (the default). - :param bool | ~typing.Callable eq: If `True` (default), include this - attribute in the generated ``__eq__`` and ``__ne__`` methods that check - two instances for equality. To override how the attribute value is - compared, pass a callable that takes a single value and returns the - value to be compared. + eq (bool | ~typing.Callable): + If `True` (default), include this attribute in the generated + ``__eq__`` and ``__ne__`` methods that check two instances for + equality. To override how the attribute value is compared, pass a + callable that takes a single value and returns the value to be + compared. - .. seealso:: `comparison` + .. seealso:: `comparison` - :param bool | ~typing.Callable order: If `True` (default), include this - attributes in the generated ``__lt__``, ``__le__``, ``__gt__`` and - ``__ge__`` methods. To override how the attribute value is ordered, - pass a callable that takes a single value and returns the value to be - ordered. + order (bool | ~typing.Callable): + If `True` (default), include this attributes in the generated + ``__lt__``, ``__le__``, ``__gt__`` and ``__ge__`` methods. To + override how the attribute value is ordered, pass a callable that + takes a single value and returns the value to be ordered. - .. seealso:: `comparison` + .. seealso:: `comparison` - :param cmp: Setting *cmp* is equivalent to setting *eq* and *order* to the - same value. Must not be mixed with *eq* or *order*. + cmp(bool | ~typing.Callable): + Setting *cmp* is equivalent to setting *eq* and *order* to the same + value. Must not be mixed with *eq* or *order*. - .. seealso:: `comparison` - :type cmp: a `bool` or a `callable`. + .. seealso:: `comparison` - :param bool | None hash: Include this attribute in the generated - ``__hash__`` method. If `None` (default), mirror *eq*'s value. This - is the correct behavior according the Python spec. Setting this value - to anything else than `None` is *discouraged*. + hash (bool | None): + Include this attribute in the generated ``__hash__`` method. If + `None` (default), mirror *eq*'s value. This is the correct + behavior according the Python spec. Setting this value to anything + else than `None` is *discouraged*. - .. seealso:: `hashing` - :param bool init: Include this attribute in the generated ``__init__`` - method. It is possible to set this to `False` and set a default value. - In that case this attributed is unconditionally initialized with the - specified default value or factory. + .. seealso:: `hashing` - .. seealso:: `init` - :param typing.Callable converter: `callable` that is called by - *attrs*-generated ``__init__`` methods to convert attribute's value to - the desired format. It is given the passed-in value, and the returned - value will be used as the new value of the attribute. The value is - converted before being passed to the validator, if any. + init (bool): + Include this attribute in the generated ``__init__`` method. It is + possible to set this to `False` and set a default value. In that + case this attributed is unconditionally initialized with the + specified default value or factory. - .. seealso:: :ref:`converters` - :param dict | None metadata: An arbitrary mapping, to be used by - third-party components. See `extending-metadata`. + .. seealso:: `init` - :param type: The type of the attribute. Nowadays, the preferred method to - specify the type is using a variable annotation (see :pep:`526`). This - argument is provided for backward compatibility. Regardless of the - approach used, the type will be stored on ``Attribute.type``. + converter (typing.Callable(): `callable` that is called by + *attrs*-generated ``__init__`` methods to convert attribute's value + to the desired format. It is given the passed-in value, and the + returned value will be used as the new value of the attribute. The + value is converted before being passed to the validator, if any. - Please note that *attrs* doesn't do anything with this metadata by - itself. You can use it as part of your own code or for `static type - checking `. - :param bool kw_only: Make this attribute keyword-only in the generated - ``__init__`` (if ``init`` is `False`, this parameter is ignored). - :param on_setattr: Allows to overwrite the *on_setattr* setting from - `attr.s`. If left `None`, the *on_setattr* value from `attr.s` is used. - Set to `attrs.setters.NO_OP` to run **no** `setattr` hooks for this - attribute -- regardless of the setting in `attr.s`. - :type on_setattr: ~typing.Callable | list[~typing.Callable] | None | - typing.Literal[attrs.setters.NO_OP] - :param str | None alias: Override this attribute's parameter name in the - generated ``__init__`` method. If left `None`, default to ``name`` - stripped of leading underscores. See `private-attributes`. + .. seealso:: :ref:`converters` + + metadata (dict | None): + An arbitrary mapping, to be used by third-party components. + + .. seealso:: `extending-metadata`. + + type (type): + The type of the attribute. Nowadays, the preferred method to + specify the type is using a variable annotation (see :pep:`526`). + This argument is provided for backwards-compatibility and for usage + with `make_class`. Regardless of the approach used, the type will + be stored on ``Attribute.type``. + + Please note that *attrs* doesn't do anything with this metadata by + itself. You can use it as part of your own code or for `static type + checking `. + + kw_only (bool): + Make this attribute keyword-only in the generated ``__init__`` (if + ``init`` is `False`, this parameter is ignored). + + on_setattr (~typing.Callable | list[~typing.Callable] | None | typing.Literal[attrs.setters.NO_OP]): + Allows to overwrite the *on_setattr* setting from `attr.s`. If left + `None`, the *on_setattr* value from `attr.s` is used. Set to + `attrs.setters.NO_OP` to run **no** `setattr` hooks for this + attribute -- regardless of the setting in `attr.s`. + + alias (str | None): + Override this attribute's parameter name in the generated + ``__init__`` method. If left `None`, default to ``name`` stripped + of leading underscores. See `private-attributes`. .. versionadded:: 15.2.0 *convert* .. versionadded:: 16.3.0 *metadata* @@ -239,8 +259,9 @@ def attrib( *hash* is `None` and therefore mirrors *eq* by default. .. versionadded:: 17.3.0 *type* .. deprecated:: 17.4.0 *convert* - .. versionadded:: 17.4.0 *converter* as a replacement for the deprecated - *convert* to achieve consistency with other noun-based arguments. + .. versionadded:: 17.4.0 + *converter* as a replacement for the deprecated *convert* to achieve + consistency with other noun-based arguments. .. versionadded:: 18.1.0 ``factory=f`` is syntactic sugar for ``default=attr.Factory(f)``. .. versionadded:: 18.2.0 *kw_only* @@ -1334,227 +1355,266 @@ def attrs( Consider using `attrs.define` / `attrs.frozen` in new code (``attr.s`` will *never* go away, though). - :param these: A dictionary of name to `attr.ib` mappings. This is useful - to avoid the definition of your attributes within the class body - because you can't (for example, if you want to add ``__repr__`` methods - to Django models) or don't want to. + Args: + these (dict[str, object]): + A dictionary of name to the (private) return value of `attr.ib` + mappings. This is useful to avoid the definition of your attributes + within the class body because you can't (for example, if you want + to add ``__repr__`` methods to Django models) or don't want to. - If *these* is not `None`, *attrs* will *not* search the class body - for attributes and will *not* remove any attributes from it. + If *these* is not `None`, *attrs* will *not* search the class body + for attributes and will *not* remove any attributes from it. - The order is deduced from the order of the attributes inside *these*. + The order is deduced from the order of the attributes inside + *these*. - :type these: `dict` of `str` to `attr.ib` + repr_ns (str): + When using nested classes, there was no way in Python 2 to + automatically detect that. This argument allows to set a custom + name for a more meaningful ``repr`` output. This argument is + pointless in Python 3 and is therefore deprecated. - :param str repr_ns: When using nested classes, there was no way in Python 2 - to automatically detect that. This argument allows to set a custom - name for a more meaningful ``repr`` output. This argument - is pointless in Python 3 and is therefore deprecated. - :param bool auto_detect: Instead of setting the *init*, *repr*, *eq*, - *order*, and *hash* arguments explicitly, assume they are set to - `True` **unless any** of the involved methods for one of the - arguments is implemented in the *current* class (meaning, it is *not* - inherited from some base class). + auto_detect (bool): + Instead of setting the *init*, *repr*, *eq*, *order*, and *hash* + arguments explicitly, assume they are set to `True` **unless any** + of the involved methods for one of the arguments is implemented in + the *current* class (meaning, it is *not* inherited from some base + class). - So, for example by implementing ``__eq__`` on a class yourself, *attrs* - will deduce ``eq=False`` and will create *neither* ``__eq__`` *nor* - ``__ne__`` (but Python classes come with a sensible ``__ne__`` by - default, so it *should* be enough to only implement ``__eq__`` in most - cases). + So, for example by implementing ``__eq__`` on a class yourself, + *attrs* will deduce ``eq=False`` and will create *neither* + ``__eq__`` *nor* ``__ne__`` (but Python classes come with a + sensible ``__ne__`` by default, so it *should* be enough to only + implement ``__eq__`` in most cases). - .. warning:: + .. warning:: - If you prevent *attrs* from creating the ordering methods for you - (``order=False``, for example, by implementing ``__le__``), it - becomes *your* responsibility to make sure its ordering is sound. - The best way is to use the `functools.total_ordering` decorator. + If you prevent *attrs* from creating the ordering methods for + you (``order=False``, for example, by implementing ``__le__``), + it becomes *your* responsibility to make sure its ordering is + sound. The best way is to use the `functools.total_ordering` + decorator. - Passing `True` or `False` to *init*, *repr*, *eq*, *order*, *cmp*, - or *hash* overrides whatever *auto_detect* would determine. + Passing `True` or `False` to *init*, *repr*, *eq*, *order*, *cmp*, + or *hash* overrides whatever *auto_detect* would determine. - :param bool repr: Create a ``__repr__`` method with a human readable - representation of *attrs* attributes.. - :param bool str: Create a ``__str__`` method that is identical to - ``__repr__``. This is usually not necessary except for `Exception`\ s. - :param bool | None eq: If `True` or `None` (default), add ``__eq__`` - and ``__ne__`` methods that check two instances for equality. + repr(bool): + Create a ``__repr__`` method with a human readable representation + of *attrs* attributes.. - They compare the instances as if they were tuples of their *attrs* - attributes if and only if the types of both classes are *identical*! + str (bool): + Create a ``__str__`` method that is identical to ``__repr__``. This + is usually not necessary except for `Exception`\ s. - .. seealso:: `comparison` - :param bool | None order: If `True`, add ``__lt__``, ``__le__``, - ``__gt__``, and ``__ge__`` methods that behave like *eq* above and - allow instances to be ordered. If `None` (default) mirror value of - *eq*. + eq (bool | None): + If `True` or `None` (default), add ``__eq__`` and ``__ne__`` + methods that check two instances for equality. - .. seealso:: `comparison` - :param bool | None cmp: Setting *cmp* is equivalent to setting *eq* and - *order* to the same value. Must not be mixed with *eq* or *order*. + They compare the instances as if they were tuples of their *attrs* + attributes if and only if the types of both classes are + *identical*! - .. seealso:: `comparison` - :param bool | None unsafe_hash: If `None` (default), the ``__hash__`` - method is generated according how *eq* and *frozen* are set. + .. seealso:: `comparison` - 1. If *both* are True, *attrs* will generate a ``__hash__`` for you. - 2. If *eq* is True and *frozen* is False, ``__hash__`` will be set to - None, marking it unhashable (which it is). - 3. If *eq* is False, ``__hash__`` will be left untouched meaning the - ``__hash__`` method of the base class will be used (if base class is - ``object``, this means it will fall back to id-based hashing.). + order (bool | None): + If `True`, add ``__lt__``, ``__le__``, ``__gt__``, and ``__ge__`` + methods that behave like *eq* above and allow instances to be + ordered. If `None` (default) mirror value of *eq*. - Although not recommended, you can decide for yourself and force *attrs* - to create one (for example, if the class is immutable even though you - didn't freeze it programmatically) by passing `True` or not. Both of - these cases are rather special and should be used carefully. + .. seealso:: `comparison` - .. seealso:: + cmp (bool | None): + Setting *cmp* is equivalent to setting *eq* and *order* to the same + value. Must not be mixed with *eq* or *order*. - - Our documentation on `hashing`, - - Python's documentation on `object.__hash__`, - - and the `GitHub issue that led to the default \ behavior - `_ for more - details. + .. seealso:: `comparison` - :param bool | None hash: Alias for *unsafe_hash*. *unsafe_hash* takes - precedence. - :param bool init: Create a ``__init__`` method that initializes the *attrs* - attributes. Leading underscores are stripped for the argument name - (unless an alias is set on the attribute). If a ``__attrs_pre_init__`` - method exists on the class, it will be called before the class is - initialized. If a ``__attrs_post_init__`` method exists on the class, - it will be called after the class is fully initialized. + unsafe_hash (bool | None): + If `None` (default), the ``__hash__`` method is generated according + how *eq* and *frozen* are set. - If ``init`` is `False`, an ``__attrs_init__`` method will be injected - instead. This allows you to define a custom ``__init__`` method that - can do pre-init work such as ``super().__init__()``, and then call - ``__attrs_init__()`` and ``__attrs_post_init__()``. + 1. If *both* are True, *attrs* will generate a ``__hash__`` for + you. + 2. If *eq* is True and *frozen* is False, ``__hash__`` will be set + to None, marking it unhashable (which it is). + 3. If *eq* is False, ``__hash__`` will be left untouched meaning + the ``__hash__`` method of the base class will be used (if base + class is ``object``, this means it will fall back to id-based + hashing.). - .. seealso:: `init` - :param bool slots: Create a :term:`slotted class ` that's - more memory-efficient. Slotted classes are generally superior to the - default dict classes, but have some gotchas you should know about, so - we encourage you to read the :term:`glossary entry `. - :param bool frozen: Make instances immutable after initialization. If - someone attempts to modify a frozen instance, - `attrs.exceptions.FrozenInstanceError` is raised. + Although not recommended, you can decide for yourself and force + *attrs* to create one (for example, if the class is immutable even + though you didn't freeze it programmatically) by passing `True` or + not. Both of these cases are rather special and should be used + carefully. - .. note:: + .. seealso:: - 1. This is achieved by installing a custom ``__setattr__`` method - on your class, so you can't implement your own. + - Our documentation on `hashing`, + - Python's documentation on `object.__hash__`, + - and the `GitHub issue that led to the default \ behavior + `_ for more + details. - 2. True immutability is impossible in Python. + hash (bool | None): + Alias for *unsafe_hash*. *unsafe_hash* takes precedence. - 3. This *does* have a minor a runtime performance `impact - ` when initializing new instances. In other words: - ``__init__`` is slightly slower with ``frozen=True``. + init (bool): + Create a ``__init__`` method that initializes the *attrs* + attributes. Leading underscores are stripped for the argument name + (unless an alias is set on the attribute). If a + ``__attrs_pre_init__`` method exists on the class, it will be + called before the class is initialized. If a + ``__attrs_post_init__`` method exists on the class, it will be + called after the class is fully initialized. - 4. If a class is frozen, you cannot modify ``self`` in - ``__attrs_post_init__`` or a self-written ``__init__``. You can - circumvent that limitation by using ``object.__setattr__(self, - "attribute_name", value)``. + If ``init`` is `False`, an ``__attrs_init__`` method will be + injected instead. This allows you to define a custom ``__init__`` + method that can do pre-init work such as ``super().__init__()``, + and then call ``__attrs_init__()`` and ``__attrs_post_init__()``. - 5. Subclasses of a frozen class are frozen too. + .. seealso:: `init` - :param bool weakref_slot: Make instances weak-referenceable. This has no - effect unless ``slots`` is also enabled. - :param bool auto_attribs: If `True`, collect :pep:`526`-annotated - attributes from the class body. + slots (bool): + Create a :term:`slotted class ` that's more + memory-efficient. Slotted classes are generally superior to the + default dict classes, but have some gotchas you should know about, + so we encourage you to read the :term:`glossary entry `. - In this case, you **must** annotate every field. If *attrs* encounters - a field that is set to an `attr.ib` but lacks a type annotation, an - `attrs.exceptions.UnannotatedAttributeError` is raised. Use - ``field_name: typing.Any = attr.ib(...)`` if you don't want to set a - type. + frozen (bool): + Make instances immutable after initialization. If someone attempts + to modify a frozen instance, `attrs.exceptions.FrozenInstanceError` + is raised. - If you assign a value to those attributes (for example, ``x: int = - 42``), that value becomes the default value like if it were passed - using ``attr.ib(default=42)``. Passing an instance of `attrs.Factory` - also works as expected in most cases (see warning below). + .. note:: - Attributes annotated as `typing.ClassVar`, and attributes that are - neither annotated nor set to an `attr.ib` are **ignored**. + 1. This is achieved by installing a custom ``__setattr__`` + method on your class, so you can't implement your own. - .. warning:: + 2. True immutability is impossible in Python. - For features that use the attribute name to create decorators (for - example, :ref:`validators `), you still *must* assign - `attr.ib` to them. Otherwise Python will either not find the name or - try to use the default value to call, for example, ``validator`` on - it. + 3. This *does* have a minor a runtime performance `impact + ` when initializing new instances. In other + words: ``__init__`` is slightly slower with ``frozen=True``. - :param bool kw_only: Make all attributes keyword-only in the generated - ``__init__`` (if *init* is `False`, this parameter is ignored). - :param bool cache_hash: Ensure that the object's hash code is computed only - once and stored on the object. If this is set to `True`, hashing - must be either explicitly or implicitly enabled for this class. If the - hash code is cached, avoid any reassignments of fields involved in hash - code computation or mutations of the objects those fields point to - after object creation. If such changes occur, the behavior of the - object's hash code is undefined. - :param bool auto_exc: If the class subclasses `BaseException` (which - implicitly includes any subclass of any exception), the following - happens to behave like a well-behaved Python exceptions class: + 4. If a class is frozen, you cannot modify ``self`` in + ``__attrs_post_init__`` or a self-written ``__init__``. You + can circumvent that limitation by using + ``object.__setattr__(self, "attribute_name", value)``. - - the values for *eq*, *order*, and *hash* are ignored and the - instances compare and hash by the instance's ids (N.B. *attrs* will - *not* remove existing implementations of ``__hash__`` or the equality - methods. It just won't add own ones.), - - all attributes that are either passed into ``__init__`` or have a - default value are additionally available as a tuple in the ``args`` - attribute, - - the value of *str* is ignored leaving ``__str__`` to base classes. - :param bool collect_by_mro: Setting this to `True` fixes the way *attrs* - collects attributes from base classes. The default behavior is - incorrect in certain cases of multiple inheritance. It should be on by - default, but is kept off for backwards-compatibility. + 5. Subclasses of a frozen class are frozen too. - .. seealso:: - Issue `#428 `_ + weakref_slot (bool): + Make instances weak-referenceable. This has no effect unless + ``slots`` is also enabled. - :param bool | None getstate_setstate: - .. note:: - This is usually only interesting for slotted classes and you should - probably just set *auto_detect* to `True`. + auto_attribs (bool): + If `True`, collect :pep:`526`-annotated attributes from the class + body. - If `True`, ``__getstate__`` and ``__setstate__`` are generated and - attached to the class. This is necessary for slotted classes to be - pickleable. If left `None`, it's `True` by default for slotted classes - and `False` for dict classes. + In this case, you **must** annotate every field. If *attrs* + encounters a field that is set to an `attr.ib` but lacks a type + annotation, an `attrs.exceptions.UnannotatedAttributeError` is + raised. Use ``field_name: typing.Any = attr.ib(...)`` if you don't + want to set a type. - If *auto_detect* is `True`, and *getstate_setstate* is left `None`, and - **either** ``__getstate__`` or ``__setstate__`` is detected directly on - the class (meaning: not inherited), it is set to `False` (this is - usually what you want). + If you assign a value to those attributes (for example, ``x: int = + 42``), that value becomes the default value like if it were passed + using ``attr.ib(default=42)``. Passing an instance of + `attrs.Factory` also works as expected in most cases (see warning + below). - :param on_setattr: A callable that is run whenever the user attempts to set - an attribute (either by assignment like ``i.x = 42`` or by using - `setattr` like ``setattr(i, "x", 42)``). It receives the same arguments - as validators: the instance, the attribute that is being modified, and - the new value. + Attributes annotated as `typing.ClassVar`, and attributes that are + neither annotated nor set to an `attr.ib` are **ignored**. - If no exception is raised, the attribute is set to the return value of - the callable. + .. warning:: - If a list of callables is passed, they're automatically wrapped in an - `attrs.setters.pipe`. - :type on_setattr: ~typing.Callable | list[~typing.Callable] | None | - typing.Literal[attrs.setters.NO_OP] + For features that use the attribute name to create decorators + (for example, :ref:`validators `), you still *must* + assign `attr.ib` to them. Otherwise Python will either not find + the name or try to use the default value to call, for example, + ``validator`` on it. - :param ~typing.Callable | None field_transformer: - A function that is called with the original class object and all fields - right before *attrs* finalizes the class. You can use this, for - example, to automatically add converters or validators to fields based - on their types. + kw_only (bool): + Make all attributes keyword-only in the generated ``__init__`` (if + *init* is `False`, this parameter is ignored). - .. seealso:: `transform-fields` + cache_hash (bool): + Ensure that the object's hash code is computed only once and stored + on the object. If this is set to `True`, hashing must be either + explicitly or implicitly enabled for this class. If the hash code + is cached, avoid any reassignments of fields involved in hash code + computation or mutations of the objects those fields point to after + object creation. If such changes occur, the behavior of the + object's hash code is undefined. - :param bool match_args: - If `True` (default), set ``__match_args__`` on the class to support - :pep:`634` (*Structural Pattern Matching*). It is a tuple of all - non-keyword-only ``__init__`` parameter names on Python 3.10 and later. - Ignored on older Python versions. + auto_exc (bool): + If the class subclasses `BaseException` (which implicitly includes + any subclass of any exception), the following happens to behave + like a well-behaved Python exceptions class: + + - the values for *eq*, *order*, and *hash* are ignored and the + instances compare and hash by the instance's ids (N.B. *attrs* + will *not* remove existing implementations of ``__hash__`` or the + equality methods. It just won't add own ones.), + - all attributes that are either passed into ``__init__`` or have a + default value are additionally available as a tuple in the + ``args`` attribute, + - the value of *str* is ignored leaving ``__str__`` to base + classes. + + collect_by_mro (bool): + Setting this to `True` fixes the way *attrs* collects attributes + from base classes. The default behavior is incorrect in certain + cases of multiple inheritance. It should be on by default, but is + kept off for backwards-compatibility. + + .. seealso:: + Issue `#428 `_ + + getstate_setstate (bool | None): + .. note:: + + This is usually only interesting for slotted classes and you + should probably just set *auto_detect* to `True`. + + If `True`, ``__getstate__`` and ``__setstate__`` are generated and + attached to the class. This is necessary for slotted classes to be + pickleable. If left `None`, it's `True` by default for slotted + classes and `False` for dict classes. + + If *auto_detect* is `True`, and *getstate_setstate* is left `None`, + and **either** ``__getstate__`` or ``__setstate__`` is detected + directly on the class (meaning: not inherited), it is set to + `False` (this is usually what you want). + + on_setattr (~typing.Callable | list[~typing.Callable] | None | typing.Literal[attrs.setters.NO_OP]): + A callable that is run whenever the user attempts to set an + attribute (either by assignment like ``i.x = 42`` or by using + `setattr` like ``setattr(i, "x", 42)``). It receives the same + arguments as validators: the instance, the attribute that is being + modified, and the new value. + + If no exception is raised, the attribute is set to the return value + of the callable. + + If a list of callables is passed, they're automatically wrapped in + an `attrs.setters.pipe`. + + field_transformer (~typing.Callable | None): + A function that is called with the original class object and all + fields right before *attrs* finalizes the class. You can use this, + for example, to automatically add converters or validators to + fields based on their types. + + .. seealso:: `transform-fields` + + match_args (bool): + If `True` (default), set ``__match_args__`` on the class to support + :pep:`634` (*Structural Pattern Matching*). It is a tuple of all + non-keyword-only ``__init__`` parameter names on Python 3.10 and + later. Ignored on older Python versions. .. versionadded:: 16.0.0 *slots* .. versionadded:: 16.1.0 *frozen* @@ -2030,13 +2090,17 @@ def fields(cls): The tuple also allows accessing the fields by their names (see below for examples). - :param type cls: Class to introspect. + Args: + cls (type): Class to introspect. - :raise TypeError: If *cls* is not a class. - :raise attrs.exceptions.NotAnAttrsClassError: If *cls* is not an *attrs* - class. + Raises: + TypeError: If *cls* is not a class. - :rtype: tuple (with name accessors) of `attrs.Attribute` + attrs.exceptions.NotAnAttrsClassError: + If *cls* is not an *attrs* class. + + Returns: + tuple (with name accessors) of `attrs.Attribute` .. versionchanged:: 16.2.0 Returned tuple allows accessing the fields by name. @@ -2067,16 +2131,20 @@ def fields(cls): def fields_dict(cls): """ - Return an ordered dictionary of *attrs* attributes for a class, whose - keys are the attribute names. + Return an ordered dictionary of *attrs* attributes for a class, whose keys + are the attribute names. - :param type cls: Class to introspect. + Args: + cls (type): Class to introspect. - :raise TypeError: If *cls* is not a class. - :raise attrs.exceptions.NotAnAttrsClassError: If *cls* is not an *attrs* - class. + Raises: + TypeError: If *cls* is not a class. - :rtype: dict + attrs.exceptions.NotAnAttrsClassError: + If *cls* is not an *attrs* class. + + Returns: + dict[str, attrs.Attribute]: Dict of attribute name to definition .. versionadded:: 18.1.0 """ @@ -2096,7 +2164,8 @@ def validate(inst): Leaves all exceptions through. - :param inst: Instance of a class with *attrs* attributes. + Args: + inst: Instance of a class with *attrs* attributes. """ if _config._run_validators is False: return @@ -2913,7 +2982,8 @@ class _CountingAttr: Returns *meth* unchanged. - :raises DefaultAlreadySetError: If default has been set before. + Raises: + DefaultAlreadySetError: If default has been set before. .. versionadded:: 17.1.0 """ @@ -2935,10 +3005,14 @@ class Factory: If passed as the default value to `attrs.field`, the factory is used to generate a new value. - :param typing.Callable factory: A callable that takes either none or - exactly one mandatory positional argument depending on *takes_self*. - :param bool takes_self: Pass the partially initialized instance that is - being initialized as a positional argument. + Args: + factory (typing.Callable): + A callable that takes either none or exactly one mandatory + positional argument depending on *takes_self*. + + takes_self (bool): + Pass the partially initialized instance that is being initialized + as a positional argument. .. versionadded:: 17.1.0 *takes_self* """ @@ -2988,24 +3062,26 @@ def make_class( r""" A quick way to create a new class called *name* with *attrs*. - :param str name: The name for the new class. + Args: + name (str): The name for the new class. - :param list | dict attrs: A list of names or a dictionary of mappings of - names to `attr.ib`\ s / `attrs.field`\ s. + attrs( list | dict): + A list of names or a dictionary of mappings of names to `attr.ib`\ + s / `attrs.field`\ s. - The order is deduced from the order of the names or attributes inside - *attrs*. Otherwise the order of the definition of the attributes is - used. + The order is deduced from the order of the names or attributes + inside *attrs*. Otherwise the order of the definition of the + attributes is used. - :param tuple bases: Classes that the new class will subclass. + bases (tuple[type, ...]): Classes that the new class will subclass. - :param dict class_body: An optional dictionary of class attributes for the - new class. + class_body (dict): + An optional dictionary of class attributes for the new class. - :param attributes_arguments: Passed unmodified to `attr.s`. + attributes_arguments: Passed unmodified to `attr.s`. - :return: A new class with *attrs*. - :rtype: type + Returns: + type: A new class with *attrs*. .. versionadded:: 17.1.0 *bases* .. versionchanged:: 18.1.0 If *attrs* is ordered, the order is retained. @@ -3087,8 +3163,9 @@ def and_(*validators): When called on a value, it runs all wrapped validators. - :param ~collections.abc.Iterable[typing.Callable] validators: Arbitrary - number of validators. + Args: + validators (~collections.abc.Iterable[typing.Callable]): + Arbitrary number of validators. .. versionadded:: 17.1.0 """ @@ -3113,8 +3190,8 @@ def pipe(*converters): Type annotations will be inferred from the wrapped converters', if they have any. - :param ~collections.abc.Iterable[typing.Callable] converters: Arbitrary - number of converters. + converters (~collections.abc.Iterable[typing.Callable]): + Arbitrary number of converters. .. versionadded:: 20.1.0 """ diff --git a/src/attr/_next_gen.py b/src/attr/_next_gen.py index 07db702d..10e05695 100644 --- a/src/attr/_next_gen.py +++ b/src/attr/_next_gen.py @@ -70,13 +70,15 @@ def define( Please note that these are all defaults and you can change them as you wish. - :param bool | None auto_attribs: If set to `True` or `False`, it behaves - exactly like `attr.s`. If left `None`, `attr.s` will try to guess: + Args: + auto_attribs (bool | None): + If set to `True` or `False`, it behaves exactly like `attr.s`. If + left `None`, `attr.s` will try to guess: - 1. If any attributes are annotated and no unannotated `attrs.fields`\ s - are found, it assumes *auto_attribs=True*. - 2. Otherwise it assumes *auto_attribs=False* and tries to collect - `attrs.fields`\ s. + 1. If any attributes are annotated and no unannotated + `attrs.fields`\ s are found, it assumes *auto_attribs=True*. + 2. Otherwise it assumes *auto_attribs=False* and tries to collect + `attrs.fields`\ s. For now, please refer to `attr.s` for the rest of the parameters. diff --git a/src/attr/converters.py b/src/attr/converters.py index cf1fa0f7..92383110 100644 --- a/src/attr/converters.py +++ b/src/attr/converters.py @@ -27,8 +27,9 @@ def optional(converter): Type annotations will be inferred from the wrapped converter's, if it has any. - :param typing.Callable converter: the converter that is used for non-`None` - values. + Args: + converter (typing.Callable): + the converter that is used for non-`None` values. .. versionadded:: 17.1.0 """ @@ -56,16 +57,24 @@ def default_if_none(default=NOTHING, factory=None): A converter that allows to replace `None` values by *default* or the result of *factory*. - :param default: Value to be used if `None` is passed. Passing an instance - of `attrs.Factory` is supported, however the ``takes_self`` option is - *not*. - :param typing.Callable factory: A callable that takes no parameters whose - result is used if `None` is passed. + Args: + default: + Value to be used if `None` is passed. Passing an instance of + `attrs.Factory` is supported, however the ``takes_self`` option is + *not*. - :raises TypeError: If **neither** *default* or *factory* is passed. - :raises TypeError: If **both** *default* and *factory* are passed. - :raises ValueError: If an instance of `attrs.Factory` is passed with - ``takes_self=True``. + factory (typing.Callable): + A callable that takes no parameters whose result is used if `None` + is passed. + + Raises: + TypeError: If **neither** *default* or *factory* is passed. + + TypeError: If **both** *default* and *factory* are passed. + + ValueError: + If an instance of `attrs.Factory` is passed with + ``takes_self=True``. .. versionadded:: 18.2.0 """ @@ -125,7 +134,8 @@ def to_bool(val): - ``"0"`` - ``0`` - :raises ValueError: for any other value. + Raises: + ValueError: For any other value. .. versionadded:: 21.3.0 """ diff --git a/src/attr/filters.py b/src/attr/filters.py index a1e40c98..5b373785 100644 --- a/src/attr/filters.py +++ b/src/attr/filters.py @@ -1,7 +1,7 @@ # SPDX-License-Identifier: MIT """ -Commonly useful filters for `attr.asdict`. +Commonly useful filters for `attrs.asdict` and `attrs.astuple`. """ from ._make import Attribute @@ -20,13 +20,16 @@ def _split_what(what): def include(*what): """ - Include *what*. + Create a filter that only allows *what*. - :param what: What to include. - :type what: `list` of classes `type`, field names `str` or - `attrs.Attribute`\\ s + Args: + what (list[type, str, attrs.Attribute]): + What to include. Can be a type, a name, or an attribute. - :rtype: `callable` + Returns: + Callable: + A callable that can be passed to `attrs.asdict`'s and + `attrs.astuple`'s *filter* argument. .. versionchanged:: 23.1.0 Accept strings with field names. """ @@ -44,13 +47,16 @@ def include(*what): def exclude(*what): """ - Exclude *what*. + Create a filters that does **not** allow *what*. - :param what: What to exclude. - :type what: `list` of classes `type`, field names `str` or - `attrs.Attribute`\\ s. + Args: + what (list[type, str, attrs.Attribute]): + What to exclude. Can be a type, a name, or an attribute. - :rtype: `callable` + Returns: + Callable: + A callable that can be passed to `attrs.asdict`'s and + `attrs.astuple`'s *filter* argument. .. versionchanged:: 23.3.0 Accept field name string as input argument """ diff --git a/src/attr/validators.py b/src/attr/validators.py index 47f234de..54607f01 100644 --- a/src/attr/validators.py +++ b/src/attr/validators.py @@ -46,8 +46,8 @@ def set_disabled(disabled): By default, they are run. - :param disabled: If `True`, disable running all validators. - :type disabled: bool + Args: + disabled (bool): If `True`, disable running all validators. .. warning:: @@ -62,8 +62,8 @@ def get_disabled(): """ Return a bool indicating whether validators are currently disabled or not. - :return: `True` if validators are currently disabled. - :rtype: bool + Returns: + bool:`True` if validators are currently disabled. .. versionadded:: 21.3.0 """ @@ -115,10 +115,13 @@ def instance_of(type): wrong type for this particular attribute (checks are performed using `isinstance` therefore it's also valid to pass a tuple of types). - :param type | tuple[type] type: The type to check for. + Args: + type (type | tuple[type]): The type to check for. - :raises TypeError: With a human readable error message, the attribute (of - type `attrs.Attribute`), the expected type, and the value it got. + Raises: + TypeError: + With a human readable error message, the attribute (of type + `attrs.Attribute`), the expected type, and the value it got. """ return _InstanceOfValidator(type) @@ -150,13 +153,18 @@ def matches_re(regex, flags=0, func=None): A validator that raises `ValueError` if the initializer is called with a string that doesn't match *regex*. - :param regex: a regex string or precompiled pattern to match against - :param int flags: flags that will be passed to the underlying re function - (default 0) - :param typing.Callable func: which underlying `re` function to call. Valid - options are `re.fullmatch`, `re.search`, and `re.match`; the default - `None` means `re.fullmatch`. For performance reasons, the pattern is - always precompiled using `re.compile`. + Args: + regex (str, re.Pattern): + A regex string or precompiled pattern to match against + + flags (int): + Flags that will be passed to the underlying re function (default 0) + + func (typing.Callable): + Which underlying `re` function to call. Valid options are + `re.fullmatch`, `re.search`, and `re.match`; the default `None` + means `re.fullmatch`. For performance reasons, the pattern is + always precompiled using `re.compile`. .. versionadded:: 19.2.0 .. versionchanged:: 21.3.0 *regex* can be a pre-compiled pattern. @@ -208,10 +216,10 @@ def optional(validator): which can be set to `None` in addition to satisfying the requirements of the sub-validator. - :param validator: A validator (or validators) that is used for non-`None` - values. - :type validator: typing.Callable | tuple[typing.Callable] | - list[typing.Callable] + Args: + validator + (typing.Callable | tuple[typing.Callable] | list[typing.Callable]): + A validator (or validators) that is used for non-`None` values. .. versionadded:: 15.1.0 .. versionchanged:: 17.1.0 *validator* can be a list of validators. @@ -248,16 +256,17 @@ class _InValidator: def in_(options): """ - A validator that raises a `ValueError` if the initializer is called - with a value that does not belong in the options provided. The check is - performed using ``value in options``. + A validator that raises a `ValueError` if the initializer is called with a + value that does not belong in the options provided. The check is performed + using ``value in options``, so *options* has to support that operation. - :param options: Allowed options. - :type options: list, tuple, `enum.Enum`, ... + Args: + options: Allowed options. - :raises ValueError: With a human readable error message, the attribute (of - type `attrs.Attribute`), the expected options, and the value it - got. + Raises: + ValueError: + With a human readable error message, the attribute (of type + `attrs.Attribute`), the expected options, and the value it got. .. versionadded:: 17.1.0 .. versionchanged:: 22.1.0 @@ -293,14 +302,15 @@ class _IsCallableValidator: def is_callable(): """ A validator that raises a `attrs.exceptions.NotCallableError` if the - initializer is called with a value for this particular attribute - that is not callable. + initializer is called with a value for this particular attribute that is + not callable. .. versionadded:: 19.1.0 - :raises attrs.exceptions.NotCallableError: With a human readable error - message containing the attribute (`attrs.Attribute`) name, - and the value it got. + Raises: + attrs.exceptions.NotCallableError: + With a human readable error message containing the attribute + (`attrs.Attribute`) name, and the value it got. """ return _IsCallableValidator() @@ -338,13 +348,16 @@ def deep_iterable(member_validator, iterable_validator=None): """ A validator that performs deep validation of an iterable. - :param member_validator: Validator(s) to apply to iterable members - :param iterable_validator: Validator to apply to iterable itself - (optional) + Args: + member_validator: Validator to apply to iterable members. + + iterable_validator: + Validator to apply to iterable itself (optional). + + Raises + TypeError: if any sub-validators fail .. versionadded:: 19.1.0 - - :raises TypeError: if any sub-validators fail """ if isinstance(member_validator, (list, tuple)): member_validator = and_(*member_validator) @@ -376,14 +389,18 @@ def deep_mapping(key_validator, value_validator, mapping_validator=None): """ A validator that performs deep validation of a dictionary. - :param key_validator: Validator to apply to dictionary keys - :param value_validator: Validator to apply to dictionary values - :param mapping_validator: Validator to apply to top-level mapping - attribute (optional) + Args: + key_validator: Validator to apply to dictionary keys. + + value_validator: Validator to apply to dictionary values. + + mapping_validator: + Validator to apply to top-level mapping attribute (optional). .. versionadded:: 19.1.0 - :raises TypeError: if any sub-validators fail + Raises: + TypeError: if any sub-validators fail """ return _DeepMapping(key_validator, value_validator, mapping_validator) @@ -408,10 +425,13 @@ class _NumberValidator: def lt(val): """ - A validator that raises `ValueError` if the initializer is called - with a number larger or equal to *val*. + A validator that raises `ValueError` if the initializer is called with a + number larger or equal to *val*. - :param val: Exclusive upper bound for values + The validator uses `operator.lt` to compare the values. + + Args: + val: Exclusive upper bound for values. .. versionadded:: 21.3.0 """ @@ -420,10 +440,13 @@ def lt(val): def le(val): """ - A validator that raises `ValueError` if the initializer is called - with a number greater than *val*. + A validator that raises `ValueError` if the initializer is called with a + number greater than *val*. - :param val: Inclusive upper bound for values + The validator uses `operator.le` to compare the values. + + Args: + val: Inclusive upper bound for values. .. versionadded:: 21.3.0 """ @@ -432,10 +455,13 @@ def le(val): def ge(val): """ - A validator that raises `ValueError` if the initializer is called - with a number smaller than *val*. + A validator that raises `ValueError` if the initializer is called with a + number smaller than *val*. - :param val: Inclusive lower bound for values + The validator uses `operator.ge` to compare the values. + + Args: + val: Inclusive lower bound for values .. versionadded:: 21.3.0 """ @@ -444,10 +470,13 @@ def ge(val): def gt(val): """ - A validator that raises `ValueError` if the initializer is called - with a number smaller or equal to *val*. + A validator that raises `ValueError` if the initializer is called with a + number smaller or equal to *val*. - :param val: Exclusive lower bound for values + The validator uses `operator.ge` to compare the values. + + Args: + val: Exclusive lower bound for values .. versionadded:: 21.3.0 """ @@ -475,7 +504,8 @@ def max_len(length): A validator that raises `ValueError` if the initializer is called with a string or iterable that is longer than *length*. - :param int length: Maximum length of the string or iterable + Args: + length (int): Maximum length of the string or iterable .. versionadded:: 21.3.0 """ @@ -503,7 +533,8 @@ def min_len(length): A validator that raises `ValueError` if the initializer is called with a string or iterable that is shorter than *length*. - :param int length: Minimum length of the string or iterable + Args: + length (int): Minimum length of the string or iterable .. versionadded:: 22.1.0 """ @@ -533,16 +564,17 @@ class _SubclassOfValidator: def _subclass_of(type): """ - A validator that raises a `TypeError` if the initializer is called - with a wrong type for this particular attribute (checks are performed using + A validator that raises a `TypeError` if the initializer is called with a + wrong type for this particular attribute (checks are performed using `issubclass` therefore it's also valid to pass a tuple of types). - :param type: The type to check for. - :type type: type or tuple of types + Args: + type (type | tuple[type, ...]): The type(s) to check for. - :raises TypeError: With a human readable error message, the attribute - (of type `attrs.Attribute`), the expected type, and the value it - got. + Raises: + TypeError: + With a human readable error message, the attribute (of type + `attrs.Attribute`), the expected type, and the value it got. """ return _SubclassOfValidator(type) @@ -594,19 +626,22 @@ def not_(validator, *, msg=None, exc_types=(ValueError, TypeError)): Intended to be used with existing validators to compose logic without needing to create inverted variants, for example, ``not_(in_(...))``. - :param validator: A validator to be logically inverted. - :param msg: Message to raise if validator fails. - Formatted with keys ``exc_types`` and ``validator``. - :type msg: str - :param exc_types: Exception type(s) to capture. - Other types raised by child validators will not be intercepted and - pass through. + Args: + validator: A validator to be logically inverted. - :raises ValueError: With a human readable error message, - the attribute (of type `attrs.Attribute`), - the validator that failed to raise an exception, - the value it got, - and the expected exception types. + msg (str): + Message to raise if validator fails. Formatted with keys + ``exc_types`` and ``validator``. + + exc_types (tuple[type, ...]): + Exception type(s) to capture. Other types raised by child + validators will not be intercepted and pass through. + + Raises: + ValueError: + With a human readable error message, the attribute (of type + `attrs.Attribute`), the validator that failed to raise an + exception, the value it got, and the expected exception types. .. versionadded:: 22.2.0 """ @@ -641,15 +676,18 @@ def or_(*validators): """ A validator that composes multiple validators into one. - When called on a value, it runs all wrapped validators until one of them - is satisfied. + When called on a value, it runs all wrapped validators until one of them is + satisfied. - :param ~collections.abc.Iterable[typing.Callable] validators: Arbitrary - number of validators. + Args: + validators (~collections.abc.Iterable[typing.Callable]): + Arbitrary number of validators. - :raises ValueError: If no validator is satisfied. Raised with a - human-readable error message listing all the wrapped validators and - the value that failed all of them. + Raises: + ValueError: + If no validator is satisfied. Raised with a human-readable error + message listing all the wrapped validators and the value that + failed all of them. .. versionadded:: 24.1.0 """