FlowerPower 0.21.0__py3-none-any.whl → 0.30.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -39,8 +39,34 @@ class RunConfig(BaseConfig):
39
39
  project_adapter_cfg: dict | None = msgspec.field(default=None)
40
40
  adapter: dict[str, Any] | None = msgspec.field(default=None)
41
41
  reload: bool = msgspec.field(default=False)
42
- on_success: Callable | tuple[Callable, tuple | None, dict | None] | None = msgspec.field(default=None)
43
- on_failure: Callable | tuple[Callable, tuple | None, dict | None] | None = msgspec.field(default=None)
42
+
43
+
44
+ class CallbackSpec(msgspec.Struct):
45
+ """Specification for a callback function with optional arguments."""
46
+ func: Callable
47
+ args: tuple | None = None
48
+ kwargs: dict | None = None
49
+
50
+
51
+ class RunConfig(BaseConfig):
52
+ inputs: dict | None = msgspec.field(default_factory=dict)
53
+ final_vars: list[str] | None = msgspec.field(default_factory=list)
54
+ config: dict | None = msgspec.field(default_factory=dict)
55
+ cache: dict | bool | None = msgspec.field(default=False)
56
+ with_adapter: WithAdapterConfig = msgspec.field(default_factory=WithAdapterConfig)
57
+ executor: ExecutorConfig = msgspec.field(default_factory=ExecutorConfig)
58
+ log_level: str | None = msgspec.field(default="INFO")
59
+ max_retries: int = msgspec.field(default=3)
60
+ retry_delay: int | float = msgspec.field(default=1)
61
+ jitter_factor: float | None = msgspec.field(default=0.1)
62
+ retry_exceptions: list[str] = msgspec.field(default_factory=lambda: ["Exception"])
63
+ # New fields for comprehensive configuration
64
+ pipeline_adapter_cfg: dict | None = msgspec.field(default=None)
65
+ project_adapter_cfg: dict | None = msgspec.field(default=None)
66
+ adapter: dict[str, Any] | None = msgspec.field(default=None)
67
+ reload: bool = msgspec.field(default=False)
68
+ on_success: CallbackSpec | None = msgspec.field(default=None)
69
+ on_failure: CallbackSpec | None = msgspec.field(default=None)
44
70
 
45
71
  def __post_init__(self):
46
72
  if isinstance(self.inputs, dict):
@@ -81,3 +107,30 @@ class RunConfig(BaseConfig):
81
107
  else:
82
108
  converted_exceptions.append(Exception)
83
109
  self.retry_exceptions = converted_exceptions
110
+
111
+ # Handle callback conversions
112
+ if self.on_success is not None and not isinstance(self.on_success, CallbackSpec):
113
+ if callable(self.on_success):
114
+ self.on_success = CallbackSpec(func=self.on_success)
115
+ elif isinstance(self.on_success, tuple) and len(self.on_success) == 3:
116
+ func, args, kwargs = self.on_success
117
+ self.on_success = CallbackSpec(func=func, args=args, kwargs=kwargs)
118
+ else:
119
+ self.on_success = None
120
+ warnings.warn(
121
+ "Invalid on_success format, must be Callable or (Callable, args, kwargs)",
122
+ RuntimeWarning
123
+ )
124
+
125
+ if self.on_failure is not None and not isinstance(self.on_failure, CallbackSpec):
126
+ if callable(self.on_failure):
127
+ self.on_failure = CallbackSpec(func=self.on_failure)
128
+ elif isinstance(self.on_failure, tuple) and len(self.on_failure) == 3:
129
+ func, args, kwargs = self.on_failure
130
+ self.on_failure = CallbackSpec(func=func, args=args, kwargs=kwargs)
131
+ else:
132
+ self.on_failure = None
133
+ warnings.warn(
134
+ "Invalid on_failure format, must be Callable or (Callable, args, kwargs)",
135
+ RuntimeWarning
136
+ )
@@ -19,13 +19,6 @@ app.add_typer(
19
19
  )
20
20
 
21
21
 
22
- if importlib.util.find_spec("paho"):
23
- from .mqtt import app as mqtt_app
24
-
25
- app.add_typer(
26
- mqtt_app, name="mqtt", help="Connect pipelines to MQTT message brokers"
27
- )
28
-
29
22
 
30
23
  @app.command()
