steve-cli 0.3.8__tar.gz → 0.3.9__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.
- {steve_cli-0.3.8 → steve_cli-0.3.9}/PKG-INFO +4 -1
- {steve_cli-0.3.8 → steve_cli-0.3.9}/pyproject.toml +5 -1
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/cli.py +40 -3
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/decorators/lineage_job.py +4 -3
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/lineage/collector.py +5 -1
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli.egg-info/PKG-INFO +4 -1
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli.egg-info/requires.txt +4 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/README.md +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/setup.cfg +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/__init__.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/decorators/__init__.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/lineage/__init__.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/lineage/adapters/__init__.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/lineage/adapters/logging.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/lineage/adapters/null.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/lineage/adapters/openlineage.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/lineage/port.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/lineage/registry.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/lineage/storage.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/storage/__init__.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/storage/metadata/__init__.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/storage/metadata/extractors/__init__.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/storage/metadata/extractors/csv.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/storage/metadata/extractors/excel.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/storage/metadata/extractors/generic.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/storage/metadata/extractors/json.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/storage/metadata/extractors/parquet.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/storage/metadata/port.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/storage/metadata/registry.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/storage/parquet.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/storage/protocol.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/storage/s3.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/storage.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/validation/__init__.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/validation/adapters/__init__.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/validation/adapters/great_expectations.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/validation/adapters/null.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/validation/adapters/validoopsie.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/validation/port.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli/validation/registry.py +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli.egg-info/SOURCES.txt +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli.egg-info/dependency_links.txt +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli.egg-info/entry_points.txt +0 -0
- {steve_cli-0.3.8 → steve_cli-0.3.9}/steve_cli.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: steve-cli
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.9
|
|
4
4
|
Summary: A simple CLI tool to run jobs from jobs.yaml with proper environment setup
|
|
5
5
|
Author: Frank
|
|
6
6
|
License: MIT
|
|
@@ -44,6 +44,8 @@ Requires-Dist: great-expectations>=0.18.0; extra == "great-expectations"
|
|
|
44
44
|
Requires-Dist: pandas>=2.0.3; extra == "great-expectations"
|
|
45
45
|
Provides-Extra: excel
|
|
46
46
|
Requires-Dist: openpyxl>=3.1.0; extra == "excel"
|
|
47
|
+
Provides-Extra: visidata
|
|
48
|
+
Requires-Dist: visidata>=3.0; extra == "visidata"
|
|
47
49
|
Provides-Extra: all
|
|
48
50
|
Requires-Dist: openlineage-python>=1.0.0; extra == "all"
|
|
49
51
|
Requires-Dist: pyarrow>=17.0.0; extra == "all"
|
|
@@ -52,6 +54,7 @@ Requires-Dist: validoopsie>=0.1.0; extra == "all"
|
|
|
52
54
|
Requires-Dist: great-expectations>=0.18.0; extra == "all"
|
|
53
55
|
Requires-Dist: pandas>=2.0.3; extra == "all"
|
|
54
56
|
Requires-Dist: openpyxl>=3.1.0; extra == "all"
|
|
57
|
+
Requires-Dist: visidata>=3.0; extra == "all"
|
|
55
58
|
|
|
56
59
|
# Steve CLI
|
|
57
60
|
|
|
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
|
|
|
5
5
|
|
|
6
6
|
[project]
|
|
7
7
|
name = "steve-cli"
|
|
8
|
-
version = "0.3.
|
|
8
|
+
version = "0.3.9"
|
|
9
9
|
description = "A simple CLI tool to run jobs from jobs.yaml with proper environment setup"
|
|
10
10
|
readme = "README.md"
|
|
11
11
|
license = {text = "MIT"}
|
|
@@ -60,6 +60,9 @@ great-expectations = [
|
|
|
60
60
|
excel = [
|
|
61
61
|
"openpyxl>=3.1.0",
|
|
62
62
|
]
|
|
63
|
+
visidata = [
|
|
64
|
+
"visidata>=3.0",
|
|
65
|
+
]
|
|
63
66
|
all = [
|
|
64
67
|
"openlineage-python>=1.0.0",
|
|
65
68
|
"pyarrow>=17.0.0",
|
|
@@ -68,6 +71,7 @@ all = [
|
|
|
68
71
|
"great-expectations>=0.18.0",
|
|
69
72
|
"pandas>=2.0.3",
|
|
70
73
|
"openpyxl>=3.1.0",
|
|
74
|
+
"visidata>=3.0",
|
|
71
75
|
]
|
|
72
76
|
|
|
73
77
|
[project.scripts]
|
|
@@ -9,6 +9,7 @@ Usage:
|
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
11
|
import os
|
|
12
|
+
import shutil
|
|
12
13
|
import signal
|
|
13
14
|
import socket
|
|
14
15
|
import subprocess
|
|
@@ -18,7 +19,7 @@ from pathlib import Path
|
|
|
18
19
|
from typing import Dict, List, Any, Optional
|
|
19
20
|
|
|
20
21
|
import click
|
|
21
|
-
from dotenv import load_dotenv
|
|
22
|
+
from dotenv import load_dotenv, dotenv_values
|
|
22
23
|
import questionary
|
|
23
24
|
import yaml
|
|
24
25
|
|
|
@@ -69,6 +70,10 @@ def run_job_command(job: Dict[str, Any]) -> int:
|
|
|
69
70
|
return 1
|
|
70
71
|
|
|
71
72
|
env = os.environ.copy()
|
|
73
|
+
for env_filename in [".env", ".workspaces.env"]:
|
|
74
|
+
env_path = Path.cwd() / env_filename
|
|
75
|
+
if env_path.exists():
|
|
76
|
+
env.update({k: v for k, v in dotenv_values(env_path).items() if v is not None})
|
|
72
77
|
job_env = job.get('env', {})
|
|
73
78
|
for key, value in job_env.items():
|
|
74
79
|
env[key] = str(value)
|
|
@@ -369,6 +374,10 @@ def apps_start(app_name: str, apps_file: Optional[Path]):
|
|
|
369
374
|
sys.exit(1)
|
|
370
375
|
|
|
371
376
|
env = os.environ.copy()
|
|
377
|
+
for env_filename in [".env", ".workspaces.env"]:
|
|
378
|
+
env_path = config.apps_file.parent / env_filename
|
|
379
|
+
if env_path.exists():
|
|
380
|
+
env.update({k: v for k, v in dotenv_values(env_path).items() if v is not None})
|
|
372
381
|
for key, value in env_vars.items():
|
|
373
382
|
env[key] = str(value)
|
|
374
383
|
|
|
@@ -537,7 +546,7 @@ def _print_tree(node: Dict[str, Any], prefix: str = "", is_last: bool = True) ->
|
|
|
537
546
|
_print_tree(child, prefix + extension, last)
|
|
538
547
|
|
|
539
548
|
|
|
540
|
-
def _list_bucket(storage_kwargs: dict, label: str, bucket_name: str) ->
|
|
549
|
+
def _list_bucket(storage_kwargs: dict, label: str, bucket_name: str) -> tuple:
|
|
541
550
|
click.echo(f" {click.style(label, fg='cyan')} ({bucket_name})")
|
|
542
551
|
try:
|
|
543
552
|
from steve_cli.storage import S3Storage
|
|
@@ -548,10 +557,12 @@ def _list_bucket(storage_kwargs: dict, label: str, bucket_name: str) -> None:
|
|
|
548
557
|
else:
|
|
549
558
|
tree = _build_tree(keys)
|
|
550
559
|
_print_tree(tree, prefix=" ")
|
|
560
|
+
return storage, keys
|
|
551
561
|
except EnvironmentError as e:
|
|
552
562
|
click.echo(f" ⚠️ {e}", err=True)
|
|
553
563
|
except Exception as e:
|
|
554
564
|
click.echo(f" ❌ {e}", err=True)
|
|
565
|
+
return None, []
|
|
555
566
|
|
|
556
567
|
|
|
557
568
|
@main.command("buckets")
|
|
@@ -602,7 +613,33 @@ def buckets(env_file: tuple):
|
|
|
602
613
|
sys.exit(0)
|
|
603
614
|
|
|
604
615
|
selected = next(o for o in options if o["label"] == choice)
|
|
605
|
-
_list_bucket(selected["kwargs"], selected["tier"], selected["bucket_name"])
|
|
616
|
+
storage, keys = _list_bucket(selected["kwargs"], selected["tier"], selected["bucket_name"])
|
|
617
|
+
|
|
618
|
+
if not storage or not keys:
|
|
619
|
+
return
|
|
620
|
+
|
|
621
|
+
file_choice = questionary.select(
|
|
622
|
+
"View a file (or press Esc to exit):",
|
|
623
|
+
choices=["(done)"] + keys,
|
|
624
|
+
).ask()
|
|
625
|
+
|
|
626
|
+
if not file_choice or file_choice == "(done)":
|
|
627
|
+
return
|
|
628
|
+
|
|
629
|
+
click.echo(f"\n📄 {click.style(file_choice, fg='cyan')}\n")
|
|
630
|
+
try:
|
|
631
|
+
import tempfile
|
|
632
|
+
data = storage.get_bytes(file_choice)
|
|
633
|
+
suffix = Path(file_choice).suffix
|
|
634
|
+
with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as tmp:
|
|
635
|
+
tmp.write(data)
|
|
636
|
+
tmp_path = tmp.name
|
|
637
|
+
if not shutil.which("vd"):
|
|
638
|
+
click.secho("visidata not found. Install it with: uv pip install 'steve-cli[visidata]'", fg="yellow")
|
|
639
|
+
return
|
|
640
|
+
subprocess.call(["vd", tmp_path])
|
|
641
|
+
except Exception as e:
|
|
642
|
+
click.secho(f"❌ Could not open file: {e}", fg="red", err=True)
|
|
606
643
|
|
|
607
644
|
|
|
608
645
|
if __name__ == '__main__':
|
|
@@ -45,10 +45,11 @@ def lineage_job(
|
|
|
45
45
|
result = fn(*args, get_storage=get_storage, **kwargs)
|
|
46
46
|
except Exception as exc:
|
|
47
47
|
session.fail(exc)
|
|
48
|
+
import sys
|
|
48
49
|
from steve_cli.validation.port import DataQualityError
|
|
49
|
-
if isinstance(exc, DataQualityError):
|
|
50
|
-
import
|
|
51
|
-
|
|
50
|
+
if isinstance(exc, (DataQualityError, EnvironmentError)):
|
|
51
|
+
import click
|
|
52
|
+
click.secho(f"ERROR {exc}", fg="red", bold=True, err=True)
|
|
52
53
|
sys.exit(1)
|
|
53
54
|
raise
|
|
54
55
|
|
|
@@ -86,7 +86,11 @@ def make_session(
|
|
|
86
86
|
kwargs = {"url": url} if prov == "openlineage" else {}
|
|
87
87
|
try:
|
|
88
88
|
port = LineageRegistry.create(prov, **kwargs)
|
|
89
|
-
except Exception:
|
|
89
|
+
except Exception as exc:
|
|
90
|
+
import logging
|
|
91
|
+
logging.getLogger(__name__).warning(
|
|
92
|
+
"Lineage disabled: could not initialize provider %r: %s", prov, exc
|
|
93
|
+
)
|
|
90
94
|
from .adapters.null import NullLineageAdapter
|
|
91
95
|
|
|
92
96
|
port = NullLineageAdapter()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: steve-cli
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.9
|
|
4
4
|
Summary: A simple CLI tool to run jobs from jobs.yaml with proper environment setup
|
|
5
5
|
Author: Frank
|
|
6
6
|
License: MIT
|
|
@@ -44,6 +44,8 @@ Requires-Dist: great-expectations>=0.18.0; extra == "great-expectations"
|
|
|
44
44
|
Requires-Dist: pandas>=2.0.3; extra == "great-expectations"
|
|
45
45
|
Provides-Extra: excel
|
|
46
46
|
Requires-Dist: openpyxl>=3.1.0; extra == "excel"
|
|
47
|
+
Provides-Extra: visidata
|
|
48
|
+
Requires-Dist: visidata>=3.0; extra == "visidata"
|
|
47
49
|
Provides-Extra: all
|
|
48
50
|
Requires-Dist: openlineage-python>=1.0.0; extra == "all"
|
|
49
51
|
Requires-Dist: pyarrow>=17.0.0; extra == "all"
|
|
@@ -52,6 +54,7 @@ Requires-Dist: validoopsie>=0.1.0; extra == "all"
|
|
|
52
54
|
Requires-Dist: great-expectations>=0.18.0; extra == "all"
|
|
53
55
|
Requires-Dist: pandas>=2.0.3; extra == "all"
|
|
54
56
|
Requires-Dist: openpyxl>=3.1.0; extra == "all"
|
|
57
|
+
Requires-Dist: visidata>=3.0; extra == "all"
|
|
55
58
|
|
|
56
59
|
# Steve CLI
|
|
57
60
|
|
|
@@ -12,6 +12,7 @@ validoopsie>=0.1.0
|
|
|
12
12
|
great-expectations>=0.18.0
|
|
13
13
|
pandas>=2.0.3
|
|
14
14
|
openpyxl>=3.1.0
|
|
15
|
+
visidata>=3.0
|
|
15
16
|
|
|
16
17
|
[dev]
|
|
17
18
|
pytest>=7.0
|
|
@@ -43,3 +44,6 @@ pyarrow>=17.0.0
|
|
|
43
44
|
[validoopsie]
|
|
44
45
|
validoopsie>=0.1.0
|
|
45
46
|
polars>=1.8.2
|
|
47
|
+
|
|
48
|
+
[visidata]
|
|
49
|
+
visidata>=3.0
|
|
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
|