FlowerPower 0.21.0__py3-none-any.whl → 0.31.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.
Files changed (40) hide show
  1. flowerpower/cfg/__init__.py +143 -25
  2. flowerpower/cfg/base.py +132 -11
  3. flowerpower/cfg/exceptions.py +53 -0
  4. flowerpower/cfg/pipeline/__init__.py +151 -35
  5. flowerpower/cfg/pipeline/adapter.py +1 -0
  6. flowerpower/cfg/pipeline/builder.py +24 -25
  7. flowerpower/cfg/pipeline/builder_adapter.py +142 -0
  8. flowerpower/cfg/pipeline/builder_executor.py +101 -0
  9. flowerpower/cfg/pipeline/run.py +134 -22
  10. flowerpower/cfg/project/__init__.py +59 -14
  11. flowerpower/cfg/project/adapter.py +6 -0
  12. flowerpower/cli/__init__.py +8 -9
  13. flowerpower/cli/cfg.py +0 -38
  14. flowerpower/cli/pipeline.py +121 -83
  15. flowerpower/cli/utils.py +120 -71
  16. flowerpower/flowerpower.py +94 -120
  17. flowerpower/pipeline/config_manager.py +180 -0
  18. flowerpower/pipeline/executor.py +126 -0
  19. flowerpower/pipeline/lifecycle_manager.py +231 -0
  20. flowerpower/pipeline/manager.py +121 -276
  21. flowerpower/pipeline/pipeline.py +66 -278
  22. flowerpower/pipeline/registry.py +45 -4
  23. flowerpower/utils/__init__.py +19 -0
  24. flowerpower/utils/adapter.py +286 -0
  25. flowerpower/utils/callback.py +73 -67
  26. flowerpower/utils/config.py +306 -0
  27. flowerpower/utils/executor.py +178 -0
  28. flowerpower/utils/filesystem.py +194 -0
  29. flowerpower/utils/misc.py +249 -76
  30. flowerpower/utils/security.py +221 -0
  31. {flowerpower-0.21.0.dist-info → flowerpower-0.31.0.dist-info}/METADATA +1 -13
  32. flowerpower-0.31.0.dist-info/RECORD +53 -0
  33. flowerpower/cfg/pipeline/_schedule.py +0 -32
  34. flowerpower/cli/mqtt.py +0 -168
  35. flowerpower/plugins/mqtt/__init__.py +0 -8
  36. flowerpower-0.21.0.dist-info/RECORD +0 -44
  37. {flowerpower-0.21.0.dist-info → flowerpower-0.31.0.dist-info}/WHEEL +0 -0
  38. {flowerpower-0.21.0.dist-info → flowerpower-0.31.0.dist-info}/entry_points.txt +0 -0
  39. {flowerpower-0.21.0.dist-info → flowerpower-0.31.0.dist-info}/licenses/LICENSE +0 -0
  40. {flowerpower-0.21.0.dist-info → flowerpower-0.31.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,231 @@
1
+ """Pipeline lifecycle management."""
2
+
3
+ from typing import TYPE_CHECKING, Any, Optional
4
+
5
+ import rich
6
+
7
+ if TYPE_CHECKING:
8
+ from .registry import PipelineRegistry, HookType
9
+
10
+
11
+ class PipelineLifecycleManager:
12
+ """Handles pipeline creation, deletion, and metadata management.
13
+
14
+ This class is responsible for:
15
+ - Creating new pipelines
16
+ - Deleting existing pipelines
17
+ - Managing pipeline metadata and summaries
18
+ - Displaying pipeline information
19
+ - Managing hooks
20
+ """
21
+
22
+ def __init__(self, registry: "PipelineRegistry"):
23
+ """Initialize the lifecycle manager.
24
+
25
+ Args:
26
+ registry: Pipeline registry for pipeline operations
27
+ """
28
+ self._registry = registry
29
+
30
+ def create_pipeline(
31
+ self,
32
+ name: str,
33
+ overwrite: bool = False,
34
+ template: Optional[str] = None,
35
+ tags: Optional[list[str]] = None,
36
+ description: Optional[str] = None
37
+ ) -> None:
38
+ """Create a new pipeline.
39
+
40
+ Args:
41
+ name: Name of the pipeline to create
42
+ overwrite: Whether to overwrite existing pipeline
43
+ template: Template to use for pipeline creation
44
+ tags: Tags to associate with the pipeline
45
+ description: Description of the pipeline
46
+ """
47
+ self._registry.create_pipeline(
48
+ name=name,
49
+ overwrite=overwrite,
50
+ template=template,
51
+ tags=tags or [],
52
+ description=description or ""
53
+ )
54
+
55
+ def delete_pipeline(
56
+ self,
57
+ name: str,
58
+ cfg: bool = True,
59
+ module: bool = False
60
+ ) -> None:
61
+ """Delete a pipeline.
62
+
63
+ Args:
64
+ name: Name of the pipeline to delete
65
+ cfg: Whether to delete configuration file
66
+ module: Whether to delete module file
67
+ """
68
+ self._registry.delete_pipeline(name=name, cfg=cfg, module=module)
69
+
70
+ def get_summary(
71
+ self,
72
+ name: Optional[str] = None,
73
+ cfg: bool = True,
74
+ code: bool = True,
75
+ project: bool = True
76
+ ) -> dict:
77
+ """Get pipeline summary information.
78
+
79
+ Args:
80
+ name: Name of pipeline to summarize, or None for all pipelines
81
+ cfg: Whether to include configuration information
82
+ code: Whether to include code information
83
+ project: Whether to include project information
84
+
85
+ Returns:
86
+ dict: Summary information
87
+ """
88
+ if name is None:
89
+ # Get summary for all pipelines
90
+ return self._registry.get_summaries(cfg=cfg, code=code, project=project)
91
+ else:
92
+ # Get summary for specific pipeline
93
+ pipeline = self._registry.get_pipeline_object(name=name)
94
+ return pipeline.get_summary(cfg=cfg, code=code, project=project)
95
+
96
+ def show_summary(
97
+ self,
98
+ name: Optional[str] = None,
99
+ cfg: bool = True,
100
+ code: bool = True,
101
+ project: bool = True,
102
+ to_html: bool = False,
103
+ to_svg: bool = False
104
+ ) -> None:
105
+ """Display pipeline summary.
106
+
107
+ Args:
108
+ name: Name of pipeline to summarize, or None for all pipelines
109
+ cfg: Whether to include configuration information
110
+ code: Whether to include code information
111
+ project: Whether to include project information
112
+ to_html: Whether to output HTML
113
+ to_svg: Whether to output SVG
114
+ """
115
+ summary = self.get_summary(name=name, cfg=cfg, code=code, project=project)
116
+
117
+ if name is None:
118
+ # Display all pipelines in a table
119
+ from rich.table import Table
120
+ table = Table(title="Pipeline Summaries")
121
+ table.add_column("Pipeline", style="cyan")
122
+ table.add_column("Tags", style="magenta")
123
+ table.add_column("Description", style="green")
124
+ table.add_column("Modified", style="yellow")
125
+
126
+ for pipeline_name, info in summary.items():
127
+ tags = ", ".join(info.get("tags", []))
128
+ desc = info.get("description", "")[:50] + "..." if len(info.get("description", "")) > 50 else info.get("description", "")
129
+ modified = info.get("modified", "N/A")
130
+ table.add_row(pipeline_name, tags, desc, modified)
131
+
132
+ rich.print(table)
133
+ else:
134
+ # Display single pipeline details
135
+ rich.print(f"Pipeline: {name}")
136
+ rich.print("=" * 50)
137
+
138
+ for key, value in summary.items():
139
+ if isinstance(value, dict):
140
+ rich.print(f"{key}:")
141
+ for sub_key, sub_value in value.items():
142
+ rich.print(f" {sub_key}: {sub_value}")
143
+ else:
144
+ rich.print(f"{key}: {value}")
145
+
146
+ def show_pipelines(self) -> None:
147
+ """Display available pipelines in a formatted table."""
148
+ pipelines = self.list_pipelines()
149
+
150
+ if not pipelines:
151
+ rich.print("No pipelines found.")
152
+ return
153
+
154
+ # Get pipeline info for display
155
+ pipeline_info = []
156
+ for name in pipelines:
157
+ try:
158
+ summary = self.get_summary(name=name, cfg=False, code=False, project=False)
159
+ pipeline_info.append({
160
+ "name": name,
161
+ "tags": ", ".join(summary.get("tags", [])),
162
+ "description": summary.get("description", "")[:50] + "..."
163
+ if len(summary.get("description", "")) > 50
164
+ else summary.get("description", "")
165
+ })
166
+ except Exception:
167
+ pipeline_info.append({
168
+ "name": name,
169
+ "tags": "",
170
+ "description": "Error loading info"
171
+ })
172
+
173
+ # Display as table
174
+ from rich.table import Table
175
+ table = Table(title="Available Pipelines")
176
+ table.add_column("Pipeline", style="cyan")
177
+ table.add_column("Tags", style="magenta")
178
+ table.add_column("Description", style="green")
179
+
180
+ for info in pipeline_info:
181
+ table.add_row(info["name"], info["tags"], info["description"])
182
+
183
+ rich.print(table)
184
+
185
+ def list_pipelines(self) -> list[str]:
186
+ """List all available pipeline names.
187
+
188
+ Returns:
189
+ list[str]: List of pipeline names
190
+ """
191
+ return self._registry.list_pipelines()
192
+
193
+ @property
194
+ def pipelines(self) -> list[str]:
195
+ """Get list of available pipeline names.
196
+
197
+ Returns:
198
+ list[str]: List of pipeline names
199
+ """
200
+ return self.list_pipelines()
201
+
202
+ @property
203
+ def summary(self) -> dict[str, dict | str]:
204
+ """Get complete summary of all pipelines.
205
+
206
+ Returns:
207
+ dict[str, dict | str]: Complete summary information
208
+ """
209
+ return self.get_summary()
210
+
211
+ def add_hook(
212
+ self,
213
+ name: str,
214
+ type: "HookType",
215
+ to: Optional[str] = None,
216
+ function_name: Optional[str] = None
217
+ ) -> None:
218
+ """Add a hook to a pipeline.
219
+
220
+ Args:
221
+ name: Name of the pipeline
222
+ type: Type of hook to add
223
+ to: Target for the hook
224
+ function_name: Name of the function to hook
225
+ """
226
+ self._registry.add_hook(
227
+ name=name,
228
+ type=type,
229
+ to=to,
230
+ function_name=function_name
231
+ )