From c733c5387f8570d503d4b0d56f5707400d720dcd Mon Sep 17 00:00:00 2001 From: Timothe Jost <timothe.jost@wanadoo.fr> Date: Tue, 10 Sep 2024 17:45:55 +0200 Subject: [PATCH] testing to add a better type hinting support means to create a pypeline --- src/pypelines/__init__.py | 2 +- src/pypelines/pipelines.py | 9 +++++++-- src/pypelines/pipes.py | 21 +++++++++++++++++---- src/pypelines/steps.py | 20 +++++++++----------- 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/pypelines/__init__.py b/src/pypelines/__init__.py index 83c651d..f49a980 100644 --- a/src/pypelines/__init__.py +++ b/src/pypelines/__init__.py @@ -1,4 +1,4 @@ -__version__ = "0.0.66" +__version__ = "0.0.67" from . import loggs from .pipes import * diff --git a/src/pypelines/pipelines.py b/src/pypelines/pipelines.py index a140325..0647e7f 100644 --- a/src/pypelines/pipelines.py +++ b/src/pypelines/pipelines.py @@ -10,7 +10,11 @@ if TYPE_CHECKING: from .graphs import PipelineGraph -class Pipeline: +class BasePipelineType(Protocol): + def __getattr__(self, name: str) -> "BasePipe": ... + + +class Pipeline(BasePipelineType): pipes: Dict[str, "BasePipe"] runner_backend_class = BaseTaskBackend @@ -61,7 +65,8 @@ class Pipeline: return pipe_class def resolve_instance(self, instance_name: str) -> "BaseStep": - """Resolve the specified instance name to a BaseStep object. + """Resolve the specified step instance name to a BaseStep object, + looking at the pipe and step names separated by a comma. Args: instance_name (str): The name of the instance in the format 'pipe_name.step_name'. diff --git a/src/pypelines/pipes.py b/src/pypelines/pipes.py index 3393780..bce4e8a 100644 --- a/src/pypelines/pipes.py +++ b/src/pypelines/pipes.py @@ -68,9 +68,22 @@ class BasePipe(BasePipeType, metaclass=ABCMeta): self.pipe_name = self.__class__.__name__ _steps: Dict[str, MethodType] = {} + + steps_members_scanner = inspect.getmembers(self, predicate=inspect.ismethod) + requires_is_step_attr = True + + for class_name, class_object in inspect.getmembers(self, predicate=inspect.isclass): + print(class_name, class_object) + if class_name == "Steps": + print("FOUND") + steps_members_scanner = inspect.getmembers(class_object(), predicate=inspect.ismethod) + requires_is_step_attr = False + break + # this loop populates self.steps dictionnary from the instanciated (bound) step methods. - for step_name, step in inspect.getmembers(self, predicate=inspect.ismethod): - if getattr(step, "is_step", False): + for step_name, step in steps_members_scanner: + print("step:", step_name) + if not requires_is_step_attr or getattr(step, "is_step", False): _steps[step_name] = step if len(_steps) < 1: @@ -86,7 +99,7 @@ class BasePipe(BasePipeType, metaclass=ABCMeta): number_of_steps_with_requirements = 0 for step in _steps.values(): - if len(step.requires): + if len(getattr(step, "requires", [])): number_of_steps_with_requirements += 1 if number_of_steps_with_requirements < len(_steps) - 1: @@ -99,7 +112,7 @@ class BasePipe(BasePipeType, metaclass=ABCMeta): # They must inherit from BaseStep self.steps = {} for step_name, step in _steps.items(): - step = self.step_class(self.pipeline, self, step) # , step_name) + step = self.step_class(self.pipeline, self, step, step_name=step_name) # , step_name) self.steps[step_name] = step # replace the bound_method by a step_class using that bound method, # so that we attach the necessary components to it. setattr(self, step_name, step) diff --git a/src/pypelines/steps.py b/src/pypelines/steps.py index 52d9486..7b31744 100644 --- a/src/pypelines/steps.py +++ b/src/pypelines/steps.py @@ -77,12 +77,7 @@ class BaseStep: pipe: "BasePipe" pipeline: "Pipeline" - def __init__( - self, - pipeline: "Pipeline", - pipe: "BasePipe", - worker: MethodType, - ): + def __init__(self, pipeline: "Pipeline", pipe: "BasePipe", worker: MethodType, step_name=None): """Initialize a BaseStep object. Args: @@ -111,12 +106,15 @@ class BaseStep: # we attach the values of the worker elements to BaseStep # as they are get only (no setter) on worker (bound method) - self.do_dispatch = self.worker.do_dispatch - self.version = self.worker.version - self.requires = self.worker.requires - self.step_name = self.worker.step_name + self.do_dispatch = getattr(self.worker, "do_dispatch", False) + self.version = getattr(self.worker, "version", 0) + self.requires = getattr(self.worker, "requires", []) + self.step_name = getattr(self.worker, "step_name", step_name) - self.callbacks = self.worker.callbacks + if not self.step_name: + raise ValueError("Step name cannot be blank nor None") + + self.callbacks = getattr(self.worker, "callbacks", []) self.worker = MethodType(worker.__func__, self) -- GitLab