31
24
  def init(
@@ -40,13 +40,11 @@ class PipelineManager:
40
40
  - Configuration management and loading
41
41
  - Pipeline creation, deletion, and discovery
42
42
  - Pipeline execution via PipelineRunner
43
- - Job scheduling via PipelineScheduler
44
43
  - Visualization via PipelineVisualizer
45
44
  - Import/export operations via PipelineIOManager
46
45
 
47
46
  Attributes:
48
47
  registry (PipelineRegistry): Handles pipeline registration and discovery
49
- scheduler (PipelineScheduler): Manages job scheduling and execution
50
48
  visualizer (PipelineVisualizer): Handles pipeline visualization
51
49
  io (PipelineIOManager): Manages pipeline import/export operations
52
50
  project_cfg (ProjectConfig): Current project configuration
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: FlowerPower
3
- Version: 0.21.0
3
+ Version: 0.30.0
4
4
  Summary: A simple workflow framework for building and managing data processing pipelines
5
5
  Author-email: "Volker L." <ligno.blades@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/legout/flowerpower
@@ -11,7 +11,7 @@ Description-Content-Type: text/markdown
11
11
  License-File: LICENSE
12
12
  Requires-Dist: duration-parser>=1.0.1
13
13
  Requires-Dist: fsspec>=2024.10.0
14
- Requires-Dist: fsspec-utils>=0.1.0
14
+ Requires-Dist: fsspec-utils[full]>=0.1.0
15
15
  Requires-Dist: humanize>=4.12.2
16
16
  Requires-Dist: msgspec>=0.19.0
17
17
  Requires-Dist: munch>=4.0.0
@@ -25,26 +25,14 @@ Provides-Extra: io
25
25
  Requires-Dist: flowerpower-io>=0.1.1; extra == "io"
26
26
  Provides-Extra: io-legacy
27
27
  Requires-Dist: flowerpower-io[legacy]>=0.1.1; extra == "io-legacy"
28
- Provides-Extra: mongodb
29
- Requires-Dist: pymongo>=4.7.2; extra == "mongodb"
30
- Provides-Extra: mqtt
31
- Requires-Dist: paho-mqtt>=2.1.0; extra == "mqtt"
32
- Requires-Dist: orjson>=3.10.11; extra == "mqtt"
33
- Requires-Dist: mmh3>=5.1.0; extra == "mqtt"
34
28
  Provides-Extra: opentelemetry
35
29
  Requires-Dist: opentelemetry-api>=1.5.0; extra == "opentelemetry"
36
30
  Requires-Dist: opentelemetry-sdk>=1.5.0; extra == "opentelemetry"
37
31
  Requires-Dist: opentelemetry-exporter-jaeger>=1.21.0; extra == "opentelemetry"
38
32
  Provides-Extra: ray
39
33
  Requires-Dist: ray>=2.34.0; extra == "ray"
40
- Provides-Extra: tui
41
- Requires-Dist: textual>=0.85.2; extra == "tui"
42
34
  Provides-Extra: ui
43
35
  Requires-Dist: sf-hamilton-ui>=0.0.11; extra == "ui"
44
- Provides-Extra: webserver
45
- Requires-Dist: sanic>=24.6.0; extra == "webserver"
46
- Requires-Dist: sanic-ext>=23.12.0; extra == "webserver"
47
- Requires-Dist: orjson>=3.10.11; extra == "webserver"
48
36
  Provides-Extra: openlineage
49
37
  Requires-Dist: openlineage-python>=1.32.0; extra == "openlineage"
50
38
  Dynamic: license-file
@@ -6,23 +6,21 @@ flowerpower/cfg/pipeline/__init__.py,sha256=HSUlDt9smo-zPqOljEl329CQg8qsd0EJfCH1
6
6
  flowerpower/cfg/pipeline/_schedule.py,sha256=kaDyij3eUj0u6VdmJW4x_AQbSAZ-r7s2Fk7QFkXU5JQ,1029
7
7
  flowerpower/cfg/pipeline/adapter.py,sha256=uBKV6BZlsRRqSYNyC1oEWPchsaH7rFPCBobG5BrF3ss,2265
8
8
  flowerpower/cfg/pipeline/builder.py,sha256=rZ-cspbV-nwtckvOA49vt7DNJNb-gRLHHWiejmJPsFs,13192
9
- flowerpower/cfg/pipeline/run.py,sha256=xdHkB3Dx2ejkRUeK9bGHrIcO_JkFH3Hok_AFSO0WWT8,4212
9
+ flowerpower/cfg/pipeline/run.py,sha256=cirZbiHsY8D87idBvbfNv1gEtKpgv3xLfiiFIXJFxrA,6733
10
10
  flowerpower/cfg/project/__init__.py,sha256=bMMZ5Zo3YgkgOGt82H1mW8I4WnoCUpa0bSLPpZiB7K4,4560
11
11
  flowerpower/cfg/project/adapter.py,sha256=2k2U25NziDEiUacLTjxaSxOVkaQBRt6ECWGRGX0v4J0,1481
12
- flowerpower/cli/__init__.py,sha256=ZojMSbKvwtsOu0gryA5_GOEtUy3l6ZxYNvvKyhWsTxk,5079
12
+ flowerpower/cli/__init__.py,sha256=RkJT3mPlSOi55dNNP8kpm_omF0zEfbmWVP16N-lkijE,4897
13
13
  flowerpower/cli/cfg.py,sha256=P7qEcjraitMxbzVWJMqWeitIdpUkW41QkUi7ol0ksW0,1455
14
- flowerpower/cli/mqtt.py,sha256=NuQtvKA3DrmLdGRsR7CFhbVhKZ4qObzwRlvENSkTc0k,6009
15
14
  flowerpower/cli/pipeline.py,sha256=I58cWjK7J4dkXdJXIePcPiD7iILnYqoje0ztkR5mNwg,21958
16
15
  flowerpower/cli/utils.py,sha256=tsxvKIqUhl4m9IzuaSoc5a3_gb6Fu4LYyV8fVodqIdA,5127
17
16
  flowerpower/pipeline/__init__.py,sha256=ltr4LQnM5Boa9w7t-lNVmmcSglIkTPuIoeYnEKWU4Og,122
18
17
  flowerpower/pipeline/base.py,sha256=oQSDfEAyY2_kDRlHNnHr6ihZvfGeOjyMJRPKob1i7U8,3560
19
18
  flowerpower/pipeline/io.py,sha256=phYJhN4LZ0c6d8_udEQ4C9cGzeV3Ku0hsj0gyE1n2UY,16246
20
- flowerpower/pipeline/manager.py,sha256=ILnFUI8YeyCJsu7wS8g8Os6cNIhxoK6EihfkN5azWaI,47698
19
+ flowerpower/pipeline/manager.py,sha256=gJMWe_T1WpxO2H9GDrNtf61S4oJuLugMHwX82jqAuEU,47579
21
20
  flowerpower/pipeline/pipeline.py,sha256=8Vhc3GGoAJI-5zv8qX4gZ5JwJrTdVoiXHWNpv5OeKGw,26207
22
21
  flowerpower/pipeline/registry.py,sha256=iHdEBPiRpZorAUe6sDkqONoP8t6cicdQYGdK8UyxuAQ,28791
23
22
  flowerpower/pipeline/visualizer.py,sha256=EVpjv-TUe1zGvdEAWyShJcVXurm02W0jkLbj7z1uAv4,4953
24
23
  flowerpower/plugins/io/__init__.py,sha256=ZmSdKoh3TavJagOz0vUItnEqAh3mAM1QpAWj0KufF_k,222
25
- flowerpower/plugins/mqtt/__init__.py,sha256=4eTTvYY4SjC7O2lMaK-Hw5LQGvZE8TVl6HsXuVVD9zQ,228
26
24
  flowerpower/settings/__init__.py,sha256=XKQa8AI9VrX8ievs-suq3Cm6PBt4cJ78ZHVIjUbXCyA,130
27
25
  flowerpower/settings/_backend.py,sha256=Up1RBqAs3jtDUOV-9wEpL68Qmom-dRWMOeHXIh0F3lw,4273
28
26
  flowerpower/settings/executor.py,sha256=vNF383g1gMGkq_CXUzateGMNcJZig-vHkVVb0Hi_b74,249
@@ -36,9 +34,9 @@ flowerpower/utils/misc.py,sha256=gY1KVJp4lF4S0THUu1LUrjXaf87TzLO-TcwHxZZh2Zk,841
36
34
  flowerpower/utils/monkey.py,sha256=vJMYANjZI13PNbEQThdX0EFP1_6bGNHgnpF7HwReNyM,58
37
35
  flowerpower/utils/open_telemetry.py,sha256=fQWJWbIQFtKIxMBjAWeF12NGnqT0isO3A3j-DSOv_vE,949
38
36
  flowerpower/utils/templates.py,sha256=ouyEeSDqa9PjW8c32fGpcINlpC0WToawRFZkMPtwsLE,1591
39
- flowerpower-0.21.0.dist-info/licenses/LICENSE,sha256=9AkLexxrmr0aBgSHiqxpJk9wgazpP1CTJyiDyr56J9k,1063
40
- flowerpower-0.21.0.dist-info/METADATA,sha256=fkVSaKr-aU6eiaRAvydDHWfXf1J_a02Ca8Zw_zCjgHA,17691
41
- flowerpower-0.21.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
42
- flowerpower-0.21.0.dist-info/entry_points.txt,sha256=61X11i5a2IwC9LBiP20XCDl5zMOigGCjMCx17B7bDbQ,52
43
- flowerpower-0.21.0.dist-info/top_level.txt,sha256=VraH4WtEUfSxs5L-rXwDQhzQb9eLHTUtgvmFZ2dAYnA,12
44
- flowerpower-0.21.0.dist-info/RECORD,,
37
+ flowerpower-0.30.0.dist-info/licenses/LICENSE,sha256=9AkLexxrmr0aBgSHiqxpJk9wgazpP1CTJyiDyr56J9k,1063
38
+ flowerpower-0.30.0.dist-info/METADATA,sha256=3nPehMWbDcryhbkgbieU-_13I_8S3-1aNL54bMdjdDs,17208
39
+ flowerpower-0.30.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
40
+ flowerpower-0.30.0.dist-info/entry_points.txt,sha256=61X11i5a2IwC9LBiP20XCDl5zMOigGCjMCx17B7bDbQ,52
41
+ flowerpower-0.30.0.dist-info/top_level.txt,sha256=VraH4WtEUfSxs5L-rXwDQhzQb9eLHTUtgvmFZ2dAYnA,12
42
+ flowerpower-0.30.0.dist-info/RECORD,,
flowerpower/cli/mqtt.py DELETED
@@ -1,168 +0,0 @@
1
- import importlib
2
- import sys
3
-
4
- import typer
5
-
6
- from ..plugins.mqtt import run_pipeline_on_message as run_pipeline_on_message_
7
- from ..plugins.mqtt import start_listener as start_listener_
8
- from .utils import load_hook, parse_dict_or_list_param
9
-
10
- app = typer.Typer(help="MQTT management commands")
11
-
12
-
13
- @app.command()
14
- def start_listener(
15
- on_message: str,
16
- topic: str,
17
- base_dir: str,
18
- host: str = "localhost",
19
- port: int = 1883,
20
- username: str | None = None,
21
- password: str | None = None,
22
- ):
23
- """Start an MQTT client to listen to messages on a topic
24
-
25
- The connection to the MQTT broker is established using the provided configuration o a
26
- MQTT event broker defined in the project configuration file `conf/project.yml`.
27
- If not configuration is found, you have to provide the connection parameters,
28
- such as `host`, `port`, `username`, and `password`.
29
-
30
- The `on_message` module should contain a function `on_message` that will be called
31
- with the message payload as argument.
32
-
33
- Args:
34
- on_message: Name of the module containing the on_message function
35
- topic: MQTT topic to listen to
36
- base_dir: Base directory for the module
37
- host: MQTT broker host
38
- port: MQTT broker port
39
- username: MQTT broker username
40
- password: MQTT broker password
41
-
42
- Examples:
43
- $ flowerpower mqtt start_listener --on-message my_module --topic my_topic --base-dir /path/to/module
44
- """
45
- sys.path.append(base_dir)
46
- on_message_module = importlib.import_module(on_message)
47
- start_listener_(
48
- on_message=on_message_module.on_message,
49
- topic=topic,
50
- base_dir=base_dir,
51
- host=host,
52
- port=port,
53
- username=username,
54
- password=password,
55
- background=False,
56
- )
57
-
58
-
59
- @app.command()
60
- def run_pipeline_on_message(
61
- name: str,
62
- topic: str | None = None,
63
- executor: str | None = None,
64
- base_dir: str | None = None,
65
- inputs: str | None = None,
66
- final_vars: str | None = None,
67
- config: str | None = None,
68
- with_tracker: bool = False,
69
- with_opentelemetry: bool = False,
70
- with_progressbar: bool = False,
71
- storage_options: str | None = None,
72
- host: str | None = None,
73
- port: int | None = None,
74
- username: str | None = None,
75
- password: str | None = None,
76
- clean_session: bool = True,
77
- qos: int = 0,
78
- client_id: str | None = None,
79
- client_id_suffix: str | None = None,
80
- config_hook: str | None = None,
81
- max_retries: int = typer.Option(
82
- 3, help="Maximum number of retry attempts if pipeline execution fails"
83
- ),
84
- retry_delay: float = typer.Option(
85
- 1.0, help="Base delay between retries in seconds"
86
- ),
87
- jitter_factor: float = typer.Option(
88
- 0.1, help="Random factor (0-1) applied to delay for jitter"
89
- ),
90
- ):
91
- """Run a pipeline on a message
92
-
93
- This command sets up an MQTT listener that executes a pipeline whenever a message is
94
- received on the specified topic. The pipeline can be configured to retry on failure
95
- using exponential backoff with jitter for better resilience.
96
-
97
- Args:
98
- name: Name of the pipeline
99
- topic: MQTT topic to listen to
100
- executor: Name of the executor
101
- base_dir: Base directory for the pipeline
102
- inputs: Inputs as JSON or key=value pairs or dict string
103
- final_vars: Final variables as JSON or list
104
- config: Config for the hamilton pipeline executor
105
- with_tracker: Enable tracking with hamilton ui
106
- with_opentelemetry: Enable OpenTelemetry tracing
107
- with_progressbar: Enable progress bar
108
- storage_options: Storage options as JSON, dict string or key=value pairs
109
- host: MQTT broker host
110
- port: MQTT broker port
111
- username: MQTT broker username
112
- password: MQTT broker password
113
- clean_session: Whether to start a clean session with the broker
114
- qos: MQTT Quality of Service level (0, 1, or 2)
115
- client_id: Custom MQTT client identifier
116
- client_id_suffix: Optional suffix to append to client_id
117
- config_hook: Function to process incoming messages into pipeline config
118
- max_retries: Maximum number of retry attempts if pipeline execution fails
119
- retry_delay: Base delay between retries in seconds
120
- jitter_factor: Random factor (0-1) applied to delay for jitter
121
-
122
- Examples:
123
- # Basic usage with a specific topic
124
- $ flowerpower mqtt run-pipeline-on-message my_pipeline --topic sensors/data
125
-
126
- # Configure retries for resilience
127
- $ flowerpower mqtt run-pipeline-on-message my_pipeline --topic sensors/data --max-retries 5 --retry-delay 2.0
128
-
129
- # Use a config hook to process messages
130
- $ flowerpower mqtt run-pipeline-on-message my_pipeline --topic data/incoming --config-hook process_message
131
-
132
-
133
- """
134
-
135
- parsed_inputs = parse_dict_or_list_param(inputs, "dict")
136
- parsed_config = parse_dict_or_list_param(config, "dict")
137
- parsed_final_vars = parse_dict_or_list_param(final_vars, "list")
138
- parsed_storage_options = parse_dict_or_list_param(storage_options, "dict")
139
-
140
- config_hook_function = None
141
- if config_hook:
142
- config_hook_function = load_hook(name, config_hook, base_dir, storage_options)
143
-
144
- run_pipeline_on_message_(
145
- name=name,
146
- topic=topic,
147
- executor=executor,
148
- base_dir=base_dir,
149
- inputs=parsed_inputs,
150
- final_vars=parsed_final_vars,
151
- config=parsed_config,
152
- with_tracker=with_tracker,
153
- with_opentelemetry=with_opentelemetry,
154
- with_progressbar=with_progressbar,
155
- storage_options=parsed_storage_options,
156
- host=host,
157
- port=port,
158
- username=username,
159
- password=password,
160
- clean_session=clean_session,
161
- qos=qos,
162
- client_id=client_id,
163
- client_id_suffix=client_id_suffix,
164
- config_hook=config_hook_function,
165
- max_retries=max_retries,
166
- retry_delay=retry_delay,
167
- jitter_factor=jitter_factor,
168
- )
@@ -1,8 +0,0 @@
1
- import warnings
2
-
3
- warnings.warn(
4
- "The flowerpower.plugins.mqtt module is deprecated. "
5
- "Please use 'flowerpower-mqtt' instead. Install it with 'pip install flowerpower-mqtt'.",
6
- DeprecationWarning,
7
- stacklevel=2,
8
- )