Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions docs/list.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Options:
-v, --verbose Verbosity: v=INFO, vv=DEBUG.
-q, --quiet Only errors shown in logs.
--write Write the events to file.
--json Output as JSON.
--help Show this message and exit.

```
Expand Down Expand Up @@ -100,3 +101,62 @@ Within Datatrail, there are two types of datasets:

Please see the CLI reference page for more information on the `list` command:
[datatrail list](../cli/#datatrail-list)

## 🤖 Machine-readable JSON output

The `--json` flag outputs structured JSON instead of formatted tables, making it easy to parse the output in scripts and pipelines:

```bash
# Get all scopes as JSON
$ datatrail ls --json
{
"scopes": [
"chime.event.baseband.raw",
"chime.event.intensity.raw",
"kko.acquisition.processed",
...
]
}

# Get larger datasets as JSON
$ datatrail ls kko.scheduled.baseband.raw --json
{
"scope": "kko.scheduled.baseband.raw",
"larger_datasets": [
"20230804095251",
"scheduled.commissioning.steady"
]
}

# Get child datasets as JSON
$ datatrail ls kko.scheduled.baseband.raw scheduled.commissioning.steady --json
{
"datasets": [
"20230616150511",
"20230604135840",
"20230604134842",
...
]
}
```

### Usage in scripts

```python
import json
import subprocess

# Get all scopes
result = subprocess.run(["datatrail", "ls", "--json"], capture_output=True, text=True)
data = json.loads(result.stdout)
scopes = data["scopes"]
Comment on lines +149 to +152

# Get datasets for a scope
result = subprocess.run(
["datatrail", "ls", "chime.event.baseband.raw", "--json"],
capture_output=True,
text=True,
)
data = json.loads(result.stdout)
larger_datasets = data["larger_datasets"]
```
70 changes: 70 additions & 0 deletions docs/ps.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Options:
-s, --show-files Show file names.
-v, --verbose Verbosity: v=INFO, vv=DEBUG.
-q, --quiet Set log level to ERROR.
--json Output as JSON.
--help Show this message and exit.
```

Expand Down Expand Up @@ -80,3 +81,72 @@ if the `--show-files` or `-s` flag is passed.
│ - baseband_308892599_111.h5 │
:
```

## 🤖 Machine-readable JSON output

The `--json` flag outputs structured JSON instead of formatted tables, making it easy to parse dataset information in scripts and pipelines:

```bash
$ datatrail ps kko.event.baseband.raw 308892599 --json
{
"dataset": "308892599",
"scope": "kko.event.baseband.raw",
"files": {
"contains_datasets": 0,
"datasets_contained": [],
"file_replica_locations": {
"minoc": [
"data/kko/baseband/raw/2023/08/07/astro_308892599/baseband_308892599_129.h5",
"data/kko/baseband/raw/2023/08/07/astro_308892599/baseband_308892599_1013.h5",
...
]
}
},
"policies": {
"replication_policy": {
"preferred_storage_elements": ["chime"],
"priority": "low",
"default": true
},
"deletion_policy": [
{
"storage_element": "minoc",
"priority": "low",
"default": true,
"delete_after_days": 36500
},
...
],
"belongs_to": [
{
"scope": "kko.event.baseband.raw",
"name": "B0531+21.commissioning.pulsar.temp"
}
]
}
}
```

### Usage in scripts

```python
import json
import subprocess

# Get dataset information
result = subprocess.run(
["datatrail", "ps", "kko.event.baseband.raw", "308892599", "--json"],
capture_output=True,
text=True,
)
data = json.loads(result.stdout)

Comment on lines +136 to +143
# Access file locations
file_locations = data["files"]["file_replica_locations"]
minoc_files = file_locations.get("minoc", [])

# Access policies
replication_policy = data["policies"]["replication_policy"]
deletion_policy = data["policies"]["deletion_policy"]
belongs_to = data["policies"]["belongs_to"]
```
12 changes: 11 additions & 1 deletion dtcli/ls.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,16 @@
@click.option("-v", "--verbose", count=True, help="Verbosity: v=INFO, vv=DEBUG.")
@click.option("-q", "--quiet", is_flag=True, help="Only errors shown in logs.")
@click.option("--write", is_flag=True, help="Write the events to file.")
@click.option("--json", "output_json", is_flag=True, help="Output as JSON.")
@click.pass_context
def list(
def list( # noqa: C901
ctx: click.Context,
scope: Optional[str] = None,
datasets: Optional[str] = None,
verbose: int = 0,
quiet: bool = False,
write: bool = False,
output_json: bool = False,
):
"""List Datatrail Scopes & Datasets.

Expand All @@ -52,6 +54,7 @@ def list(
verbose (int): Verbosity: v=INFO, vv=DEBUG.
quiet (bool): Only errors shown in logs.
write (bool): Write the events to file.
output_json (bool): Output as JSON.
"""
# Set logging level.
set_log_level(logger, verbose, quiet)
Expand All @@ -73,6 +76,13 @@ def list(
return None
results = functions.list(scope, datasets, verbose, quiet)

# Output JSON if requested.
if output_json:
print(json.dumps(results, indent=2))
if "error" in results:
ctx.exit(1)
return
Comment on lines +79 to +84

# Display scopes.
if "scopes" in results.keys():
table = Table(
Expand Down
33 changes: 32 additions & 1 deletion dtcli/ps.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,16 @@
@click.option("-s", "--show-files", is_flag=True, help="Show file names.")
@click.option("-v", "--verbose", count=True, help="Verbosity: v=INFO, vv=DEBUG.")
@click.option("-q", "--quiet", is_flag=True, help="Set log level to ERROR.")
@click.option("--json", "output_json", is_flag=True, help="Output as JSON.")
@click.pass_context
def ps(
def ps( # noqa: C901
ctx: click.Context,
scope: str,
dataset: str,
show_files: bool,
verbose: int,
quiet: bool,
output_json: bool,
):
"""Detailed status of a dataset.

Expand All @@ -44,6 +46,7 @@ def ps(
show_files (bool): Show list of files.
verbose (int): Verbosity: v=INFO, vv=DUBUG.
quiet (bool): Set log level to ERROR.
output_json (bool): Output as JSON.

Returns:
None
Expand Down Expand Up @@ -73,13 +76,41 @@ def ps(
try:
files, policies = functions.ps(scope, dataset, verbose, quiet)
if isinstance(files, str) or isinstance(policies, str):
if output_json:
import json

print(
json.dumps(
{"error": {"files": str(files), "policies": str(policies)}},
indent=2,
)
)
ctx.exit(1)
Comment on lines +79 to +88
error_console.print("Error: files = ", files)
error_console.print("Error: policies = ", policies)
return None
except Exception as e:
if output_json:
import json

print(json.dumps({"error": str(e)}, indent=2))
ctx.exit(1)
error_console.print(e)
return None

# Handle JSON output
if output_json:
import json

result = {
"dataset": dataset,
"scope": scope,
"files": files,
"policies": policies,
}
print(json.dumps(result, indent=2))
return None
Comment on lines +105 to +112

if show_files and files:
# Files table
file_table = create_files_table(dataset, scope, files)
Expand Down
Loading
Loading