unitysvc-services 0.1.8__py3-none-any.whl → 0.1.10__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.
Potentially problematic release.
This version of unitysvc-services might be problematic. Click here for more details.
- unitysvc_services/publisher.py +150 -28
- unitysvc_services/test.py +47 -16
- {unitysvc_services-0.1.8.dist-info → unitysvc_services-0.1.10.dist-info}/METADATA +1 -1
- {unitysvc_services-0.1.8.dist-info → unitysvc_services-0.1.10.dist-info}/RECORD +8 -8
- {unitysvc_services-0.1.8.dist-info → unitysvc_services-0.1.10.dist-info}/WHEEL +0 -0
- {unitysvc_services-0.1.8.dist-info → unitysvc_services-0.1.10.dist-info}/entry_points.txt +0 -0
- {unitysvc_services-0.1.8.dist-info → unitysvc_services-0.1.10.dist-info}/licenses/LICENSE +0 -0
- {unitysvc_services-0.1.8.dist-info → unitysvc_services-0.1.10.dist-info}/top_level.txt +0 -0
unitysvc_services/publisher.py
CHANGED
|
@@ -11,6 +11,9 @@ from typing import Any
|
|
|
11
11
|
import httpx
|
|
12
12
|
import typer
|
|
13
13
|
from rich.console import Console
|
|
14
|
+
from rich.table import Table
|
|
15
|
+
|
|
16
|
+
import unitysvc_services
|
|
14
17
|
|
|
15
18
|
from .api import UnitySvcAPI
|
|
16
19
|
from .models.base import ProviderStatusEnum, SellerStatusEnum
|
|
@@ -641,6 +644,16 @@ class ServiceDataPublisher(UnitySvcAPI):
|
|
|
641
644
|
files = find_files_by_schema(data_dir, "seller_v1")
|
|
642
645
|
return sorted([f[0] for f in files])
|
|
643
646
|
|
|
647
|
+
@staticmethod
|
|
648
|
+
def _get_status_display(status: str) -> tuple[str, str]:
|
|
649
|
+
"""Get color and symbol for status display."""
|
|
650
|
+
status_map = {
|
|
651
|
+
"created": ("[green]+[/green]", "green"),
|
|
652
|
+
"updated": ("[blue]~[/blue]", "blue"),
|
|
653
|
+
"unchanged": ("[dim]=[/dim]", "dim"),
|
|
654
|
+
}
|
|
655
|
+
return status_map.get(status, ("[green]✓[/green]", "green"))
|
|
656
|
+
|
|
644
657
|
async def _publish_offering_task(
|
|
645
658
|
self, offering_file: Path, console: Console, semaphore: asyncio.Semaphore
|
|
646
659
|
) -> tuple[Path, dict[str, Any] | Exception]:
|
|
@@ -664,8 +677,10 @@ class ServiceDataPublisher(UnitySvcAPI):
|
|
|
664
677
|
console.print(f" [yellow]⊘[/yellow] Skipped offering: [cyan]{offering_name}[/cyan] - {reason}")
|
|
665
678
|
else:
|
|
666
679
|
provider_name = result.get("provider_name")
|
|
680
|
+
status = result.get("status", "created")
|
|
681
|
+
symbol, color = self._get_status_display(status)
|
|
667
682
|
console.print(
|
|
668
|
-
f" [
|
|
683
|
+
f" {symbol} [{color}]{status.capitalize()}[/{color}] offering: [cyan]{offering_name}[/cyan] "
|
|
669
684
|
f"(provider: {provider_name})"
|
|
670
685
|
)
|
|
671
686
|
|
|
@@ -684,7 +699,8 @@ class ServiceDataPublisher(UnitySvcAPI):
|
|
|
684
699
|
Returns a summary of successes and failures.
|
|
685
700
|
"""
|
|
686
701
|
# Validate all service directories first
|
|
687
|
-
|
|
702
|
+
schema_dir = Path(unitysvc_services.__file__).parent / "schema"
|
|
703
|
+
validator = DataValidator(data_dir, schema_dir)
|
|
688
704
|
validation_errors = validator.validate_all_service_directories(data_dir)
|
|
689
705
|
if validation_errors:
|
|
690
706
|
return {
|
|
@@ -699,6 +715,9 @@ class ServiceDataPublisher(UnitySvcAPI):
|
|
|
699
715
|
"total": len(offering_files),
|
|
700
716
|
"success": 0,
|
|
701
717
|
"failed": 0,
|
|
718
|
+
"created": 0,
|
|
719
|
+
"updated": 0,
|
|
720
|
+
"unchanged": 0,
|
|
702
721
|
"errors": [],
|
|
703
722
|
}
|
|
704
723
|
|
|
@@ -720,6 +739,14 @@ class ServiceDataPublisher(UnitySvcAPI):
|
|
|
720
739
|
results["errors"].append({"file": str(offering_file), "error": str(result)})
|
|
721
740
|
else:
|
|
722
741
|
results["success"] += 1
|
|
742
|
+
# Track status counts
|
|
743
|
+
status = result.get("status", "created")
|
|
744
|
+
if status == "created":
|
|
745
|
+
results["created"] += 1
|
|
746
|
+
elif status == "updated":
|
|
747
|
+
results["updated"] += 1
|
|
748
|
+
elif status == "unchanged":
|
|
749
|
+
results["unchanged"] += 1
|
|
723
750
|
|
|
724
751
|
return results
|
|
725
752
|
|
|
@@ -747,8 +774,10 @@ class ServiceDataPublisher(UnitySvcAPI):
|
|
|
747
774
|
else:
|
|
748
775
|
service_name = result.get("service_name")
|
|
749
776
|
provider_name = result.get("provider_name")
|
|
777
|
+
status = result.get("status", "created")
|
|
778
|
+
symbol, color = self._get_status_display(status)
|
|
750
779
|
console.print(
|
|
751
|
-
f" [
|
|
780
|
+
f" {symbol} [{color}]{status.capitalize()}[/{color}] listing: [cyan]{listing_name}[/cyan] "
|
|
752
781
|
f"(service: {service_name}, provider: {provider_name})"
|
|
753
782
|
)
|
|
754
783
|
|
|
@@ -767,7 +796,8 @@ class ServiceDataPublisher(UnitySvcAPI):
|
|
|
767
796
|
Returns a summary of successes and failures.
|
|
768
797
|
"""
|
|
769
798
|
# Validate all service directories first
|
|
770
|
-
|
|
799
|
+
schema_dir = Path(unitysvc_services.__file__).parent / "schema"
|
|
800
|
+
validator = DataValidator(data_dir, schema_dir)
|
|
771
801
|
validation_errors = validator.validate_all_service_directories(data_dir)
|
|
772
802
|
if validation_errors:
|
|
773
803
|
return {
|
|
@@ -782,6 +812,9 @@ class ServiceDataPublisher(UnitySvcAPI):
|
|
|
782
812
|
"total": len(listing_files),
|
|
783
813
|
"success": 0,
|
|
784
814
|
"failed": 0,
|
|
815
|
+
"created": 0,
|
|
816
|
+
"updated": 0,
|
|
817
|
+
"unchanged": 0,
|
|
785
818
|
"errors": [],
|
|
786
819
|
}
|
|
787
820
|
|
|
@@ -803,6 +836,14 @@ class ServiceDataPublisher(UnitySvcAPI):
|
|
|
803
836
|
results["errors"].append({"file": str(listing_file), "error": str(result)})
|
|
804
837
|
else:
|
|
805
838
|
results["success"] += 1
|
|
839
|
+
# Track status counts
|
|
840
|
+
status = result.get("status", "created")
|
|
841
|
+
if status == "created":
|
|
842
|
+
results["created"] += 1
|
|
843
|
+
elif status == "updated":
|
|
844
|
+
results["updated"] += 1
|
|
845
|
+
elif status == "unchanged":
|
|
846
|
+
results["unchanged"] += 1
|
|
806
847
|
|
|
807
848
|
return results
|
|
808
849
|
|
|
@@ -828,7 +869,11 @@ class ServiceDataPublisher(UnitySvcAPI):
|
|
|
828
869
|
reason = result.get("reason", "unknown")
|
|
829
870
|
console.print(f" [yellow]⊘[/yellow] Skipped provider: [cyan]{provider_name}[/cyan] - {reason}")
|
|
830
871
|
else:
|
|
831
|
-
|
|
872
|
+
status = result.get("status", "created")
|
|
873
|
+
symbol, color = self._get_status_display(status)
|
|
874
|
+
console.print(
|
|
875
|
+
f" {symbol} [{color}]{status.capitalize()}[/{color}] provider: [cyan]{provider_name}[/cyan]"
|
|
876
|
+
)
|
|
832
877
|
|
|
833
878
|
return (provider_file, result)
|
|
834
879
|
except Exception as e:
|
|
@@ -848,6 +893,9 @@ class ServiceDataPublisher(UnitySvcAPI):
|
|
|
848
893
|
"total": len(provider_files),
|
|
849
894
|
"success": 0,
|
|
850
895
|
"failed": 0,
|
|
896
|
+
"created": 0,
|
|
897
|
+
"updated": 0,
|
|
898
|
+
"unchanged": 0,
|
|
851
899
|
"errors": [],
|
|
852
900
|
}
|
|
853
901
|
|
|
@@ -869,6 +917,14 @@ class ServiceDataPublisher(UnitySvcAPI):
|
|
|
869
917
|
results["errors"].append({"file": str(provider_file), "error": str(result)})
|
|
870
918
|
else:
|
|
871
919
|
results["success"] += 1
|
|
920
|
+
# Track status counts
|
|
921
|
+
status = result.get("status", "created")
|
|
922
|
+
if status == "created":
|
|
923
|
+
results["created"] += 1
|
|
924
|
+
elif status == "updated":
|
|
925
|
+
results["updated"] += 1
|
|
926
|
+
elif status == "unchanged":
|
|
927
|
+
results["unchanged"] += 1
|
|
872
928
|
|
|
873
929
|
return results
|
|
874
930
|
|
|
@@ -894,7 +950,11 @@ class ServiceDataPublisher(UnitySvcAPI):
|
|
|
894
950
|
reason = result.get("reason", "unknown")
|
|
895
951
|
console.print(f" [yellow]⊘[/yellow] Skipped seller: [cyan]{seller_name}[/cyan] - {reason}")
|
|
896
952
|
else:
|
|
897
|
-
|
|
953
|
+
status = result.get("status", "created")
|
|
954
|
+
symbol, color = self._get_status_display(status)
|
|
955
|
+
console.print(
|
|
956
|
+
f" {symbol} [{color}]{status.capitalize()}[/{color}] seller: [cyan]{seller_name}[/cyan]"
|
|
957
|
+
)
|
|
898
958
|
|
|
899
959
|
return (seller_file, result)
|
|
900
960
|
except Exception as e:
|
|
@@ -914,6 +974,9 @@ class ServiceDataPublisher(UnitySvcAPI):
|
|
|
914
974
|
"total": len(seller_files),
|
|
915
975
|
"success": 0,
|
|
916
976
|
"failed": 0,
|
|
977
|
+
"created": 0,
|
|
978
|
+
"updated": 0,
|
|
979
|
+
"unchanged": 0,
|
|
917
980
|
"errors": [],
|
|
918
981
|
}
|
|
919
982
|
|
|
@@ -935,6 +998,14 @@ class ServiceDataPublisher(UnitySvcAPI):
|
|
|
935
998
|
results["errors"].append({"file": str(seller_file), "error": str(result)})
|
|
936
999
|
else:
|
|
937
1000
|
results["success"] += 1
|
|
1001
|
+
# Track status counts
|
|
1002
|
+
status = result.get("status", "created")
|
|
1003
|
+
if status == "created":
|
|
1004
|
+
results["created"] += 1
|
|
1005
|
+
elif status == "updated":
|
|
1006
|
+
results["updated"] += 1
|
|
1007
|
+
elif status == "unchanged":
|
|
1008
|
+
results["unchanged"] += 1
|
|
938
1009
|
|
|
939
1010
|
return results
|
|
940
1011
|
|
|
@@ -958,6 +1029,9 @@ class ServiceDataPublisher(UnitySvcAPI):
|
|
|
958
1029
|
"total_success": 0,
|
|
959
1030
|
"total_failed": 0,
|
|
960
1031
|
"total_found": 0,
|
|
1032
|
+
"total_created": 0,
|
|
1033
|
+
"total_updated": 0,
|
|
1034
|
+
"total_unchanged": 0,
|
|
961
1035
|
}
|
|
962
1036
|
|
|
963
1037
|
# Publish in order: sellers -> providers -> offerings -> listings
|
|
@@ -975,6 +1049,9 @@ class ServiceDataPublisher(UnitySvcAPI):
|
|
|
975
1049
|
all_results["total_success"] += results["success"]
|
|
976
1050
|
all_results["total_failed"] += results["failed"]
|
|
977
1051
|
all_results["total_found"] += results["total"]
|
|
1052
|
+
all_results["total_created"] += results.get("created", 0)
|
|
1053
|
+
all_results["total_updated"] += results.get("updated", 0)
|
|
1054
|
+
all_results["total_unchanged"] += results.get("unchanged", 0)
|
|
978
1055
|
except Exception as e:
|
|
979
1056
|
# If a publish method fails catastrophically, record the error
|
|
980
1057
|
all_results[data_type] = {
|
|
@@ -1045,43 +1122,72 @@ def publish_callback(
|
|
|
1045
1122
|
try:
|
|
1046
1123
|
all_results = asyncio.run(_publish_all_async())
|
|
1047
1124
|
|
|
1048
|
-
#
|
|
1125
|
+
# Create summary table
|
|
1126
|
+
console.print("\n[bold cyan]Publishing Summary[/bold cyan]")
|
|
1127
|
+
|
|
1128
|
+
table = Table(show_header=True, header_style="bold cyan", border_style="cyan")
|
|
1129
|
+
table.add_column("Type", style="cyan", no_wrap=True)
|
|
1130
|
+
table.add_column("Found", justify="right")
|
|
1131
|
+
table.add_column("Success", justify="right", style="green")
|
|
1132
|
+
table.add_column("Failed", justify="right", style="red")
|
|
1133
|
+
table.add_column("Created", justify="right", style="green")
|
|
1134
|
+
table.add_column("Updated", justify="right", style="blue")
|
|
1135
|
+
table.add_column("Unchanged", justify="right", style="dim")
|
|
1136
|
+
|
|
1049
1137
|
data_type_display_names = {
|
|
1050
1138
|
"sellers": "Sellers",
|
|
1051
1139
|
"providers": "Providers",
|
|
1052
|
-
"offerings": "
|
|
1053
|
-
"listings": "
|
|
1140
|
+
"offerings": "Offerings",
|
|
1141
|
+
"listings": "Listings",
|
|
1054
1142
|
}
|
|
1055
1143
|
|
|
1144
|
+
# Add rows for each data type
|
|
1056
1145
|
for data_type in ["sellers", "providers", "offerings", "listings"]:
|
|
1057
1146
|
display_name = data_type_display_names[data_type]
|
|
1058
1147
|
results = all_results[data_type]
|
|
1059
1148
|
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1149
|
+
table.add_row(
|
|
1150
|
+
display_name,
|
|
1151
|
+
str(results['total']),
|
|
1152
|
+
str(results['success']),
|
|
1153
|
+
str(results['failed']),
|
|
1154
|
+
str(results.get('created', 0)),
|
|
1155
|
+
str(results.get('updated', 0)),
|
|
1156
|
+
str(results.get('unchanged', 0)),
|
|
1157
|
+
)
|
|
1158
|
+
|
|
1159
|
+
# Add separator and total row
|
|
1160
|
+
table.add_section()
|
|
1161
|
+
table.add_row(
|
|
1162
|
+
"[bold]Total[/bold]",
|
|
1163
|
+
f"[bold]{all_results['total_found']}[/bold]",
|
|
1164
|
+
f"[bold green]{all_results['total_success']}[/bold green]",
|
|
1165
|
+
f"[bold red]{all_results['total_failed']}[/bold red]",
|
|
1166
|
+
f"[bold green]{all_results['total_created']}[/bold green]",
|
|
1167
|
+
f"[bold blue]{all_results['total_updated']}[/bold blue]",
|
|
1168
|
+
f"[bold]{all_results['total_unchanged']}[/bold]",
|
|
1169
|
+
)
|
|
1063
1170
|
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1171
|
+
console.print(table)
|
|
1172
|
+
|
|
1173
|
+
# Display errors if any
|
|
1174
|
+
has_errors = False
|
|
1175
|
+
for data_type in ["sellers", "providers", "offerings", "listings"]:
|
|
1176
|
+
display_name = data_type_display_names[data_type]
|
|
1177
|
+
results = all_results[data_type]
|
|
1067
1178
|
|
|
1068
|
-
# Display errors if any
|
|
1069
1179
|
if results.get("errors"):
|
|
1070
|
-
|
|
1180
|
+
if not has_errors:
|
|
1181
|
+
console.print("\n[bold red]Errors:[/bold red]")
|
|
1182
|
+
has_errors = True
|
|
1183
|
+
|
|
1184
|
+
console.print(f"\n [bold red]{display_name}:[/bold red]")
|
|
1071
1185
|
for error in results["errors"]:
|
|
1072
1186
|
# Check if this is a skipped item
|
|
1073
1187
|
if isinstance(error, dict) and error.get("error", "").startswith("skipped"):
|
|
1074
1188
|
continue
|
|
1075
|
-
console.print(f"
|
|
1076
|
-
console.print(f"
|
|
1077
|
-
|
|
1078
|
-
# Final summary
|
|
1079
|
-
console.print(f"\n[bold cyan]{'=' * 60}[/bold cyan]")
|
|
1080
|
-
console.print("[bold]Final Publishing Summary[/bold]")
|
|
1081
|
-
console.print(f"[bold cyan]{'=' * 60}[/bold cyan]\n")
|
|
1082
|
-
console.print(f" Total found: {all_results['total_found']}")
|
|
1083
|
-
console.print(f" [green]✓ Success:[/green] {all_results['total_success']}")
|
|
1084
|
-
console.print(f" [red]✗ Failed:[/red] {all_results['total_failed']}")
|
|
1189
|
+
console.print(f" [red]✗[/red] {error.get('file', 'unknown')}")
|
|
1190
|
+
console.print(f" {error.get('error', 'unknown error')}")
|
|
1085
1191
|
|
|
1086
1192
|
if all_results["total_failed"] > 0:
|
|
1087
1193
|
console.print(
|
|
@@ -1153,6 +1259,10 @@ def publish_providers(
|
|
|
1153
1259
|
console.print(f" Total found: {result['total']}")
|
|
1154
1260
|
console.print(f" [green]✓ Success:[/green] {result['success']}")
|
|
1155
1261
|
console.print(f" [red]✗ Failed:[/red] {result['failed']}")
|
|
1262
|
+
if result["success"] > 0:
|
|
1263
|
+
console.print(f" [green]+ Created: {result['created']}[/green]")
|
|
1264
|
+
console.print(f" [blue]~ Updated: {result['updated']}[/blue]")
|
|
1265
|
+
console.print(f" [dim]= Unchanged: {result['unchanged']}[/dim]")
|
|
1156
1266
|
|
|
1157
1267
|
# Display errors if any
|
|
1158
1268
|
if result["errors"]:
|
|
@@ -1220,6 +1330,10 @@ def publish_sellers(
|
|
|
1220
1330
|
console.print(f" Total found: {result['total']}")
|
|
1221
1331
|
console.print(f" [green]✓ Success: {result['success']}[/green]")
|
|
1222
1332
|
console.print(f" [red]✗ Failed: {result['failed']}[/red]")
|
|
1333
|
+
if result["success"] > 0:
|
|
1334
|
+
console.print(f" [green]+ Created: {result['created']}[/green]")
|
|
1335
|
+
console.print(f" [blue]~ Updated: {result['updated']}[/blue]")
|
|
1336
|
+
console.print(f" [dim]= Unchanged: {result['unchanged']}[/dim]")
|
|
1223
1337
|
|
|
1224
1338
|
if result["errors"]:
|
|
1225
1339
|
console.print("\n[bold red]Errors:[/bold red]")
|
|
@@ -1264,7 +1378,7 @@ def publish_offerings(
|
|
|
1264
1378
|
console.print(f"[blue]Backend URL:[/blue] {os.getenv('UNITYSVC_BASE_URL', 'N/A')}\n")
|
|
1265
1379
|
else:
|
|
1266
1380
|
console.print(f"[blue]Scanning for service offerings in:[/blue] {data_path}")
|
|
1267
|
-
console.print(f"[blue]Backend URL:[/
|
|
1381
|
+
console.print(f"[blue]Backend URL:[/blue] {os.getenv('UNITYSVC_BASE_URL', 'N/A')}\n")
|
|
1268
1382
|
|
|
1269
1383
|
async def _publish_offerings_async():
|
|
1270
1384
|
async with ServiceDataPublisher() as publisher:
|
|
@@ -1286,6 +1400,10 @@ def publish_offerings(
|
|
|
1286
1400
|
console.print(f" Total found: {result['total']}")
|
|
1287
1401
|
console.print(f" [green]✓ Success: {result['success']}[/green]")
|
|
1288
1402
|
console.print(f" [red]✗ Failed: {result['failed']}[/red]")
|
|
1403
|
+
if result["success"] > 0:
|
|
1404
|
+
console.print(f" [green]+ Created: {result['created']}[/green]")
|
|
1405
|
+
console.print(f" [blue]~ Updated: {result['updated']}[/blue]")
|
|
1406
|
+
console.print(f" [dim]= Unchanged: {result['unchanged']}[/dim]")
|
|
1289
1407
|
|
|
1290
1408
|
if result["errors"]:
|
|
1291
1409
|
console.print("\n[bold red]Errors:[/bold red]")
|
|
@@ -1353,6 +1471,10 @@ def publish_listings(
|
|
|
1353
1471
|
console.print(f" Total found: {result['total']}")
|
|
1354
1472
|
console.print(f" [green]✓ Success: {result['success']}[/green]")
|
|
1355
1473
|
console.print(f" [red]✗ Failed: {result['failed']}[/red]")
|
|
1474
|
+
if result["success"] > 0:
|
|
1475
|
+
console.print(f" [green]+ Created: {result['created']}[/green]")
|
|
1476
|
+
console.print(f" [blue]~ Updated: {result['updated']}[/blue]")
|
|
1477
|
+
console.print(f" [dim]= Unchanged: {result['unchanged']}[/dim]")
|
|
1356
1478
|
|
|
1357
1479
|
if result["errors"]:
|
|
1358
1480
|
console.print("\n[bold red]Errors:[/bold red]")
|
unitysvc_services/test.py
CHANGED
|
@@ -720,26 +720,38 @@ def run(
|
|
|
720
720
|
if verbose and result["stdout"]:
|
|
721
721
|
console.print(f" [dim]stdout:[/dim] {result['stdout'][:200]}")
|
|
722
722
|
|
|
723
|
-
# Save successful test output to .out
|
|
724
|
-
if result.get("
|
|
723
|
+
# Save successful test output to .out and .err files
|
|
724
|
+
if result.get("listing_file") and result.get("actual_filename"):
|
|
725
725
|
listing_file = Path(result["listing_file"])
|
|
726
726
|
actual_filename = result["actual_filename"]
|
|
727
|
-
|
|
728
|
-
# Create filename: {listing_stem}_{actual_filename}.out
|
|
729
|
-
# e.g., "svclisting_test.py.out" for svclisting.json and test.py
|
|
730
727
|
listing_stem = listing_file.stem
|
|
731
|
-
|
|
728
|
+
|
|
729
|
+
# Create filename pattern: {service_name}_{listing_stem}_{actual_filename}.out/.err
|
|
730
|
+
# e.g., "llama-3-1-405b-instruct_svclisting_test.py.out"
|
|
731
|
+
base_filename = f"{service_name}_{listing_stem}_{actual_filename}"
|
|
732
|
+
out_filename = f"{base_filename}.out"
|
|
733
|
+
err_filename = f"{base_filename}.err"
|
|
732
734
|
|
|
733
735
|
# Save to listing directory
|
|
734
|
-
|
|
736
|
+
out_path = listing_file.parent / out_filename
|
|
737
|
+
err_path = listing_file.parent / err_filename
|
|
735
738
|
|
|
736
739
|
# Write stdout to .out file
|
|
737
740
|
try:
|
|
738
|
-
with open(
|
|
739
|
-
f.write(result["stdout"])
|
|
740
|
-
console.print(f" [dim]→ Output saved to:[/dim] {
|
|
741
|
+
with open(out_path, "w", encoding="utf-8") as f:
|
|
742
|
+
f.write(result["stdout"] or "")
|
|
743
|
+
console.print(f" [dim]→ Output saved to:[/dim] {out_path}")
|
|
741
744
|
except Exception as e:
|
|
742
745
|
console.print(f" [yellow]⚠ Failed to save output: {e}[/yellow]")
|
|
746
|
+
|
|
747
|
+
# Write stderr to .err file
|
|
748
|
+
try:
|
|
749
|
+
with open(err_path, "w", encoding="utf-8") as f:
|
|
750
|
+
f.write(result["stderr"] or "")
|
|
751
|
+
if result["stderr"]:
|
|
752
|
+
console.print(f" [dim]→ Error output saved to:[/dim] {err_path}")
|
|
753
|
+
except Exception as e:
|
|
754
|
+
console.print(f" [yellow]⚠ Failed to save error output: {e}[/yellow]")
|
|
743
755
|
else:
|
|
744
756
|
console.print(f" [red]✗ Failed[/red] - {result['error']}")
|
|
745
757
|
if verbose:
|
|
@@ -748,16 +760,36 @@ def run(
|
|
|
748
760
|
if result["stderr"]:
|
|
749
761
|
console.print(f" [dim]stderr:[/dim] {result['stderr'][:200]}")
|
|
750
762
|
|
|
751
|
-
# Write failed test
|
|
752
|
-
if result.get("
|
|
763
|
+
# Write failed test outputs and script to current directory
|
|
764
|
+
if result.get("listing_file") and result.get("actual_filename"):
|
|
753
765
|
listing_file = Path(result["listing_file"])
|
|
754
766
|
actual_filename = result["actual_filename"]
|
|
755
767
|
listing_stem = listing_file.stem
|
|
756
768
|
|
|
757
769
|
# Create filename: failed_{service_name}_{listing_stem}_{actual_filename}
|
|
770
|
+
# This will be the base name for .out, .err, and the script file
|
|
758
771
|
failed_filename = f"failed_{service_name}_{listing_stem}_{actual_filename}"
|
|
759
772
|
|
|
760
|
-
#
|
|
773
|
+
# Write stdout to .out file in current directory
|
|
774
|
+
out_filename = f"{failed_filename}.out"
|
|
775
|
+
try:
|
|
776
|
+
with open(out_filename, "w", encoding="utf-8") as f:
|
|
777
|
+
f.write(result["stdout"] or "")
|
|
778
|
+
console.print(f" [yellow]→ Output saved to:[/yellow] {out_filename}")
|
|
779
|
+
except Exception as e:
|
|
780
|
+
console.print(f" [yellow]⚠ Failed to save output: {e}[/yellow]")
|
|
781
|
+
|
|
782
|
+
# Write stderr to .err file in current directory
|
|
783
|
+
err_filename = f"{failed_filename}.err"
|
|
784
|
+
try:
|
|
785
|
+
with open(err_filename, "w", encoding="utf-8") as f:
|
|
786
|
+
f.write(result["stderr"] or "")
|
|
787
|
+
console.print(f" [yellow]→ Error output saved to:[/yellow] {err_filename}")
|
|
788
|
+
except Exception as e:
|
|
789
|
+
console.print(f" [yellow]⚠ Failed to save error output: {e}[/yellow]")
|
|
790
|
+
|
|
791
|
+
# Write failed test script content to current directory (for debugging)
|
|
792
|
+
# rendered_content is always set if we got here (set during template rendering)
|
|
761
793
|
content_with_env = result["rendered_content"]
|
|
762
794
|
|
|
763
795
|
# Add environment variables as comments at the top
|
|
@@ -774,14 +806,13 @@ def run(
|
|
|
774
806
|
|
|
775
807
|
content_with_env = env_header + content_with_env
|
|
776
808
|
|
|
777
|
-
# Write to current directory
|
|
778
809
|
try:
|
|
779
810
|
with open(failed_filename, "w", encoding="utf-8") as f:
|
|
780
811
|
f.write(content_with_env)
|
|
781
|
-
console.print(f" [yellow]→ Test
|
|
812
|
+
console.print(f" [yellow]→ Test script saved to:[/yellow] {failed_filename}")
|
|
782
813
|
console.print(" [dim] (includes environment variables for reproduction)[/dim]")
|
|
783
814
|
except Exception as e:
|
|
784
|
-
console.print(f" [yellow]⚠ Failed to save test
|
|
815
|
+
console.print(f" [yellow]⚠ Failed to save test script: {e}[/yellow]")
|
|
785
816
|
|
|
786
817
|
console.print()
|
|
787
818
|
|
|
@@ -4,11 +4,11 @@ unitysvc_services/cli.py,sha256=omHzrWk8iZJUjZTE5KCmEK1wnRGGnQk_BNV-hKqucnA,725
|
|
|
4
4
|
unitysvc_services/format_data.py,sha256=Jl9Vj3fRX852fHSUa5DzO-oiFQwuQHC3WMCDNIlo1Lc,5460
|
|
5
5
|
unitysvc_services/list.py,sha256=QDp9BByaoeFeJxXJN9RQ-jU99mH9Guq9ampfXCbpZmI,7033
|
|
6
6
|
unitysvc_services/populate.py,sha256=jiqS2D3_widV6siPe3OBvw7ZdG9MuddEIOuTUCtMM5c,7605
|
|
7
|
-
unitysvc_services/publisher.py,sha256=
|
|
7
|
+
unitysvc_services/publisher.py,sha256=7KFzQ3cB33t5t5LDUPYZ7LoP6LXoT9Y5PgqNzP-kOmk,61695
|
|
8
8
|
unitysvc_services/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
9
|
unitysvc_services/query.py,sha256=q0_g5YAl9cPlHpW7k7Y6A-t4fQSdI-_4Jl6g2KgkEm0,24049
|
|
10
10
|
unitysvc_services/scaffold.py,sha256=Y73IX8vskImxSvxDgR0mvEFuAMYnBKfttn3bjcz3jmQ,40331
|
|
11
|
-
unitysvc_services/test.py,sha256=
|
|
11
|
+
unitysvc_services/test.py,sha256=Uf06_mgRcEGf9HHYzW2BGTzrDKwd3n7Xb60DFChP8kM,32472
|
|
12
12
|
unitysvc_services/update.py,sha256=K9swocTUnqqiSgARo6GmuzTzUySSpyqqPPW4xF7ZU-g,9659
|
|
13
13
|
unitysvc_services/utils.py,sha256=4tEBdO90XpkS6j73ZXnz5dNLVXJaPUILWMwzk5_fUQ4,15276
|
|
14
14
|
unitysvc_services/validator.py,sha256=NYoIWV2iMyjse1-mIVz2GnFXNDewLnJVDIDAjqnsBCs,30241
|
|
@@ -23,9 +23,9 @@ unitysvc_services/schema/listing_v1.json,sha256=gzSK5ncnqmcb44WPnv0FG9xyJ-wUznca
|
|
|
23
23
|
unitysvc_services/schema/provider_v1.json,sha256=L2rudq1RcfAE67WJXmowJu5_YReqxioiQO0263SWaNc,22033
|
|
24
24
|
unitysvc_services/schema/seller_v1.json,sha256=QhYuaJBugWVbgAEBhrSyYAPT1Ss_6Z0rz0lA2FhJOo8,8841
|
|
25
25
|
unitysvc_services/schema/service_v1.json,sha256=sifCZzx0hT7k6tpDCkPUgXYG9e5OVUaeKudTjEPFO4E,24293
|
|
26
|
-
unitysvc_services-0.1.
|
|
27
|
-
unitysvc_services-0.1.
|
|
28
|
-
unitysvc_services-0.1.
|
|
29
|
-
unitysvc_services-0.1.
|
|
30
|
-
unitysvc_services-0.1.
|
|
31
|
-
unitysvc_services-0.1.
|
|
26
|
+
unitysvc_services-0.1.10.dist-info/licenses/LICENSE,sha256=_p8V6A8OMPu2HIztn3O01v0-urZFwk0Dd3Yk_PTIlL8,1065
|
|
27
|
+
unitysvc_services-0.1.10.dist-info/METADATA,sha256=oehP4td47B1x0c1Rg8zNO2OLlvdKvLhzbvqb5mIQCgk,7235
|
|
28
|
+
unitysvc_services-0.1.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
29
|
+
unitysvc_services-0.1.10.dist-info/entry_points.txt,sha256=RBhVHKky3rsOly4jVa29c7UAw5ZwNNWnttmtzozr5O0,97
|
|
30
|
+
unitysvc_services-0.1.10.dist-info/top_level.txt,sha256=GIotQj-Ro2ruR7eupM1r58PWqIHTAq647ORL7E2kneo,18
|
|
31
|
+
unitysvc_services-0.1.10.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|