FlowerPower 0.11.6.20__py3-none-any.whl → 0.20.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.
- flowerpower/cfg/__init__.py +3 -3
- flowerpower/cfg/pipeline/__init__.py +5 -3
- flowerpower/cfg/project/__init__.py +3 -3
- flowerpower/cfg/project/job_queue.py +1 -128
- flowerpower/cli/__init__.py +5 -5
- flowerpower/cli/cfg.py +0 -3
- flowerpower/cli/job_queue.py +400 -132
- flowerpower/cli/pipeline.py +14 -413
- flowerpower/cli/utils.py +0 -1
- flowerpower/flowerpower.py +537 -28
- flowerpower/job_queue/__init__.py +5 -94
- flowerpower/job_queue/base.py +201 -3
- flowerpower/job_queue/rq/concurrent_workers/thread_worker.py +0 -3
- flowerpower/job_queue/rq/manager.py +388 -77
- flowerpower/pipeline/__init__.py +2 -0
- flowerpower/pipeline/base.py +2 -2
- flowerpower/pipeline/io.py +14 -16
- flowerpower/pipeline/manager.py +21 -642
- flowerpower/pipeline/pipeline.py +571 -0
- flowerpower/pipeline/registry.py +242 -10
- flowerpower/pipeline/visualizer.py +1 -2
- flowerpower/plugins/_io/__init__.py +8 -0
- flowerpower/plugins/mqtt/manager.py +6 -6
- flowerpower/settings/backend.py +0 -2
- flowerpower/settings/job_queue.py +1 -57
- flowerpower/utils/misc.py +0 -256
- flowerpower/utils/monkey.py +1 -83
- {flowerpower-0.11.6.20.dist-info → flowerpower-0.20.0.dist-info}/METADATA +308 -152
- flowerpower-0.20.0.dist-info/RECORD +58 -0
- flowerpower/fs/__init__.py +0 -29
- flowerpower/fs/base.py +0 -662
- flowerpower/fs/ext.py +0 -2143
- flowerpower/fs/storage_options.py +0 -1420
- flowerpower/job_queue/apscheduler/__init__.py +0 -11
- flowerpower/job_queue/apscheduler/_setup/datastore.py +0 -110
- flowerpower/job_queue/apscheduler/_setup/eventbroker.py +0 -93
- flowerpower/job_queue/apscheduler/manager.py +0 -1051
- flowerpower/job_queue/apscheduler/setup.py +0 -554
- flowerpower/job_queue/apscheduler/trigger.py +0 -169
- flowerpower/job_queue/apscheduler/utils.py +0 -311
- flowerpower/pipeline/job_queue.py +0 -583
- flowerpower/pipeline/runner.py +0 -603
- flowerpower/plugins/io/base.py +0 -2520
- flowerpower/plugins/io/helpers/datetime.py +0 -298
- flowerpower/plugins/io/helpers/polars.py +0 -875
- flowerpower/plugins/io/helpers/pyarrow.py +0 -570
- flowerpower/plugins/io/helpers/sql.py +0 -202
- flowerpower/plugins/io/loader/__init__.py +0 -28
- flowerpower/plugins/io/loader/csv.py +0 -37
- flowerpower/plugins/io/loader/deltatable.py +0 -190
- flowerpower/plugins/io/loader/duckdb.py +0 -19
- flowerpower/plugins/io/loader/json.py +0 -37
- flowerpower/plugins/io/loader/mqtt.py +0 -159
- flowerpower/plugins/io/loader/mssql.py +0 -26
- flowerpower/plugins/io/loader/mysql.py +0 -26
- flowerpower/plugins/io/loader/oracle.py +0 -26
- flowerpower/plugins/io/loader/parquet.py +0 -35
- flowerpower/plugins/io/loader/postgres.py +0 -26
- flowerpower/plugins/io/loader/pydala.py +0 -19
- flowerpower/plugins/io/loader/sqlite.py +0 -23
- flowerpower/plugins/io/metadata.py +0 -244
- flowerpower/plugins/io/saver/__init__.py +0 -28
- flowerpower/plugins/io/saver/csv.py +0 -36
- flowerpower/plugins/io/saver/deltatable.py +0 -186
- flowerpower/plugins/io/saver/duckdb.py +0 -19
- flowerpower/plugins/io/saver/json.py +0 -36
- flowerpower/plugins/io/saver/mqtt.py +0 -28
- flowerpower/plugins/io/saver/mssql.py +0 -26
- flowerpower/plugins/io/saver/mysql.py +0 -26
- flowerpower/plugins/io/saver/oracle.py +0 -26
- flowerpower/plugins/io/saver/parquet.py +0 -36
- flowerpower/plugins/io/saver/postgres.py +0 -26
- flowerpower/plugins/io/saver/pydala.py +0 -20
- flowerpower/plugins/io/saver/sqlite.py +0 -24
- flowerpower/utils/scheduler.py +0 -311
- flowerpower-0.11.6.20.dist-info/RECORD +0 -102
- {flowerpower-0.11.6.20.dist-info → flowerpower-0.20.0.dist-info}/WHEEL +0 -0
- {flowerpower-0.11.6.20.dist-info → flowerpower-0.20.0.dist-info}/entry_points.txt +0 -0
- {flowerpower-0.11.6.20.dist-info → flowerpower-0.20.0.dist-info}/licenses/LICENSE +0 -0
- {flowerpower-0.11.6.20.dist-info → flowerpower-0.20.0.dist-info}/top_level.txt +0 -0
flowerpower/cfg/__init__.py
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
from pathlib import Path
|
2
2
|
|
3
3
|
import msgspec
|
4
|
+
from fsspec_utils import AbstractFileSystem, BaseStorageOptions, filesystem
|
4
5
|
from munch import Munch
|
5
6
|
|
6
|
-
from ..fs import AbstractFileSystem, BaseStorageOptions, get_filesystem
|
7
7
|
from .base import BaseConfig
|
8
8
|
from .pipeline import PipelineConfig, init_pipeline_config
|
9
9
|
from .project import ProjectConfig, init_project_config
|
@@ -77,7 +77,7 @@ class Config(BaseConfig):
|
|
77
77
|
```
|
78
78
|
"""
|
79
79
|
if fs is None:
|
80
|
-
fs =
|
80
|
+
fs = filesystem(
|
81
81
|
base_dir, cached=True, dirfs=True, storage_options=storage_options
|
82
82
|
)
|
83
83
|
project = ProjectConfig.load(
|
@@ -123,7 +123,7 @@ class Config(BaseConfig):
|
|
123
123
|
```
|
124
124
|
"""
|
125
125
|
if fs is None and self.fs is None:
|
126
|
-
self.fs =
|
126
|
+
self.fs = filesystem(
|
127
127
|
self.base_dir, cached=True, dirfs=True, **storage_options
|
128
128
|
)
|
129
129
|
|
@@ -1,12 +1,14 @@
|
|
1
1
|
import msgspec
|
2
2
|
import yaml
|
3
|
+
from fsspec_utils import AbstractFileSystem, BaseStorageOptions, filesystem
|
3
4
|
from hamilton.function_modifiers import source, value
|
4
5
|
from munch import Munch, munchify
|
5
6
|
|
6
|
-
from ...fs import AbstractFileSystem, BaseStorageOptions, get_filesystem
|
7
7
|
from ..base import BaseConfig
|
8
8
|
from .adapter import AdapterConfig
|
9
|
+
from .run import ExecutorConfig as ExecutorConfig
|
9
10
|
from .run import RunConfig
|
11
|
+
from .run import WithAdapterConfig as WithAdapterConfig
|
10
12
|
from .schedule import ScheduleConfig
|
11
13
|
|
12
14
|
|
@@ -166,7 +168,7 @@ class PipelineConfig(BaseConfig):
|
|
166
168
|
```
|
167
169
|
"""
|
168
170
|
if fs is None:
|
169
|
-
fs =
|
171
|
+
fs = filesystem(
|
170
172
|
base_dir, cached=False, dirfs=True, storage_options=storage_options
|
171
173
|
)
|
172
174
|
if fs.exists("conf/pipelines"):
|
@@ -207,7 +209,7 @@ class PipelineConfig(BaseConfig):
|
|
207
209
|
```
|
208
210
|
"""
|
209
211
|
if fs is None:
|
210
|
-
fs =
|
212
|
+
fs = filesystem(
|
211
213
|
base_dir, cached=True, dirfs=True, storage_options=storage_options
|
212
214
|
)
|
213
215
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import msgspec
|
2
|
+
from fsspec_utils import AbstractFileSystem, BaseStorageOptions, filesystem
|
2
3
|
|
3
|
-
from ...fs import AbstractFileSystem, BaseStorageOptions, get_filesystem
|
4
4
|
from ..base import BaseConfig
|
5
5
|
from .adapter import AdapterConfig
|
6
6
|
from .job_queue import JobQueueConfig
|
@@ -71,7 +71,7 @@ class ProjectConfig(BaseConfig):
|
|
71
71
|
```
|
72
72
|
"""
|
73
73
|
if fs is None:
|
74
|
-
fs =
|
74
|
+
fs = filesystem(
|
75
75
|
base_dir, cached=False, dirfs=True, storage_options=storage_options
|
76
76
|
)
|
77
77
|
if fs.exists("conf/project.yml"):
|
@@ -103,7 +103,7 @@ class ProjectConfig(BaseConfig):
|
|
103
103
|
```
|
104
104
|
"""
|
105
105
|
if fs is None:
|
106
|
-
fs =
|
106
|
+
fs = filesystem(
|
107
107
|
base_dir, cached=True, dirfs=True, storage_options=storage_options
|
108
108
|
)
|
109
109
|
|
@@ -1,5 +1,3 @@
|
|
1
|
-
import datetime as dt
|
2
|
-
import importlib
|
3
1
|
import os
|
4
2
|
|
5
3
|
import msgspec
|
@@ -29,120 +27,6 @@ class JobQueueBackendConfig(BaseConfig):
|
|
29
27
|
verify_ssl: bool = msgspec.field(default=False)
|
30
28
|
|
31
29
|
|
32
|
-
class APSDataStoreConfig(JobQueueBackendConfig):
|
33
|
-
type: str = msgspec.field(default=settings.APS_BACKEND_DS or "memory")
|
34
|
-
username: str | None = msgspec.field(default=None)
|
35
|
-
password: str | None = msgspec.field(default=None)
|
36
|
-
host: str | None = msgspec.field(default=None)
|
37
|
-
port: int | None = msgspec.field(default=None)
|
38
|
-
database: str | None = msgspec.field(default=None)
|
39
|
-
schema: str | None = msgspec.field(default=None)
|
40
|
-
|
41
|
-
def __post_init__(self):
|
42
|
-
self.update_settings_from_env()
|
43
|
-
self.host = (
|
44
|
-
settings.APS_BACKEND_DS_HOST
|
45
|
-
or BACKEND_PROPERTIES[self.type]["default_host"]
|
46
|
-
)
|
47
|
-
self.port = (
|
48
|
-
settings.APS_BACKEND_DS_PORT
|
49
|
-
or BACKEND_PROPERTIES[self.type]["default_port"]
|
50
|
-
)
|
51
|
-
self.database = (
|
52
|
-
settings.APS_BACKEND_DS_DB
|
53
|
-
or BACKEND_PROPERTIES[self.type]["default_database"]
|
54
|
-
)
|
55
|
-
self.username = (
|
56
|
-
settings.APS_BACKEND_DS_USERNAME
|
57
|
-
or BACKEND_PROPERTIES[self.type]["default_username"]
|
58
|
-
)
|
59
|
-
self.password = (
|
60
|
-
settings.APS_BACKEND_DS_PASSWORD
|
61
|
-
or BACKEND_PROPERTIES[self.type]["default_password"]
|
62
|
-
)
|
63
|
-
|
64
|
-
def update_settings_from_env(self):
|
65
|
-
if os.getenv("FP_APS_BACKEND_DS") is not None:
|
66
|
-
settings.APS_BACKEND_DS = os.getenv("FP_APS_BACKEND_DS")
|
67
|
-
if os.getenv("FP_APS_BACKEND_DS_USERNAME") is not None:
|
68
|
-
settings.APS_BACKEND_DS_USERNAME = os.getenv("FP_APS_BACKEND_DS_USERNAME")
|
69
|
-
if os.getenv("FP_APS_BACKEND_DS_PASSWORD") is not None:
|
70
|
-
settings.APS_BACKEND_DS_PASSWORD = os.getenv("FP_APS_BACKEND_DS_PASSWORD")
|
71
|
-
if os.getenv("FP_APS_BACKEND_DS_HOST") is not None:
|
72
|
-
settings.APS_BACKEND_DS_HOST = os.getenv("FP_APS_BACKEND_DS_HOST")
|
73
|
-
if os.getenv("FP_APS_BACKEND_DS_PORT") is not None:
|
74
|
-
settings.APS_BACKEND_DS_PORT = int(os.getenv("FP_APS_BACKEND_DS_PORT"))
|
75
|
-
if os.getenv("FP_APS_BACKEND_DS_DB") is not None:
|
76
|
-
settings.APS_BACKEND_DS_DB = os.getenv("FP_APS_BACKEND_DS_DB")
|
77
|
-
|
78
|
-
|
79
|
-
class APSEventBrokerConfig(JobQueueBackendConfig):
|
80
|
-
type: str = msgspec.field(default=settings.APS_BACKEND_EB or "memory")
|
81
|
-
username: str | None = msgspec.field(default=None)
|
82
|
-
password: str | None = msgspec.field(default=None)
|
83
|
-
host: str | None = msgspec.field(default=None)
|
84
|
-
port: int | None = msgspec.field(default=None)
|
85
|
-
database: str | None = msgspec.field(default=None)
|
86
|
-
from_ds_sqla: bool = msgspec.field(
|
87
|
-
default_factory=lambda: settings.APS_BACKEND_EB == "postgresql"
|
88
|
-
and settings.APS_BACKEND_DS == "postgresql"
|
89
|
-
)
|
90
|
-
|
91
|
-
def __post_init__(self):
|
92
|
-
self.update_settings_from_env()
|
93
|
-
self.host = (
|
94
|
-
settings.APS_BACKEND_EB_HOST
|
95
|
-
or BACKEND_PROPERTIES[self.type]["default_host"]
|
96
|
-
)
|
97
|
-
self.port = (
|
98
|
-
settings.APS_BACKEND_EB_PORT
|
99
|
-
or BACKEND_PROPERTIES[self.type]["default_port"]
|
100
|
-
)
|
101
|
-
self.database = (
|
102
|
-
settings.APS_BACKEND_EB_DB
|
103
|
-
or BACKEND_PROPERTIES[self.type]["default_database"]
|
104
|
-
)
|
105
|
-
self.username = (
|
106
|
-
settings.APS_BACKEND_EB_USERNAME
|
107
|
-
or BACKEND_PROPERTIES[self.type]["default_username"]
|
108
|
-
)
|
109
|
-
self.password = (
|
110
|
-
settings.APS_BACKEND_EB_PASSWORD
|
111
|
-
or BACKEND_PROPERTIES[self.type]["default_password"]
|
112
|
-
)
|
113
|
-
|
114
|
-
def update_settings_from_env(self):
|
115
|
-
if os.getenv("FP_APS_BACKEND_EB") is not None:
|
116
|
-
settings.APS_BACKEND_EB = os.getenv("FP_APS_BACKEND_EB")
|
117
|
-
if os.getenv("FP_APS_BACKEND_EB_USERNAME") is not None:
|
118
|
-
settings.APS_BACKEND_EB_USERNAME = os.getenv("FP_APS_BACKEND_EB_USERNAME")
|
119
|
-
if os.getenv("FP_APS_BACKEND_EB_PASSWORD") is not None:
|
120
|
-
settings.APS_BACKEND_EB_PASSWORD = os.getenv("FP_APS_BACKEND_EB_PASSWORD")
|
121
|
-
if os.getenv("FP_APS_BACKEND_EB_HOST") is not None:
|
122
|
-
settings.APS_BACKEND_EB_HOST = os.getenv("FP_APS_BACKEND_EB_HOST")
|
123
|
-
if os.getenv("FP_APS_BACKEND_EB_PORT") is not None:
|
124
|
-
settings.APS_BACKEND_EB_PORT = int(os.getenv("FP_APS_BACKEND_EB_PORT"))
|
125
|
-
if os.getenv("FP_APS_BACKEND_EB_DB") is not None:
|
126
|
-
settings.APS_BACKEND_EB_DB = os.getenv("FP_APS_BACKEND_EB_DB")
|
127
|
-
|
128
|
-
|
129
|
-
class APSBackendConfig(BaseConfig):
|
130
|
-
data_store: APSDataStoreConfig = msgspec.field(default_factory=APSDataStoreConfig)
|
131
|
-
event_broker: APSEventBrokerConfig = msgspec.field(
|
132
|
-
default_factory=APSEventBrokerConfig
|
133
|
-
)
|
134
|
-
cleanup_interval: int | float | dt.timedelta = msgspec.field(
|
135
|
-
default=settings.APS_CLEANUP_INTERVAL
|
136
|
-
) # int in seconds
|
137
|
-
max_concurrent_jobs: int = msgspec.field(default=settings.APS_MAX_CONCURRENT_JOBS)
|
138
|
-
default_job_executor: str | None = msgspec.field(default=settings.EXECUTOR)
|
139
|
-
# num_workers: int | None = msgspec.field(default=settings.APS_NUM_WORKERS)
|
140
|
-
|
141
|
-
# def __post_init__(self):
|
142
|
-
# self.data_store.update_settings_from_env()
|
143
|
-
# self.event_broker.update_settings_from_env()
|
144
|
-
|
145
|
-
|
146
30
|
class RQBackendConfig(JobQueueBackendConfig):
|
147
31
|
type: str = msgspec.field(default="redis")
|
148
32
|
username: str | None = msgspec.field(default=settings.RQ_BACKEND_USERNAME)
|
@@ -215,20 +99,9 @@ class JobQueueConfig(BaseConfig):
|
|
215
99
|
)
|
216
100
|
self.num_workers = self.num_workers or settings.RQ_NUM_WORKERS
|
217
101
|
|
218
|
-
elif self.type == "apscheduler":
|
219
|
-
self.backend = self.backend or APSBackendConfig()
|
220
|
-
if isinstance(self.backend, dict):
|
221
|
-
self.backend = APSBackendConfig.from_dict(self.backend)
|
222
|
-
elif isinstance(self.backend, APSBackendConfig):
|
223
|
-
pass
|
224
|
-
else:
|
225
|
-
raise ValueError(
|
226
|
-
f"Invalid backend type for APScheduler: {type(self.backend)}"
|
227
|
-
)
|
228
|
-
self.num_workers = self.num_workers or settings.APS_NUM_WORKERS
|
229
102
|
else:
|
230
103
|
raise ValueError(
|
231
|
-
f"Invalid job queue type: {self.type}. Valid types:
|
104
|
+
f"Invalid job queue type: {self.type}. Valid types: ['rq']"
|
232
105
|
)
|
233
106
|
|
234
107
|
def update_type(self, type: str):
|
flowerpower/cli/__init__.py
CHANGED
@@ -18,7 +18,7 @@ app.add_typer(
|
|
18
18
|
pipeline_app, name="pipeline", help="Manage and execute FlowerPower pipelines"
|
19
19
|
)
|
20
20
|
|
21
|
-
if importlib.util.find_spec("
|
21
|
+
if importlib.util.find_spec("rq"):
|
22
22
|
from .job_queue import app as job_queue_app
|
23
23
|
|
24
24
|
app.add_typer(
|
@@ -53,7 +53,7 @@ def init(
|
|
53
53
|
"rq",
|
54
54
|
"--job-queue-type",
|
55
55
|
"-q",
|
56
|
-
help="Job queue backend type to use (rq
|
56
|
+
help="Job queue backend type to use (rq)",
|
57
57
|
),
|
58
58
|
):
|
59
59
|
"""
|
@@ -69,7 +69,7 @@ def init(
|
|
69
69
|
base_dir: Base directory where the project will be created. If not provided,
|
70
70
|
the current directory's parent will be used
|
71
71
|
storage_options: Storage options for filesystem access, as a JSON or dict string
|
72
|
-
job_queue_type: Type of job queue backend to use (rq
|
72
|
+
job_queue_type: Type of job queue backend to use (rq)
|
73
73
|
|
74
74
|
Examples:
|
75
75
|
# Create a project in the current directory using its name
|
@@ -81,8 +81,8 @@ def init(
|
|
81
81
|
# Create a project in a specific location
|
82
82
|
$ flowerpower init --name my-project --base-dir /path/to/projects
|
83
83
|
|
84
|
-
# Create a project with
|
85
|
-
$ flowerpower init --job-queue-type
|
84
|
+
# Create a project with RQ as the job queue backend (default)
|
85
|
+
$ flowerpower init --job-queue-type rq
|
86
86
|
"""
|
87
87
|
parsed_storage_options = {}
|
88
88
|
if storage_options:
|