gen3-dataops-toolkit 3.2.0__tar.gz → 3.4.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.
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/PKG-INFO +28 -2
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/README.md +26 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/pyproject.toml +2 -2
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/cli/config_cmds.py +19 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/cli/synth.py +88 -8
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/config.py +35 -2
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/services/synthetic_data/generate_synth_metadata.sh +16 -10
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/validate/validate.py +86 -21
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/__init__.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/cli/__init__.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/cli/_internal/__init__.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/cli/_internal/dispatch.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/cli/_internal/registry.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/cli/_internal/resolve.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/cli/_internal/runner.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/cli/_internal/safety.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/cli/delete_cmds.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/cli/dict_cmds.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/cli/ec2_cmds.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/cli/indexd_cmds.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/cli/jobs.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/cli/k8s.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/cli/main.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/cli/metadata.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/cli/pipeline_cmds.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/cli/release_cmds.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/indexd/__init__.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/indexd/file_access.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/indexd/indexd_registrar.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/ingest/ingest.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/resolver.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/services/delete/delete_all_metadata_for_project.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/services/delete/delete_metadata.sh +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/services/delete/delete_metadata_by_guid.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/services/dictionary/deploy_dd.sh +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/services/dictionary/pull_dict.sh +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/services/dictionary/upload_dictionary.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/services/indexd/register_indexd.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/services/indexd/verify_file_access.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/services/k8s_ops/argocd_restart_etl.sh +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/services/k8s_ops/argocd_restart_ms.sh +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/services/k8s_ops/argocd_restart_schema.sh +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/services/k8s_ops/login_to_pod.sh +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/services/k8s_ops/restart_etl_and_ms.sh +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/services/synthetic_data/delete_synth_metadata_sheepdog.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/services/synthetic_data/full_deploy_dd_and_synth.sh +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/services/synthetic_data/upload_synth_metadata_sheepdog.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/services/upload/metadata/upload_all_studies.sh +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/services/upload/metadata/upload_metadata.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/upload/__init__.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/upload/metadata_deleter.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/upload/metadata_submitter.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/upload/upload_synthdata_s3.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/utils/athena_utils.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/utils/dbt_utils.py +0 -0
- {gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/utils/release_writer.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gen3-dataops-toolkit
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.4.0
|
|
4
4
|
Summary: Gen3 DataOps toolkit (g3dt): operate SSM-published Gen3 data pipeline environments
|
|
5
5
|
License: Apache-2.0
|
|
6
6
|
Author: JoshuaHarris391
|
|
@@ -17,7 +17,7 @@ Requires-Dist: awswrangler (>=3.14.0,<4.0.0)
|
|
|
17
17
|
Requires-Dist: boto3
|
|
18
18
|
Requires-Dist: gen3 (>=4.27.4,<5.0.0)
|
|
19
19
|
Requires-Dist: gen3-metadata (>=1.4.0,<2.0.0)
|
|
20
|
-
Requires-Dist: gen3_validator (>=2.
|
|
20
|
+
Requires-Dist: gen3_validator (>=2.3.0,<3.0.0)
|
|
21
21
|
Requires-Dist: numpy (<2.0.0)
|
|
22
22
|
Requires-Dist: openpyxl (>=3.1.0)
|
|
23
23
|
Requires-Dist: pyarrow (>=14.0.0,<19.0.0)
|
|
@@ -182,6 +182,32 @@ Synthetic data is only schema-valid against the dictionary that generated it, so
|
|
|
182
182
|
refuses a batch that doesn't match the version being uploaded (override with
|
|
183
183
|
`--allow-version-mismatch`).
|
|
184
184
|
|
|
185
|
+
### Synthetic data: LLM configuration
|
|
186
|
+
|
|
187
|
+
`synth generate --llm` and `synth deploy` generate LLM-realistic values with
|
|
188
|
+
[gen3-metadata-simulator](https://github.com/AustralianBioCommons/gen3-metadata-simulator).
|
|
189
|
+
The provider and model resolve with precedence **CLI flags > SSM > default**:
|
|
190
|
+
the CDK config's optional `llm` block publishes `app/llm_provider` /
|
|
191
|
+
`app/llm_model` to SSM, so every operator gets the deployment's values, and
|
|
192
|
+
`--llm-provider` / `--llm-model` override them for one run (e.g. to try a
|
|
193
|
+
model before adding it to the CDK config). Environments deployed without the
|
|
194
|
+
block fall back to provider `anthropic`, and the `--llm` path errors with
|
|
195
|
+
guidance when no model is configured anywhere.
|
|
196
|
+
|
|
197
|
+
Only the API key stays local — as a *path* to the file holding it, never the
|
|
198
|
+
key itself, set once per operator:
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
g3dt config set llm_api_key_file ~/.g3dt/anthropic_api_key
|
|
202
|
+
g3dt synth generate AusDiab_Simulated --llm -n 5 -e test
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
(or per run with `--llm-api-key-file`; the vendor env var `ANTHROPIC_API_KEY`
|
|
206
|
+
/ `OPENAI_API_KEY` also works as a fallback.) The old `~/.g3dt/.env`
|
|
207
|
+
(`LLM_PROVIDER`/`LLM_MODEL`/`LLM_API_KEY_FILE`) is **no longer read**.
|
|
208
|
+
`g3dt config show --env <env>` prints the resolved provider, model, and key
|
|
209
|
+
path.
|
|
210
|
+
|
|
185
211
|
## Verifying download access (check-download)
|
|
186
212
|
|
|
187
213
|
Registration alone does not prove a file can be downloaded. Two failure modes
|
|
@@ -148,6 +148,32 @@ Synthetic data is only schema-valid against the dictionary that generated it, so
|
|
|
148
148
|
refuses a batch that doesn't match the version being uploaded (override with
|
|
149
149
|
`--allow-version-mismatch`).
|
|
150
150
|
|
|
151
|
+
### Synthetic data: LLM configuration
|
|
152
|
+
|
|
153
|
+
`synth generate --llm` and `synth deploy` generate LLM-realistic values with
|
|
154
|
+
[gen3-metadata-simulator](https://github.com/AustralianBioCommons/gen3-metadata-simulator).
|
|
155
|
+
The provider and model resolve with precedence **CLI flags > SSM > default**:
|
|
156
|
+
the CDK config's optional `llm` block publishes `app/llm_provider` /
|
|
157
|
+
`app/llm_model` to SSM, so every operator gets the deployment's values, and
|
|
158
|
+
`--llm-provider` / `--llm-model` override them for one run (e.g. to try a
|
|
159
|
+
model before adding it to the CDK config). Environments deployed without the
|
|
160
|
+
block fall back to provider `anthropic`, and the `--llm` path errors with
|
|
161
|
+
guidance when no model is configured anywhere.
|
|
162
|
+
|
|
163
|
+
Only the API key stays local — as a *path* to the file holding it, never the
|
|
164
|
+
key itself, set once per operator:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
g3dt config set llm_api_key_file ~/.g3dt/anthropic_api_key
|
|
168
|
+
g3dt synth generate AusDiab_Simulated --llm -n 5 -e test
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
(or per run with `--llm-api-key-file`; the vendor env var `ANTHROPIC_API_KEY`
|
|
172
|
+
/ `OPENAI_API_KEY` also works as a fallback.) The old `~/.g3dt/.env`
|
|
173
|
+
(`LLM_PROVIDER`/`LLM_MODEL`/`LLM_API_KEY_FILE`) is **no longer read**.
|
|
174
|
+
`g3dt config show --env <env>` prints the resolved provider, model, and key
|
|
175
|
+
path.
|
|
176
|
+
|
|
151
177
|
## Verifying download access (check-download)
|
|
152
178
|
|
|
153
179
|
Registration alone does not prove a file can be downloaded. Two failure modes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "gen3-dataops-toolkit"
|
|
3
|
-
version = "3.
|
|
3
|
+
version = "3.4.0"
|
|
4
4
|
description = "Gen3 DataOps toolkit (g3dt): operate SSM-published Gen3 data pipeline environments"
|
|
5
5
|
authors = ["JoshuaHarris391 <harjo391@gmail.com>"]
|
|
6
6
|
readme = "README.md"
|
|
@@ -19,7 +19,7 @@ numpy = "<2.0.0"
|
|
|
19
19
|
pyyaml = ">=6.0.2,<7.0.0"
|
|
20
20
|
tzlocal = ">=5.3.1,<6.0.0"
|
|
21
21
|
gen3 = ">=4.27.4, <5.0.0"
|
|
22
|
-
gen3_validator = ">=2.
|
|
22
|
+
gen3_validator = ">=2.3.0,<3.0.0"
|
|
23
23
|
pytz = ">=2025.2,<2026.0"
|
|
24
24
|
s3fs = "2025.10.0"
|
|
25
25
|
pyjwt = ">=2.10.1,<3.0.0"
|
|
@@ -118,6 +118,11 @@ def show(
|
|
|
118
118
|
typer.echo(f" namespace : {e.namespace}")
|
|
119
119
|
typer.echo(f" cluster_name : {e.cluster_name}")
|
|
120
120
|
typer.echo(f" ec2_instance_id : {e.ec2_instance_id}")
|
|
121
|
+
# Synthetic-data LLM facts: provider/model from SSM (the CDK's optional
|
|
122
|
+
# llm block); only the key *path* is local, from the marker.
|
|
123
|
+
typer.echo(f" llm_provider : {e.llm_provider}")
|
|
124
|
+
typer.echo(f" llm_model : {e.llm_model or '(not set — pass --llm-model or add the llm block to the CDK config)'}")
|
|
125
|
+
typer.echo(f" llm_api_key_file : {config.llm_api_key_file() or '(not set — g3dt config set llm_api_key_file <path>)'}")
|
|
121
126
|
if study:
|
|
122
127
|
s = study_of(study, env)
|
|
123
128
|
typer.secho(f"Study: {study} -> {s.key}", bold=True)
|
|
@@ -199,6 +204,20 @@ def diff(
|
|
|
199
204
|
check(f"gen3.{camel}", gen3.get(camel), rc.get(f"app/{leaf}"))
|
|
200
205
|
check("toolkitVersion", inputs.get("toolkitVersion"), rc.get("meta/toolkitVersion"))
|
|
201
206
|
|
|
207
|
+
# Optional inputs: compared only when the file defines them — an absent
|
|
208
|
+
# input legitimately publishes no SSM parameter (or, for the dictionary
|
|
209
|
+
# fields, predates their addition), so absence on both sides is not drift.
|
|
210
|
+
for camel, leaf in {
|
|
211
|
+
"dictionaryBaseUrl": "dictionary_base_url",
|
|
212
|
+
"dictionaryPath": "dictionary_path",
|
|
213
|
+
}.items():
|
|
214
|
+
if camel in gen3:
|
|
215
|
+
check(f"gen3.{camel}", gen3.get(camel), rc.get(f"app/{leaf}"))
|
|
216
|
+
llm = inputs.get("llm") or {}
|
|
217
|
+
for camel, leaf in {"provider": "llm_provider", "model": "llm_model"}.items():
|
|
218
|
+
if camel in llm:
|
|
219
|
+
check(f"llm.{camel}", llm.get(camel), rc.get(f"app/{leaf}"))
|
|
220
|
+
|
|
202
221
|
if not drift:
|
|
203
222
|
typer.secho(
|
|
204
223
|
f"No drift: SSM /{project}/{config.env_base(env)} matches {file}.",
|
|
@@ -9,9 +9,14 @@ Every command accepts ``--env``; targeting a **production** environment (any env
|
|
|
9
9
|
whose name contains ``prod``) shows a warning and requires typing the env name to
|
|
10
10
|
confirm — it cannot be bypassed.
|
|
11
11
|
|
|
12
|
-
Generation defaults to keyless ``random`` data (no API calls). Pass ``--llm``
|
|
13
|
-
LLM-realistic values
|
|
14
|
-
|
|
12
|
+
Generation defaults to keyless ``random`` data (no API calls). Pass ``--llm``
|
|
13
|
+
for LLM-realistic values. The LLM provider and model come from the
|
|
14
|
+
environment's SSM tree (the CDK config's optional ``llm`` block, published as
|
|
15
|
+
``app/llm_provider`` / ``app/llm_model``) and can be overridden per run with
|
|
16
|
+
``--llm-provider`` / ``--llm-model``. Only the API key stays local: point at
|
|
17
|
+
its file once with ``g3dt config set llm_api_key_file <path>`` (or per run
|
|
18
|
+
with ``--llm-api-key-file``); the vendor env var ``ANTHROPIC_API_KEY`` /
|
|
19
|
+
``OPENAI_API_KEY`` also works. The old ``~/.g3dt/.env`` is no longer read.
|
|
15
20
|
"""
|
|
16
21
|
from __future__ import annotations
|
|
17
22
|
|
|
@@ -21,6 +26,7 @@ from typing import Optional
|
|
|
21
26
|
|
|
22
27
|
import typer
|
|
23
28
|
|
|
29
|
+
from g3dt import config
|
|
24
30
|
from g3dt.config import (
|
|
25
31
|
dictionary_filename,
|
|
26
32
|
dictionary_url,
|
|
@@ -38,6 +44,45 @@ app = typer.Typer(
|
|
|
38
44
|
|
|
39
45
|
SYNTH_DIR = Path("~/.g3dt/synth_metadata").expanduser()
|
|
40
46
|
|
|
47
|
+
|
|
48
|
+
def _llm_env_overrides(
|
|
49
|
+
e,
|
|
50
|
+
llm_provider: Optional[str],
|
|
51
|
+
llm_model: Optional[str],
|
|
52
|
+
llm_api_key_file: Optional[Path],
|
|
53
|
+
) -> dict:
|
|
54
|
+
"""Resolve the effective LLM settings for a run: flags > SSM > default.
|
|
55
|
+
|
|
56
|
+
Returns env-var overrides for the generator script, which forwards
|
|
57
|
+
provider/model to gen3-metadata-simulator as CLI flags (the simulator's
|
|
58
|
+
own precedence puts flags first). Exits with guidance when no model is
|
|
59
|
+
configured anywhere; the key-file path is optional — the simulator falls
|
|
60
|
+
back to the vendor env var and raises its own error if neither exists.
|
|
61
|
+
"""
|
|
62
|
+
effective_provider = llm_provider or e.llm_provider
|
|
63
|
+
effective_model = llm_model or e.llm_model
|
|
64
|
+
if not effective_model:
|
|
65
|
+
typer.secho(
|
|
66
|
+
"No LLM model configured. Set the llm block in the CDK config "
|
|
67
|
+
"(published to SSM as app/llm_model) and redeploy, or pass "
|
|
68
|
+
"--llm-model for this run.",
|
|
69
|
+
fg=typer.colors.RED,
|
|
70
|
+
err=True,
|
|
71
|
+
)
|
|
72
|
+
raise typer.Exit(1)
|
|
73
|
+
overrides = {
|
|
74
|
+
"G3DT_LLM_PROVIDER": effective_provider,
|
|
75
|
+
"G3DT_LLM_MODEL": effective_model,
|
|
76
|
+
}
|
|
77
|
+
key_file = (
|
|
78
|
+
str(Path(llm_api_key_file).expanduser())
|
|
79
|
+
if llm_api_key_file
|
|
80
|
+
else config.llm_api_key_file()
|
|
81
|
+
)
|
|
82
|
+
if key_file:
|
|
83
|
+
overrides["LLM_API_KEY_FILE"] = key_file
|
|
84
|
+
return overrides
|
|
85
|
+
|
|
41
86
|
#: Written into each generated batch so `synth upload` can tell which dictionary
|
|
42
87
|
#: produced it. A batch is only valid against that dictionary, and the directory
|
|
43
88
|
#: name alone cannot be trusted: --schema and --version are separate options, so
|
|
@@ -110,19 +155,35 @@ def deploy(
|
|
|
110
155
|
env: str = typer.Option(
|
|
111
156
|
"test", "--env", "-e", help="Target environment (prod requires typed confirmation)."
|
|
112
157
|
),
|
|
158
|
+
llm_provider: Optional[str] = typer.Option(
|
|
159
|
+
None, "--llm-provider",
|
|
160
|
+
help="LLM vendor override (anthropic|openai); default: the env's SSM app/llm_provider.",
|
|
161
|
+
),
|
|
162
|
+
llm_model: Optional[str] = typer.Option(
|
|
163
|
+
None, "--llm-model",
|
|
164
|
+
help="LLM model override; default: the env's SSM app/llm_model.",
|
|
165
|
+
),
|
|
166
|
+
llm_api_key_file: Optional[Path] = typer.Option(
|
|
167
|
+
None, "--llm-api-key-file", exists=True, dir_okay=False,
|
|
168
|
+
help="Path to the file holding the LLM API key; default: the marker's "
|
|
169
|
+
"llm_api_key_file (set once: g3dt config set llm_api_key_file <path>).",
|
|
170
|
+
),
|
|
113
171
|
) -> None:
|
|
114
172
|
"""Full end-to-end synthetic deploy (dict + LLM-generate + upload + restarts).
|
|
115
173
|
|
|
116
174
|
Wraps services/synthetic_data/full_deploy_dd_and_synth.sh (LLM-backed
|
|
117
|
-
generation).
|
|
175
|
+
generation). Provider/model come from the env's SSM tree unless
|
|
176
|
+
overridden; the API key path comes from --llm-api-key-file or the marker.
|
|
118
177
|
"""
|
|
119
178
|
e = env_of(env)
|
|
120
179
|
safety.confirm_prod_strict("synthetic full deploy", env)
|
|
180
|
+
env_vars = script_env(e)
|
|
181
|
+
env_vars.update(_llm_env_overrides(e, llm_provider, llm_model, llm_api_key_file))
|
|
121
182
|
runner.run(
|
|
122
183
|
runner.bash_script(
|
|
123
184
|
"services/synthetic_data/full_deploy_dd_and_synth.sh", env
|
|
124
185
|
),
|
|
125
|
-
env=
|
|
186
|
+
env=env_vars,
|
|
126
187
|
)
|
|
127
188
|
|
|
128
189
|
|
|
@@ -147,8 +208,22 @@ def generate(
|
|
|
147
208
|
llm: bool = typer.Option(
|
|
148
209
|
False,
|
|
149
210
|
"--llm",
|
|
150
|
-
help="Generate LLM-realistic values;
|
|
151
|
-
"
|
|
211
|
+
help="Generate LLM-realistic values; provider/model resolve from the "
|
|
212
|
+
"env's SSM tree (override with --llm-provider/--llm-model). Default is "
|
|
213
|
+
"keyless random data (no API key, no API calls).",
|
|
214
|
+
),
|
|
215
|
+
llm_provider: Optional[str] = typer.Option(
|
|
216
|
+
None, "--llm-provider",
|
|
217
|
+
help="LLM vendor override (anthropic|openai); default: the env's SSM app/llm_provider.",
|
|
218
|
+
),
|
|
219
|
+
llm_model: Optional[str] = typer.Option(
|
|
220
|
+
None, "--llm-model",
|
|
221
|
+
help="LLM model override; default: the env's SSM app/llm_model.",
|
|
222
|
+
),
|
|
223
|
+
llm_api_key_file: Optional[Path] = typer.Option(
|
|
224
|
+
None, "--llm-api-key-file", exists=True, dir_okay=False,
|
|
225
|
+
help="Path to the file holding the LLM API key; default: the marker's "
|
|
226
|
+
"llm_api_key_file (set once: g3dt config set llm_api_key_file <path>).",
|
|
152
227
|
),
|
|
153
228
|
seed: int = typer.Option(None, "--seed", help="RNG seed for reproducible output."),
|
|
154
229
|
schema: str = typer.Option(
|
|
@@ -227,11 +302,16 @@ def generate(
|
|
|
227
302
|
args += ["--num-records", num_records]
|
|
228
303
|
if seed is not None:
|
|
229
304
|
args += ["--seed", str(seed)]
|
|
305
|
+
env_vars = script_env(e, ver)
|
|
306
|
+
if effective_provider == "llm":
|
|
307
|
+
env_vars.update(
|
|
308
|
+
_llm_env_overrides(e, llm_provider, llm_model, llm_api_key_file)
|
|
309
|
+
)
|
|
230
310
|
runner.run(
|
|
231
311
|
runner.bash_script(
|
|
232
312
|
"services/synthetic_data/generate_synth_metadata.sh", *args
|
|
233
313
|
),
|
|
234
|
-
env=
|
|
314
|
+
env=env_vars,
|
|
235
315
|
)
|
|
236
316
|
# Only after a successful generate: runner.run raises on failure, so a
|
|
237
317
|
# half-written batch is never stamped as valid.
|
|
@@ -50,11 +50,21 @@ DEFAULT_REGION = "ap-southeast-2"
|
|
|
50
50
|
DEFAULT_DICT_BASE_URL = "https://raw.githubusercontent.com"
|
|
51
51
|
DEFAULT_DICT_PATH = "dictionary/prod_dict/acdc_schema.json"
|
|
52
52
|
|
|
53
|
+
#: Synthetic-data LLM facts, published by the CDK's OPTIONAL ``llm`` config
|
|
54
|
+
#: block as ``app/llm_provider`` / ``app/llm_model`` and consumed by
|
|
55
|
+
#: gen3-metadata-simulator through ``g3dt synth``. Optional app inputs:
|
|
56
|
+
#: environments deployed without the block fall back to this provider default.
|
|
57
|
+
#: The model deliberately has no default — ``g3dt synth`` errors with guidance
|
|
58
|
+
#: when the ``--llm`` path is used and no model is configured anywhere.
|
|
59
|
+
DEFAULT_LLM_PROVIDER = "anthropic"
|
|
60
|
+
|
|
53
61
|
#: Marker locations, most specific first.
|
|
54
62
|
MARKER_PATHS = ("g3dt.yaml", "~/.g3dt/g3dt.yaml", "/etc/g3dt/g3dt.yaml")
|
|
55
63
|
|
|
56
|
-
#: Marker keys `g3dt config set` may write.
|
|
57
|
-
|
|
64
|
+
#: Marker keys `g3dt config set` may write. ``llm_api_key_file`` is the path
|
|
65
|
+
#: to the file holding the synth LLM API key — the one LLM setting that stays
|
|
66
|
+
#: local (the provider and model come from SSM; the key never leaves the box).
|
|
67
|
+
SETTABLE_MARKER_KEYS = ("project", "region", "default_env", "llm_api_key_file")
|
|
58
68
|
|
|
59
69
|
#: Gen3 app facts mirrored to SSM /{project}/{env}/app/* by the CDK.
|
|
60
70
|
REQUIRED_APP_KEYS = (
|
|
@@ -150,6 +160,18 @@ def require_project(marker: Optional[dict] = None) -> str:
|
|
|
150
160
|
return project
|
|
151
161
|
|
|
152
162
|
|
|
163
|
+
def llm_api_key_file(marker: Optional[dict] = None) -> Optional[str]:
|
|
164
|
+
"""Path to the file holding the synth LLM API key, from the marker.
|
|
165
|
+
|
|
166
|
+
Set once per operator with ``g3dt config set llm_api_key_file <path>``.
|
|
167
|
+
Returns ``None`` when unset — gen3-metadata-simulator then falls back to
|
|
168
|
+
the vendor's standard env var (``ANTHROPIC_API_KEY`` / ``OPENAI_API_KEY``).
|
|
169
|
+
"""
|
|
170
|
+
m = marker if marker is not None else load_marker()
|
|
171
|
+
value = m.get("llm_api_key_file")
|
|
172
|
+
return str(Path(str(value)).expanduser()) if value else None
|
|
173
|
+
|
|
174
|
+
|
|
153
175
|
def set_marker_value(key: str, value: str) -> Tuple[Optional[str], str, Path]:
|
|
154
176
|
"""Set one bootstrap key in the user's marker file and write it back.
|
|
155
177
|
|
|
@@ -230,6 +252,11 @@ class EnvConfig:
|
|
|
230
252
|
# hand-built EnvConfig still composes a valid URL.
|
|
231
253
|
dictionary_base_url: str = DEFAULT_DICT_BASE_URL
|
|
232
254
|
dictionary_path: str = DEFAULT_DICT_PATH
|
|
255
|
+
# Optional synthetic-data LLM inputs (SSM app/llm_provider, app/llm_model).
|
|
256
|
+
# The model has no default on purpose: synth's --llm path checks and errors
|
|
257
|
+
# with guidance rather than silently picking a model.
|
|
258
|
+
llm_provider: str = DEFAULT_LLM_PROVIDER
|
|
259
|
+
llm_model: Optional[str] = None
|
|
233
260
|
|
|
234
261
|
|
|
235
262
|
def _app_or_default(rc, leaf: str, default: str) -> str:
|
|
@@ -289,6 +316,10 @@ def resolve_env(env: str, project: Optional[str] = None) -> EnvConfig:
|
|
|
289
316
|
rc, "dictionary_base_url", DEFAULT_DICT_BASE_URL
|
|
290
317
|
),
|
|
291
318
|
dictionary_path=_app_or_default(rc, "dictionary_path", DEFAULT_DICT_PATH),
|
|
319
|
+
# Same optional-app-fact contract: the CDK publishes these only when
|
|
320
|
+
# the config has an llm block, so absence means "use the defaults".
|
|
321
|
+
llm_provider=_app_or_default(rc, "llm_provider", DEFAULT_LLM_PROVIDER),
|
|
322
|
+
llm_model=(_app_or_default(rc, "llm_model", "") or None),
|
|
292
323
|
)
|
|
293
324
|
|
|
294
325
|
|
|
@@ -395,6 +426,8 @@ def script_env(e: EnvConfig, version: Optional[str] = None) -> Dict[str, str]:
|
|
|
395
426
|
"G3DT_NAMESPACE": e.namespace,
|
|
396
427
|
"G3DT_CLUSTER_NAME": e.cluster_name,
|
|
397
428
|
"G3DT_SCHEMA_REPO": e.schema_repo,
|
|
429
|
+
"G3DT_LLM_PROVIDER": e.llm_provider,
|
|
430
|
+
"G3DT_LLM_MODEL": e.llm_model,
|
|
398
431
|
}
|
|
399
432
|
env.update({k: v for k, v in values.items() if v is not None})
|
|
400
433
|
return env
|
|
@@ -8,14 +8,13 @@
|
|
|
8
8
|
# The tool takes a LOCAL bundled Gen3 schema file (pulled by pull_dict.sh into
|
|
9
9
|
# ~/.g3dt/schemas/acdc_schema_<version>.json, or $G3DT_SCHEMA_DIR if set). The
|
|
10
10
|
# default provider is keyless 'random'; pass --provider llm for LLM-realistic
|
|
11
|
-
# values
|
|
12
|
-
#
|
|
11
|
+
# values. The LLM vendor/model arrive as $G3DT_LLM_PROVIDER / $G3DT_LLM_MODEL
|
|
12
|
+
# (resolved by g3dt: CLI flags > SSM app/llm_* > default) and are forwarded to
|
|
13
|
+
# the simulator as flags; the API key file path arrives as $LLM_API_KEY_FILE.
|
|
14
|
+
# The old ~/.g3dt/.env is no longer read.
|
|
13
15
|
|
|
14
16
|
set -euo pipefail
|
|
15
17
|
|
|
16
|
-
# LLM provider config file (lives outside the installed package).
|
|
17
|
-
ENV_FILE="${G3DT_ENV_FILE:-$HOME/.g3dt/.env}"
|
|
18
|
-
|
|
19
18
|
usage() {
|
|
20
19
|
cat <<EOF
|
|
21
20
|
Usage: $(basename "$0") --schema <path> --version <ver> [options]
|
|
@@ -32,8 +31,8 @@ Options:
|
|
|
32
31
|
--num-records N|n1,n2 Records per study: one number for all, or a comma list
|
|
33
32
|
(one per study). Default: ${DEFAULT_NUM_RECORDS}
|
|
34
33
|
--provider random|llm Value strategy. Default: ${DEFAULT_PROVIDER}
|
|
35
|
-
'random' needs no key; 'llm'
|
|
36
|
-
|
|
34
|
+
'random' needs no key; 'llm' uses \$G3DT_LLM_PROVIDER /
|
|
35
|
+
\$G3DT_LLM_MODEL / \$LLM_API_KEY_FILE (set by g3dt).
|
|
37
36
|
--seed N RNG seed for reproducible output.
|
|
38
37
|
--output-root DIR Root output dir. Default: ${DEFAULT_OUTPUT_ROOT}
|
|
39
38
|
-h, --help Show this help and exit.
|
|
@@ -123,9 +122,16 @@ for i in "${!STUDY_ARRAY[@]}"; do
|
|
|
123
122
|
--num-records "$N"
|
|
124
123
|
--provider "$PROVIDER")
|
|
125
124
|
[[ -n "$SEED" ]] && CMD+=(--seed "$SEED")
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
125
|
+
if [[ "$PROVIDER" == "llm" ]]; then
|
|
126
|
+
# Vendor/model resolved by g3dt (flags > SSM > default) and forwarded
|
|
127
|
+
# as simulator flags, because the simulator's own precedence puts
|
|
128
|
+
# flags above any .env or environment variable.
|
|
129
|
+
[[ -n "${G3DT_LLM_PROVIDER:-}" ]] && CMD+=(--llm-provider "$G3DT_LLM_PROVIDER")
|
|
130
|
+
[[ -n "${G3DT_LLM_MODEL:-}" ]] && CMD+=(--llm-model "$G3DT_LLM_MODEL")
|
|
131
|
+
# Neutralize any .env in the caller's CWD: /dev/null exists (satisfies
|
|
132
|
+
# the simulator's exists=True check) and dotenv-parses to empty, so
|
|
133
|
+
# only the flags above and the inherited $LLM_API_KEY_FILE apply.
|
|
134
|
+
CMD+=(--env-file /dev/null)
|
|
129
135
|
fi
|
|
130
136
|
"${CMD[@]}"
|
|
131
137
|
done
|
|
@@ -479,6 +479,49 @@ def truncate_linkage_results(linkage_results_dict: dict) -> dict:
|
|
|
479
479
|
return linkage_results_dict
|
|
480
480
|
|
|
481
481
|
|
|
482
|
+
#: The eight fields every result row carries, as emitted by
|
|
483
|
+
#: ``gen3_validator.validate.validate_object`` (FAIL rows) and
|
|
484
|
+
#: ``gen3_validator.validate.error_record`` (ERROR rows).
|
|
485
|
+
VALIDATION_RESULT_BASE_COLUMNS = [
|
|
486
|
+
"node",
|
|
487
|
+
"index",
|
|
488
|
+
"validation_result",
|
|
489
|
+
"invalid_key",
|
|
490
|
+
"schema_path",
|
|
491
|
+
"validator",
|
|
492
|
+
"validator_value",
|
|
493
|
+
"validation_error",
|
|
494
|
+
]
|
|
495
|
+
|
|
496
|
+
#: Full column contract of the results table, in write order.
|
|
497
|
+
VALIDATION_RESULT_COLUMNS = [
|
|
498
|
+
"validation_id",
|
|
499
|
+
"index",
|
|
500
|
+
"node",
|
|
501
|
+
"study_id",
|
|
502
|
+
"validation_result",
|
|
503
|
+
"invalid_key",
|
|
504
|
+
"schema_path",
|
|
505
|
+
"validator",
|
|
506
|
+
"validator_value",
|
|
507
|
+
"validation_error",
|
|
508
|
+
"schema_version",
|
|
509
|
+
]
|
|
510
|
+
|
|
511
|
+
#: Written when a study validates clean, so that every run leaves exactly one
|
|
512
|
+
#: gradeable row. Excluded by the validation gate — see
|
|
513
|
+
#: :func:`run_validation_gate`.
|
|
514
|
+
PASS_MARKER_ROW = {
|
|
515
|
+
"node": None,
|
|
516
|
+
"index": None,
|
|
517
|
+
"validation_result": "PASS",
|
|
518
|
+
"invalid_key": None,
|
|
519
|
+
"schema_path": None,
|
|
520
|
+
"validator": None,
|
|
521
|
+
"validator_value": None,
|
|
522
|
+
"validation_error": None,
|
|
523
|
+
}
|
|
524
|
+
|
|
482
525
|
#: validation_error patterns treated as known noise by the validation gate —
|
|
483
526
|
#: structural artefacts of the export (null-typed fields, extra export-side
|
|
484
527
|
#: properties, the Gen3 'programs' root requirement), not data quality issues.
|
|
@@ -497,9 +540,14 @@ def run_validation_gate(glue_database: str, athena_s3_output: str,
|
|
|
497
540
|
|
|
498
541
|
The gate looks at the most recent ``validation_id`` in the results table,
|
|
499
542
|
filters out the known-noise error patterns
|
|
500
|
-
(:data:`VALIDATION_GATE_IGNORED_ERRORS`) and synthetic
|
|
501
|
-
aggregates what remains. An empty result means the latest
|
|
502
|
-
is clean; any rows are genuine schema failures an operator
|
|
543
|
+
(:data:`VALIDATION_GATE_IGNORED_ERRORS`), PASS markers and synthetic
|
|
544
|
+
studies, and aggregates what remains. An empty result means the latest
|
|
545
|
+
validation run is clean; any rows are genuine schema failures an operator
|
|
546
|
+
must fix.
|
|
547
|
+
|
|
548
|
+
ERROR rows are deliberately NOT filtered out. A record whose node is absent
|
|
549
|
+
from the dictionary could not be checked at all, which is a failure to
|
|
550
|
+
validate rather than a clean result, and must hold the gate closed.
|
|
503
551
|
|
|
504
552
|
Callers (the validator Glue job) FAIL the run when rows come back, so the
|
|
505
553
|
validation Step Function goes red until the data is fixed and validation
|
|
@@ -523,6 +571,7 @@ WHERE validation_id = (
|
|
|
523
571
|
FROM "{glue_database}"."{results_table}"
|
|
524
572
|
)
|
|
525
573
|
{ignore_clauses}
|
|
574
|
+
AND validation_result <> 'PASS'
|
|
526
575
|
AND study_id NOT LIKE '%synthetic%'
|
|
527
576
|
GROUP BY node, study_id, invalid_key, validator_value, validation_error
|
|
528
577
|
ORDER BY node, study_id
|
|
@@ -567,6 +616,7 @@ def validate_pipeline(
|
|
|
567
616
|
resolver=None,
|
|
568
617
|
metadata_table: pd.DataFrame = None,
|
|
569
618
|
write_iceberg: bool = True,
|
|
619
|
+
results_table: str = "full_validation_results",
|
|
570
620
|
) -> pd.DataFrame:
|
|
571
621
|
"""
|
|
572
622
|
Orchestrate the validation workflow for a study: load + resolve schema, find the latest
|
|
@@ -592,9 +642,14 @@ def validate_pipeline(
|
|
|
592
642
|
write_iceberg: When False, skip the per-study Iceberg write and leave it
|
|
593
643
|
to the caller (who can concatenate several studies' results into a
|
|
594
644
|
single write). The CSV write-back always happens.
|
|
645
|
+
results_table: Table to write into when ``write_iceberg`` is True. Callers
|
|
646
|
+
validating an isolated warehouse (e.g. the CI databases) MUST pass
|
|
647
|
+
their own — the real and CI results must never share a table, since
|
|
648
|
+
the gate grades whichever run has the greatest validation_id.
|
|
595
649
|
|
|
596
650
|
Returns:
|
|
597
|
-
The study's validation results DataFrame.
|
|
651
|
+
The study's validation results DataFrame. Never empty: a study with no
|
|
652
|
+
failures yields a single PASS marker row.
|
|
598
653
|
|
|
599
654
|
Raises:
|
|
600
655
|
RuntimeError: When expected inputs are missing or a pipeline step fails.
|
|
@@ -663,24 +718,34 @@ def validate_pipeline(
|
|
|
663
718
|
logger.info("Getting Schema Version")
|
|
664
719
|
schema_version = resolver.get_schema_version(schema = schema)
|
|
665
720
|
|
|
666
|
-
|
|
721
|
+
if not results:
|
|
722
|
+
# No failures. Record the run anyway: the validation gate grades
|
|
723
|
+
# the greatest validation_id in the results table, so a clean run
|
|
724
|
+
# that writes nothing would leave the previous FAILING run as the
|
|
725
|
+
# latest and the gate could never go green no matter how many
|
|
726
|
+
# times the data was fixed. A PASS marker also guarantees the
|
|
727
|
+
# table exists after the first run, which is what stops a fresh
|
|
728
|
+
# environment reporting TABLE_NOT_FOUND.
|
|
729
|
+
logger.info("No validation failures for study '%s'; writing PASS marker.", study_id)
|
|
730
|
+
results = [PASS_MARKER_ROW.copy()]
|
|
731
|
+
|
|
732
|
+
# Build with an explicit column list rather than inferring it from the
|
|
733
|
+
# rows: pd.DataFrame([]) has NO columns, so the reindex below used to
|
|
734
|
+
# raise KeyError and surface as "Validation failed." — a clean study
|
|
735
|
+
# failing with the same message as a dirty one.
|
|
736
|
+
full_validation_results_df = pd.DataFrame(results, columns=VALIDATION_RESULT_BASE_COLUMNS)
|
|
667
737
|
full_validation_results_df["validation_id"] = latest_validation_id
|
|
668
738
|
full_validation_results_df["study_id"] = study_id
|
|
669
739
|
full_validation_results_df["schema_version"] = schema_version
|
|
670
|
-
|
|
671
|
-
full_validation_results_df = full_validation_results_df[
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
"validator",
|
|
680
|
-
"validator_value",
|
|
681
|
-
"validation_error",
|
|
682
|
-
"schema_version"
|
|
683
|
-
]]
|
|
740
|
+
|
|
741
|
+
full_validation_results_df = full_validation_results_df[VALIDATION_RESULT_COLUMNS]
|
|
742
|
+
|
|
743
|
+
# 'index' is the only numeric column. A PASS-only frame leaves it
|
|
744
|
+
# entirely null, which would infer a different Iceberg column type
|
|
745
|
+
# than a frame containing failures — and full_validation_results
|
|
746
|
+
# already exists in deployed environments. Pin it so both shapes
|
|
747
|
+
# write the same schema.
|
|
748
|
+
full_validation_results_df = full_validation_results_df.astype({"index": "Int64"})
|
|
684
749
|
|
|
685
750
|
logger.info("Validation completed (%s rows).", len(full_validation_results_df))
|
|
686
751
|
except Exception as e:
|
|
@@ -703,12 +768,12 @@ def validate_pipeline(
|
|
|
703
768
|
logger.info(
|
|
704
769
|
"Writing Parquet to Glue DB '%s', table '%s'.",
|
|
705
770
|
glue_database,
|
|
706
|
-
|
|
771
|
+
results_table,
|
|
707
772
|
)
|
|
708
773
|
write_iceberg_to_db(
|
|
709
774
|
df=full_validation_results_df,
|
|
710
775
|
database=glue_database,
|
|
711
|
-
table=
|
|
776
|
+
table=results_table,
|
|
712
777
|
athena_s3_output=athena_s3_output,
|
|
713
778
|
workgroup=workgroup,
|
|
714
779
|
)
|
|
File without changes
|
|
File without changes
|
{gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/cli/_internal/__init__.py
RENAMED
|
File without changes
|
{gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/cli/_internal/dispatch.py
RENAMED
|
File without changes
|
{gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/cli/_internal/registry.py
RENAMED
|
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
|
{gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/indexd/indexd_registrar.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/services/dictionary/deploy_dd.sh
RENAMED
|
File without changes
|
{gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/services/dictionary/pull_dict.sh
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/services/k8s_ops/login_to_pod.sh
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/upload/metadata_deleter.py
RENAMED
|
File without changes
|
{gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/upload/metadata_submitter.py
RENAMED
|
File without changes
|
{gen3_dataops_toolkit-3.2.0 → gen3_dataops_toolkit-3.4.0}/src/g3dt/upload/upload_synthdata_s3.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|