katalyst-taxonomy-cli 2.0.1a1__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.
- katalyst_taxonomy_cli/__init__.py +14 -0
- katalyst_taxonomy_cli/__main__.py +12 -0
- katalyst_taxonomy_cli/_wiring.py +248 -0
- katalyst_taxonomy_cli/app.py +550 -0
- katalyst_taxonomy_cli/commands/__init__.py +1 -0
- katalyst_taxonomy_cli/commands/api.py +104 -0
- katalyst_taxonomy_cli/commands/backend.py +96 -0
- katalyst_taxonomy_cli/commands/bundle.py +106 -0
- katalyst_taxonomy_cli/commands/clone.py +68 -0
- katalyst_taxonomy_cli/commands/config.py +748 -0
- katalyst_taxonomy_cli/commands/config_filters.py +159 -0
- katalyst_taxonomy_cli/commands/config_home.py +179 -0
- katalyst_taxonomy_cli/commands/config_plugins.py +180 -0
- katalyst_taxonomy_cli/commands/config_profile.py +604 -0
- katalyst_taxonomy_cli/commands/config_schemas.py +257 -0
- katalyst_taxonomy_cli/commands/config_sources.py +141 -0
- katalyst_taxonomy_cli/commands/core.py +468 -0
- katalyst_taxonomy_cli/commands/create.py +145 -0
- katalyst_taxonomy_cli/commands/deps.py +48 -0
- katalyst_taxonomy_cli/commands/diff.py +63 -0
- katalyst_taxonomy_cli/commands/drafts.py +63 -0
- katalyst_taxonomy_cli/commands/export.py +186 -0
- katalyst_taxonomy_cli/commands/init.py +84 -0
- katalyst_taxonomy_cli/commands/kinds.py +302 -0
- katalyst_taxonomy_cli/commands/lifecycle.py +127 -0
- katalyst_taxonomy_cli/commands/lint.py +256 -0
- katalyst_taxonomy_cli/commands/plugin.py +148 -0
- katalyst_taxonomy_cli/commands/promote.py +95 -0
- katalyst_taxonomy_cli/commands/query.py +187 -0
- katalyst_taxonomy_cli/commands/relate.py +137 -0
- katalyst_taxonomy_cli/commands/relocate.py +129 -0
- katalyst_taxonomy_cli/commands/remove.py +95 -0
- katalyst_taxonomy_cli/commands/resolve.py +48 -0
- katalyst_taxonomy_cli/commands/rollback.py +51 -0
- katalyst_taxonomy_cli/commands/self_update.py +530 -0
- katalyst_taxonomy_cli/commands/show.py +33 -0
- katalyst_taxonomy_cli/commands/status.py +107 -0
- katalyst_taxonomy_cli/commands/sync.py +60 -0
- katalyst_taxonomy_cli/commands/update.py +112 -0
- katalyst_taxonomy_cli/commands/versions.py +54 -0
- katalyst_taxonomy_cli/context.py +145 -0
- katalyst_taxonomy_cli/discovery.py +157 -0
- katalyst_taxonomy_cli/fields.py +70 -0
- katalyst_taxonomy_cli/install.py +330 -0
- katalyst_taxonomy_cli/options.py +20 -0
- katalyst_taxonomy_cli/output.py +92 -0
- katalyst_taxonomy_cli/py.typed +0 -0
- katalyst_taxonomy_cli-2.0.1a1.dist-info/METADATA +12 -0
- katalyst_taxonomy_cli-2.0.1a1.dist-info/RECORD +51 -0
- katalyst_taxonomy_cli-2.0.1a1.dist-info/WHEEL +4 -0
- katalyst_taxonomy_cli-2.0.1a1.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"""kata tax backend — inspect backends and refresh a remote (github, git) backend's snapshot."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
import click
|
|
8
|
+
|
|
9
|
+
from katalyst_taxonomy_cli.context import CliContext
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@click.group("backend")
|
|
13
|
+
def backend() -> None:
|
|
14
|
+
"""Backend operations: status, and refreshing a github or git backend."""
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _source(payload: dict[str, Any]) -> str:
|
|
18
|
+
"""What the backend reads: ``owner/name`` (github) or the redacted URL (git)."""
|
|
19
|
+
return str(payload.get("repo") or payload.get("url") or "?")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _render(ctx: CliContext, payload: dict[str, Any], *, heading: str) -> None:
|
|
23
|
+
if ctx.output_format == "json":
|
|
24
|
+
ctx.output.json_out(payload)
|
|
25
|
+
return
|
|
26
|
+
ctx.output.echo(heading)
|
|
27
|
+
# Rendered from the fields the backend's status reports — a git remote is a ``url``,
|
|
28
|
+
# a github repository a ``repo`` — never from its type.
|
|
29
|
+
by_url = "url" in payload
|
|
30
|
+
rows = [
|
|
31
|
+
("backend", str(payload.get("backend"))),
|
|
32
|
+
("type", str(payload.get("type"))),
|
|
33
|
+
("url" if by_url else "repo", _source(payload)),
|
|
34
|
+
(
|
|
35
|
+
"ref",
|
|
36
|
+
str(payload.get("ref") or ("(remote HEAD)" if by_url else "(default branch)")),
|
|
37
|
+
),
|
|
38
|
+
("path", str(payload.get("path") or "(repository root)")),
|
|
39
|
+
("sha", str(payload.get("sha") or "(not fetched)")),
|
|
40
|
+
("refresh", f"{payload.get('refreshSeconds')}s"),
|
|
41
|
+
]
|
|
42
|
+
if "depth" in payload:
|
|
43
|
+
rows.append(("depth", "full" if payload.get("depth") == 0 else str(payload.get("depth"))))
|
|
44
|
+
if "auth" in payload:
|
|
45
|
+
rows.append(
|
|
46
|
+
(
|
|
47
|
+
"auth",
|
|
48
|
+
"embedded in the url (redacted)"
|
|
49
|
+
if payload.get("auth") == "url"
|
|
50
|
+
else "git (ssh-agent, ~/.ssh/config, credential helpers)",
|
|
51
|
+
)
|
|
52
|
+
)
|
|
53
|
+
if "tokenSource" in payload:
|
|
54
|
+
rows.append(("token", str(payload.get("tokenSource"))))
|
|
55
|
+
if "changed" in payload:
|
|
56
|
+
rows.append(("changed", "yes" if payload["changed"] else "no"))
|
|
57
|
+
if payload.get("lastError"):
|
|
58
|
+
rows.append(("last error", str(payload["lastError"])))
|
|
59
|
+
ctx.output.key_value(rows)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@backend.command("refresh")
|
|
63
|
+
@click.argument("name")
|
|
64
|
+
@click.pass_obj
|
|
65
|
+
def refresh(ctx: CliContext, name: str) -> None:
|
|
66
|
+
"""Re-check github or git backend NAME's ref now, fetching the new tree if it moved.
|
|
67
|
+
|
|
68
|
+
A remote backend serves a cached snapshot and re-checks its ref once its
|
|
69
|
+
``refresh`` window passes; this re-checks immediately. Nothing is written to the
|
|
70
|
+
repository, the remote or the configuration.
|
|
71
|
+
"""
|
|
72
|
+
from katalyst_taxonomy.adapters.orchestration import refresh_backend
|
|
73
|
+
|
|
74
|
+
try:
|
|
75
|
+
payload = refresh_backend(ctx.cwd, name, profile=ctx.profile)
|
|
76
|
+
except ValueError as exc:
|
|
77
|
+
raise click.ClickException(str(exc)) from exc
|
|
78
|
+
sha = str(payload.get("sha") or "")[:12]
|
|
79
|
+
verb = "updated to" if payload.get("changed") else "unchanged at"
|
|
80
|
+
_render(ctx, payload, heading=f"Refreshed {name}: {_source(payload)} {verb} {sha}")
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@backend.command("status")
|
|
84
|
+
@click.argument("name")
|
|
85
|
+
@click.pass_obj
|
|
86
|
+
def status(ctx: CliContext, name: str) -> None:
|
|
87
|
+
"""Show what github or git backend NAME is serving, without fetching."""
|
|
88
|
+
from katalyst_taxonomy.adapters.orchestration import refreshable_backend
|
|
89
|
+
|
|
90
|
+
from .._wiring import load_registry
|
|
91
|
+
|
|
92
|
+
try:
|
|
93
|
+
inner = refreshable_backend(load_registry(ctx), name)
|
|
94
|
+
except ValueError as exc:
|
|
95
|
+
raise click.ClickException(str(exc)) from exc
|
|
96
|
+
_render(ctx, inner.status(), heading=f"Backend {name}")
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"""kata tax bundle — manage schema bundles installed from a source (add / list / remove)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
|
|
7
|
+
from katalyst_taxonomy_cli._wiring import create_bundle_service
|
|
8
|
+
from katalyst_taxonomy_cli.context import CliContext
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@click.group("bundle")
|
|
12
|
+
def bundle() -> None:
|
|
13
|
+
"""Manage schema bundles installed from a source.
|
|
14
|
+
|
|
15
|
+
Bundles are fetched from PyPI, git, GitHub, or a local path into the shared source
|
|
16
|
+
cache, then path-imported and registered into the taxonomy at runtime. The pinned
|
|
17
|
+
source (an exact commit or version) is recorded in config.yaml's spec.schemas, so
|
|
18
|
+
every process — and every machine with that config — loads the same bundle.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@bundle.command("add")
|
|
23
|
+
@click.argument("source_uri")
|
|
24
|
+
@click.option("-y", "--yes", is_flag=True, help="Skip the confirmation prompt.")
|
|
25
|
+
@click.pass_obj
|
|
26
|
+
def add_bundle(ctx: CliContext, source_uri: str, yes: bool) -> None:
|
|
27
|
+
"""Install a schema bundle from SOURCE_URI.
|
|
28
|
+
|
|
29
|
+
SOURCE_URI may be:
|
|
30
|
+
|
|
31
|
+
pypi:<name>[==<version>] e.g. pypi:acme-bundle==1.2.0
|
|
32
|
+
|
|
33
|
+
git:<url>[@<ref>] e.g. git:git@github.com:acme/b.git@v1
|
|
34
|
+
|
|
35
|
+
github:<owner>/<repo>[@<ref>] e.g. github:acme/bundle@v1.0.0
|
|
36
|
+
|
|
37
|
+
file://<path> or a local path
|
|
38
|
+
|
|
39
|
+
git:, github: and file:// take an optional trailing #path=<sub/dir> for a
|
|
40
|
+
bundle in a subdirectory (monorepo), e.g. github:acme/mono@v2#path=bundles/acme.
|
|
41
|
+
A private github: repository reads GITHUB_TOKEN / GH_TOKEN, then `gh auth token`.
|
|
42
|
+
|
|
43
|
+
A git:/github: ref is pinned to its commit and a pypi: name to its version in
|
|
44
|
+
config.yaml. Installing executes the bundle's Python at load time. Only bundles
|
|
45
|
+
that depend solely on katalyst-engine are accepted.
|
|
46
|
+
"""
|
|
47
|
+
from katalyst_taxonomy.services.bundle_service import install_bundle
|
|
48
|
+
|
|
49
|
+
if not yes:
|
|
50
|
+
click.echo(
|
|
51
|
+
"Installing a remote bundle path-imports and executes its Python code.\n"
|
|
52
|
+
f"Source: {source_uri}"
|
|
53
|
+
)
|
|
54
|
+
if not click.confirm("Proceed?", default=False):
|
|
55
|
+
ctx.output.echo("Aborted.")
|
|
56
|
+
raise SystemExit(1)
|
|
57
|
+
|
|
58
|
+
try:
|
|
59
|
+
result = install_bundle(create_bundle_service(), source_uri)
|
|
60
|
+
except Exception as exc: # noqa: BLE001
|
|
61
|
+
ctx.output.echo(f"Error: {exc}")
|
|
62
|
+
raise SystemExit(1) from exc
|
|
63
|
+
|
|
64
|
+
kinds = ", ".join(result.provided_kinds) or "(none)"
|
|
65
|
+
ctx.output.echo(
|
|
66
|
+
f"Installed bundle '{result.fqn}' v{result.version}\n"
|
|
67
|
+
f" source: {result.resolved_source}\n"
|
|
68
|
+
f" kinds: {kinds}"
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@bundle.command("list")
|
|
73
|
+
@click.pass_obj
|
|
74
|
+
def list_bundles(ctx: CliContext) -> None:
|
|
75
|
+
"""List schema bundles declared with a source in config.yaml."""
|
|
76
|
+
from katalyst_taxonomy.services.source_providers import source_bundle_infos
|
|
77
|
+
from katalyst_taxonomy.sources.bundle_sources import shown_source
|
|
78
|
+
from katalyst_taxonomy.sources.cache import is_pinned
|
|
79
|
+
|
|
80
|
+
bundles = [i for i in source_bundle_infos(ctx.profile) if i.state != "not-a-bundle"]
|
|
81
|
+
if not bundles:
|
|
82
|
+
ctx.output.echo("No schema bundles installed from a source.")
|
|
83
|
+
return
|
|
84
|
+
ctx.output.echo(f"Schema bundles from sources ({len(bundles)}):")
|
|
85
|
+
for b in bundles:
|
|
86
|
+
version = f" v{b.version}" if b.version else ""
|
|
87
|
+
kinds = ", ".join(b.provided_kinds) or "(none)"
|
|
88
|
+
pin = "pinned" if is_pinned(b.source) else "unpinned"
|
|
89
|
+
ctx.output.echo(
|
|
90
|
+
f" {b.name or b.fqn or '(unnamed)'}{version} [{shown_source(b.source)}] "
|
|
91
|
+
f"{pin}, {b.state} kinds: {kinds}"
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
@bundle.command("remove")
|
|
96
|
+
@click.argument("name")
|
|
97
|
+
@click.pass_obj
|
|
98
|
+
def remove_bundle(ctx: CliContext, name: str) -> None:
|
|
99
|
+
"""Remove a schema bundle installed from a source, by name or FQN."""
|
|
100
|
+
from katalyst_taxonomy.services.bundle_service import remove_bundle as remove
|
|
101
|
+
|
|
102
|
+
result = remove(name)
|
|
103
|
+
if not result.success:
|
|
104
|
+
ctx.output.echo(f"Error: {result.error}")
|
|
105
|
+
raise SystemExit(1)
|
|
106
|
+
ctx.output.echo(f"Removed bundle '{result.name}' ({result.source_uri}).")
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""kata tax clone — Clone an existing taxonomy node."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
|
|
7
|
+
from katalyst_taxonomy_cli.context import CliContext
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@click.command("clone")
|
|
11
|
+
@click.argument("node_type")
|
|
12
|
+
@click.argument("source_name")
|
|
13
|
+
@click.argument("target_name")
|
|
14
|
+
@click.option("--source-system", default=None, help="Source system name.")
|
|
15
|
+
@click.option("--source-subsystem", default=None, help="Source subsystem name.")
|
|
16
|
+
@click.option("--source-stack", default=None, help="Source stack name.")
|
|
17
|
+
@click.option("--target-system", default=None, help="Target system name.")
|
|
18
|
+
@click.option("--target-subsystem", default=None, help="Target subsystem name.")
|
|
19
|
+
@click.option("--target-stack", default=None, help="Target stack name.")
|
|
20
|
+
@click.option("--description", default=None, help="New description for cloned node.")
|
|
21
|
+
@click.option("-y", "--yes", "non_interactive", is_flag=True, help="Non-interactive mode.")
|
|
22
|
+
@click.option(
|
|
23
|
+
"--backend",
|
|
24
|
+
"backend",
|
|
25
|
+
default=None,
|
|
26
|
+
help=(
|
|
27
|
+
"Filesystem backend (repository) to clone within. Defaults to the profile's only "
|
|
28
|
+
"filesystem backend, else the one the current directory is inside."
|
|
29
|
+
),
|
|
30
|
+
)
|
|
31
|
+
@click.pass_obj
|
|
32
|
+
def clone(
|
|
33
|
+
ctx: CliContext,
|
|
34
|
+
node_type: str,
|
|
35
|
+
source_name: str,
|
|
36
|
+
target_name: str,
|
|
37
|
+
source_system: str | None,
|
|
38
|
+
source_subsystem: str | None,
|
|
39
|
+
source_stack: str | None,
|
|
40
|
+
target_system: str | None,
|
|
41
|
+
target_subsystem: str | None,
|
|
42
|
+
target_stack: str | None,
|
|
43
|
+
description: str | None,
|
|
44
|
+
non_interactive: bool,
|
|
45
|
+
backend: str | None,
|
|
46
|
+
) -> None:
|
|
47
|
+
"""Clone an existing taxonomy node to a new name, within one repository."""
|
|
48
|
+
from katalyst_taxonomy.adapters.orchestration import run_clone
|
|
49
|
+
from katalyst_taxonomy.services.permissions import refuse_read_only_addresses
|
|
50
|
+
|
|
51
|
+
# A source or target in a read-only backend (github, git) is refused before any
|
|
52
|
+
# repository is chosen: naming one is the error, not an ambiguity.
|
|
53
|
+
refuse_read_only_addresses(ctx.cwd, "clone", source_name, target_name, profile=ctx.profile)
|
|
54
|
+
exit_code = run_clone(
|
|
55
|
+
path=ctx.repository(backend).root,
|
|
56
|
+
node_type=node_type,
|
|
57
|
+
source_name=source_name,
|
|
58
|
+
target_name=target_name,
|
|
59
|
+
source_system=source_system,
|
|
60
|
+
source_stack=source_stack,
|
|
61
|
+
target_system=target_system,
|
|
62
|
+
target_stack=target_stack,
|
|
63
|
+
description=description,
|
|
64
|
+
yes=non_interactive,
|
|
65
|
+
output=None,
|
|
66
|
+
err_output=None,
|
|
67
|
+
)
|
|
68
|
+
raise SystemExit(exit_code)
|