steve-cli 0.3.13__tar.gz → 0.3.14__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. {steve_cli-0.3.13 → steve_cli-0.3.14}/PKG-INFO +1 -1
  2. {steve_cli-0.3.13 → steve_cli-0.3.14}/pyproject.toml +1 -1
  3. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/cli.py +143 -4
  4. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli.egg-info/PKG-INFO +1 -1
  5. {steve_cli-0.3.13 → steve_cli-0.3.14}/README.md +0 -0
  6. {steve_cli-0.3.13 → steve_cli-0.3.14}/setup.cfg +0 -0
  7. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/__init__.py +0 -0
  8. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/decorators/__init__.py +0 -0
  9. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/decorators/lineage_job.py +0 -0
  10. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/lineage/__init__.py +0 -0
  11. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/lineage/adapters/__init__.py +0 -0
  12. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/lineage/adapters/logging.py +0 -0
  13. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/lineage/adapters/null.py +0 -0
  14. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/lineage/adapters/openlineage.py +0 -0
  15. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/lineage/collector.py +0 -0
  16. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/lineage/port.py +0 -0
  17. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/lineage/registry.py +0 -0
  18. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/lineage/storage.py +0 -0
  19. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/storage/__init__.py +0 -0
  20. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/storage/metadata/__init__.py +0 -0
  21. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/storage/metadata/extractors/__init__.py +0 -0
  22. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/storage/metadata/extractors/csv.py +0 -0
  23. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/storage/metadata/extractors/excel.py +0 -0
  24. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/storage/metadata/extractors/generic.py +0 -0
  25. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/storage/metadata/extractors/json.py +0 -0
  26. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/storage/metadata/extractors/parquet.py +0 -0
  27. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/storage/metadata/port.py +0 -0
  28. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/storage/metadata/registry.py +0 -0
  29. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/storage/parquet.py +0 -0
  30. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/storage/protocol.py +0 -0
  31. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/storage/s3.py +0 -0
  32. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/storage.py +0 -0
  33. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/validation/__init__.py +0 -0
  34. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/validation/adapters/__init__.py +0 -0
  35. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/validation/adapters/great_expectations.py +0 -0
  36. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/validation/adapters/null.py +0 -0
  37. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/validation/adapters/validoopsie.py +0 -0
  38. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/validation/port.py +0 -0
  39. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli/validation/registry.py +0 -0
  40. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli.egg-info/SOURCES.txt +0 -0
  41. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli.egg-info/dependency_links.txt +0 -0
  42. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli.egg-info/entry_points.txt +0 -0
  43. {steve_cli-0.3.13 → steve_cli-0.3.14}/steve_cli.egg-info/requires.txt +0 -0
  44. {steve_cli-0.3.13 → steve_cli-0.3.14}/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.13
3
+ Version: 0.3.14
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
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
5
5
 
6
6
  [project]
7
7
  name = "steve-cli"
8
- version = "0.3.13"
8
+ version = "0.3.14"
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"}
@@ -300,6 +300,34 @@ def apps(ctx: click.Context, apps_file: Optional[Path]):
300
300
  ctx.invoke(apps_start, app_name=choice, apps_file=apps_file)
301
301
 
302
302
 
