FlowerPower 0.11.6.20__py3-none-any.whl → 0.21.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 (101) hide show
  1. flowerpower/__init__.py +2 -6
  2. flowerpower/cfg/__init__.py +7 -14
  3. flowerpower/cfg/base.py +29 -25
  4. flowerpower/cfg/pipeline/__init__.py +8 -6
  5. flowerpower/cfg/pipeline/_schedule.py +32 -0
  6. flowerpower/cfg/pipeline/adapter.py +0 -5
  7. flowerpower/cfg/pipeline/builder.py +377 -0
  8. flowerpower/cfg/pipeline/run.py +36 -0
  9. flowerpower/cfg/project/__init__.py +11 -24
  10. flowerpower/cfg/project/adapter.py +0 -12
  11. flowerpower/cli/__init__.py +2 -21
  12. flowerpower/cli/cfg.py +0 -3
  13. flowerpower/cli/mqtt.py +0 -6
  14. flowerpower/cli/pipeline.py +22 -415
  15. flowerpower/cli/utils.py +0 -1
  16. flowerpower/flowerpower.py +345 -146
  17. flowerpower/pipeline/__init__.py +2 -0
  18. flowerpower/pipeline/base.py +21 -12
  19. flowerpower/pipeline/io.py +58 -54
  20. flowerpower/pipeline/manager.py +165 -726
  21. flowerpower/pipeline/pipeline.py +643 -0
  22. flowerpower/pipeline/registry.py +285 -18
  23. flowerpower/pipeline/visualizer.py +5 -6
  24. flowerpower/plugins/io/__init__.py +8 -0
  25. flowerpower/plugins/mqtt/__init__.py +7 -11
  26. flowerpower/settings/__init__.py +0 -2
  27. flowerpower/settings/{backend.py → _backend.py} +0 -21
  28. flowerpower/settings/logging.py +1 -1
  29. flowerpower/utils/logging.py +24 -12
  30. flowerpower/utils/misc.py +17 -256
  31. flowerpower/utils/monkey.py +1 -83
  32. flowerpower-0.21.0.dist-info/METADATA +463 -0
  33. flowerpower-0.21.0.dist-info/RECORD +44 -0
  34. flowerpower/cfg/pipeline/schedule.py +0 -74
  35. flowerpower/cfg/project/job_queue.py +0 -238
  36. flowerpower/cli/job_queue.py +0 -1061
  37. flowerpower/fs/__init__.py +0 -29
  38. flowerpower/fs/base.py +0 -662
  39. flowerpower/fs/ext.py +0 -2143
  40. flowerpower/fs/storage_options.py +0 -1420
  41. flowerpower/job_queue/__init__.py +0 -294
  42. flowerpower/job_queue/apscheduler/__init__.py +0 -11
  43. flowerpower/job_queue/apscheduler/_setup/datastore.py +0 -110
  44. flowerpower/job_queue/apscheduler/_setup/eventbroker.py +0 -93
  45. flowerpower/job_queue/apscheduler/manager.py +0 -1051
  46. flowerpower/job_queue/apscheduler/setup.py +0 -554
  47. flowerpower/job_queue/apscheduler/trigger.py +0 -169
  48. flowerpower/job_queue/apscheduler/utils.py +0 -311
  49. flowerpower/job_queue/base.py +0 -413
  50. flowerpower/job_queue/rq/__init__.py +0 -10
  51. flowerpower/job_queue/rq/_trigger.py +0 -37
  52. flowerpower/job_queue/rq/concurrent_workers/gevent_worker.py +0 -226
  53. flowerpower/job_queue/rq/concurrent_workers/thread_worker.py +0 -231
  54. flowerpower/job_queue/rq/manager.py +0 -1582
  55. flowerpower/job_queue/rq/setup.py +0 -154
  56. flowerpower/job_queue/rq/utils.py +0 -69
  57. flowerpower/mqtt.py +0 -12
  58. flowerpower/pipeline/job_queue.py +0 -583
  59. flowerpower/pipeline/runner.py +0 -603
  60. flowerpower/plugins/io/base.py +0 -2520
  61. flowerpower/plugins/io/helpers/datetime.py +0 -298
  62. flowerpower/plugins/io/helpers/polars.py +0 -875
  63. flowerpower/plugins/io/helpers/pyarrow.py +0 -570
  64. flowerpower/plugins/io/helpers/sql.py +0 -202
  65. flowerpower/plugins/io/loader/__init__.py +0 -28
  66. flowerpower/plugins/io/loader/csv.py +0 -37
  67. flowerpower/plugins/io/loader/deltatable.py +0 -190
  68. flowerpower/plugins/io/loader/duckdb.py +0 -19
  69. flowerpower/plugins/io/loader/json.py +0 -37
  70. flowerpower/plugins/io/loader/mqtt.py +0 -159
  71. flowerpower/plugins/io/loader/mssql.py +0 -26
  72. flowerpower/plugins/io/loader/mysql.py +0 -26
  73. flowerpower/plugins/io/loader/oracle.py +0 -26
  74. flowerpower/plugins/io/loader/parquet.py +0 -35
  75. flowerpower/plugins/io/loader/postgres.py +0 -26
  76. flowerpower/plugins/io/loader/pydala.py +0 -19
  77. flowerpower/plugins/io/loader/sqlite.py +0 -23
  78. flowerpower/plugins/io/metadata.py +0 -244
  79. flowerpower/plugins/io/saver/__init__.py +0 -28
  80. flowerpower/plugins/io/saver/csv.py +0 -36
  81. flowerpower/plugins/io/saver/deltatable.py +0 -186
  82. flowerpower/plugins/io/saver/duckdb.py +0 -19
  83. flowerpower/plugins/io/saver/json.py +0 -36
  84. flowerpower/plugins/io/saver/mqtt.py +0 -28
  85. flowerpower/plugins/io/saver/mssql.py +0 -26
  86. flowerpower/plugins/io/saver/mysql.py +0 -26
  87. flowerpower/plugins/io/saver/oracle.py +0 -26
  88. flowerpower/plugins/io/saver/parquet.py +0 -36
  89. flowerpower/plugins/io/saver/postgres.py +0 -26
  90. flowerpower/plugins/io/saver/pydala.py +0 -20
  91. flowerpower/plugins/io/saver/sqlite.py +0 -24
  92. flowerpower/plugins/mqtt/cfg.py +0 -17
  93. flowerpower/plugins/mqtt/manager.py +0 -962
  94. flowerpower/settings/job_queue.py +0 -87
  95. flowerpower/utils/scheduler.py +0 -311
  96. flowerpower-0.11.6.20.dist-info/METADATA +0 -537
  97. flowerpower-0.11.6.20.dist-info/RECORD +0 -102
  98. {flowerpower-0.11.6.20.dist-info → flowerpower-0.21.0.dist-info}/WHEEL +0 -0
  99. {flowerpower-0.11.6.20.dist-info → flowerpower-0.21.0.dist-info}/entry_points.txt +0 -0
  100. {flowerpower-0.11.6.20.dist-info → flowerpower-0.21.0.dist-info}/licenses/LICENSE +0 -0
  101. {flowerpower-0.11.6.20.dist-info → flowerpower-0.21.0.dist-info}/top_level.txt +0 -0
