csrd-utils 0.3.54__tar.gz → 0.3.56__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.
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/PKG-INFO +1 -1
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/pyproject.toml +1 -1
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/__main__.py +109 -5
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/generator.py +14 -0
- csrd_utils-0.3.56/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/acceptance/__init__.py +0 -0
- csrd_utils-0.3.56/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/unit/__init__.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/.gitignore +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/README.md +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/__init__.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/audit.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/augmentor.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/cluster.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/doctor.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/caching/conftest.fragment.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/caching/docker-compose.fragment.yaml +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/caching/manifest.yaml +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/caching/requirements.fragment +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/caching/settings.fragment.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/caching/src/app/cache.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/caching/tests/test_cache.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/logging/conftest.fragment.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/logging/manifest.yaml +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/logging/requirements.fragment +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/logging/settings.fragment.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/logging/src/app/middleware/logging.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/logging/tests/test_logging_middleware.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/metrics/conftest.fragment.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/metrics/docker-compose.fragment.yaml +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/metrics/manifest.yaml +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/metrics/requirements.fragment +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/metrics/settings.fragment.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/metrics/src/app/middleware/metrics.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/metrics/tests/test_metrics_middleware.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/tracing/conftest.fragment.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/tracing/manifest.yaml +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/tracing/requirements.fragment +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/tracing/settings.fragment.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/tracing/src/app/middleware/tracing.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/tracing/tests/test_tracing_middleware.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/workers/conftest.fragment.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/workers/docker-compose.fragment.yaml +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/workers/manifest.yaml +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/workers/requirements.fragment +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/workers/settings.fragment.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/workers/src/app/workers/__init__.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/workers/src/app/workers/celery_app.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/workers/src/app/workers/tasks.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/workers/tests/test_workers.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/fragments.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/resources.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/README.md +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/cookiecutter.json +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/hooks/post_gen_project.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/.cookiecutterignore +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/.dockerignore +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/Dockerfile +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/README.md +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/__init__.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/cache.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/delegates/__init__.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/delegates/upstreams.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/dependencies/__init__.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/dependencies/delegates.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/dependencies/item_repository.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/dependencies/worker_broker.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/docker-compose.yml +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/middleware/__init__.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/middleware/logging.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/repositories/__init__.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/repositories/item_repository.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/requirements.txt +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/settings.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/__init__.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/acceptance/test_logging_middleware.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/conftest.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/test_items.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/unit/test_cache.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/unit/test_database_settings.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/unit/test_delegates.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/unit/test_settings_contracts.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/tests/unit/test_worker_broker.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/views/__init__.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/views/unversioned/__init__.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/views/unversioned/health_view.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/views/unversioned/items_view.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/workers/__init__.py +0 -0
- {csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/{{cookiecutter.__service_name_snake}}/workers/tasks.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: csrd-utils
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.56
|
|
4
4
|
Summary: CLI utilities for csrd service generation and feature augmentation
|
|
5
5
|
Project-URL: Repository, https://github.com/csrd-api/fastapi-common
|
|
6
6
|
Project-URL: Documentation, https://github.com/csrd-api/fastapi-common/tree/main/packages/utils
|
|
@@ -213,12 +213,19 @@ def _collect_new_service_config(args: argparse.Namespace) -> GenerateServiceArgs
|
|
|
213
213
|
has_database = args.database != "none"
|
|
214
214
|
selected_database = "sqlite" if not has_database else args.database
|
|
215
215
|
normalized_name = _normalize_service_name(args.name)
|
|
216
|
+
# Auto-advance port when default (8080) is already taken in the workspace spec.
|
|
217
|
+
output_root = args.output.resolve()
|
|
218
|
+
effective_port = (
|
|
219
|
+
_next_free_port(output_root, args.port)
|
|
220
|
+
if _is_workspace(output_root) and args.port == 8080
|
|
221
|
+
else args.port
|
|
222
|
+
)
|
|
216
223
|
return GenerateServiceArgs(
|
|
217
224
|
{
|
|
218
225
|
"name": normalized_name,
|
|
219
226
|
"output_dir": args.output,
|
|
220
227
|
"description": args.description,
|
|
221
|
-
"port":
|
|
228
|
+
"port": effective_port,
|
|
222
229
|
"model_name": args.model_name,
|
|
223
230
|
"model_name_plural": args.model_name_plural,
|
|
224
231
|
"has_database": has_database,
|
|
@@ -242,7 +249,15 @@ def _collect_new_service_config(args: argparse.Namespace) -> GenerateServiceArgs
|
|
|
242
249
|
else:
|
|
243
250
|
output_dir = Path(_prompt_text("Output directory", str(args.output)))
|
|
244
251
|
description = _prompt_text("Service description", args.description)
|
|
245
|
-
|
|
252
|
+
|
|
253
|
+
# Suggest the next available port based on what's already in the workspace spec.
|
|
254
|
+
workspace_root_candidate = output_dir.resolve()
|
|
255
|
+
default_port = (
|
|
256
|
+
_next_free_port(workspace_root_candidate, args.port)
|
|
257
|
+
if _is_workspace(workspace_root_candidate)
|
|
258
|
+
else args.port
|
|
259
|
+
)
|
|
260
|
+
port = _prompt_int("HTTP port", default_port)
|
|
246
261
|
model_name = _prompt_text("Model name", args.model_name)
|
|
247
262
|
|
|
248
263
|
plural_default = args.model_name_plural
|
|
@@ -331,7 +346,9 @@ def _collect_new_cluster_config(args: argparse.Namespace) -> GenerateClusterArgs
|
|
|
331
346
|
)
|
|
332
347
|
|
|
333
348
|
print("Interactive cluster mode: press Enter to accept defaults.")
|
|
334
|
-
cluster_name =
|
|
349
|
+
cluster_name = (
|
|
350
|
+
_prompt_text("Cluster name", args.name or "my-cluster") if not args.name else args.name
|
|
351
|
+
)
|
|
335
352
|
preset = _prompt_choice("Preset", list(PRESETS.keys()), args.preset)
|
|
336
353
|
services: list[ServiceSpec] = []
|
|
337
354
|
|
|
@@ -421,6 +438,70 @@ def _create_workspace(config: GenerateWorkspaceArgs) -> Path:
|
|
|
421
438
|
return workspace_root
|
|
422
439
|
|
|
423
440
|
|
|
441
|
+
def _generate_services_from_cluster_spec(
|
|
442
|
+
spec: ClusterSpec, workspace_root: Path, force: bool = False
|
|
443
|
+
) -> list[Path]:
|
|
444
|
+
"""Scaffold source trees for every service in a cluster spec that lacks one.
|
|
445
|
+
|
|
446
|
+
Derives generate_service arguments from each ServiceSpec so the resulting
|
|
447
|
+
workspace has src/<service>/ code alongside the compose wiring.
|
|
448
|
+
"""
|
|
449
|
+
|
|
450
|
+
normalized = normalize_cluster_spec(spec)
|
|
451
|
+
services = normalized["services"]
|
|
452
|
+
port_map = {str(svc["name"]): int(svc["port"]) for svc in services}
|
|
453
|
+
|
|
454
|
+
generated: list[Path] = []
|
|
455
|
+
for service in services:
|
|
456
|
+
name = str(service["name"])
|
|
457
|
+
service_type = str(service["type"])
|
|
458
|
+
port = int(service["port"])
|
|
459
|
+
features = list(service.get("features", []))
|
|
460
|
+
delegates_list = list(service.get("delegates", []))
|
|
461
|
+
broker = str(service.get("broker", "redis"))
|
|
462
|
+
|
|
463
|
+
# Derive upstreams from delegate targets + their ports
|
|
464
|
+
upstreams = ",".join(f"http://{t}:{port_map[t]}" for t in delegates_list if t in port_map)
|
|
465
|
+
|
|
466
|
+
has_database = service_type == "db"
|
|
467
|
+
has_delegates = bool(delegates_list) or service_type == "delegate"
|
|
468
|
+
has_workers = service_type == "worker" or "workers" in features
|
|
469
|
+
has_caching = "caching" in features
|
|
470
|
+
has_structured_logging = "logging" in features
|
|
471
|
+
database = str(service.get("database", "sqlite")) if has_database else "sqlite"
|
|
472
|
+
|
|
473
|
+
src_dir = workspace_root / "src" / name.replace("-", "_")
|
|
474
|
+
if src_dir.exists() and any(src_dir.iterdir()) and not force:
|
|
475
|
+
print(f"Skipped existing service: {name}")
|
|
476
|
+
continue
|
|
477
|
+
|
|
478
|
+
try:
|
|
479
|
+
result = generate_service(
|
|
480
|
+
name=name,
|
|
481
|
+
output_dir=workspace_root,
|
|
482
|
+
description=f"{name} service",
|
|
483
|
+
port=port,
|
|
484
|
+
model_name="Item",
|
|
485
|
+
model_name_plural="items",
|
|
486
|
+
has_database=has_database,
|
|
487
|
+
database=database,
|
|
488
|
+
has_delegates=has_delegates,
|
|
489
|
+
upstreams=upstreams,
|
|
490
|
+
has_workers=has_workers,
|
|
491
|
+
broker=broker,
|
|
492
|
+
has_caching=has_caching,
|
|
493
|
+
cache_backend="redis",
|
|
494
|
+
has_structured_logging=has_structured_logging,
|
|
495
|
+
overwrite_if_exists=force,
|
|
496
|
+
)
|
|
497
|
+
generated.append(result)
|
|
498
|
+
print(f"Generated service: {name}")
|
|
499
|
+
except Exception as exc:
|
|
500
|
+
print(f"WARN: could not scaffold service '{name}': {exc}")
|
|
501
|
+
|
|
502
|
+
return generated
|
|
503
|
+
|
|
504
|
+
|
|
424
505
|
def _default_service_namespace(output_dir: Path) -> argparse.Namespace:
|
|
425
506
|
return argparse.Namespace(
|
|
426
507
|
interactive=True,
|
|
@@ -446,7 +527,7 @@ def _default_service_namespace(output_dir: Path) -> argparse.Namespace:
|
|
|
446
527
|
def _default_cluster_namespace(output_dir: Path) -> argparse.Namespace:
|
|
447
528
|
return argparse.Namespace(
|
|
448
529
|
spec=None,
|
|
449
|
-
name=
|
|
530
|
+
name=output_dir.name, # Default cluster name to workspace folder name
|
|
450
531
|
output=output_dir,
|
|
451
532
|
preset="none",
|
|
452
533
|
force=False,
|
|
@@ -461,6 +542,22 @@ def _is_workspace(path: Path) -> bool:
|
|
|
461
542
|
return (path / WORKSPACE_MARKER).is_file()
|
|
462
543
|
|
|
463
544
|
|
|
545
|
+
def _next_free_port(workspace_root: Path, start: int = 8080) -> int:
|
|
546
|
+
"""Return the lowest port >= start that is not already used in the workspace cluster spec."""
|
|
547
|
+
spec_path = workspace_root / WORKSPACE_CLUSTER_SPEC
|
|
548
|
+
if not spec_path.is_file():
|
|
549
|
+
return start
|
|
550
|
+
try:
|
|
551
|
+
raw = yaml.safe_load(spec_path.read_text(encoding="utf-8")) or {}
|
|
552
|
+
used = {int(svc["port"]) for svc in raw.get("services", []) if "port" in svc}
|
|
553
|
+
except Exception:
|
|
554
|
+
return start
|
|
555
|
+
port = start
|
|
556
|
+
while port in used:
|
|
557
|
+
port += 1
|
|
558
|
+
return port
|
|
559
|
+
|
|
560
|
+
|
|
464
561
|
def _service_is_interactive(args: argparse.Namespace) -> bool:
|
|
465
562
|
explicit_interactive = getattr(args, "interactive", None)
|
|
466
563
|
return bool(explicit_interactive) if explicit_interactive is not None else args.name is None
|
|
@@ -1262,7 +1359,14 @@ def main() -> int:
|
|
|
1262
1359
|
cluster_config["output_dir"],
|
|
1263
1360
|
force=cluster_config["overwrite_if_exists"],
|
|
1264
1361
|
)
|
|
1265
|
-
|
|
1362
|
+
_save_workspace_cluster_spec(workspace_root, cluster_config["spec"])
|
|
1363
|
+
print(f"Generated cluster scaffold at: {generated_cluster}")
|
|
1364
|
+
scaffolded = _generate_services_from_cluster_spec(
|
|
1365
|
+
cluster_config["spec"],
|
|
1366
|
+
workspace_root,
|
|
1367
|
+
force=cluster_config["overwrite_if_exists"],
|
|
1368
|
+
)
|
|
1369
|
+
print(f"Scaffolded {len(scaffolded)} service(s) under src/.")
|
|
1266
1370
|
except (FileExistsError, FileNotFoundError, ValueError) as exc:
|
|
1267
1371
|
print(f"ERROR: {exc}")
|
|
1268
1372
|
return 1
|
|
@@ -49,6 +49,7 @@ dev = [
|
|
|
49
49
|
asyncio_mode = "auto"
|
|
50
50
|
testpaths = ["tests"]
|
|
51
51
|
pythonpath = ["src"]
|
|
52
|
+
consider_namespace_packages = true
|
|
52
53
|
|
|
53
54
|
[tool.mypy]
|
|
54
55
|
python_version = "3.12"
|
|
@@ -289,6 +290,19 @@ def _move_tests_to_workspace_root(
|
|
|
289
290
|
unit_dst.mkdir(parents=True, exist_ok=True)
|
|
290
291
|
acceptance_dst.mkdir(parents=True, exist_ok=True)
|
|
291
292
|
|
|
293
|
+
# Ensure every test directory level has an __init__.py so pytest uses
|
|
294
|
+
# package-based import paths and avoids module-name collisions across services.
|
|
295
|
+
def _ensure_init(dir_path: Path) -> None:
|
|
296
|
+
init = dir_path / "__init__.py"
|
|
297
|
+
if not init.exists():
|
|
298
|
+
init.write_text("", encoding="utf-8")
|
|
299
|
+
|
|
300
|
+
_ensure_init(tests_root)
|
|
301
|
+
_ensure_init(tests_root / "unit")
|
|
302
|
+
_ensure_init(tests_root / "acceptance")
|
|
303
|
+
_ensure_init(unit_dst)
|
|
304
|
+
_ensure_init(acceptance_dst)
|
|
305
|
+
|
|
292
306
|
def _copy_tree(src_dir: Path, dst_dir: Path) -> None:
|
|
293
307
|
if not src_dir.is_dir():
|
|
294
308
|
return
|
|
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
|
{csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/caching/conftest.fragment.py
RENAMED
|
File without changes
|
{csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/caching/docker-compose.fragment.yaml
RENAMED
|
File without changes
|
|
File without changes
|
{csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/caching/requirements.fragment
RENAMED
|
File without changes
|
{csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/caching/settings.fragment.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/logging/conftest.fragment.py
RENAMED
|
File without changes
|
|
File without changes
|
{csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/logging/requirements.fragment
RENAMED
|
File without changes
|
{csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/logging/settings.fragment.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/metrics/conftest.fragment.py
RENAMED
|
File without changes
|
{csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/metrics/docker-compose.fragment.yaml
RENAMED
|
File without changes
|
|
File without changes
|
{csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/metrics/requirements.fragment
RENAMED
|
File without changes
|
{csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/metrics/settings.fragment.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/tracing/conftest.fragment.py
RENAMED
|
File without changes
|
|
File without changes
|
{csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/tracing/requirements.fragment
RENAMED
|
File without changes
|
{csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/tracing/settings.fragment.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/workers/conftest.fragment.py
RENAMED
|
File without changes
|
{csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/workers/docker-compose.fragment.yaml
RENAMED
|
File without changes
|
|
File without changes
|
{csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/workers/requirements.fragment
RENAMED
|
File without changes
|
{csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/workers/settings.fragment.py
RENAMED
|
File without changes
|
{csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/workers/src/app/workers/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/workers/src/app/workers/tasks.py
RENAMED
|
File without changes
|
{csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/features/workers/tests/test_workers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{csrd_utils-0.3.54 → csrd_utils-0.3.56}/src/csrd_utils/templates/cookiecutter-service/README.md
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
|
|
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
|