303
+ @apps.command('status')
304
+ @click.argument('app_name', required=False, default=None)
305
+ @click.option('--apps-file', '-f', type=click.Path(exists=True, path_type=Path),
306
+ help='Path to apps.yaml file (default: ./apps.yaml)')
307
+ def apps_status(app_name: Optional[str], apps_file: Optional[Path]):
308
+ """Show status of one or all apps."""
309
+ config = AppsConfig(apps_file)
310
+ if not config.apps:
311
+ click.echo("❌ No apps found in apps.yaml")
312
+ return
313
+ apps_to_show = [a for a in config.apps if a.get('name') == app_name] if app_name else config.apps
314
+ if not apps_to_show:
315
+ click.echo(f"❌ App '{app_name}' not found", err=True)
316
+ sys.exit(1)
317
+ for app_data in apps_to_show:
318
+ name = app_data.get('name', 'unnamed')
319
+ port = app_data.get('port', '?')
320
+ pid = _get_running_pid(name)
321
+ if pid:
322
+ uf = _url_file(name)
323
+ url = uf.read_text().strip() if uf.exists() else f'http://localhost:{port}'
324
+ status = click.style('● running', fg='green')
325
+ click.echo(f" {click.style(name, fg='blue', bold=True)} {status} {click.style(url, fg='cyan')} (PID {pid})")
326
+ else:
327
+ status = click.style('○ stopped', fg='yellow')
328
+ click.echo(f" {click.style(name, fg='blue', bold=True)} {status}")
329
+
330
+
303
331
  @apps.command('ls')
304
332
  @click.option('--apps-file', '-f', type=click.Path(exists=True, path_type=Path),
305
333
  help='Path to apps.yaml file (default: ./apps.yaml)')
@@ -335,12 +363,31 @@ def apps_list(apps_file: Optional[Path]):
335
363
 
336
364
 
337
365
  @apps.command('start')
338
- @click.argument('app_name')
366
+ @click.argument('app_name', required=False, default=None)
339
367
  @click.option('--apps-file', '-f', type=click.Path(exists=True, path_type=Path),
340
368
  help='Path to apps.yaml file (default: ./apps.yaml)')
341
- def apps_start(app_name: str, apps_file: Optional[Path]):
369
+ def apps_start(app_name: Optional[str], apps_file: Optional[Path]):
342
370
  """Start an app by name and register it with the auth-proxy."""
343
371
  config = AppsConfig(apps_file)
372
+ if app_name is None:
373
+ all_names = config.list_apps()
374
+ if not all_names:
375
+ click.echo("❌ No apps found in apps.yaml")
376
+ sys.exit(1)
377
+ choices = [
378
+ questionary.Choice(title=n, value=n, disabled="running")
379
+ if _get_running_pid(n) else questionary.Choice(title=n, value=n)
380
+ for n in all_names
381
+ ]
382
+ if all(c.disabled for c in choices):
383
+ click.echo("⚠️ All apps are already running")
384
+ return
385
+ app_name = questionary.select(
386
+ "Select an app to start:",
387
+ choices=choices,
388
+ ).ask()
389
+ if app_name is None:
390
+ sys.exit(0)
344
391
  app_def = config.get_app(app_name)
345
392
  if not app_def:
346
393
  available = config.list_apps()
@@ -426,13 +473,34 @@ def apps_start(app_name: str, apps_file: Optional[Path]):
426
473
 
427
474
 
428
475
  @apps.command('stop')
429
- @click.argument('app_name')
476
+ @click.argument('app_name', required=False, default=None)
430
477
  @click.option('--apps-file', '-f', type=click.Path(exists=True, path_type=Path),
431
478
  help='Path to apps.yaml file (default: ./apps.yaml)')
432
- def apps_stop(app_name: str, apps_file: Optional[Path]):
479
+ def apps_stop(app_name: Optional[str], apps_file: Optional[Path]):
433
480
  """Stop a running app and deregister it from the auth-proxy."""
434
481
  session_name = _get_session_name()
435
482
 
483
+ if app_name is None:
484
+ config = AppsConfig(apps_file)
485
+ all_names = config.list_apps()
486
+ if not all_names:
487
+ click.echo("❌ No apps found in apps.yaml")
488
+ sys.exit(1)
489
+ choices = [
490
+ questionary.Choice(title=n, value=n)
491
+ if _get_running_pid(n) else questionary.Choice(title=n, value=n, disabled="stopped")
492
+ for n in all_names
493
+ ]
494
+ if all(c.disabled for c in choices):
495
+ click.echo("⚠️ No apps are running")
496
+ return
497
+ app_name = questionary.select(
498
+ "Select an app to stop:",
499
+ choices=choices,
500
+ ).ask()
501
+ if app_name is None:
502
+ sys.exit(0)
503
+
436
504
  pid = _get_running_pid(app_name)
