Skip to content

Commit 74369b1

Browse files
committed
enable custom step registration via folder path in config.json
1 parent e1a71c2 commit 74369b1

File tree

1 file changed

+52
-9
lines changed

1 file changed

+52
-9
lines changed

pipeline_lib/core/pipeline.py

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import importlib
44
import json
55
import logging
6+
import os
67
import pkgutil
78
from typing import Optional
89

@@ -14,18 +15,13 @@ class Pipeline:
1415
"""Base class for pipelines."""
1516

1617
_step_registry = {}
18+
logger = logging.getLogger("Pipeline")
1719

1820
def __init__(self, initial_data: Optional[DataContainer] = None):
1921
self.steps = []
2022
if not all(isinstance(step, PipelineStep) for step in self.steps):
2123
raise TypeError("All steps must be instances of PipelineStep")
2224
self.initial_data = initial_data
23-
self.init_logger()
24-
25-
def init_logger(self) -> None:
26-
"""Initialize the logger."""
27-
self.logger = logging.getLogger(self.__class__.__name__)
28-
self.logger.debug(f"{self.__class__.__name__} initialized")
2925

3026
@classmethod
3127
def register_step(cls, step_class):
@@ -65,13 +61,56 @@ def auto_register_steps_from_package(cls, package_name):
6561
):
6662
cls.register_step(attribute)
6763

64+
@staticmethod
65+
def load_and_register_custom_steps(custom_steps_path: str) -> None:
66+
"""
67+
Dynamically loads and registers step classes found in the specified directory.
68+
69+
This method scans a specified directory for Python files (excluding __init__.py),
70+
dynamically imports these files as modules, and registers all classes derived from
71+
PipelineStep found within these modules.
72+
73+
Parameters
74+
----------
75+
custom_steps_path : str
76+
The path to the directory containing custom step implementation files.
77+
78+
Returns
79+
-------
80+
NoReturn
81+
This function does not return anything.
82+
"""
83+
Pipeline.logger.debug(f"Loading custom steps from: {custom_steps_path}")
84+
for filename in os.listdir(custom_steps_path):
85+
if filename.endswith(".py") and not filename.startswith("__"):
86+
filepath = os.path.join(custom_steps_path, filename)
87+
module_name = os.path.splitext(filename)[0]
88+
spec = importlib.util.spec_from_file_location(module_name, filepath)
89+
module = importlib.util.module_from_spec(spec)
90+
91+
try:
92+
spec.loader.exec_module(module)
93+
Pipeline.logger.debug(f"Successfully loaded module: {module_name}")
94+
95+
for attribute_name in dir(module):
96+
attribute = getattr(module, attribute_name)
97+
if (
98+
isinstance(attribute, type)
99+
and issubclass(attribute, PipelineStep)
100+
and attribute is not PipelineStep
101+
):
102+
Pipeline.register_step(attribute)
103+
Pipeline.logger.debug(f"Registered step class: {attribute_name}")
104+
except Exception as e:
105+
Pipeline.logger.error(f"Failed to load module: {module_name}. Error: {e}")
106+
68107
def run(self) -> DataContainer:
69108
"""Run the pipeline on the given data."""
70109

71110
data = DataContainer()
72111

73112
for i, step in enumerate(self.steps):
74-
self.logger.info(f"Running {step.__class__.__name__} - {i + 1} / {len(self.steps)}")
113+
Pipeline.logger.info(f"Running {step.__class__.__name__} - {i + 1} / {len(self.steps)}")
75114
data = step.execute(data)
76115
return data
77116

@@ -85,14 +124,18 @@ def from_json(cls, path: str) -> Pipeline:
85124
with open(path, "r") as config_file:
86125
config = json.load(config_file)
87126

88-
pipeline = Pipeline() # Assuming you have a default or base Pipeline class
127+
custom_steps_path = config.get("custom_steps_path")
128+
if custom_steps_path:
129+
Pipeline.load_and_register_custom_steps(custom_steps_path)
130+
131+
pipeline = Pipeline()
89132
steps = []
90133

91134
for step_config in config["pipeline"]["steps"]:
92135
step_type = step_config["step_type"]
93136
parameters = step_config.get("parameters", {})
94137

95-
pipeline.logger.info(
138+
Pipeline.logger.info(
96139
f"Creating step {step_type} with parameters: \n {json.dumps(parameters, indent=4)}"
97140
)
98141

0 commit comments

Comments
 (0)