From 05e930c36f5e16fe579c7b49ca1667821d9ffd1e Mon Sep 17 00:00:00 2001 From: Hynek Schlawack Date: Tue, 21 Jul 2020 14:43:09 +0200 Subject: [PATCH] Rename converters.chain to converters.pipe Consistent with setters.pipe and conveys better that it acts like a UNIX pipe. Signed-off-by: Hynek Schlawack --- changelog.d/618.change.rst | 4 ++-- docs/api.rst | 4 ++-- src/attr/_make.py | 12 +++++++----- src/attr/converters.py | 4 ++-- src/attr/converters.pyi | 2 +- tests/test_converters.py | 12 ++++++------ 6 files changed, 20 insertions(+), 18 deletions(-) diff --git a/changelog.d/618.change.rst b/changelog.d/618.change.rst index cbea0888..8bd542c5 100644 --- a/changelog.d/618.change.rst +++ b/changelog.d/618.change.rst @@ -1,4 +1,4 @@ -Added ``attr.converters.chain()``. -The feature allows combining multiple conversion callbacks into one. +Added ``attr.converters.pipe()``. +The feature allows combining multiple conversion callbacks into one by piping the value through all of them, and retuning the last result. As part of this feature, we had to relax the type information for converter callables. diff --git a/docs/api.rst b/docs/api.rst index 5313d381..0f888330 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -481,13 +481,13 @@ Validators Converters ---------- -.. autofunction:: attr.converters.chain +.. autofunction:: attr.converters.pipe For convenience, it's also possible to pass a list to `attr.ib`'s converter argument. Thus the following two statements are equivalent:: - x = attr.ib(converter=attr.converter.chain(c1, c2, c3)) + x = attr.ib(converter=attr.converter.pipe(c1, c2, c3)) x = attr.ib(converter=[c1, c2, c3]) .. autofunction:: attr.converters.optional diff --git a/src/attr/_make.py b/src/attr/_make.py index a9851cd7..68cdf43a 100644 --- a/src/attr/_make.py +++ b/src/attr/_make.py @@ -254,7 +254,7 @@ def attrib( validator = and_(*validator) if converter and isinstance(converter, (list, tuple)): - converter = chain(*converter) + converter = pipe(*converter) return _CountingAttr( default=default, @@ -2579,11 +2579,12 @@ def and_(*validators): return _AndValidator(tuple(vals)) -def chain(*converters): +def pipe(*converters): """ A converter that composes multiple converters into one. - When called on a value, it runs all wrapped converters. + When called on a value, it runs all wrapped converters, returning the + *last* value. :param converters: Arbitrary number of converters. :type converters: callables @@ -2591,9 +2592,10 @@ def chain(*converters): .. versionadded:: 20.1.0 """ - def chain_converter(val): + def pipe_converter(val): for converter in converters: val = converter(val) + return val - return chain_converter + return pipe_converter diff --git a/src/attr/converters.py b/src/attr/converters.py index 11599ee9..715ce178 100644 --- a/src/attr/converters.py +++ b/src/attr/converters.py @@ -4,11 +4,11 @@ Commonly useful converters. from __future__ import absolute_import, division, print_function -from ._make import NOTHING, Factory, chain +from ._make import NOTHING, Factory, pipe __all__ = [ - "chain", + "pipe", "optional", "default_if_none", ] diff --git a/src/attr/converters.pyi b/src/attr/converters.pyi index 2bf4cf74..7b0caa14 100644 --- a/src/attr/converters.pyi +++ b/src/attr/converters.pyi @@ -3,7 +3,7 @@ from . import _ConverterType _T = TypeVar("_T") -def chain(*validators: _ConverterType) -> _ConverterType: ... +def pipe(*validators: _ConverterType) -> _ConverterType: ... def optional(converter: _ConverterType) -> _ConverterType: ... @overload def default_if_none(default: _T) -> _ConverterType: ... diff --git a/tests/test_converters.py b/tests/test_converters.py index b27a41af..f86e07e2 100644 --- a/tests/test_converters.py +++ b/tests/test_converters.py @@ -11,7 +11,7 @@ import pytest import attr from attr import Factory, attrib -from attr.converters import chain, default_if_none, optional +from attr.converters import default_if_none, optional, pipe class TestOptional(object): @@ -101,12 +101,12 @@ class TestDefaultIfNone(object): assert [] == c(None) -class TestChain(object): +class TestPipe(object): def test_success(self): """ Succeeds if all wrapped converters succeed. """ - c = chain(str, strtobool, bool) + c = pipe(str, strtobool, bool) assert True is c("True") is c(True) @@ -114,7 +114,7 @@ class TestChain(object): """ Fails if any wrapped converter fails. """ - c = chain(str, strtobool) + c = pipe(str, strtobool) # First wrapped converter fails: with pytest.raises(ValueError): @@ -126,12 +126,12 @@ class TestChain(object): def test_sugar(self): """ - `chain(c1, c2, c3)` and `[c1, c2, c3]` are equivalent. + `pipe(c1, c2, c3)` and `[c1, c2, c3]` are equivalent. """ @attr.s class C(object): - a1 = attrib(default="True", converter=chain(str, strtobool, bool)) + a1 = attrib(default="True", converter=pipe(str, strtobool, bool)) a2 = attrib(default=True, converter=[str, strtobool, bool]) c = C()