entropy-data 0.3.6__tar.gz → 0.3.7__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.
- {entropy_data-0.3.6 → entropy_data-0.3.7}/CHANGELOG.md +5 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/PKG-INFO +1 -1
- {entropy_data-0.3.6 → entropy_data-0.3.7}/pyproject.toml +1 -1
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/access.py +21 -3
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/api_keys.py +3 -4
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/assets.py +11 -4
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/connection.py +3 -4
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/events.py +3 -4
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/gitconnections.py +2 -6
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/lineage.py +2 -6
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/notification_channels.py +2 -6
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/organization.py +3 -4
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/search.py +3 -3
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/usage.py +2 -6
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/output.py +14 -4
- {entropy_data-0.3.6 → entropy_data-0.3.7}/tests/commands/test_access_request.py +36 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/.editorconfig +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/.github/dependabot.yml +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/.github/pull_request_template.md +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/.github/workflows/ci.yaml +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/.github/workflows/release.yaml +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/.gitignore +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/.pre-commit-config.yaml +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/CLAUDE.md +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/Dockerfile +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/LICENSE +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/README.md +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/release +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/__init__.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/__main__.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/cli.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/client.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/__init__.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/certifications.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/connectors.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/costs.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/datacontracts.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/dataproducts.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/definitions.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/example_data.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/git_credentials.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/import_export.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/semantics.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/settings.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/sourcesystems.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/tags.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/teams.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/test_results.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/config.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/util.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/tests/__init__.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/tests/commands/__init__.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/tests/commands/test_api_keys.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/tests/commands/test_assets.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/tests/commands/test_connection.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/tests/commands/test_connectors.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/tests/commands/test_costs.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/tests/commands/test_datacontracts.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/tests/commands/test_dataproducts.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/tests/commands/test_git_credentials.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/tests/commands/test_gitconnections.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/tests/commands/test_lineage.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/tests/commands/test_notification_channels.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/tests/commands/test_organization.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/tests/commands/test_semantics.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/tests/commands/test_settings.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/tests/commands/test_tags.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/tests/commands/test_teams.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/tests/commands/test_usage.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/tests/conftest.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/tests/test_client.py +0 -0
- {entropy_data-0.3.6 → entropy_data-0.3.7}/tests/test_config.py +0 -0
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.3.7]
|
|
6
|
+
|
|
7
|
+
- Add `yaml` as a third value for `--output` / `-o` alongside `table` and `json`. Useful when piping results into editors or files that expect YAML (e.g. data contracts).
|
|
8
|
+
- `entropy-data access list` now supports `--provider-dataproduct`, `--consumer-dataproduct`, and `--consumer-type` filters, passed through to the existing `providerDataProductId`, `consumerDataProductId`, and `consumerType` query parameters of `GET /api/access`.
|
|
9
|
+
|
|
5
10
|
## [0.3.6]
|
|
6
11
|
|
|
7
12
|
- `entropy-data connection add` now sets the newly added connection as the default, overriding any previously set default.
|
|
@@ -17,6 +17,18 @@ RESOURCE_TYPE = "access"
|
|
|
17
17
|
@access_app.command("list")
|
|
18
18
|
def list_access(
|
|
19
19
|
page: Annotated[int, typer.Option("--page", "-p", help="Page number (0-indexed).")] = 0,
|
|
20
|
+
provider_dataproduct: Annotated[
|
|
21
|
+
Optional[str],
|
|
22
|
+
typer.Option("--provider-dataproduct", help="Filter by provider data product ID."),
|
|
23
|
+
] = None,
|
|
24
|
+
consumer_dataproduct: Annotated[
|
|
25
|
+
Optional[str],
|
|
26
|
+
typer.Option("--consumer-dataproduct", help="Filter by consumer data product ID."),
|
|
27
|
+
] = None,
|
|
28
|
+
consumer_type: Annotated[
|
|
29
|
+
Optional[str],
|
|
30
|
+
typer.Option("--consumer-type", help="Filter by consumer type (e.g. team, user, dataProduct)."),
|
|
31
|
+
] = None,
|
|
20
32
|
output: Annotated[Optional[OutputFormat], typer.Option("--output", "-o", help="Output format.")] = None,
|
|
21
33
|
) -> None:
|
|
22
34
|
"""List all access agreements."""
|
|
@@ -25,7 +37,14 @@ def list_access(
|
|
|
25
37
|
fmt = output or get_output_format()
|
|
26
38
|
try:
|
|
27
39
|
client = get_client()
|
|
28
|
-
|
|
40
|
+
params: dict = {"p": page}
|
|
41
|
+
if provider_dataproduct:
|
|
42
|
+
params["providerDataProductId"] = provider_dataproduct
|
|
43
|
+
if consumer_dataproduct:
|
|
44
|
+
params["consumerDataProductId"] = consumer_dataproduct
|
|
45
|
+
if consumer_type:
|
|
46
|
+
params["consumerType"] = consumer_type
|
|
47
|
+
data, has_next = client.list_resources(RESOURCE_PATH, params=params)
|
|
29
48
|
print_resource_list(data, RESOURCE_TYPE, fmt, has_next_page=has_next, page=page)
|
|
30
49
|
except Exception as e:
|
|
31
50
|
handle_error(e)
|
|
@@ -166,8 +185,7 @@ def request_access(
|
|
|
166
185
|
consumer_count = sum(c is not None for c in (consumer_team, consumer_user, consumer_dataproduct))
|
|
167
186
|
if consumer_count != 1:
|
|
168
187
|
error_console.print(
|
|
169
|
-
"[red]Error: provide exactly one of --consumer-team, --consumer-user, "
|
|
170
|
-
"or --consumer-dataproduct.[/red]"
|
|
188
|
+
"[red]Error: provide exactly one of --consumer-team, --consumer-user, or --consumer-dataproduct.[/red]"
|
|
171
189
|
)
|
|
172
190
|
raise SystemExit(2)
|
|
173
191
|
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"""API Keys commands."""
|
|
2
2
|
|
|
3
|
-
import json
|
|
4
3
|
from typing import Annotated, Optional
|
|
5
4
|
|
|
6
5
|
import typer
|
|
7
6
|
|
|
8
|
-
from entropy_data.output import OutputFormat, console, print_success
|
|
7
|
+
from entropy_data.output import OutputFormat, console, print_data, print_success
|
|
9
8
|
|
|
10
9
|
api_keys_app = typer.Typer(no_args_is_help=True)
|
|
11
10
|
RESOURCE_PATH = "api-keys"
|
|
@@ -38,8 +37,8 @@ def create_api_key(
|
|
|
38
37
|
|
|
39
38
|
_raise_for_status(response)
|
|
40
39
|
data = response.json()
|
|
41
|
-
if fmt
|
|
42
|
-
|
|
40
|
+
if fmt != OutputFormat.table:
|
|
41
|
+
print_data(data, fmt)
|
|
43
42
|
else:
|
|
44
43
|
print_success(f"API key created: {data.get('organizationApiKeyId')}")
|
|
45
44
|
key = data.get("key")
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
"""Assets commands."""
|
|
2
2
|
|
|
3
|
-
import json
|
|
4
3
|
from pathlib import Path
|
|
5
4
|
from typing import Annotated, Optional
|
|
6
5
|
|
|
7
6
|
import typer
|
|
8
7
|
|
|
9
|
-
from entropy_data.output import
|
|
8
|
+
from entropy_data.output import (
|
|
9
|
+
OutputFormat,
|
|
10
|
+
console,
|
|
11
|
+
print_data,
|
|
12
|
+
print_link,
|
|
13
|
+
print_resource,
|
|
14
|
+
print_resource_list,
|
|
15
|
+
print_success,
|
|
16
|
+
)
|
|
10
17
|
from entropy_data.util import read_body
|
|
11
18
|
|
|
12
19
|
assets_app = typer.Typer(no_args_is_help=True)
|
|
@@ -101,8 +108,8 @@ def list_asset_tags(
|
|
|
101
108
|
)
|
|
102
109
|
_raise_for_status(response)
|
|
103
110
|
data = response.json()
|
|
104
|
-
if fmt
|
|
105
|
-
|
|
111
|
+
if fmt != OutputFormat.table:
|
|
112
|
+
print_data(data, fmt)
|
|
106
113
|
else:
|
|
107
114
|
for tag in data:
|
|
108
115
|
console.print(tag)
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
"""Connection management commands."""
|
|
2
2
|
|
|
3
|
-
import json
|
|
4
3
|
from typing import Annotated, Optional
|
|
5
4
|
|
|
6
5
|
import typer
|
|
7
6
|
from rich.table import Table
|
|
8
7
|
|
|
9
8
|
from entropy_data import config as cfg
|
|
10
|
-
from entropy_data.output import OutputFormat, console, print_error, print_success
|
|
9
|
+
from entropy_data.output import OutputFormat, console, print_data, print_error, print_success
|
|
11
10
|
|
|
12
11
|
connection_app = typer.Typer(no_args_is_help=True)
|
|
13
12
|
|
|
@@ -102,7 +101,7 @@ def get_connection(
|
|
|
102
101
|
is_default = config.get("default_connection_name") == resolved_name
|
|
103
102
|
|
|
104
103
|
fmt = output or get_output_format()
|
|
105
|
-
if fmt
|
|
104
|
+
if fmt != OutputFormat.table:
|
|
106
105
|
payload = {
|
|
107
106
|
"name": resolved_name,
|
|
108
107
|
"host": conn.get("host", cfg.DEFAULT_HOST),
|
|
@@ -110,7 +109,7 @@ def get_connection(
|
|
|
110
109
|
"api_key": displayed_key,
|
|
111
110
|
"default": is_default,
|
|
112
111
|
}
|
|
113
|
-
|
|
112
|
+
print_data(payload, fmt)
|
|
114
113
|
return
|
|
115
114
|
|
|
116
115
|
table = Table(show_header=False)
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"""Events commands."""
|
|
2
2
|
|
|
3
|
-
import json
|
|
4
3
|
from typing import Annotated, Optional
|
|
5
4
|
|
|
6
5
|
import typer
|
|
7
6
|
|
|
8
|
-
from entropy_data.output import OutputFormat,
|
|
7
|
+
from entropy_data.output import OutputFormat, print_data, print_resource_list
|
|
9
8
|
|
|
10
9
|
events_app = typer.Typer(no_args_is_help=True)
|
|
11
10
|
|
|
@@ -24,8 +23,8 @@ def poll_events(
|
|
|
24
23
|
try:
|
|
25
24
|
client = get_client()
|
|
26
25
|
data = client.get_events(last_event_id=last_event_id)
|
|
27
|
-
if fmt
|
|
28
|
-
|
|
26
|
+
if fmt != OutputFormat.table:
|
|
27
|
+
print_data(data, fmt)
|
|
29
28
|
else:
|
|
30
29
|
print_resource_list(data, "events", fmt)
|
|
31
30
|
except Exception as e:
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"""Git connection subcommands. Used as a sub-typer of dataproducts and datacontracts."""
|
|
2
2
|
|
|
3
|
-
import json
|
|
4
3
|
from typing import Annotated, Optional
|
|
5
4
|
|
|
6
5
|
import typer
|
|
7
6
|
|
|
8
|
-
from entropy_data.output import OutputFormat, print_link, print_success
|
|
7
|
+
from entropy_data.output import OutputFormat, print_data, print_link, print_success
|
|
9
8
|
|
|
10
9
|
GIT_CONNECTION_TYPES = ("github", "gitlab", "bitbucket", "azuredevops")
|
|
11
10
|
|
|
@@ -31,10 +30,7 @@ def make_gitconnection_app(resource_path: str, resource_label: str) -> typer.Typ
|
|
|
31
30
|
try:
|
|
32
31
|
client = get_client()
|
|
33
32
|
data = client.get_gitconnection(resource_path, id)
|
|
34
|
-
|
|
35
|
-
print(json.dumps(data, indent=2))
|
|
36
|
-
else:
|
|
37
|
-
print(json.dumps(data, indent=2))
|
|
33
|
+
print_data(data, fmt)
|
|
38
34
|
except Exception as e:
|
|
39
35
|
handle_error(e)
|
|
40
36
|
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
"""Lineage commands (OpenLineage events)."""
|
|
2
2
|
|
|
3
|
-
import json
|
|
4
3
|
from pathlib import Path
|
|
5
4
|
from typing import Annotated, Optional
|
|
6
5
|
|
|
7
6
|
import typer
|
|
8
7
|
|
|
9
|
-
from entropy_data.output import OutputFormat,
|
|
8
|
+
from entropy_data.output import OutputFormat, print_resource_list, print_success
|
|
10
9
|
from entropy_data.util import read_body
|
|
11
10
|
|
|
12
11
|
lineage_app = typer.Typer(no_args_is_help=True)
|
|
@@ -46,10 +45,7 @@ def list_lineage(
|
|
|
46
45
|
params["dataProductId"] = data_product_id
|
|
47
46
|
client = get_client()
|
|
48
47
|
data, _ = client.list_resources(RESOURCE_PATH, params=params)
|
|
49
|
-
|
|
50
|
-
console.print_json(json.dumps(data))
|
|
51
|
-
else:
|
|
52
|
-
print_resource_list(data, RESOURCE_TYPE, fmt)
|
|
48
|
+
print_resource_list(data, RESOURCE_TYPE, fmt)
|
|
53
49
|
except Exception as e:
|
|
54
50
|
handle_error(e)
|
|
55
51
|
|
{entropy_data-0.3.6 → entropy_data-0.3.7}/src/entropy_data/commands/notification_channels.py
RENAMED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
"""Team notification channel subcommands."""
|
|
2
2
|
|
|
3
|
-
import json
|
|
4
3
|
from pathlib import Path
|
|
5
4
|
from typing import Annotated, Optional
|
|
6
5
|
|
|
7
6
|
import typer
|
|
8
7
|
|
|
9
|
-
from entropy_data.output import OutputFormat,
|
|
8
|
+
from entropy_data.output import OutputFormat, print_data, print_success
|
|
10
9
|
from entropy_data.util import read_body
|
|
11
10
|
|
|
12
11
|
notifications_app = typer.Typer(no_args_is_help=True)
|
|
@@ -34,10 +33,7 @@ def get_channel(
|
|
|
34
33
|
response = client.session.get(_channel_url(client, team_id, channel_id), timeout=REQUEST_TIMEOUT)
|
|
35
34
|
_raise_for_status(response)
|
|
36
35
|
data = response.json()
|
|
37
|
-
|
|
38
|
-
console.print_json(json.dumps(data))
|
|
39
|
-
else:
|
|
40
|
-
console.print_json(json.dumps(data))
|
|
36
|
+
print_data(data, fmt)
|
|
41
37
|
except Exception as e:
|
|
42
38
|
handle_error(e)
|
|
43
39
|
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
"""Organization commands."""
|
|
2
2
|
|
|
3
|
-
import json
|
|
4
3
|
from typing import Annotated, Optional
|
|
5
4
|
|
|
6
5
|
import typer
|
|
7
6
|
from rich.table import Table
|
|
8
7
|
|
|
9
|
-
from entropy_data.output import OutputFormat, console, print_resource, print_resource_list
|
|
8
|
+
from entropy_data.output import OutputFormat, console, print_data, print_resource, print_resource_list
|
|
10
9
|
|
|
11
10
|
organization_app = typer.Typer(no_args_is_help=True)
|
|
12
11
|
members_app = typer.Typer(no_args_is_help=True)
|
|
@@ -29,8 +28,8 @@ def get_organization(
|
|
|
29
28
|
)
|
|
30
29
|
_raise_for_status(response)
|
|
31
30
|
data = response.json()
|
|
32
|
-
if fmt
|
|
33
|
-
|
|
31
|
+
if fmt != OutputFormat.table:
|
|
32
|
+
print_data(data, fmt)
|
|
34
33
|
return
|
|
35
34
|
|
|
36
35
|
table = Table(show_header=False)
|
|
@@ -5,7 +5,7 @@ from typing import Annotated, Optional
|
|
|
5
5
|
|
|
6
6
|
import typer
|
|
7
7
|
|
|
8
|
-
from entropy_data.output import OutputFormat, console
|
|
8
|
+
from entropy_data.output import OutputFormat, console, print_data
|
|
9
9
|
|
|
10
10
|
search_app = typer.Typer(no_args_is_help=True)
|
|
11
11
|
|
|
@@ -29,8 +29,8 @@ def search_query(
|
|
|
29
29
|
params["resourceType"] = resource_type
|
|
30
30
|
data = client.search(query, **params)
|
|
31
31
|
|
|
32
|
-
if fmt
|
|
33
|
-
|
|
32
|
+
if fmt != OutputFormat.table:
|
|
33
|
+
print_data(data, fmt)
|
|
34
34
|
return
|
|
35
35
|
|
|
36
36
|
# Table output for search results
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
"""Usage commands (OpenTelemetry traces)."""
|
|
2
2
|
|
|
3
|
-
import json
|
|
4
3
|
from pathlib import Path
|
|
5
4
|
from typing import Annotated, Optional
|
|
6
5
|
|
|
7
6
|
import typer
|
|
8
7
|
|
|
9
|
-
from entropy_data.output import OutputFormat,
|
|
8
|
+
from entropy_data.output import OutputFormat, print_resource_list, print_success
|
|
10
9
|
from entropy_data.util import read_body
|
|
11
10
|
|
|
12
11
|
usage_app = typer.Typer(no_args_is_help=True)
|
|
@@ -41,10 +40,7 @@ def list_usage(
|
|
|
41
40
|
params["dataContractId"] = data_contract_id
|
|
42
41
|
client = get_client()
|
|
43
42
|
data, _ = client.list_resources(RESOURCE_PATH, params=params)
|
|
44
|
-
|
|
45
|
-
console.print_json(json.dumps(data))
|
|
46
|
-
else:
|
|
47
|
-
print_resource_list(data, RESOURCE_TYPE, fmt)
|
|
43
|
+
print_resource_list(data, RESOURCE_TYPE, fmt)
|
|
48
44
|
except Exception as e:
|
|
49
45
|
handle_error(e)
|
|
50
46
|
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import json
|
|
4
4
|
from enum import Enum
|
|
5
5
|
|
|
6
|
+
import yaml
|
|
6
7
|
from rich.console import Console
|
|
7
8
|
from rich.table import Table
|
|
8
9
|
|
|
@@ -13,6 +14,15 @@ error_console = Console(stderr=True)
|
|
|
13
14
|
class OutputFormat(str, Enum):
|
|
14
15
|
table = "table"
|
|
15
16
|
json = "json"
|
|
17
|
+
yaml = "yaml"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def print_data(data, fmt: OutputFormat) -> None:
|
|
21
|
+
"""Print data structured as JSON or YAML."""
|
|
22
|
+
if fmt == OutputFormat.yaml:
|
|
23
|
+
console.print(yaml.safe_dump(data, sort_keys=False, default_flow_style=False), end="")
|
|
24
|
+
else:
|
|
25
|
+
console.print_json(json.dumps(data))
|
|
16
26
|
|
|
17
27
|
|
|
18
28
|
# Column definitions per resource type: list of (header, dict_key)
|
|
@@ -96,8 +106,8 @@ def _get_nested(data: dict, key: str) -> str:
|
|
|
96
106
|
|
|
97
107
|
def print_resource(data: dict, resource_type: str, fmt: OutputFormat) -> None:
|
|
98
108
|
"""Print a single resource."""
|
|
99
|
-
if fmt
|
|
100
|
-
|
|
109
|
+
if fmt != OutputFormat.table:
|
|
110
|
+
print_data(data, fmt)
|
|
101
111
|
return
|
|
102
112
|
|
|
103
113
|
columns = RESOURCE_COLUMNS.get(resource_type, [])
|
|
@@ -120,8 +130,8 @@ def print_resource_list(
|
|
|
120
130
|
title: str | None = None,
|
|
121
131
|
) -> None:
|
|
122
132
|
"""Print a list of resources."""
|
|
123
|
-
if fmt
|
|
124
|
-
|
|
133
|
+
if fmt != OutputFormat.table:
|
|
134
|
+
print_data(data, fmt)
|
|
125
135
|
return
|
|
126
136
|
|
|
127
137
|
columns = RESOURCE_COLUMNS.get(resource_type, [])
|
|
@@ -116,3 +116,39 @@ def test_request_multiple_consumers(monkeypatch, tmp_path):
|
|
|
116
116
|
],
|
|
117
117
|
)
|
|
118
118
|
assert result.exit_code == 2
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@responses.activate
|
|
122
|
+
def test_list_with_filters(monkeypatch, tmp_path):
|
|
123
|
+
_setup(monkeypatch, tmp_path)
|
|
124
|
+
responses.add(responses.GET, f"{BASE_URL}/api/access", json=[], status=200)
|
|
125
|
+
result = runner.invoke(
|
|
126
|
+
app,
|
|
127
|
+
[
|
|
128
|
+
"access",
|
|
129
|
+
"list",
|
|
130
|
+
"--provider-dataproduct",
|
|
131
|
+
"dp_provider",
|
|
132
|
+
"--consumer-dataproduct",
|
|
133
|
+
"dp_consumer",
|
|
134
|
+
"--consumer-type",
|
|
135
|
+
"team",
|
|
136
|
+
],
|
|
137
|
+
)
|
|
138
|
+
assert result.exit_code == 0
|
|
139
|
+
qs = responses.calls[0].request.url.split("?", 1)[1]
|
|
140
|
+
assert "providerDataProductId=dp_provider" in qs
|
|
141
|
+
assert "consumerDataProductId=dp_consumer" in qs
|
|
142
|
+
assert "consumerType=team" in qs
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
@responses.activate
|
|
146
|
+
def test_list_without_filters(monkeypatch, tmp_path):
|
|
147
|
+
_setup(monkeypatch, tmp_path)
|
|
148
|
+
responses.add(responses.GET, f"{BASE_URL}/api/access", json=[], status=200)
|
|
149
|
+
result = runner.invoke(app, ["access", "list"])
|
|
150
|
+
assert result.exit_code == 0
|
|
151
|
+
qs = responses.calls[0].request.url.split("?", 1)[1]
|
|
152
|
+
assert "providerDataProductId" not in qs
|
|
153
|
+
assert "consumerDataProductId" not in qs
|
|
154
|
+
assert "consumerType" not in qs
|
|
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
|
|
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
|