diff --git a/README.md b/README.md index 919a6bb..0d19233 100644 --- a/README.md +++ b/README.md @@ -760,3 +760,24 @@ processing at value 3 processing at value 4 [0, 2] ``` + +# Chaining pipes + +You can combine multiple pipes into a new one: + +```python +class ErrorDatabase: + def __init__(self): + self.lines = [] + + def filter_lines_by(self, predicate): + filtered_lines = list(self.lines | predicate) + # further processing of filtered_lines + # ... + return filtered_lines + +db = ErrorDatabase() +# here we combine pipes into a new one to pass it to a function call +expired_reports = has_error_code | reported_by_end_customer | older_than_days(30) +errors = db.filter_lines_by(expired_reports) +``` \ No newline at end of file diff --git a/pipe.py b/pipe.py index f6d24ef..681c9ac 100644 --- a/pipe.py +++ b/pipe.py @@ -39,8 +39,15 @@ def __init__(self, function): def __ror__(self, other): return self.function(other) + def __or__(self, other): + return self.__class__( + lambda iterable, *args2, **kwargs2: other.function( + self.function(iterable, *args2, **kwargs2) + ) + ) + def __call__(self, *args, **kwargs): - return Pipe( + return self.__class__( lambda iterable, *args2, **kwargs2: self.function( iterable, *args, *args2, **kwargs, **kwargs2 ) diff --git a/tests/test_pipe.py b/tests/test_pipe.py index 8bba1c9..e47e41c 100644 --- a/tests/test_pipe.py +++ b/tests/test_pipe.py @@ -38,3 +38,15 @@ def test_enumerate(): data = [4, "abc", {"key": "value"}] expected = [(5, 4), (6, "abc"), (7, {"key": "value"})] assert list(data | pipe.enumerate(start=5)) == expected + + +def test_concatenate_pipes(): + data = range(10) + is_even = pipe.where(lambda x: x % 2 == 0) + higher_than_4 = pipe.where(lambda x: x > 4) + expected = [6,8] + # standard behavior + assert list(data | is_even | higher_than_4) == expected + # concatenated pipes + is_even_and_higher_than_4 = is_even | higher_than_4 + assert list(data | is_even_and_higher_than_4) == expected