ddeutil-workflow 0.0.1__tar.gz

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 (44) hide show
  1. ddeutil_workflow-0.0.1/LICENSE +21 -0
  2. ddeutil_workflow-0.0.1/PKG-INFO +251 -0
  3. ddeutil_workflow-0.0.1/README.md +215 -0
  4. ddeutil_workflow-0.0.1/pyproject.toml +136 -0
  5. ddeutil_workflow-0.0.1/setup.cfg +4 -0
  6. ddeutil_workflow-0.0.1/src/ddeutil/workflow/__about__.py +1 -0
  7. ddeutil_workflow-0.0.1/src/ddeutil/workflow/__init__.py +0 -0
  8. ddeutil_workflow-0.0.1/src/ddeutil/workflow/__regex.py +44 -0
  9. ddeutil_workflow-0.0.1/src/ddeutil/workflow/__types.py +11 -0
  10. ddeutil_workflow-0.0.1/src/ddeutil/workflow/conn.py +235 -0
  11. ddeutil_workflow-0.0.1/src/ddeutil/workflow/dataset.py +306 -0
  12. ddeutil_workflow-0.0.1/src/ddeutil/workflow/exceptions.py +82 -0
  13. ddeutil_workflow-0.0.1/src/ddeutil/workflow/hooks/__init__.py +9 -0
  14. ddeutil_workflow-0.0.1/src/ddeutil/workflow/hooks/_postgres.py +2 -0
  15. ddeutil_workflow-0.0.1/src/ddeutil/workflow/loader.py +310 -0
  16. ddeutil_workflow-0.0.1/src/ddeutil/workflow/pipeline.py +338 -0
  17. ddeutil_workflow-0.0.1/src/ddeutil/workflow/schedule.py +87 -0
  18. ddeutil_workflow-0.0.1/src/ddeutil/workflow/tasks/__init__.py +10 -0
  19. ddeutil_workflow-0.0.1/src/ddeutil/workflow/tasks/_polars.py +41 -0
  20. ddeutil_workflow-0.0.1/src/ddeutil/workflow/utils/__init__.py +0 -0
  21. ddeutil_workflow-0.0.1/src/ddeutil/workflow/utils/receive.py +33 -0
  22. ddeutil_workflow-0.0.1/src/ddeutil/workflow/utils/selection.py +2 -0
  23. ddeutil_workflow-0.0.1/src/ddeutil/workflow/vendors/__dict.py +333 -0
  24. ddeutil_workflow-0.0.1/src/ddeutil/workflow/vendors/__init__.py +0 -0
  25. ddeutil_workflow-0.0.1/src/ddeutil/workflow/vendors/__schedule.py +667 -0
  26. ddeutil_workflow-0.0.1/src/ddeutil/workflow/vendors/aws_warpped.py +185 -0
  27. ddeutil_workflow-0.0.1/src/ddeutil/workflow/vendors/minio_warpped.py +11 -0
  28. ddeutil_workflow-0.0.1/src/ddeutil/workflow/vendors/sftp_wrapped.py +209 -0
  29. ddeutil_workflow-0.0.1/src/ddeutil_workflow.egg-info/PKG-INFO +251 -0
  30. ddeutil_workflow-0.0.1/src/ddeutil_workflow.egg-info/SOURCES.txt +42 -0
  31. ddeutil_workflow-0.0.1/src/ddeutil_workflow.egg-info/dependency_links.txt +1 -0
  32. ddeutil_workflow-0.0.1/src/ddeutil_workflow.egg-info/requires.txt +13 -0
  33. ddeutil_workflow-0.0.1/src/ddeutil_workflow.egg-info/top_level.txt +1 -0
  34. ddeutil_workflow-0.0.1/tests/test_base_data.py +14 -0
  35. ddeutil_workflow-0.0.1/tests/test_base_local_and_global.py +158 -0
  36. ddeutil_workflow-0.0.1/tests/test_base_regex.py +46 -0
  37. ddeutil_workflow-0.0.1/tests/test_conn.py +94 -0
  38. ddeutil_workflow-0.0.1/tests/test_dataset.py +88 -0
  39. ddeutil_workflow-0.0.1/tests/test_loader.py +51 -0
  40. ddeutil_workflow-0.0.1/tests/test_loader_simple.py +89 -0
  41. ddeutil_workflow-0.0.1/tests/test_pipeline.py +46 -0
  42. ddeutil_workflow-0.0.1/tests/test_pipeline_run.py +117 -0
  43. ddeutil_workflow-0.0.1/tests/test_pipeline_task.py +11 -0
  44. ddeutil_workflow-0.0.1/tests/test_schedule.py +55 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Data Developer & Engineering
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,251 @@
1
+ Metadata-Version: 2.1
2
+ Name: ddeutil-workflow
3
+ Version: 0.0.1
4
+ Summary: Data Developer & Engineer Workflow Utility Objects
5
+ Author-email: ddeutils <korawich.anu@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/ddeutils/ddeutil-workflow/
8
+ Project-URL: Source Code, https://github.com/ddeutils/ddeutil-workflow/
9
+ Keywords: data,workflow,utility,pipeline
10
+ Classifier: Topic :: Utilities
11
+ Classifier: Natural Language :: English
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Requires-Python: >=3.9.13
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: fmtutil
25
+ Requires-Dist: ddeutil-io
26
+ Requires-Dist: ddeutil-model
27
+ Requires-Dist: python-dotenv
28
+ Provides-Extra: test
29
+ Requires-Dist: sqlalchemy==2.0.30; extra == "test"
30
+ Requires-Dist: paramiko==3.4.0; extra == "test"
31
+ Requires-Dist: sshtunnel==0.4.0; extra == "test"
32
+ Requires-Dist: boto3==1.34.109; extra == "test"
33
+ Requires-Dist: fsspec==2024.5.0; extra == "test"
34
+ Requires-Dist: polars==0.20.26; extra == "test"
35
+ Requires-Dist: pyarrow==16.1.0; extra == "test"
36
+
37
+ # Data Utility: _Workflow_
38
+
39
+ [![test](https://github.com/ddeutils/ddeutil-workflow/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/ddeutils/ddeutil-workflow/actions/workflows/tests.yml)
40
+ [![python support version](https://img.shields.io/pypi/pyversions/ddeutil-workflow)](https://pypi.org/project/ddeutil-workflow/)
41
+ [![size](https://img.shields.io/github/languages/code-size/ddeutils/ddeutil-workflow)](https://github.com/ddeutils/ddeutil-workflow)
42
+
43
+ **Table of Contents**:
44
+
45
+ - [Installation](#installation)
46
+ - [Getting Started](#getting-started)
47
+ - [Connection](#connection)
48
+ - [Dataset](#dataset)
49
+ - [Schedule](#schedule)
50
+ - [Examples](#examples)
51
+ - [Python](#python)
52
+ - [Tasks (EL)](#tasks-extract--load)
53
+ - [Hooks (T)](#hooks-transform)
54
+
55
+ This **Utility Workflow** objects was created for easy to make a simple metadata
56
+ driven pipeline that able to **ETL, T, EL, or ELT** by `.yaml` file.
57
+
58
+ I think we should not create the multiple pipeline per use-case if we able to
59
+ write some dynamic pipeline that just change the input parameters per use-case
60
+ instead. This way we can handle a lot of pipelines in our orgs with metadata only.
61
+ It called **Metadata Driven**.
62
+
63
+ Next, we should get some monitoring tools for manage logging that return from
64
+ pipeline running. Because it not show us what is a use-case that running data
65
+ pipeline.
66
+
67
+ > [!NOTE]
68
+ > _Disclaimer_: I inspire the dynamic statement from the GitHub Action `.yml` files
69
+ > and all of config file from several data orchestration framework tools from my
70
+ > experience on Data Engineer.
71
+
72
+ ## Installation
73
+
74
+ ```shell
75
+ pip install ddeutil-workflow
76
+ ```
77
+
78
+ This project need `ddeutil-io`, `ddeutil-model` extension namespace packages.
79
+
80
+ ## Getting Started
81
+
82
+ The first step, you should start create the connections and datasets for In and
83
+ Out of you data that want to use in pipeline of workflow. Some of this component
84
+ is similar component of the **Airflow** because I like it concepts.
85
+
86
+ ### Connection
87
+
88
+ The connection for worker able to do any thing.
89
+
90
+ ```yaml
91
+ conn_postgres_data:
92
+ type: conn.Postgres
93
+ url: 'postgres//username:${ENV_PASS}@hostname:port/database?echo=True&time_out=10'
94
+ ```
95
+
96
+ ```python
97
+ from ddeutil.workflow.conn import Conn
98
+
99
+ conn = Conn.from_loader(name='conn_postgres_data', externals={})
100
+ assert conn.ping()
101
+ ```
102
+
103
+ ### Dataset
104
+
105
+ The dataset is define any objects on the connection.
106
+
107
+ ```yaml
108
+ ds_postgres_customer_tbl:
109
+ type: dataset.PostgresTbl
110
+ conn: 'conn_postgres_data'
111
+ features:
112
+ id: serial primary key
113
+ name: varchar( 100 ) not null
114
+ ```
115
+
116
+ ```python
117
+ from ddeutil.workflow.dataset import PostgresTbl
118
+
119
+ dataset = PostgresTbl.from_loader(name='ds_postgres_customer_tbl', externals={})
120
+ assert dataset.exists()
121
+ ```
122
+
123
+ ### Schedule
124
+
125
+ ```yaml
126
+ schd_for_node:
127
+ type: schedule.Scdl
128
+ cron: "*/5 * * * *"
129
+ ```
130
+
131
+ ```python
132
+ from ddeutil.workflow.schedule import Scdl
133
+
134
+ scdl = Scdl.from_loader(name='schd_for_node', externals={})
135
+ assert '*/5 * * * *' == str(scdl.cronjob)
136
+
137
+ cron_iterate = scdl.generate('2022-01-01 00:00:00')
138
+ assert '2022-01-01 00:05:00' f"{cron_iterate.next:%Y-%m-%d %H:%M:%S}"
139
+ assert '2022-01-01 00:10:00' f"{cron_iterate.next:%Y-%m-%d %H:%M:%S}"
140
+ assert '2022-01-01 00:15:00' f"{cron_iterate.next:%Y-%m-%d %H:%M:%S}"
141
+ assert '2022-01-01 00:20:00' f"{cron_iterate.next:%Y-%m-%d %H:%M:%S}"
142
+ assert '2022-01-01 00:25:00' f"{cron_iterate.next:%Y-%m-%d %H:%M:%S}"
143
+ ```
144
+
145
+ ## Examples
146
+
147
+ This is examples that use workflow file for running common Data Engineering
148
+ use-case.
149
+
150
+ ### Python
151
+
152
+ The state of doing lists that worker should to do. It be collection of the stage.
153
+
154
+ ```yaml
155
+ run_py_local:
156
+ type: ddeutil.workflow.pipe.Pipeline
157
+ params:
158
+ author-run: utils.receive.string
159
+ run-date: utils.receive.datetime
160
+ jobs:
161
+ first-job:
162
+ stages:
163
+ - name: Printing Information
164
+ id: define-func
165
+ run: |
166
+ x = '${{ params.author-run }}'
167
+ print(f'Hello {x}')
168
+
169
+ def echo(name: str):
170
+ print(f'Hello {name}')
171
+
172
+ - name: Run Sequence and use var from Above
173
+ vars:
174
+ x: ${{ params.author-run }}
175
+ run: |
176
+ print(f'Receive x from above with {x}')
177
+ # Change x value
178
+ x: int = 1
179
+
180
+ - name: Call Function
181
+ vars:
182
+ echo: ${{ stages.define-func.outputs.echo }}
183
+ run: |
184
+ echo('Caller')
185
+ ```
186
+
187
+ ```python
188
+ from ddeutil.workflow.pipeline import Pipeline
189
+
190
+ pipe = Pipeline.from_loader(name='run_py_local', externals={})
191
+ pipe.execute(params={'author-run': 'Local Workflow', 'run-date': '2024-01-01'})
192
+ ```
193
+
194
+ ```shell
195
+ > Hello Local Workflow
196
+ > Receive x from above with Local Workflow
197
+ > Hello Caller
198
+ ```
199
+
200
+ ### Tasks (Extract & Load)
201
+
202
+ ```yaml
203
+ pipe_el_pg_to_lake:
204
+ type: ddeutil.workflow.pipe.Pipeline
205
+ params:
206
+ run-date: utils.receive.datetime
207
+ author-email: utils.receive.string
208
+ jobs:
209
+ extract-load:
210
+ stages:
211
+ - name: "Extract Load from Postgres to Lake"
212
+ id: extract
213
+ task: tasks/postgres-to-delta@polars
214
+ with:
215
+ source:
216
+ conn: conn_postgres_url
217
+ query: |
218
+ select * from ${{ params.name }}
219
+ where update_date = '${{ params.datetime }}'
220
+ sink:
221
+ conn: conn_az_lake
222
+ endpoint: "/${{ params.name }}"
223
+ ```
224
+
225
+ ### Hooks (Transform)
226
+
227
+ ```yaml
228
+ pipe_hook_mssql_proc:
229
+ type: ddeutil.workflow.pipe.Pipeline
230
+ params:
231
+ run_date: utils.receive.datetime
232
+ sp_name: utils.receive.string
233
+ source_name: utils.receive.string
234
+ target_name: utils.receive.string
235
+ jobs:
236
+ transform:
237
+ stages:
238
+ - name: "Transform Data in MS SQL Server"
239
+ hook: hooks/mssql-proc@odbc
240
+ with:
241
+ exec: ${{ params.sp_name }}
242
+ params:
243
+ run_mode: "T"
244
+ run_date: ${{ params.run_date }}
245
+ source: ${{ params.source_name }}
246
+ target: ${{ params.target_name }}
247
+ ```
248
+
249
+ ## License
250
+
251
+ This project was licensed under the terms of the [MIT license](LICENSE).
@@ -0,0 +1,215 @@
1
+ # Data Utility: _Workflow_
2
+
3
+ [![test](https://github.com/ddeutils/ddeutil-workflow/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/ddeutils/ddeutil-workflow/actions/workflows/tests.yml)
4
+ [![python support version](https://img.shields.io/pypi/pyversions/ddeutil-workflow)](https://pypi.org/project/ddeutil-workflow/)
5
+ [![size](https://img.shields.io/github/languages/code-size/ddeutils/ddeutil-workflow)](https://github.com/ddeutils/ddeutil-workflow)
6
+
7
+ **Table of Contents**:
8
+
9
+ - [Installation](#installation)
10
+ - [Getting Started](#getting-started)
11
+ - [Connection](#connection)
12
+ - [Dataset](#dataset)
13
+ - [Schedule](#schedule)
14
+ - [Examples](#examples)
15
+ - [Python](#python)
16
+ - [Tasks (EL)](#tasks-extract--load)
17
+ - [Hooks (T)](#hooks-transform)
18
+
19
+ This **Utility Workflow** objects was created for easy to make a simple metadata
20
+ driven pipeline that able to **ETL, T, EL, or ELT** by `.yaml` file.
21
+
22
+ I think we should not create the multiple pipeline per use-case if we able to
23
+ write some dynamic pipeline that just change the input parameters per use-case
24
+ instead. This way we can handle a lot of pipelines in our orgs with metadata only.
25
+ It called **Metadata Driven**.
26
+
27
+ Next, we should get some monitoring tools for manage logging that return from
28
+ pipeline running. Because it not show us what is a use-case that running data
29
+ pipeline.
30
+
31
+ > [!NOTE]
32
+ > _Disclaimer_: I inspire the dynamic statement from the GitHub Action `.yml` files
33
+ > and all of config file from several data orchestration framework tools from my
34
+ > experience on Data Engineer.
35
+
36
+ ## Installation
37
+
38
+ ```shell
39
+ pip install ddeutil-workflow
40
+ ```
41
+
42
+ This project need `ddeutil-io`, `ddeutil-model` extension namespace packages.
43
+
44
+ ## Getting Started
45
+
46
+ The first step, you should start create the connections and datasets for In and
47
+ Out of you data that want to use in pipeline of workflow. Some of this component
48
+ is similar component of the **Airflow** because I like it concepts.
49
+
50
+ ### Connection
51
+
52
+ The connection for worker able to do any thing.
53
+
54
+ ```yaml
55
+ conn_postgres_data:
56
+ type: conn.Postgres
57
+ url: 'postgres//username:${ENV_PASS}@hostname:port/database?echo=True&time_out=10'
58
+ ```
59
+
60
+ ```python
61
+ from ddeutil.workflow.conn import Conn
62
+
63
+ conn = Conn.from_loader(name='conn_postgres_data', externals={})
64
+ assert conn.ping()
65
+ ```
66
+
67
+ ### Dataset
68
+
69
+ The dataset is define any objects on the connection.
70
+
71
+ ```yaml
72
+ ds_postgres_customer_tbl:
73
+ type: dataset.PostgresTbl
74
+ conn: 'conn_postgres_data'
75
+ features:
76
+ id: serial primary key
77
+ name: varchar( 100 ) not null
78
+ ```
79
+
80
+ ```python
81
+ from ddeutil.workflow.dataset import PostgresTbl
82
+
83
+ dataset = PostgresTbl.from_loader(name='ds_postgres_customer_tbl', externals={})
84
+ assert dataset.exists()
85
+ ```
86
+
87
+ ### Schedule
88
+
89
+ ```yaml
90
+ schd_for_node:
91
+ type: schedule.Scdl
92
+ cron: "*/5 * * * *"
93
+ ```
94
+
95
+ ```python
96
+ from ddeutil.workflow.schedule import Scdl
97
+
98
+ scdl = Scdl.from_loader(name='schd_for_node', externals={})
99
+ assert '*/5 * * * *' == str(scdl.cronjob)
100
+
101
+ cron_iterate = scdl.generate('2022-01-01 00:00:00')
102
+ assert '2022-01-01 00:05:00' f"{cron_iterate.next:%Y-%m-%d %H:%M:%S}"
103
+ assert '2022-01-01 00:10:00' f"{cron_iterate.next:%Y-%m-%d %H:%M:%S}"
104
+ assert '2022-01-01 00:15:00' f"{cron_iterate.next:%Y-%m-%d %H:%M:%S}"
105
+ assert '2022-01-01 00:20:00' f"{cron_iterate.next:%Y-%m-%d %H:%M:%S}"
106
+ assert '2022-01-01 00:25:00' f"{cron_iterate.next:%Y-%m-%d %H:%M:%S}"
107
+ ```
108
+
109
+ ## Examples
110
+
111
+ This is examples that use workflow file for running common Data Engineering
112
+ use-case.
113
+
114
+ ### Python
115
+
116
+ The state of doing lists that worker should to do. It be collection of the stage.
117
+
118
+ ```yaml
119
+ run_py_local:
120
+ type: ddeutil.workflow.pipe.Pipeline
121
+ params:
122
+ author-run: utils.receive.string
123
+ run-date: utils.receive.datetime
124
+ jobs:
125
+ first-job:
126
+ stages:
127
+ - name: Printing Information
128
+ id: define-func
129
+ run: |
130
+ x = '${{ params.author-run }}'
131
+ print(f'Hello {x}')
132
+
133
+ def echo(name: str):
134
+ print(f'Hello {name}')
135
+
136
+ - name: Run Sequence and use var from Above
137
+ vars:
138
+ x: ${{ params.author-run }}
139
+ run: |
140
+ print(f'Receive x from above with {x}')
141
+ # Change x value
142
+ x: int = 1
143
+
144
+ - name: Call Function
145
+ vars:
146
+ echo: ${{ stages.define-func.outputs.echo }}
147
+ run: |
148
+ echo('Caller')
149
+ ```
150
+
151
+ ```python
152
+ from ddeutil.workflow.pipeline import Pipeline
153
+
154
+ pipe = Pipeline.from_loader(name='run_py_local', externals={})
155
+ pipe.execute(params={'author-run': 'Local Workflow', 'run-date': '2024-01-01'})
156
+ ```
157
+
158
+ ```shell
159
+ > Hello Local Workflow
160
+ > Receive x from above with Local Workflow
161
+ > Hello Caller
162
+ ```
163
+
164
+ ### Tasks (Extract & Load)
165
+
166
+ ```yaml
167
+ pipe_el_pg_to_lake:
168
+ type: ddeutil.workflow.pipe.Pipeline
169
+ params:
170
+ run-date: utils.receive.datetime
171
+ author-email: utils.receive.string
172
+ jobs:
173
+ extract-load:
174
+ stages:
175
+ - name: "Extract Load from Postgres to Lake"
176
+ id: extract
177
+ task: tasks/postgres-to-delta@polars
178
+ with:
179
+ source:
180
+ conn: conn_postgres_url
181
+ query: |
182
+ select * from ${{ params.name }}
183
+ where update_date = '${{ params.datetime }}'
184
+ sink:
185
+ conn: conn_az_lake
186
+ endpoint: "/${{ params.name }}"
187
+ ```
188
+
189
+ ### Hooks (Transform)
190
+
191
+ ```yaml
192
+ pipe_hook_mssql_proc:
193
+ type: ddeutil.workflow.pipe.Pipeline
194
+ params:
195
+ run_date: utils.receive.datetime
196
+ sp_name: utils.receive.string
197
+ source_name: utils.receive.string
198
+ target_name: utils.receive.string
199
+ jobs:
200
+ transform:
201
+ stages:
202
+ - name: "Transform Data in MS SQL Server"
203
+ hook: hooks/mssql-proc@odbc
204
+ with:
205
+ exec: ${{ params.sp_name }}
206
+ params:
207
+ run_mode: "T"
208
+ run_date: ${{ params.run_date }}
209
+ source: ${{ params.source_name }}
210
+ target: ${{ params.target_name }}
211
+ ```
212
+
213
+ ## License
214
+
215
+ This project was licensed under the terms of the [MIT license](LICENSE).
@@ -0,0 +1,136 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "ddeutil-workflow"
7
+ description = "Data Developer & Engineer Workflow Utility Objects"
8
+ readme = {file = "README.md", content-type = "text/markdown"}
9
+ license = {text = "MIT"}
10
+ authors = [{ name = "ddeutils", email = "korawich.anu@gmail.com" }]
11
+ keywords = ['data', 'workflow', 'utility', 'pipeline']
12
+ classifiers = [
13
+ "Topic :: Utilities",
14
+ "Natural Language :: English",
15
+ "Development Status :: 3 - Alpha",
16
+ # "Development Status :: 4 - Beta",
17
+ # "Development Status :: 5 - Production/Stable",
18
+ "Intended Audience :: Developers",
19
+ "Operating System :: OS Independent",
20
+ "Programming Language :: Python",
21
+ "Programming Language :: Python :: 3 :: Only",
22
+ "Programming Language :: Python :: 3.9",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ "Programming Language :: Python :: 3.12",
26
+ ]
27
+ requires-python = ">=3.9.13"
28
+ dependencies = [
29
+ "fmtutil",
30
+ "ddeutil-io",
31
+ "ddeutil-model",
32
+ "python-dotenv",
33
+ ]
34
+ dynamic = ["version"]
35
+
36
+ [project.urls]
37
+ Homepage = "https://github.com/ddeutils/ddeutil-workflow/"
38
+ "Source Code" = "https://github.com/ddeutils/ddeutil-workflow/"
39
+
40
+ [project.optional-dependencies]
41
+ test = [
42
+ "sqlalchemy==2.0.30",
43
+ # SFTP warpper
44
+ "paramiko==3.4.0",
45
+ "sshtunnel==0.4.0",
46
+ # AWS
47
+ "boto3==1.34.109",
48
+ # Open files
49
+ "fsspec==2024.5.0",
50
+ # Polars
51
+ "polars==0.20.26",
52
+ "pyarrow==16.1.0",
53
+ ]
54
+
55
+ [tool.setuptools.dynamic]
56
+ version = {attr = "ddeutil.workflow.__about__.__version__"}
57
+
58
+ [tool.setuptools.packages.find]
59
+ where = ["src"]
60
+
61
+ [tool.shelf.version]
62
+ version = "./src/ddeutil/workflow/__about__.py"
63
+ changelog = "CHANGELOG.md"
64
+
65
+ [tool.coverage.run]
66
+ branch = true
67
+ relative_files = true
68
+ concurrency = ["thread", "multiprocessing"]
69
+ source = ["ddeutil", "tests"]
70
+ omit = ["scripts/"]
71
+
72
+ [tool.coverage.report]
73
+ exclude_lines = ["raise NotImplementedError"]
74
+
75
+ [tool.pytest.ini_options]
76
+ pythonpath = ["src"]
77
+ console_output_style = "count"
78
+ addopts = [
79
+ "--strict-config",
80
+ "--strict-markers",
81
+ ]
82
+ filterwarnings = ["error"]
83
+
84
+ [tool.black]
85
+ line-length = 80
86
+ target-version = ['py39']
87
+ exclude = """
88
+ (
89
+ /(
90
+ \\.git
91
+ | \\.eggs
92
+ | \\.__pycache__
93
+ | \\.idea
94
+ | \\.ruff_cache
95
+ | \\.mypy_cache
96
+ | \\.pytest_cache
97
+ | \\.venv
98
+ | build
99
+ | dist
100
+ | venv
101
+ | __legacy
102
+ )/
103
+ )
104
+ """
105
+
106
+ [tool.ruff]
107
+ line-length = 80
108
+ exclude = [
109
+ "__pypackages__",
110
+ ".git",
111
+ ".mypy_cache",
112
+ ".ruff_cache",
113
+ ".venv",
114
+ "build",
115
+ "dist",
116
+ "venv",
117
+ "__legacy",
118
+ ]
119
+
120
+ [tool.ruff.lint]
121
+ select = [
122
+ "E", # pycodestyle errors
123
+ "W", # pycodestyle warnings
124
+ "F", # pyflakes
125
+ "I", # isort
126
+ "C", # flake8-comprehensions
127
+ "B", # flake8-bugbear
128
+ ]
129
+ ignore = [
130
+ "E501", # line too long, handled by black
131
+ "B008", # do not perform function calls in argument defaults
132
+ "C901", # too complex
133
+ ]
134
+
135
+ [tool.ruff.lint.per-file-ignores]
136
+ "__init__.py" = ["F401"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1 @@
1
+ __version__: str = "0.0.1"
@@ -0,0 +1,44 @@
1
+ # -------------------------------------------------------------------------
2
+ # Copyright (c) 2022 Korawich Anuttra. All rights reserved.
3
+ # Licensed under the MIT License. See LICENSE in the project root for
4
+ # license information.
5
+ # --------------------------------------------------------------------------
6
+ import re
7
+ from re import (
8
+ IGNORECASE,
9
+ MULTILINE,
10
+ UNICODE,
11
+ VERBOSE,
12
+ Pattern,
13
+ )
14
+
15
+
16
+ class RegexConf:
17
+ """Regular expression config."""
18
+
19
+ # NOTE: Search caller
20
+ __re_caller: str = r"""
21
+ \$
22
+ {{
23
+ \s*(?P<caller>
24
+ [a-zA-Z0-9_.\s'\"\[\]\(\)\-\{}]+?
25
+ )\s*
26
+ }}
27
+ """
28
+ RE_CALLER: Pattern = re.compile(
29
+ __re_caller, MULTILINE | IGNORECASE | UNICODE | VERBOSE
30
+ )
31
+
32
+ # NOTE: Search task
33
+ __re_task_fmt: str = r"""
34
+ ^
35
+ (?P<path>[^/@]+)
36
+ /
37
+ (?P<func>[^@]+)
38
+ @
39
+ (?P<tag>.+)
40
+ $
41
+ """
42
+ RE_TASK_FMT: Pattern = re.compile(
43
+ __re_task_fmt, MULTILINE | IGNORECASE | UNICODE | VERBOSE
44
+ )
@@ -0,0 +1,11 @@
1
+ # ------------------------------------------------------------------------------
2
+ # Copyright (c) 2022 Korawich Anuttra. All rights reserved.
3
+ # Licensed under the MIT License. See LICENSE in the project root for
4
+ # license information.
5
+ # ------------------------------------------------------------------------------
6
+ from __future__ import annotations
7
+
8
+ from typing import Any
9
+
10
+ TupleStr = tuple[str, ...]
11
+ DictData = dict[str, Any]