@@ -1,537 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: FlowerPower
3
- Version: 0.11.6.20
4
- Summary: A simple workflow framework. Hamilton + APScheduler = FlowerPower
5
- Author-email: "Volker L." <ligno.blades@gmail.com>
6
- Project-URL: Homepage, https://github.com/legout/flowerpower
7
- Project-URL: Bug Tracker, https://github.com/legout/flowerpower/issues
8
- Keywords: hamilton,workflow,pipeline,scheduler,apscheduler,dask,ray
9
- Requires-Python: >=3.11
10
- Description-Content-Type: text/markdown
11
- License-File: LICENSE
12
- Requires-Dist: dill>=0.3.8
13
- Requires-Dist: duration-parser>=1.0.1
14
- Requires-Dist: fsspec>=2024.10.0
15
- Requires-Dist: humanize>=4.12.2
16
- Requires-Dist: msgspec>=0.19.0
17
- Requires-Dist: munch>=4.0.0
18
- Requires-Dist: orjson>=3.10.15
19
- Requires-Dist: python-dotenv>=1.0.1
20
- Requires-Dist: pyyaml>=6.0.1
21
- Requires-Dist: rich>=13.9.3
22
- Requires-Dist: s3fs>=2024.10.0
23
- Requires-Dist: sf-hamilton-sdk>=0.5.2
24
- Requires-Dist: sf-hamilton[rich,tqdm,visualization]>=1.69.0
25
- Requires-Dist: typer>=0.12.3
26
- Provides-Extra: apscheduler
27
- Requires-Dist: aiosqlite>=0.21.0; extra == "apscheduler"
28
- Requires-Dist: apscheduler==4.0.0a5; extra == "apscheduler"
29
- Requires-Dist: asyncpg>=0.29.0; extra == "apscheduler"
30
- Requires-Dist: greenlet>=3.0.3; extra == "apscheduler"
31
- Requires-Dist: sqlalchemy>=2.0.30; extra == "apscheduler"
32
- Requires-Dist: cron-descriptor>=1.4.5; extra == "apscheduler"
33
- Provides-Extra: io
34
- Requires-Dist: adbc-driver-manager>=1.4.0; extra == "io"
35
- Requires-Dist: aiosqlite>=0.21.0; extra == "io"
36
- Requires-Dist: datafusion>=43.1.0; extra == "io"
37
- Requires-Dist: deltalake>=0.24.0; extra == "io"
38
- Requires-Dist: duckdb>=1.1.3; extra == "io"
39
- Requires-Dist: orjson>=3.10.12; extra == "io"
40
- Requires-Dist: pandas>=2.2.3; extra == "io"
41
- Requires-Dist: polars>=1.15.0; extra == "io"
42
- Requires-Dist: pyarrow>=18.1.0; extra == "io"
43
- Requires-Dist: pydala2>=0.9.4.5; extra == "io"
44
- Requires-Dist: redis>=5.2.1; extra == "io"
45
- Requires-Dist: sherlock>=0.4.1; extra == "io"
46
- Requires-Dist: sqlalchemy>=2.0.30; extra == "io"
47
- Provides-Extra: io-legacy
48
- Requires-Dist: adbc-driver-manager>=1.4.0; extra == "io-legacy"
49
- Requires-Dist: aiosqlite>=0.21.0; extra == "io-legacy"
50
- Requires-Dist: datafusion>=43.1.0; extra == "io-legacy"
51
- Requires-Dist: deltalake>=0.24.0; extra == "io-legacy"
52
- Requires-Dist: duckdb>=1.1.3; extra == "io-legacy"
53
- Requires-Dist: orjson>=3.10.12; extra == "io-legacy"
54
- Requires-Dist: pandas>=2.2.3; extra == "io-legacy"
55
- Requires-Dist: polars-lts-cpu>=1.15.0; extra == "io-legacy"
56
- Requires-Dist: pyarrow>=18.1.0; extra == "io-legacy"
57
- Requires-Dist: pydala2>=0.9.4.5; extra == "io-legacy"
58
- Requires-Dist: redis>=5.2.1; extra == "io-legacy"
59
- Requires-Dist: sherlock>=0.4.1; extra == "io-legacy"
60
- Requires-Dist: sqlalchemy>=2.0.30; extra == "io-legacy"
61
- Provides-Extra: mongodb
62
- Requires-Dist: pymongo>=4.7.2; extra == "mongodb"
63
- Provides-Extra: mqtt
64
- Requires-Dist: paho-mqtt>=2.1.0; extra == "mqtt"
65
- Requires-Dist: orjson>=3.10.11; extra == "mqtt"
66
- Requires-Dist: mmh3>=5.1.0; extra == "mqtt"
67
- Provides-Extra: opentelemetry
68
- Requires-Dist: opentelemetry-api>=1.5.0; extra == "opentelemetry"
69
- Requires-Dist: opentelemetry-sdk>=1.5.0; extra == "opentelemetry"
70
- Requires-Dist: opentelemetry-exporter-jaeger>=1.21.0; extra == "opentelemetry"
71
- Provides-Extra: ray
72
- Requires-Dist: ray>=2.34.0; extra == "ray"
73
- Provides-Extra: redis
74
- Requires-Dist: redis>=5.0.4; extra == "redis"
75
- Provides-Extra: rq
76
- Requires-Dist: rq>=2.3.1; extra == "rq"
77
- Requires-Dist: rq-scheduler>=0.14.0; extra == "rq"
78
- Requires-Dist: cron-descriptor>=1.4.5; extra == "rq"
79
- Provides-Extra: tui
80
- Requires-Dist: textual>=0.85.2; extra == "tui"
81
- Provides-Extra: ui
82
- Requires-Dist: sf-hamilton-ui>=0.0.11; extra == "ui"
83
- Provides-Extra: webserver
84
- Requires-Dist: sanic>=24.6.0; extra == "webserver"
85
- Requires-Dist: sanic-ext>=23.12.0; extra == "webserver"
86
- Requires-Dist: orjson>=3.10.11; extra == "webserver"
87
- Provides-Extra: openlineage
88
- Requires-Dist: openlineage-python>=1.32.0; extra == "openlineage"
89
- Dynamic: license-file
90
-
91
- <div align="center">
92
- <h1>FlowerPower 🌸 - Build & Orchestrate Data Pipelines</h1>
93
- <h3>Simple Workflow Framework - Hamilton + APScheduler or RQ = FlowerPower</h3>
94
- <img src="./image.png" alt="FlowerPower Logo" width="400" height="300">
95
- </div>
96
-
97
-
98
-
99
- [![PyPI version](https://img.shields.io/pypi/v/flowerpower.svg?style=flat-square)](https://pypi.org/project/flowerpower/) <!-- Placeholder -->
100
- [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/legout/flowerpower/blob/main/LICENSE)
101
- [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/legout/flowerpower)
102
-
103
-
104
- **FlowerPower** is a Python framework designed for building, configuring, scheduling, and executing data processing pipelines with ease and flexibility. It promotes a modular, configuration-driven approach, allowing you to focus on your pipeline logic while FlowerPower handles the orchestration.
105
-
106
- It is leveraging the [Hamilton](https://github.com/DAGWorks-Inc/hamilton) library for defining dataflows in a clean, functional way within your Python pipeline scripts. Pipelines are defined in Python modules and configured using YAML files, making it easy to manage and understand your data workflows.
107
- FlowerPower integrates with job queue systems like [APScheduler](https://github.com/scheduler/apscheduler) and [RQ](https://github.com/rq/rq), enabling you to schedule and manage your pipeline runs efficiently. It also provides a web UI (Hamilton UI) for monitoring and managing your pipelines.
108
- FlowerPower is designed to be extensible, allowing you to easily swap components like job queue backends or add custom I/O plugins. This flexibility makes it suitable for a wide range of data processing tasks, from simple ETL jobs to complex data workflows.
109
-
110
-
111
- ## ✨ Key Features
112
-
113
- * **Modular Pipeline Design:** Thanks to [Hamilton](https://github.com/DAGWorks-Inc/hamilton), you can define your data processing logic in Python modules, using functions as nodes in a directed acyclic graph (DAG).
114
- * **Configuration-Driven:** Define pipeline parameters, execution logic, and scheduling declaratively using simple YAML files.
115
- * **Job Queue Integration:** Built-in support for different asynchronous execution models:
116
- * **APScheduler:** For time-based scheduling (cron, interval, date).
117
- * **RQ (Redis Queue):** For distributed task queues.
118
- * **Extensible I/O Plugins:** Connect to various data sources and destinations (CSV, JSON, Parquet, DeltaTable, DuckDB, PostgreSQL, MySQL, MSSQL, Oracle, MQTT, SQLite, and more).
119
- * **Multiple Interfaces:** Interact with your pipelines via:
120
- * **Command Line Interface (CLI):** For running, managing, and inspecting pipelines.
121
- * **Web UI:** A graphical interface for monitoring and managing pipelines and schedules. ([Hamilton UI](https://hamilton.dagworks.io/en/latest/hamilton-ui/ui/))
122
- * **Filesystem Abstraction:** Simplified file handling with support for local and remote filesystems (e.g., S3, GCS).
123
-
124
- ## 📦 Installation
125
-
126
- We recommend using [uv](https://github.com/astral-sh/uv) for installing FlowerPower and managing your project environments. `uv` is an extremely fast Python package installer and resolver.
127
-
128
- ```bash
129
- # Create and activate a virtual environment (recommended)
130
- uv venv
131
- source .venv/bin/activate # Or .\.venv\Scripts\activate on Windows
132
-
133
- # Install FlowerPower
134
- uv pip install flowerpower
135
-
136
- # Optional: Install additional dependencies for specific features
137
- uv pip install flowerpower[apscheduler,rq] # Example for APScheduler and RQ
138
- uv pip install flowerpower[io] # Example for I/O plugins (CSV, JSON, Parquet, DeltaTable, DuckDB, PostgreSQL, MySQL, MSSQL, Oracle, SQLite)
139
- uv pip install flowerpower[ui] # Example for Hamilton UI
140
- uv pip install flowerpower[all] # Install all optional dependencies
141
- ```
142
-
143
- *(Note: Specify required Python versions if known, e.g., Python 3.8+)*
144
-
145
- ## 🚀 Getting Started
146
-
147
- Let's build a simple "Hello World" pipeline.
148
-
149
- ### 1. Initialize Your Project:
150
-
151
- You can quickly set up the standard FlowerPower project structure using the CLI or Python.
152
-
153
- **Using the CLI:**
154
-
155
- Navigate to your desired parent directory and run:
156
- ```bash
157
- flowerpower init --name hello-flowerpower-project
158
- ```
159
-
160
-
161
- **Using Python:**
162
-
163
- Alternatively, you can initialize programmatically:
164
- ```python
165
- from flowerpower import init_project
166
-
167
- # Creates the structure in the current directory
168
- init_project(name='hello-flowerpower-project', job_queue_type='rq') # Or 'apscheduler'
169
- ```
170
-
171
- This will create a `hello-flowerpower-project` directory with the necessary `conf/` and `pipelines/` subdirectories and default configuration files.
172
-
173
- ```
174
- hello-flowerpower-project/
175
- ├── conf/
176
- │ ├── project.yml
177
- │ └── pipelines/
178
- └── pipelines/
179
- ```
180
-
181
- Now, navigate into your new project directory:
182
-
183
- ```bash
184
- cd hello-flowerpower-project
185
- ```
186
-
187
- **Configure Project (`conf/project.yml`):**
188
-
189
- Open `conf/project.yml` and define your project name and choose your job queue backend. Here's an example using RQ:
190
-
191
- ```yaml
192
- name: hello-flowerpower
193
- job_queue:
194
- type: rq
195
- backend:
196
- type: redis
197
- host: localhost
198
- port: 6379
199
- # ... other redis options
200
- queues:
201
- - default
202
- - high
203
- - low
204
- # adapter: ... # Optional adapter configurations (e.g., Hamilton Tracker, MLflow), see `conf/project.yml` for details
205
- ```
206
-
207
- ### 2. Create Your Pipeline
208
-
209
- You can create a new pipeline using the CLI or programmatically.
210
-
211
- **Using the CLI:**
212
-
213
- ```bash
214
- flowerpower pipeline new hello_world
215
- ```
216
-
217
- **Using Python:**
218
-
219
- There is a `PipelineManager` class to manage pipelines programmatically:
220
-
221
- ```python
222
- from flowerpower.pipeline import PipelineManager
223
- pm = PipelineManager(base_dir='.')
224
- pm.new(name='hello_world') # Creates a new pipeline
225
- ```
226
-
227
- This will create a new file `hello_world.py` in the `pipelines/` directory and a corresponding configuration file `hello_world.yml` in `conf/pipelines/`.
228
-
229
- **Implement Pipeline (`pipelines/hello_world.py`):**
230
-
231
- Open `pipelines/hello_world.py` and write your pipeline logic using Python and Hamilton. FlowerPower makes configuration easily accessible.
232
-
233
- ```python
234
- # FlowerPower pipeline hello_world.py
235
- # Created on 2025-05-03 22:34:09
236
-
237
- ####################################################################################################
238
- # Import necessary libraries
239
- # NOTE: Remove or comment out imports that are not used in the pipeline
240
-
241
- from hamilton.function_modifiers import parameterize
242
-
243
- from pathlib import Path
244
-
245
- from flowerpower.cfg import Config
246
-
247
- ####################################################################################################
248
- # Load pipeline parameters. Do not modify this section.
249
-
250
- PARAMS = Config.load(
251
- Path(__file__).parents[1], pipeline_name="hello_world"
252
- ).pipeline.h_params
253
-
254
-
255
- ####################################################################################################
256
- # Helper functions.
257
- # This functions have to start with an underscore (_).
258
-
259
-
260
- ####################################################################################################
261
- # Pipeline functions
262
-
263
- @parameterize(**PARAMS.greeting_message) # Inject 'message' from params
264
- def greeting_message(message: str) -> str:
265
- """Provides the greeting part."""
266
- return f"{message},"
267
-
268
- @parameterize(**PARAMS.target_name) # Inject 'name' from params
269
- def target_name(name: str) -> str:
270
- """Provides the target name."""
271
- return f"{name}!"
272
-
273
- def full_greeting(greeting_message: str, target_name: str) -> str:
274
- """Combines the greeting and target."""
275
- print(f"Generating greeting: {greeting_message} {target_name}")
276
- return f"{greeting_message} {target_name}"
277
-
278
- # You can add more complex Hamilton functions here...
279
- ```
280
-
281
- **Configure Pipeline (`conf/pipelines/hello_world.yml`):**
282
-
283
- Open `conf/pipelines/hello_world.yml` and specify parameters, run configurations, and scheduling for your pipeline.
284
-
285
- ```yaml
286
- # adapter: ... # Pipeline-specific adapter overrides
287
-
288
- params: # Parameters accessible in your Python code
289
- greeting_message:
290
- message: "Hello"
291
- target:
292
- name: "World"
293
-
294
- run: # How to execute the pipeline
295
- final_vars: # Specify the desired output(s) from your Hamilton DAG
296
- - full_greeting
297
- # inputs: # Optional: Specify input variables to the pipeline
298
- # message: "Hello"
299
- # config: ... # Runtime configuration overrides for Hamilton
300
- # executor: ... # Execution backend (e.g., threadpool, multiprocessing)
301
-
302
- schedule: # Optional: How often to run the pipeline
303
- cron: "0 * * * *" # Run hourly
304
- # interval: # e.g., { "minutes": 15 }
305
- # date: # e.g., "2025-12-31 23:59:59"
306
- ```
307
- ### 3. Run Your Pipeline 🏃‍♀️
308
-
309
- FlowerPower offers flexibility in how you execute your pipelines:
310
- - **Synchronous Execution:** Run the pipeline directly.
311
- - **Asynchronous Execution:** Use job queues for scheduling, background execution, or distributed processing.
312
-
313
- #### 1. Synchronous Execution:
314
-
315
- For quick testing or local runs, you can execute your pipeline synchronously. This is useful for debugging or running pipelines in a local environment.
316
-
317
- * **Via CLI:**
318
- ```bash
319
- # Run the pipeline synchronously
320
- flowerpower pipeline run hello_world --base_dir .
321
- ```
322
- * **Via Python:**
323
- ```python
324
- from flowerpower.pipeline import PipelineManager
325
- pm = PipelineManager(base_dir='.')
326
- pm.run('hello_world') # Execute the pipeline named 'hello_world'
327
-
328
- #### 2. Asynchronous Execution (Job Queues):
329
-
330
- For scheduling, background execution, or distributed processing, leverage FlowerPower's job queue integration. Ideal for distributed task queues where workers can pick up jobs.
331
-
332
- You have to install the job queue backend you want to use. FlowerPower supports two job queue backends: RQ (Redis Queue) and APScheduler.
333
- ```bash
334
- # Install RQ (Redis Queue) or APScheduler
335
- uv pip install flowerpower[rq] # For RQ (Redis Queue)
336
- uv pip install flowerpower[apscheduler] # For APScheduler
337
- ```
338
- * **Note:** Ensure you have the required dependencies installed for your chosen job queue backend. For RQ, you need Redis running. For APScheduler, you need a data store (PostgreSQL, MySQL, SQLite, MongoDB) and an event broker (Redis, MQTT, PostgreSQL).
339
-
340
- **a) Configuring Job Queue Backends:**
341
-
342
- Configuration of the job queue backend is done in your `conf/project.yml`. Currently, FlowerPower supports two job queue backends:
343
-
344
- * **RQ (Redis Queue):**
345
- * **Requires:** Access to a running Redis server.
346
- * Configure in `conf/project.yml`:
347
- ```yaml
348
- job_queue:
349
- type: rq
350
- backend:
351
- type: redis
352
- host: localhost
353
- port: 6379
354
- ... # other redis options
355
-
356
- * **APScheduler:**
357
- * **Requires:**
358
- * A **Data Store:** To persist job information (Options: PostgreSQL, MySQL, SQLite, MongoDB).
359
- * An **Event Broker:** To notify workers of scheduled jobs (Options: Redis, MQTT, PostgreSQL).
360
- * Configure in `cong/project.yml`:
361
- ```yaml
362
- job_queue:
363
- type: apscheduler
364
- backend:
365
- type: postgresql # or mysql, sqlite, mongodb
366
- host: localhost
367
- port: 5432
368
- user: your_user
369
- password: your_password
370
- database: your_database
371
- ... # other database options
372
- event_broker:
373
- type: redis # or mqtt, postgresql
374
- host: localhost
375
- port: 6379
376
- ... # other redis options
377
- ```
378
-
379
- It is possible to override the job queue backend configuration using environment variables, the `settings` module or by monkey patching the backend configuration of the `PipelineManager` or `JobQueueManager` classes. This might be useful for testing or when you want to avoid hardcoding values in your configuration files.
380
- * **Using the `settings` module:**
381
- e.g to override the RQ backend username and password:
382
- ```python
383
- from flowerpower import settings
384
-
385
- # Override some configuration values. e.g. when using rq
386
- settings.RQ_BACKEND_USERNAME = 'your_username'
387
- settings.RQ_BACKEND_PASSWORD = 'your_password'
388
- ```
389
- See the `flowerpower/settings/job_queue.py` file for all available settings.
390
-
391
- * **Monkey Patching:**
392
- e.g to override the APScheduler data store username and password:
393
- ```python
394
- from flowerpower.pipeline import PipelineManager
395
-
396
- pm = PipelineManager(base_dir='.')
397
- pm.project_cfg.job_queue.backend.username = 'your_username'
398
- pm.project_cfg.job_queue.backend.password = 'your_password'
399
- ```
400
- * **Using Environment Variables:**
401
- e.g. use a `.env` file or set them in your environment. Here is a list of the available environment variables for the job queue backend configuration:
402
- ```
403
- FP_JOB_QUEUE_TYPE
404
-
405
- # RQ (Redis Queue) backend
406
- FP_RQ_BACKEND
407
- FP_RQ_BACKEND_USERNAME
408
- FP_RQ_BACKEND_PASSWORD
409
- FP_RQ_BACKEND_HOST
410
- FP_RQ_BACKEND_PORT
411
-
412
- # APScheduler data store
413
- FP_APS_BACKEND_DS
414
- FP_APS_BACKEND_DS_USERNAME
415
- FP_APS_BACKEND_DS_PASSWORD
416
- FP_APS_BACKEND_DS_HOST
417
- FP_APS_BACKEND_DS_PORT
418
-
419
- # APScheduler event broker
420
- FP_APS_BACKEND_EB
421
- FP_APS_BACKEND_EB_USERNAME
422
- FP_APS_BACKEND_EB_PASSWORD
423
- FP_APS_BACKEND_EB_HOST
424
- FP_APS_BACKEND_EB_PORT
425
- ```
426
-
427
-
428
- **b) Add Job to Queue:**
429
- Run your pipeline using the job queue system. This allows you to schedule jobs, run them in the background, or distribute them across multiple workers.
430
-
431
- * **Via CLI:**
432
- ```bash
433
- # This will run the pipeline immediately and return the job result (blocking, until the job is done)
434
- flowerpower pipeline run-job hello_world --base_dir .
435
-
436
- # Submit the pipeline to the job queue and return the job ID (non-blocking)
437
- flowerpower pipeline add-job hello_world --base_dir .
438
- ```
439
- * **Via Python:**
440
-
441
- ```python
442
- from flowerpower.pipeline import PipelineManager
443
- pm = PipelineManager(base_dir='.')
444
-
445
- # submit the pipeline to the job queue and return the job ID (non-blocking)
446
- job_id = pm.add_job('hello_world')
447
-
448
- # submit the pipeline to the job queue, runs it immediately and returns the job ID (non-blocking)
449
- result = pm.run_job('hello_world')
450
- ```
451
-
452
- These commands will add the pipeline to the job queue, allowing it to be executed in the background or at scheduled intervals. The jobs will be processed by one or more workers, depending on your job queue configuration. You have to start the job queue workers separately.
453
-
454
-
455
- **c) Start Job Queue Workers:**
456
- To process jobs in the queue, you need to start one or more workers.
457
-
458
- * **Via CLI:**
459
- ```bash
460
- flowerpower job-queue start-worker --base_dir . # Start the job queue worker
461
- ```
462
-
463
- * **Via Python:**
464
- ```python
465
- from flowerpower.job_queue import JobQueueManager
466
- with JobQueueManager(base_dir='.'):
467
- # Start the job queue worker
468
- jqm.start_worker()
469
- ```
470
-
471
-
472
- ## Local Development Setup (Docker):
473
-
474
- To easily set up required services like Redis, PostgreSQL, or MQTT locally for testing job queues, a basic `docker-compose.yml` file is provided in the `docker/` directory. This file includes configurations for various services useful during development.
475
-
476
- ```bash
477
- # Navigate to the docker directory and start services
478
- cd docker
479
- docker-compose up -d redis postgres # Example: Start Redis and PostgreSQL
480
- ```
481
- *(Note: Review and adapt `docker/docker-compose.yml` for your specific needs. It's intended for development, not production.)*
482
-
483
-
484
-
485
- ## ⚙️ Configuration Overview
486
-
487
- FlowerPower uses a layered configuration system:
488
-
489
- * **`conf/project.yml`:** Defines global settings for your project, primarily the `job_queue` backend (RQ or APScheduler) and configurations for integrated `adapter`s (like Hamilton Tracker, MLflow, etc.).
490
- * **`conf/pipelines/*.yml`:** Each file defines a specific pipeline. It contains:
491
- * `params`: Input parameters for your Hamilton functions.
492
- * `run`: Execution details like target outputs (`final_vars`), Hamilton runtime `config`, and `executor` settings.
493
- * `schedule`: Defines when the pipeline should run automatically (using `cron`, `interval`, or `date`).
494
- * `adapter`: Pipeline-specific overrides for adapter settings.
495
-
496
- ## 🛠️ Basic Usage
497
-
498
- The primary way to interact with pipelines is often through the CLI:
499
-
500
- ```bash
501
- # Run a pipeline manually
502
- flowerpower pipeline run hello_world --base_dir .
503
-
504
- # Add a job to the queue
505
- flowerpower pipeline add-job hello_world --base_dir .
506
-
507
- # Schedule a pipeline
508
- flowerpower pipeline schedule hello_world --base_dir . # Schedules like cron, interval, or date are configured in the pipeline config
509
-
510
- # And many more commands...
511
- flowerpower --help # List all available commands
512
-
513
- ```
514
-
515
- ## 🖥️ UI
516
-
517
- The FlowerPower web UI (Hamilton UI) provides a graphical interface for monitoring and managing your pipelines. It allows you to visualize pipeline runs, schedules, and potentially manage configurations.
518
-
519
- ```bash
520
- # Start the web UI
521
- flowerpower ui
522
- ```
523
-
524
- ## 📖 Documentation
525
-
526
- There is not much documentation yet, but you can find some examples in the `examples/` directory. The examples cover various use cases, including:
527
- * Basic pipeline creation and execution.
528
- * Using different job queue backends (RQ and APScheduler).
529
- * Configuring and scheduling pipelines.
530
-
531
-
532
- There is a first version of documentation in `docs/`. This documentation is generated using [Pocket Flow Tutorial Project](https://github.com/The-Pocket/PocketFlow-Tutorial-Codebase-Knowledge). Although it is not complete and might be wrong in some parts, it can be a good starting point for understanding how to use FlowerPower.
533
-
534
-
535
- ## 📜 License
536
-
537
- This project is licensed under the MIT License - see the `LICENSE` file for details. (Placeholder - update with actual license)
@@ -1,102 +0,0 @@
1
- flowerpower/__init__.py,sha256=LO27AXn-YcsQ0cbytUJAMPs8cFLo1bQwV47N-f_tous,571
2
- flowerpower/flowerpower.py,sha256=ISR-0PtGa4hkhIJ-f1-xPp8WlSmsuwRVTnf5mZEMtDw,13752
3
- flowerpower/mqtt.py,sha256=ztsbPG4zvyqjiWsbG4dpxtYsxEz_ESw4n7tUdzkeqlM,337
4
- flowerpower/cfg/__init__.py,sha256=2RVEX962cVkd5KjXfW3DPhMd6BO56wAsvEQCEa2i__Q,8849
5
- flowerpower/cfg/base.py,sha256=W1_trbWUs9d56T06QHR5YlSLMbf7GnvtL6lQNAujJcY,4709
6
- flowerpower/cfg/pipeline/__init__.py,sha256=jfvOWFqLamccPEBAow_GNaqa-iSfg5gopdz4PLxRGfA,9169
7
- flowerpower/cfg/pipeline/adapter.py,sha256=PuXEAl6YbluoRj5jdoABD8xHPstgHsKJUIDs2HJBgRk,2517
8
- flowerpower/cfg/pipeline/run.py,sha256=v6xumlVYoqbQWIPwSIch9r8Z7IDGsSnBnW6-Oy0dhVk,2058
9
- flowerpower/cfg/pipeline/schedule.py,sha256=viw1Gd8pKq73Yw2-Tm9074YHP_yB5RPl9pYaqI8VDqI,2450
10
- flowerpower/cfg/project/__init__.py,sha256=7QwrkaaGzw9xMIp_2uVj-E3sf-LYn-urIWC0DkTNc74,5346
11
- flowerpower/cfg/project/adapter.py,sha256=zIBwelSoQJ277_SA506tYEVSf0kEPJODaggocYm5rK4,2044
12
- flowerpower/cfg/project/job_queue.py,sha256=vj4kW86MXnqmew_r9GRTZZwfnSj_Ui586fX1Q-n6qTI,10369
13
- flowerpower/cli/__init__.py,sha256=ys6uxRJyunYUAZYTtLkNYKqRdOG02A2YmXw_beDEib0,5730
14
- flowerpower/cli/cfg.py,sha256=B9yV6g9bTGRXOR1PewQTxf_XfcYbcsE3GeLAxlbE2qc,1530
15
- flowerpower/cli/job_queue.py,sha256=IKNWw3WSGIOrW-TYC7TDE6DeOSRG1hxnvPtQFn2XwU4,37145
16
- flowerpower/cli/mqtt.py,sha256=GM5d6bzG01THZd7SwXFAC3j0cait642eXT50P3R22vk,6281
17
- flowerpower/cli/pipeline.py,sha256=60P6u_QOSgp0jJXEMxazEEo5Sh7-SWFo-Kkuaz21YuI,37845
18
- flowerpower/cli/utils.py,sha256=nDSSj_1nlYlMmj252kRZeohhFqHv9yvdgDEduQCyWOc,5152
19
- flowerpower/fs/__init__.py,sha256=uZaPXErEfQqQRbKRIjkB9yiygd45X5_psYn9-VVrBTQ,910
20
- flowerpower/fs/base.py,sha256=TqgqBsaFj13O1NpAr8kHuGJ9CTlaSWViMB8Ai_iuCjs,22761
21
- flowerpower/fs/ext.py,sha256=7Ue70LL-ktGH_A_bi_nyI0P1WY_fboY5HqdPpqh8a6c,70604
22
- flowerpower/fs/storage_options.py,sha256=msq5TpxAU8tcE_Bxjw6SyxaFa75UjdYnR4-O9U2wmbk,48034
23
- flowerpower/job_queue/__init__.py,sha256=a25hIqv2xoFKb4JZlyUukS0ppZ9-2sJKH3XAvbk3rlk,10788
24
- flowerpower/job_queue/base.py,sha256=YwLunDQSyqkSU_vJ69C5SSybJeJP1bAiZ3teUtOchxA,13640
25
- flowerpower/job_queue/apscheduler/__init__.py,sha256=TXiUTu_j2v7DJPi57POnGHkePTLPUXXJ0so50SPPtp0,235
26
- flowerpower/job_queue/apscheduler/manager.py,sha256=NZeegRf16Gyq1qo_ZxhcNAdRIS0MrbtHQadlf-_tIsI,35766
27
- flowerpower/job_queue/apscheduler/setup.py,sha256=e8NGs6I4IrtnsrQMkXTJ8bSI7iCaI5swgpFqAWnkbqA,19669
28
- flowerpower/job_queue/apscheduler/trigger.py,sha256=kStQO_ipAn2xBbX3fSg4X3ORNOulalRyOhKBb0lkSAg,5111
29
- flowerpower/job_queue/apscheduler/utils.py,sha256=2zJ_xmLXpvXUQNF1XS2Gqm3Ogo907ctZ50GtvQB_rhE,9354
30
- flowerpower/job_queue/apscheduler/_setup/datastore.py,sha256=oV8pw7x0dZBDxhR54d-Y2O9hVanxhBuZbUNpxcizxak,3490
31
- flowerpower/job_queue/apscheduler/_setup/eventbroker.py,sha256=qh8v9vAc-3v4e66wdXyrVZyIxFyqmOpzwKkolE8mVko,2872
32
- flowerpower/job_queue/rq/__init__.py,sha256=VCGpAzd8K3GLHb8A-wFevNKj2xF23K7J7ykad7giVks,193
33
- flowerpower/job_queue/rq/_trigger.py,sha256=w1WKs_8nd9d4e_Y25yuG0vV2N4A58rWZz8RUORJepH0,1134
34
- flowerpower/job_queue/rq/manager.py,sha256=k3vL6w7hJYTN44mU9M4vsSt_f1iauIn_Zbu23riOUNs,57365
35
- flowerpower/job_queue/rq/setup.py,sha256=nCJlWJzfcgf7iwqTPQPk6ZQOe9p-KUmC3lfMrYrC-Lc,5332
36
- flowerpower/job_queue/rq/utils.py,sha256=QjyNhSM1_gMZkV2cO8eR99XeEji4AMwpxE1TANaRgTg,2009
37
- flowerpower/job_queue/rq/concurrent_workers/gevent_worker.py,sha256=X8rKfSbuITpWiwCyNqN-WVeodBkafFuj-zvbZb7z6lw,7511
38
- flowerpower/job_queue/rq/concurrent_workers/thread_worker.py,sha256=M_jjci-pypEsbHe-gCQS6jmJBrA-Tb7W19sEWi6htFU,7801
39
- flowerpower/pipeline/__init__.py,sha256=xbEn_RN0vVNqLZMSFOCdV41ggUkYrghFVJYd_EC0C44,75
40
- flowerpower/pipeline/base.py,sha256=CO2PsOACRHFd8-g-0BUTc1ZMVdaBnhQftJda7HDxPZI,3305
41
- flowerpower/pipeline/io.py,sha256=8Mlw4G7ehHHZEk4Qui-HcKBM3tBF4FuqUbjfNxK09iU,15963
42
- flowerpower/pipeline/job_queue.py,sha256=hl38-0QZCH5wujUf0qIqYznIPDLsJAoNDcOD7YGVQ6s,26114
43
- flowerpower/pipeline/manager.py,sha256=KVpOclUEUAETUNJamJJGuKt3oxCaLitQgxWxkE1q028,74460
44
- flowerpower/pipeline/registry.py,sha256=6ngmHyKyQsxvIO4qRYxljedY0BE1wE3lpfksEGOzjNs,18963
45
- flowerpower/pipeline/runner.py,sha256=dsSVYixFXqlxFk8EJfT4wV_7IwgkXq0ErwH_yf_NGS8,25654
46
- flowerpower/pipeline/visualizer.py,sha256=amjMrl5NetErE198HzZBPWVZBi_t5jj9ydxWpuNLoTI,5013
47
- flowerpower/plugins/io/base.py,sha256=6jL6b_kaM_UGyP_3YKLjHfz66xNAAZH1sp36JZyQz8g,97270
48
- flowerpower/plugins/io/metadata.py,sha256=PCrepLilXRWKDsB5BKFF_-OFs712s1zBeitW-84lDLQ,7005
49
- flowerpower/plugins/io/helpers/datetime.py,sha256=1WBUg2ywcsodJQwoF6JiIGc9yhVobvE2IErWp4i95m4,10649
50
- flowerpower/plugins/io/helpers/polars.py,sha256=2U0XMIDGWr7b7GcD7Qc0v-tSdZz_IiNo1Ws5kSOju6U,29359
51
- flowerpower/plugins/io/helpers/pyarrow.py,sha256=uFaradEOTReqiDGQy5QyXCC1hY4_Vp_R-3FoosaUJBY,19070
52
- flowerpower/plugins/io/helpers/sql.py,sha256=BPIxjarKF3p93EdtUu-md8KislE9q8IWNSeZ5toFU6U,7298
53
- flowerpower/plugins/io/loader/__init__.py,sha256=MKH42nvVokaWas0wFgX1yrpU5iLpvHjRqqF-KzwLHCg,780
54
- flowerpower/plugins/io/loader/csv.py,sha256=Q5bmcbbr530sT1kQ2YiJwvsMUPqi0VcZWsLOygmzRyI,827
55
- flowerpower/plugins/io/loader/deltatable.py,sha256=YNPOIKRrThbJmksV8dr-iXrQqD7qVjV4dRG7xfGBqqU,6747
56
- flowerpower/plugins/io/loader/duckdb.py,sha256=FOrDVJvImkEe3o4Qc1X7D6r9uUzHxfaml-tVdbFCaC0,468
57
- flowerpower/plugins/io/loader/json.py,sha256=Z8hPxiPsv_9PpaCXki4qDX70G95wGL-tGd7ALC2LtZ0,739
58
- flowerpower/plugins/io/loader/mqtt.py,sha256=0bjGW4ZkrFp3ouWbH1E0yeTUKRhYTFWdQOvTrONPz8Y,5098
59
- flowerpower/plugins/io/loader/mssql.py,sha256=RfptbTjerPXq3Pye7S-_70D0jlEWPcJpSTyyqD7BTRM,807
60
- flowerpower/plugins/io/loader/mysql.py,sha256=e1a4Yq3-mJlmxdEvzPaMZxGMrrm58_1zo_xzU_5m8HM,807
61
- flowerpower/plugins/io/loader/oracle.py,sha256=zHFsKIjdRnYZprjrr8svfyODK1ugSZKUqhSWBMfAMPY,823
62
- flowerpower/plugins/io/loader/parquet.py,sha256=UUpZmhdDOK8ZI7CMPKThNxDUc_6tFz3DbGZSexO3hDI,787
63
- flowerpower/plugins/io/loader/postgres.py,sha256=1rjo0K5oYaXYu3i62bw-5Avuovc2ikI8MezySqK7GFw,835
64
- flowerpower/plugins/io/loader/pydala.py,sha256=iCvHQCYAisrxZIaQzZrzTmWaND_LzamuMEOpxQFUdC4,420
65
- flowerpower/plugins/io/loader/sqlite.py,sha256=CCI2bPLMVYUOg7mxy54sbR15qwvKRGL8r_982jARUig,609
66
- flowerpower/plugins/io/saver/__init__.py,sha256=RWcUdrcmi2JR4mb77jPZd-lSG5rQBIqS7Pl4vbPfUes,780
67
- flowerpower/plugins/io/saver/csv.py,sha256=i_kZvuco5joBaBfidplWglQsNqO7v873j_Xo5f78S5M,736
68
- flowerpower/plugins/io/saver/deltatable.py,sha256=9UWXkmbMvomFe8jWop5GRA9hyfhiAFWZbSNROXngWHQ,7040
69
- flowerpower/plugins/io/saver/duckdb.py,sha256=NpnoO5CffrNcCUPH_4KH4RFei8T40sHgjYySm0n1pV8,415
70
- flowerpower/plugins/io/saver/json.py,sha256=19a0K3aNQQxtSjskv4G6_5XfiFBoZnHGZAd_W3UgFSs,734
71
- flowerpower/plugins/io/saver/mqtt.py,sha256=vIlnRSMwPzyZzGbvi9TBX4j4Qn1iSbgUbrMU2giJSCU,573
72
- flowerpower/plugins/io/saver/mssql.py,sha256=_ZyO2wq1hjRb-Wnz3lZLLpaI1gMM3IH4ItkU-4PeZSE,740
73
- flowerpower/plugins/io/saver/mysql.py,sha256=7rSyRhRDMJZFNEsqope39uxBCbNqhr03X-QmwvLAzXU,740
74
- flowerpower/plugins/io/saver/oracle.py,sha256=lli9uO0z4FhKIbrziKFz0x6Gug-jSay7pclsywIGYsc,756
75
- flowerpower/plugins/io/saver/parquet.py,sha256=3xhYInpXCgA3yg5NYxH4yfcZKpaRCEAXtVKTbJxh5LA,784
76
- flowerpower/plugins/io/saver/postgres.py,sha256=Pur9y2edErJMHheUOUGJn4L-lUoPLp0tFScDCNITzuQ,766
77
- flowerpower/plugins/io/saver/pydala.py,sha256=v8MGw_NRwriw6JFTUlMy-uMg9Jsx2iylbEX60GfXhh4,475
78
- flowerpower/plugins/io/saver/sqlite.py,sha256=_7USGGQIjkAvtFFv4xYTJ79IzqMnv8PfzC18T_TDPLA,575
79
- flowerpower/plugins/mqtt/__init__.py,sha256=B35HETcaAmtqgAjMeohy79oLcsj0T_dRRjmyHMG5Qq4,253
80
- flowerpower/plugins/mqtt/cfg.py,sha256=4F9ow0wEjSnU8UaWmJYGszkU0ZY2du2nHmGHXRVsC70,484
81
- flowerpower/plugins/mqtt/manager.py,sha256=WJIKu_0wfrxph_L0AjV-7RYVFtie2cOmdVGjjlr5DIA,37197
82
- flowerpower/settings/__init__.py,sha256=g1JKxxQKgBSbghzhCvEPOgD4ofjCGJdWCf8T0husyMQ,178
83
- flowerpower/settings/backend.py,sha256=jb4H3DXil5uN4BDo3ipqP6-1Hpnrm6qvIZQWiHZcDXg,4994
84
- flowerpower/settings/executor.py,sha256=vNF383g1gMGkq_CXUzateGMNcJZig-vHkVVb0Hi_b74,249
85
- flowerpower/settings/general.py,sha256=RxY6PGF_L8ApFlLPHulZ2I8_-aHYqOj63fUu9kSQTjI,227
86
- flowerpower/settings/hamilton.py,sha256=GVzWKz3B-wy07etY1mNUstEa4DFrQ_lM2cjE0qG_6qw,623
87
- flowerpower/settings/job_queue.py,sha256=wrehB9Suwks9y5Gvfg-cex6SQOoeFfSwZDxdKNmKhcA,2972
88
- flowerpower/settings/logging.py,sha256=xzoiM-87WGduC-RJu8RfyeweHGTM7SnHXHQPbxKweLE,67
89
- flowerpower/settings/retry.py,sha256=W3AAVSxmTUAeeSbzRGA37RxqtKKyUdi2MkwDzCsXP94,181
90
- flowerpower/utils/callback.py,sha256=sGYSrEbnl0xfRa1X-mA-om3erpH7pmpsWdyPQ9HpU7E,6736
91
- flowerpower/utils/logging.py,sha256=QO1Q3pv-m3mK2xT_VbkjTsomFnDeuqBmRuOtoxaowgg,864
92
- flowerpower/utils/misc.py,sha256=SK913FEYmOjS7GfSQ8oXNFiQ7owrH70fxp952vN5aWg,17099
93
- flowerpower/utils/monkey.py,sha256=VPl3yimoWhwD9kI05BFsjNvtyQiDyLfY4Q85Bb6Ma0w,2903
94
- flowerpower/utils/open_telemetry.py,sha256=fQWJWbIQFtKIxMBjAWeF12NGnqT0isO3A3j-DSOv_vE,949
95
- flowerpower/utils/scheduler.py,sha256=2zJ_xmLXpvXUQNF1XS2Gqm3Ogo907ctZ50GtvQB_rhE,9354
96
- flowerpower/utils/templates.py,sha256=ouyEeSDqa9PjW8c32fGpcINlpC0WToawRFZkMPtwsLE,1591
97
- flowerpower-0.11.6.20.dist-info/licenses/LICENSE,sha256=9AkLexxrmr0aBgSHiqxpJk9wgazpP1CTJyiDyr56J9k,1063
98
- flowerpower-0.11.6.20.dist-info/METADATA,sha256=8R1Z8YSTAbhnhg1Bwmq_b5UFRduIMI7o73_pxXy2JP4,21613
99
- flowerpower-0.11.6.20.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
100
- flowerpower-0.11.6.20.dist-info/entry_points.txt,sha256=61X11i5a2IwC9LBiP20XCDl5zMOigGCjMCx17B7bDbQ,52
101
- flowerpower-0.11.6.20.dist-info/top_level.txt,sha256=VraH4WtEUfSxs5L-rXwDQhzQb9eLHTUtgvmFZ2dAYnA,12
102
- flowerpower-0.11.6.20.dist-info/RECORD,,