unitysvc-services 0.1.0__py3-none-any.whl
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.
- unitysvc_services/__init__.py +4 -0
- unitysvc_services/cli.py +21 -0
- unitysvc_services/format_data.py +145 -0
- unitysvc_services/list.py +245 -0
- unitysvc_services/models/__init__.py +6 -0
- unitysvc_services/models/base.py +352 -0
- unitysvc_services/models/listing_v1.py +72 -0
- unitysvc_services/models/provider_v1.py +53 -0
- unitysvc_services/models/seller_v1.py +110 -0
- unitysvc_services/models/service_v1.py +80 -0
- unitysvc_services/populate.py +186 -0
- unitysvc_services/publisher.py +925 -0
- unitysvc_services/query.py +471 -0
- unitysvc_services/scaffold.py +1039 -0
- unitysvc_services/update.py +293 -0
- unitysvc_services/utils.py +240 -0
- unitysvc_services/validator.py +515 -0
- unitysvc_services-0.1.0.dist-info/METADATA +172 -0
- unitysvc_services-0.1.0.dist-info/RECORD +23 -0
- unitysvc_services-0.1.0.dist-info/WHEEL +5 -0
- unitysvc_services-0.1.0.dist-info/entry_points.txt +2 -0
- unitysvc_services-0.1.0.dist-info/licenses/LICENSE +21 -0
- unitysvc_services-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,186 @@
|
|
1
|
+
"""Populate command - populate services by executing provider scripts."""
|
2
|
+
|
3
|
+
import json
|
4
|
+
import os
|
5
|
+
import subprocess
|
6
|
+
import tomllib
|
7
|
+
from pathlib import Path
|
8
|
+
|
9
|
+
import typer
|
10
|
+
from rich.console import Console
|
11
|
+
|
12
|
+
from .utils import find_files_by_schema
|
13
|
+
|
14
|
+
app = typer.Typer(help="Populate services")
|
15
|
+
console = Console()
|
16
|
+
|
17
|
+
|
18
|
+
@app.command()
|
19
|
+
def populate(
|
20
|
+
data_dir: Path | None = typer.Argument(
|
21
|
+
None,
|
22
|
+
help="Directory containing provider data files (default: ./data or UNITYSVC_DATA_DIR env var)",
|
23
|
+
),
|
24
|
+
provider_name: str | None = typer.Option(
|
25
|
+
None,
|
26
|
+
"--provider",
|
27
|
+
"-p",
|
28
|
+
help="Only populate services for a specific provider",
|
29
|
+
),
|
30
|
+
dry_run: bool = typer.Option(
|
31
|
+
False,
|
32
|
+
"--dry-run",
|
33
|
+
help="Show what would be executed without actually running commands",
|
34
|
+
),
|
35
|
+
):
|
36
|
+
"""
|
37
|
+
Populate services by executing provider-specific update scripts.
|
38
|
+
|
39
|
+
This command scans provider files for 'services_populator' configuration and executes
|
40
|
+
the specified commands with environment variables from 'provider_access_info'.
|
41
|
+
"""
|
42
|
+
# Set data directory
|
43
|
+
if data_dir is None:
|
44
|
+
data_dir_str = os.getenv("UNITYSVC_DATA_DIR")
|
45
|
+
if data_dir_str:
|
46
|
+
data_dir = Path(data_dir_str)
|
47
|
+
else:
|
48
|
+
data_dir = Path.cwd() / "data"
|
49
|
+
|
50
|
+
if not data_dir.is_absolute():
|
51
|
+
data_dir = Path.cwd() / data_dir
|
52
|
+
|
53
|
+
if not data_dir.exists():
|
54
|
+
console.print(f"[red]✗[/red] Data directory not found: {data_dir}", style="bold red")
|
55
|
+
raise typer.Exit(code=1)
|
56
|
+
|
57
|
+
console.print(f"[blue]Scanning for provider configurations in:[/blue] {data_dir}\n")
|
58
|
+
|
59
|
+
# Find all provider files by schema
|
60
|
+
provider_results = find_files_by_schema(data_dir, "provider_v1")
|
61
|
+
provider_files = [file_path for file_path, _, _ in provider_results]
|
62
|
+
|
63
|
+
if not provider_files:
|
64
|
+
console.print("[yellow]No provider files found.[/yellow]")
|
65
|
+
raise typer.Exit(code=0)
|
66
|
+
|
67
|
+
console.print(f"[cyan]Found {len(provider_files)} provider file(s)[/cyan]\n")
|
68
|
+
|
69
|
+
# Process each provider
|
70
|
+
total_executed = 0
|
71
|
+
total_skipped = 0
|
72
|
+
total_failed = 0
|
73
|
+
|
74
|
+
for provider_file in provider_files:
|
75
|
+
try:
|
76
|
+
# Load provider configuration
|
77
|
+
if provider_file.suffix == ".toml":
|
78
|
+
with open(provider_file, "rb") as f:
|
79
|
+
provider_config = tomllib.load(f)
|
80
|
+
else:
|
81
|
+
with open(provider_file) as f:
|
82
|
+
provider_config = json.load(f)
|
83
|
+
|
84
|
+
provider_name_in_file = provider_config.get("name", "unknown")
|
85
|
+
|
86
|
+
# Skip if provider filter is set and doesn't match
|
87
|
+
if provider_name and provider_name_in_file != provider_name:
|
88
|
+
console.print(f"[dim]Skipping provider: {provider_name_in_file} (filter: {provider_name})[/dim]")
|
89
|
+
total_skipped += 1
|
90
|
+
continue
|
91
|
+
|
92
|
+
# Check if services_populator is configured
|
93
|
+
services_populator = provider_config.get("services_populator")
|
94
|
+
if not services_populator:
|
95
|
+
console.print(f"[yellow]⏭️ Skipping {provider_name_in_file}: No services_populator configured[/yellow]")
|
96
|
+
total_skipped += 1
|
97
|
+
continue
|
98
|
+
|
99
|
+
command = services_populator.get("command")
|
100
|
+
if not command:
|
101
|
+
console.print(
|
102
|
+
f"[yellow]⏭️ Skipping {provider_name_in_file}: No command specified in services_populator[/yellow]"
|
103
|
+
)
|
104
|
+
total_skipped += 1
|
105
|
+
continue
|
106
|
+
|
107
|
+
console.print(f"[bold cyan]Processing provider:[/bold cyan] {provider_name_in_file}")
|
108
|
+
|
109
|
+
# Prepare environment variables from provider_access_info
|
110
|
+
env = os.environ.copy()
|
111
|
+
provider_access_info = provider_config.get("provider_access_info", {})
|
112
|
+
if provider_access_info:
|
113
|
+
for key, value in provider_access_info.items():
|
114
|
+
env[key] = str(value)
|
115
|
+
console.print(
|
116
|
+
f"[dim] Set {len(provider_access_info)} environment variable(s) from provider_access_info[/dim]"
|
117
|
+
)
|
118
|
+
|
119
|
+
# Get the provider directory (parent of provider file)
|
120
|
+
provider_dir = provider_file.parent
|
121
|
+
|
122
|
+
# Build command - handle both string and list formats
|
123
|
+
if isinstance(command, str):
|
124
|
+
cmd_parts = command.split()
|
125
|
+
else:
|
126
|
+
cmd_parts = command
|
127
|
+
|
128
|
+
# Resolve script path relative to provider directory
|
129
|
+
script_path = provider_dir / cmd_parts[0]
|
130
|
+
if script_path.exists():
|
131
|
+
cmd_parts[0] = str(script_path)
|
132
|
+
|
133
|
+
full_command = ["python3"] + cmd_parts
|
134
|
+
|
135
|
+
console.print(f"[blue] Command:[/blue] {' '.join(full_command)}")
|
136
|
+
console.print(f"[blue] Working directory:[/blue] {provider_dir}")
|
137
|
+
|
138
|
+
if dry_run:
|
139
|
+
console.print("[yellow] [DRY-RUN] Would execute command[/yellow]\n")
|
140
|
+
total_skipped += 1
|
141
|
+
continue
|
142
|
+
|
143
|
+
# Execute the command
|
144
|
+
try:
|
145
|
+
result = subprocess.run(
|
146
|
+
full_command,
|
147
|
+
cwd=provider_dir,
|
148
|
+
env=env,
|
149
|
+
capture_output=False,
|
150
|
+
text=True,
|
151
|
+
)
|
152
|
+
|
153
|
+
if result.returncode == 0:
|
154
|
+
console.print(f"[green]✓[/green] Successfully populated services for {provider_name_in_file}\n")
|
155
|
+
total_executed += 1
|
156
|
+
else:
|
157
|
+
console.print(
|
158
|
+
f"[red]✗[/red] Command failed for {provider_name_in_file} (exit code: {result.returncode})\n",
|
159
|
+
style="bold red",
|
160
|
+
)
|
161
|
+
total_failed += 1
|
162
|
+
|
163
|
+
except subprocess.SubprocessError as e:
|
164
|
+
console.print(
|
165
|
+
f"[red]✗[/red] Failed to execute command for {provider_name_in_file}: {e}\n",
|
166
|
+
style="bold red",
|
167
|
+
)
|
168
|
+
total_failed += 1
|
169
|
+
|
170
|
+
except Exception as e:
|
171
|
+
console.print(
|
172
|
+
f"[red]✗[/red] Error processing {provider_file}: {e}\n",
|
173
|
+
style="bold red",
|
174
|
+
)
|
175
|
+
total_failed += 1
|
176
|
+
|
177
|
+
# Print summary
|
178
|
+
console.print("\n" + "=" * 50)
|
179
|
+
console.print("[bold]Populate Services Summary:[/bold]")
|
180
|
+
console.print(f" Total providers found: {len(provider_files)}")
|
181
|
+
console.print(f" [green]✓ Successfully executed: {total_executed}[/green]")
|
182
|
+
console.print(f" [yellow]⏭️ Skipped: {total_skipped}[/yellow]")
|
183
|
+
console.print(f" [red]✗ Failed: {total_failed}[/red]")
|
184
|
+
|
185
|
+
if total_failed > 0:
|
186
|
+
raise typer.Exit(code=1)
|