437
505
  if not pid:
438
506
  click.echo(f"⚠️ App '{app_name}' is not running")
@@ -452,6 +520,77 @@ def apps_stop(app_name: str, apps_file: Optional[Path]):
452
520
  click.echo(f"🔌 Deregistered from auth-proxy")
453
521
 
454
522
 
523
+ @apps.command('restart')
524
+ @click.argument('app_name', required=False, default=None)
525
+ @click.option('--apps-file', '-f', type=click.Path(exists=True, path_type=Path),
526
+ help='Path to apps.yaml file (default: ./apps.yaml)')
527
+ @click.pass_context
528
+ def apps_restart(ctx: click.Context, app_name: Optional[str], apps_file: Optional[Path]):
529
+ """Restart a running app."""
530
+ if app_name is None:
531
+ config = AppsConfig(apps_file)
532
+ all_names = config.list_apps()
533
+ if not all_names:
534
+ click.echo("❌ No apps found in apps.yaml")
535
+ sys.exit(1)
536
+ choices = [
537
+ questionary.Choice(title=n, value=n)
538
+ if _get_running_pid(n) else questionary.Choice(title=n, value=n, disabled="stopped")
539
+ for n in all_names
540
+ ]
541
+ if all(c.disabled for c in choices):
542
+ click.echo("⚠️ No apps are running")
543
+ return
544
+ app_name = questionary.select(
545
+ "Select an app to restart:",
546
+ choices=choices,
547
+ ).ask()
548
+ if app_name is None:
549
+ sys.exit(0)
550
+ ctx.invoke(apps_stop, app_name=app_name, apps_file=apps_file)
551
+ ctx.invoke(apps_start, app_name=app_name, apps_file=apps_file)
552
+
553
+
554
+ @apps.command('logs')
555
+ @click.argument('app_name', required=False, default=None)
556
+ @click.option('--apps-file', '-f', type=click.Path(exists=True, path_type=Path),
557
+ help='Path to apps.yaml file (default: ./apps.yaml)')
558
+ @click.option('--lines', '-n', default=50, show_default=True, help='Number of lines to show initially')
559
+ def apps_logs(app_name: Optional[str], apps_file: Optional[Path], lines: int):
560
+ """Tail the log file for an app."""
561
+ if app_name is None:
562
+ config = AppsConfig(apps_file)
563
+ all_names = config.list_apps()
564
+ if not all_names:
565
+ click.echo("❌ No apps found in apps.yaml")
566
+ sys.exit(1)
567
+ choices = [
568
+ questionary.Choice(title=n, value=n)
569
+ if (APPS_DIR / f"{n}.log").exists() else questionary.Choice(title=n, value=n, disabled="no logs")
570
+ for n in all_names
571
+ ]
572
+ if all(c.disabled for c in choices):
573
+ click.echo("⚠️ No log files found")
574
+ return
575
+ app_name = questionary.select(
576
+ "Select an app to view logs:",
577
+ choices=choices,
578
+ ).ask()
579
+ if app_name is None:
580
+ sys.exit(0)
581
+
582
+ log_file = APPS_DIR / f"{app_name}.log"
583
+ if not log_file.exists():
584
+ click.echo(f"❌ No log file found for '{app_name}' at {log_file}", err=True)
585
+ sys.exit(1)
586
+
587
+ click.echo(f"📄 Logs for {click.style(app_name, fg='blue', bold=True)} ({log_file}):\n")
588
+ try:
589
+ subprocess.call(["tail", f"-n{lines}", "-f", str(log_file)])
590
+ except KeyboardInterrupt:
591
+ pass
592
+
593
+
455
594
  SETUP_IGNORE = [".env.example", ".env.template"]
456
595
 
457
596
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: steve-cli
3
- Version: 0.3.13
3
+ Version: 0.3.14
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
File without changes
File without changes