Skip to content

Commit 8302940

Browse files
feat: update Pipe to allow custom init in subclass
1 parent acca312 commit 8302940

File tree

2 files changed

+38
-21
lines changed

2 files changed

+38
-21
lines changed

pipd/pipe.py

+37-20
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import re
44
import traceback
5-
from typing import Any, Callable, Dict, Iterator, Optional, Type
5+
from typing import Any, Callable, Dict, Iterable, Iterator, Optional, Type
66

77

88
def is_iterable(obj):
@@ -52,46 +52,63 @@ def method(*args, **kwargs):
5252

5353

5454
class Pipe(metaclass=PipeMeta):
55-
functions: Dict[str, Type[Function]] = {}
55+
_functions: Dict[str, Type[Function]] = {}
5656

5757
def __init__(
5858
self,
5959
*iterable,
60-
function: Optional[Callable] = identity,
61-
handler: Optional[Callable] = log_traceback_and_continue,
60+
function: Callable = identity,
61+
handler: Callable = log_traceback_and_continue,
6262
):
6363
if len(iterable) == 1 and is_iterable(iterable[0]):
6464
iterable = iterable[0]
65-
self.iterable = iterable
66-
self.function = function
67-
self.handler = handler
65+
self._iterable: Iterable = iterable
66+
self._function = function
67+
self._handler = handler
6868

6969
def __iter__(self):
70-
for item in self.function(iter(self.iterable)):
70+
for item in self._function(iter(self._iterable)):
7171
try:
7272
yield item
7373
except Exception as e:
74-
self.handler(e)
74+
self._handler(e)
7575

76-
def close(self):
77-
# Necessary to use `yield from` on a Pipe object
78-
pass
79-
80-
def list(self):
81-
return list(self)
76+
def _new_pipe(
77+
self,
78+
iterable: Optional[Iterable] = None,
79+
function: Optional[Callable] = None,
80+
functions: Optional[Dict[str, Type[Function]]] = None,
81+
handler: Optional[Callable] = None,
82+
):
83+
# This is for composition intead of init so that init can be customized
84+
pipe = self.__class__()
85+
pipe._iterable = iterable or self._iterable
86+
pipe._function = function or self._function
87+
pipe._functions = functions or self._functions
88+
pipe._handler = handler or self._handler
89+
return pipe
8290

8391
def __getattr__(self, name):
8492
def method(*args, **kwargs):
85-
cls = self.__class__
86-
function = self.functions[name](*args, **kwargs)
87-
return cls(self.iterable, function=compose(self.function, function))
93+
return self._new_pipe(
94+
function=compose(self._function, self._functions[name](*args, **kwargs))
95+
)
8896

8997
return method
9098

9199
def __call__(self, *iterable):
92-
return self.__class__(*iterable, function=self.function)
100+
if len(iterable) == 1 and is_iterable(iterable[0]):
101+
iterable = iterable[0]
102+
return self._new_pipe(iterable=iterable)
103+
104+
def close(self):
105+
# Necessary to use `yield from` on a Pipe object
106+
pass
107+
108+
def list(self):
109+
return list(self)
93110

94111
@classmethod
95112
def add_fn(cls, fn: Type[Function], name: Optional[str] = None):
96113
fn_name = camelcase_to_snakecase(fn.__name__) if name is None else name
97-
cls.functions[fn_name] = fn
114+
cls._functions[fn_name] = fn

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
setup(
44
name="pipd",
55
packages=find_packages(exclude=[]),
6-
version="0.1.7",
6+
version="0.1.8",
77
description="Utility functions for python data pipelines.",
88
long_description_content_type="text/markdown",
99
author="ElevenLabs",

0 commit comments

Comments
 (0)