tinyfan 0.1.1__tar.gz → 0.2.0__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.
- {tinyfan-0.1.1 → tinyfan-0.2.0}/PKG-INFO +2 -1
- tinyfan-0.2.0/examples/README.md +12 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/examples/configs.py +1 -1
- {tinyfan-0.1.1 → tinyfan-0.2.0}/pyproject.toml +9 -31
- {tinyfan-0.1.1 → tinyfan-0.2.0}/src/tinyfan/codegen.py +24 -12
- {tinyfan-0.1.1 → tinyfan-0.2.0}/src/tinyfan/flow.py +4 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/src/tinyfan/utils/merge.py +10 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/tests/test_codegen.py +12 -1
- {tinyfan-0.1.1 → tinyfan-0.2.0}/uv.lock +14 -1
- {tinyfan-0.1.1 → tinyfan-0.2.0}/.github/workflows/publish.yml +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/.gitignore +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/.python-version +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/README.md +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/examples/configmap.yaml +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/examples/getting-started.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/examples/packaged/.python-version +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/examples/packaged/Dockerfile +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/examples/packaged/README.md +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/examples/packaged/pyproject.toml +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/examples/packaged/src/tinyfan_examples_packaged/__init__.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/examples/packaged/src/tinyfan_examples_packaged/asset.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/examples/resource.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/examples/secret.yaml +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/src/tinyfan/__init__.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/src/tinyfan/argo_typing.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/src/tinyfan/cli.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/src/tinyfan/config.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/src/tinyfan/flowrundata.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/src/tinyfan/resources/__init__.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/src/tinyfan/resources/base.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/src/tinyfan/stores/__init__.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/src/tinyfan/stores/base.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/src/tinyfan/stores/bigquery.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/src/tinyfan/stores/gcs_pickle.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/src/tinyfan/stores/naive.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/src/tinyfan/utils/__init__.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/src/tinyfan/utils/embed.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/src/tinyfan/utils/exjson.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/src/tinyfan/utils/typing.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/src/tinyfan/utils/yaml.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/tests/__init__.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/tests/codegen_samples/directory/__init__.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/tests/codegen_samples/directory/asset.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/tests/codegen_samples/directory/asset2.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/tests/codegen_samples/singlefile.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/tests/conftest.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/tests/helpers.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/tests/openapi2jsonschema.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/tests/test_decorators.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/tests/utils/__init__.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/tests/utils/embed_samples/directory/__init__.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/tests/utils/embed_samples/directory/dep.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/tests/utils/embed_samples/singlefile.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/tests/utils/test_embed.py +0 -0
- {tinyfan-0.1.1 → tinyfan-0.2.0}/tests/utils/test_exjson.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tinyfan
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Tiny Argo Workflows python devkit
|
|
5
5
|
Project-URL: Documentation, https://github.com/eunchuldev/tinyfan#readme
|
|
6
6
|
Project-URL: Issues, https://github.com/eunchuldev/tinyfan/issues
|
|
@@ -31,6 +31,7 @@ Requires-Dist: jsonschema[format]; extra == 'dev'
|
|
|
31
31
|
Requires-Dist: mypy>=1.14; extra == 'dev'
|
|
32
32
|
Requires-Dist: pytest>=8.3.3; extra == 'dev'
|
|
33
33
|
Requires-Dist: ruff; extra == 'dev'
|
|
34
|
+
Requires-Dist: types-croniter; extra == 'dev'
|
|
34
35
|
Requires-Dist: types-jsonschema; extra == 'dev'
|
|
35
36
|
Requires-Dist: types-pyyaml; extra == 'dev'
|
|
36
37
|
Provides-Extra: gcs
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# How to run
|
|
2
|
+
|
|
3
|
+
```bash
|
|
4
|
+
# setup k3d
|
|
5
|
+
k3d cluster create tinyfan
|
|
6
|
+
kubectl config use-context k3d-tinyfan
|
|
7
|
+
# install argowf
|
|
8
|
+
kubectl create namespace argo
|
|
9
|
+
kubectl apply -n argo -f "https://github.com/argoproj/argo-workflows/releases/download/v3.6.4/quick-start-minimal.yaml"
|
|
10
|
+
# apply manifests
|
|
11
|
+
tinyfan examples/getting-started.py | kubectl apply -n argo -f -
|
|
12
|
+
```
|
|
@@ -27,5 +27,5 @@ def trace_configs(
|
|
|
27
27
|
secretkey: SecretKeyRef,
|
|
28
28
|
):
|
|
29
29
|
print(
|
|
30
|
-
f
|
|
30
|
+
f"{constant} - {cliarg} - {configmap.get('otherkey')} - {configmapkey.get_value()} - {secret.get('othersecretkey')} - {secretkey.get_value()}"
|
|
31
31
|
)
|
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "tinyfan"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.2.0"
|
|
4
4
|
description = 'Tiny Argo Workflows python devkit'
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.12"
|
|
7
|
-
keywords = [
|
|
8
|
-
|
|
9
|
-
"tinyfan",
|
|
10
|
-
"workflow",
|
|
11
|
-
"pipeline",
|
|
12
|
-
]
|
|
13
|
-
authors = [
|
|
14
|
-
{ name = "eunchuldev", email = "eunchulsong@gmail.com" },
|
|
15
|
-
]
|
|
7
|
+
keywords = ["argo-workflow", "tinyfan", "workflow", "pipeline"]
|
|
8
|
+
authors = [{ name = "eunchuldev", email = "eunchulsong@gmail.com" }]
|
|
16
9
|
classifiers = [
|
|
17
10
|
"Operating System :: OS Independent",
|
|
18
11
|
"License :: OSI Approved :: MIT License",
|
|
@@ -20,32 +13,16 @@ classifiers = [
|
|
|
20
13
|
"Programming Language :: Python :: 3.11",
|
|
21
14
|
"Programming Language :: Python :: 3.12",
|
|
22
15
|
]
|
|
23
|
-
dependencies = [
|
|
24
|
-
"croniter>=3.0.3",
|
|
25
|
-
"pyyaml>=6.0.2",
|
|
26
|
-
"typer-slim>=0.15.1",
|
|
27
|
-
]
|
|
16
|
+
dependencies = ["croniter>=3.0.3", "pyyaml>=6.0.2", "typer-slim>=0.15.1"]
|
|
28
17
|
|
|
29
18
|
[project.scripts]
|
|
30
19
|
tinyfan = "tinyfan.cli:main"
|
|
31
20
|
|
|
32
21
|
[project.optional-dependencies]
|
|
33
|
-
all = [
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
]
|
|
38
|
-
gcs = [
|
|
39
|
-
"google-cloud-storage",
|
|
40
|
-
]
|
|
41
|
-
bigquery = [
|
|
42
|
-
"google-cloud-bigquery[pandas]",
|
|
43
|
-
"tinyfan[pandas]",
|
|
44
|
-
]
|
|
45
|
-
pandas = [
|
|
46
|
-
"pandas",
|
|
47
|
-
"pyarrow",
|
|
48
|
-
]
|
|
22
|
+
all = ["tinyfan[gcs]", "tinyfan[bigquery]", "tinyfan[pandas]"]
|
|
23
|
+
gcs = ["google-cloud-storage"]
|
|
24
|
+
bigquery = ["google-cloud-bigquery[pandas]", "tinyfan[pandas]"]
|
|
25
|
+
pandas = ["pandas", "pyarrow"]
|
|
49
26
|
dev = [
|
|
50
27
|
"pytest >= 8.3.3",
|
|
51
28
|
"jsonpatch>=1",
|
|
@@ -54,6 +31,7 @@ dev = [
|
|
|
54
31
|
"ruff",
|
|
55
32
|
"types-PyYAML",
|
|
56
33
|
"types-jsonschema",
|
|
34
|
+
"types-croniter",
|
|
57
35
|
]
|
|
58
36
|
|
|
59
37
|
[project.urls]
|
|
@@ -13,8 +13,9 @@ import datetime
|
|
|
13
13
|
import croniter
|
|
14
14
|
from .argo_typing import ScriptTemplate
|
|
15
15
|
from .utils.embed import embed
|
|
16
|
-
from .utils.merge import deepmerge
|
|
16
|
+
from .utils.merge import deepmerge, dropnone
|
|
17
17
|
from .config import CLI_CONFIG_STATE, Config, ConfigValue, ConfigMapKeyRef, ConfigMapRef, SecretKeyRef, SecretRef
|
|
18
|
+
from .flowrundata import FlowRunData
|
|
18
19
|
|
|
19
20
|
VALID_CRON_REGEXP = r"^(?:(?:(?:(?:\d+,)+\d+|(?:\d+(?:\/|-|#)\d+)|\d+L?|\*(?:\/\d+)?|L(?:-\d+)?|\?|[A-Z]{3}(?:-[A-Z]{3})?) ?){5,7})|(@hourly|@daily|@midnight|@weekly|@monthly|@yearly|@annually)$"
|
|
20
21
|
VALID_DEPENDS_REGEXP = r"^(?!.*\.[A-Za-z0-9_]+\.[A-Za-z0-9_]+)(?!.*\.(?!Succeeded|Failed|Errored|Skipped|Omitted|Daemoned)\w+)(?!.*(?:&&|\|\|)\s*(?:&&|\|\|))(?!.*!!)[A-Za-z0-9_&|!().\s]+$"
|
|
@@ -88,19 +89,21 @@ class AssetNode:
|
|
|
88
89
|
t1 = cron.get_next(datetime.datetime)
|
|
89
90
|
t2 = cron.get_next(datetime.datetime)
|
|
90
91
|
duration_sec = (t2 - t1).total_seconds()
|
|
92
|
+
data_interval_start_tmpl = (
|
|
93
|
+
f"sprig.dateModify('-{duration_sec}s', sprig.toDate('2006-01-02T15:04:05Z07:00', workflow.scheduledTime))"
|
|
94
|
+
)
|
|
91
95
|
return re.sub(
|
|
92
96
|
r'"(\{\{tasks\.[^.]+\.outputs\.parameters\.rundata\}\})"',
|
|
93
97
|
r"\1",
|
|
94
98
|
json.dumps(
|
|
95
99
|
{
|
|
96
|
-
"ds": "{{=sprig.date('2006-01-02',
|
|
97
|
-
"ts": "{{
|
|
100
|
+
"ds": "{{=sprig.date('2006-01-02', %s)}}" % data_interval_start_tmpl,
|
|
101
|
+
"ts": "{{=%s}}" % data_interval_start_tmpl,
|
|
98
102
|
"data_interval_start": {
|
|
99
|
-
DATETIME_ANNOTATION: "{{
|
|
103
|
+
DATETIME_ANNOTATION: "{{=%s}}" % data_interval_start_tmpl,
|
|
100
104
|
},
|
|
101
105
|
"data_interval_end": {
|
|
102
|
-
DATETIME_ANNOTATION: "{{
|
|
103
|
-
% duration_sec,
|
|
106
|
+
DATETIME_ANNOTATION: "{{workflow.scheduledTime}}",
|
|
104
107
|
},
|
|
105
108
|
"parents": {
|
|
106
109
|
p.asset.name: "{{tasks.%s.outputs.parameters.rundata}}" % p.asset.name for p in self.parents
|
|
@@ -136,6 +139,7 @@ class AssetTree:
|
|
|
136
139
|
set(self.flow.assets.keys())
|
|
137
140
|
| set((self.flow.resources or {}).keys())
|
|
138
141
|
| set((self.flow.configs or {}).keys())
|
|
142
|
+
| set(inspect.get_annotations(FlowRunData).keys())
|
|
139
143
|
)
|
|
140
144
|
unknown_names = [n for n in func_param_names if n not in known_names]
|
|
141
145
|
if len(unknown_names) > 0:
|
|
@@ -169,6 +173,7 @@ class AssetTree:
|
|
|
169
173
|
self,
|
|
170
174
|
embedded: bool = True,
|
|
171
175
|
container: ScriptTemplate = {},
|
|
176
|
+
serviceAccountName: str | None = None,
|
|
172
177
|
) -> str:
|
|
173
178
|
if len(self.nodes) == 0:
|
|
174
179
|
return ""
|
|
@@ -184,7 +189,7 @@ class AssetTree:
|
|
|
184
189
|
root_location = get_root_path(list(self.nodes.values())[0].asset.func)
|
|
185
190
|
source += embed(root_location)
|
|
186
191
|
if not root_location.endswith(".py"):
|
|
187
|
-
source += "from {{inputs.parameters.module_name}}
|
|
192
|
+
source += "from {{inputs.parameters.module_name}} import {{inputs.parameters.asset_name}}\n"
|
|
188
193
|
source += "asset = {{inputs.parameters.asset_name}}.asset\n"
|
|
189
194
|
else:
|
|
190
195
|
source = (
|
|
@@ -217,14 +222,15 @@ class AssetTree:
|
|
|
217
222
|
"apiVersion": "argoproj.io/v1alpha1",
|
|
218
223
|
"kind": "CronWorkflow",
|
|
219
224
|
"metadata": {
|
|
220
|
-
"name": f"""{self.flow.name}-{
|
|
221
|
-
"generateName": f"""{self.flow.name}-{
|
|
225
|
+
"name": f"""{self.flow.name}-{encode_schedule_to_k8sname(tz, schedule)}""",
|
|
226
|
+
"generateName": f"""{self.flow.name}-{encode_schedule_to_k8sname(tz, schedule)}-""",
|
|
222
227
|
},
|
|
223
228
|
"spec": {
|
|
224
229
|
"schedule": schedule,
|
|
225
230
|
"timezone": tz,
|
|
226
231
|
"workflowSpec": {
|
|
227
232
|
"entrypoint": "flow",
|
|
233
|
+
**dropnone({"serviceAccountName": serviceAccountName or self.flow.serviceAccountName}),
|
|
228
234
|
"podSpecPatch": yaml_dump(
|
|
229
235
|
{
|
|
230
236
|
"containers": [
|
|
@@ -247,6 +253,7 @@ class AssetTree:
|
|
|
247
253
|
"templates": [
|
|
248
254
|
{
|
|
249
255
|
"name": node.asset.name.replace("_", "-"),
|
|
256
|
+
**dropnone({"serviceAccountName": node.asset.serviceAccountName}),
|
|
250
257
|
"script": deepmerge(
|
|
251
258
|
{
|
|
252
259
|
"image": DEFAULT_IMAGE,
|
|
@@ -389,15 +396,20 @@ def codegen(
|
|
|
389
396
|
location: str | None = None,
|
|
390
397
|
embedded: bool = False,
|
|
391
398
|
container: ScriptTemplate = {},
|
|
399
|
+
serviceAccountName: str | None = None,
|
|
392
400
|
) -> str:
|
|
393
401
|
"""Generate argocd workflow resource as yaml from tinyfan definitions"""
|
|
394
402
|
CLI_CONFIG_STATE.codegen = True
|
|
395
403
|
if flow:
|
|
396
|
-
result = AssetTree(flow).compile(embedded, container)
|
|
404
|
+
result = AssetTree(flow).compile(embedded, container, serviceAccountName)
|
|
397
405
|
elif location:
|
|
398
406
|
import_all_submodules(location)
|
|
399
|
-
result = "\n---\n".join(
|
|
407
|
+
result = "\n---\n".join(
|
|
408
|
+
AssetTree(flow).compile(embedded, container, serviceAccountName) for flow in FLOW_REGISTER.values()
|
|
409
|
+
)
|
|
400
410
|
else:
|
|
401
|
-
result = "\n---\n".join(
|
|
411
|
+
result = "\n---\n".join(
|
|
412
|
+
AssetTree(flow).compile(embedded, container, serviceAccountName) for flow in FLOW_REGISTER.values()
|
|
413
|
+
)
|
|
402
414
|
CLI_CONFIG_STATE.codegen = False
|
|
403
415
|
return result
|
|
@@ -22,6 +22,7 @@ class Flow:
|
|
|
22
22
|
assets: dict[str, "Asset[Any, Any, Any]"] = field(default_factory=dict)
|
|
23
23
|
resources: dict[str, ResourceBase] | None = None
|
|
24
24
|
container: ScriptTemplate | None = None
|
|
25
|
+
serviceAccountName: str | None = None
|
|
25
26
|
store: StoreBase = field(default_factory=NaiveStore)
|
|
26
27
|
configs: dict[str, Config | ConfigValue | str | None] = field(default_factory=dict)
|
|
27
28
|
|
|
@@ -48,6 +49,7 @@ class Asset(Generic[Ret, UMeta, StoreIdx]):
|
|
|
48
49
|
depends: str | None = None
|
|
49
50
|
name: str = field(init=False)
|
|
50
51
|
container: ScriptTemplate | None = None
|
|
52
|
+
serviceAccountName: str | None = None
|
|
51
53
|
|
|
52
54
|
def __post_init__(self):
|
|
53
55
|
self.name = self.func.__name__
|
|
@@ -110,6 +112,7 @@ def asset(
|
|
|
110
112
|
tz: str | None = None,
|
|
111
113
|
metadata: UMeta | None = None,
|
|
112
114
|
container: ScriptTemplate | None = None,
|
|
115
|
+
serviceAccountName: str | None = None,
|
|
113
116
|
) -> Callable[..., AssetFunc[Ret, UMeta, StoreIdx]]:
|
|
114
117
|
def wrapper(func: Callable[..., Ret]) -> AssetFunc[Ret, UMeta, StoreIdx]:
|
|
115
118
|
asset = Asset[Ret, UMeta, StoreIdx](
|
|
@@ -121,6 +124,7 @@ def asset(
|
|
|
121
124
|
tz=tz or flow.tz,
|
|
122
125
|
metadata=metadata,
|
|
123
126
|
container=container,
|
|
127
|
+
serviceAccountName=serviceAccountName,
|
|
124
128
|
)
|
|
125
129
|
return AssetFunc(func, asset)
|
|
126
130
|
|
|
@@ -15,3 +15,13 @@ def deepmerge(dict1: T, dict2: T, *args: T) -> T:
|
|
|
15
15
|
for arg in args:
|
|
16
16
|
deepmerge(dict1, arg)
|
|
17
17
|
return dict1
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def dropnone(d: dict) -> dict:
|
|
21
|
+
dropping = []
|
|
22
|
+
for k in d:
|
|
23
|
+
if d[k] is None:
|
|
24
|
+
dropping.append(k)
|
|
25
|
+
for k in dropping:
|
|
26
|
+
del d[k]
|
|
27
|
+
return d
|
|
@@ -13,7 +13,7 @@ def sample_flow() -> Generator:
|
|
|
13
13
|
flow: Flow = Flow("test")
|
|
14
14
|
|
|
15
15
|
@asset(flow=flow, schedule="@daily")
|
|
16
|
-
def asset1(): # type: ignore
|
|
16
|
+
def asset1(ds: str): # type: ignore
|
|
17
17
|
print("asset1 is executed")
|
|
18
18
|
return "hello"
|
|
19
19
|
|
|
@@ -127,3 +127,14 @@ def test_codegen_directory(validate_crds):
|
|
|
127
127
|
if e.json_path != "$.spec.templates[0].script" or e.validator != "required":
|
|
128
128
|
raise e
|
|
129
129
|
assert_code_is_running(actual)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def test_rundata_data_interval(sample_flow):
|
|
133
|
+
tree = AssetTree(sample_flow)
|
|
134
|
+
node = list(tree.nodes.values())[0]
|
|
135
|
+
# rundatatmpl = node.rundatatmpl("0 * * * * *")
|
|
136
|
+
daily = node.rundatatmpl("@daily")
|
|
137
|
+
assert (
|
|
138
|
+
daily
|
|
139
|
+
== """{"ds": "{{=sprig.date('2006-01-02', sprig.dateModify('-86400.0s', sprig.toDate('2006-01-02T15:04:05Z07:00', workflow.scheduledTime)))}}", "ts": "{{=sprig.dateModify('-86400.0s', sprig.toDate('2006-01-02T15:04:05Z07:00', workflow.scheduledTime))}}", "data_interval_start": {"__tinyfan_datetime__": "{{=sprig.dateModify('-86400.0s', sprig.toDate('2006-01-02T15:04:05Z07:00', workflow.scheduledTime))}}"}, "data_interval_end": {"__tinyfan_datetime__": "{{workflow.scheduledTime}}"}, "parents": {}, "asset_name": "asset1", "flow_name": "test", "module_name": "tests.test_codegen"}"""
|
|
140
|
+
)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
version = 1
|
|
2
|
+
revision = 1
|
|
2
3
|
requires-python = ">=3.12"
|
|
3
4
|
|
|
4
5
|
[[package]]
|
|
@@ -774,7 +775,7 @@ wheels = [
|
|
|
774
775
|
|
|
775
776
|
[[package]]
|
|
776
777
|
name = "tinyfan"
|
|
777
|
-
version = "0.
|
|
778
|
+
version = "0.2.0"
|
|
778
779
|
source = { editable = "." }
|
|
779
780
|
dependencies = [
|
|
780
781
|
{ name = "croniter" },
|
|
@@ -800,6 +801,7 @@ dev = [
|
|
|
800
801
|
{ name = "mypy" },
|
|
801
802
|
{ name = "pytest" },
|
|
802
803
|
{ name = "ruff" },
|
|
804
|
+
{ name = "types-croniter" },
|
|
803
805
|
{ name = "types-jsonschema" },
|
|
804
806
|
{ name = "types-pyyaml" },
|
|
805
807
|
]
|
|
@@ -829,9 +831,11 @@ requires-dist = [
|
|
|
829
831
|
{ name = "tinyfan", extras = ["pandas"], marker = "extra == 'all'" },
|
|
830
832
|
{ name = "tinyfan", extras = ["pandas"], marker = "extra == 'bigquery'" },
|
|
831
833
|
{ name = "typer-slim", specifier = ">=0.15.1" },
|
|
834
|
+
{ name = "types-croniter", marker = "extra == 'dev'" },
|
|
832
835
|
{ name = "types-jsonschema", marker = "extra == 'dev'" },
|
|
833
836
|
{ name = "types-pyyaml", marker = "extra == 'dev'" },
|
|
834
837
|
]
|
|
838
|
+
provides-extras = ["all", "gcs", "bigquery", "pandas", "dev"]
|
|
835
839
|
|
|
836
840
|
[[package]]
|
|
837
841
|
name = "typer-slim"
|
|
@@ -846,6 +850,15 @@ wheels = [
|
|
|
846
850
|
{ url = "https://files.pythonhosted.org/packages/1f/7b/032ecd581e2170513bb6dc3cdb2581e20fdb94a272bae70fe93f2bca580b/typer_slim-0.15.1-py3-none-any.whl", hash = "sha256:20233cb89938ea3cca633afee10b906a1b0e7c5330f31ed8c55f4f0779efe6df", size = 44968 },
|
|
847
851
|
]
|
|
848
852
|
|
|
853
|
+
[[package]]
|
|
854
|
+
name = "types-croniter"
|
|
855
|
+
version = "5.0.1.20241205"
|
|
856
|
+
source = { registry = "https://pypi.org/simple" }
|
|
857
|
+
sdist = { url = "https://files.pythonhosted.org/packages/77/2f/f3298f148a7983df2a878d53c4a17ef1dd8654a155e11caa8decb7d79670/types_croniter-5.0.1.20241205.tar.gz", hash = "sha256:8a7cb10aa0b487c654a10c14d4e99098c92a5d68ee55c7a92a3df095831a6933", size = 10928 }
|
|
858
|
+
wheels = [
|
|
859
|
+
{ url = "https://files.pythonhosted.org/packages/dc/ec/ff0222b912fdff040a1908ea226f64ff5a1a384a4062a8714eb8b80ea5d9/types_croniter-5.0.1.20241205-py3-none-any.whl", hash = "sha256:e36e992d6a4600ddf510991a20d3273b888ecea5d77a19078348e00775ba54d3", size = 9375 },
|
|
860
|
+
]
|
|
861
|
+
|
|
849
862
|
[[package]]
|
|
850
863
|
name = "types-jsonschema"
|
|
851
864
|
version = "4.23.0.20240813"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|