datatrail-cli 0.13.0__tar.gz → 1.0.0__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.
- datatrail_cli-1.0.0/.github/workflows/codeql.yml +101 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/.github/workflows/continuous-deployment.yml +4 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/.github/workflows/continuous-integration.yml +4 -1
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/.github/workflows/docs.yml +3 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/.github/workflows/stale.yml +5 -0
- datatrail_cli-1.0.0/.release-please-manifest.json +3 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/CHANGELOG.md +50 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/PKG-INFO +10 -3
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/README.md +2 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/docs/commands.md +3 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/docs/install.md +2 -0
- datatrail_cli-1.0.0/docs/inventory.md +80 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/docs/list.md +105 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/docs/ps.md +24 -0
- datatrail_cli-1.0.0/docs/pull-manifest.md +69 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/dtcli/clear.py +2 -2
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/dtcli/cli.py +18 -2
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/dtcli/config.py +48 -8
- datatrail_cli-1.0.0/dtcli/doctor.py +169 -0
- datatrail_cli-1.0.0/dtcli/inventory.py +423 -0
- datatrail_cli-1.0.0/dtcli/locking.py +42 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/dtcli/ls.py +135 -1
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/dtcli/ps.py +40 -10
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/dtcli/pull.py +14 -3
- datatrail_cli-1.0.0/dtcli/pull_manifest.py +445 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/dtcli/src/functions.py +208 -20
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/dtcli/unregistered.py +2 -2
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/dtcli/utilities/cadcclient.py +188 -62
- datatrail_cli-1.0.0/dtcli/utilities/results.py +12 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/dtcli/utilities/utilities.py +35 -0
- datatrail_cli-1.0.0/dtcli/verify.py +326 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/mkdocs.yml +2 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/pyproject.toml +17 -4
- datatrail_cli-1.0.0/tests/conftest.py +105 -0
- datatrail_cli-1.0.0/tests/test_cadc_summary.py +41 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/tests/test_cli.py +184 -1
- datatrail_cli-1.0.0/tests/test_config.py +159 -0
- datatrail_cli-1.0.0/tests/test_doctor.py +336 -0
- datatrail_cli-1.0.0/tests/test_functions.py +443 -0
- datatrail_cli-1.0.0/tests/test_inventory.py +406 -0
- datatrail_cli-1.0.0/tests/test_locking.py +62 -0
- datatrail_cli-1.0.0/tests/test_pull_manifest.py +462 -0
- datatrail_cli-1.0.0/tests/test_pull_reliability.py +355 -0
- datatrail_cli-1.0.0/tests/test_utils.py +96 -0
- datatrail_cli-1.0.0/tests/test_verify.py +223 -0
- datatrail_cli-1.0.0/uv.lock +1702 -0
- datatrail_cli-0.13.0/.release-please-manifest.json +0 -3
- datatrail_cli-0.13.0/tests/test_functions.py +0 -114
- datatrail_cli-0.13.0/tests/test_utils.py +0 -43
- datatrail_cli-0.13.0/uv.lock +0 -3431
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/.gitignore +0 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/.pre-commit-config.yaml +0 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/LICENSE +0 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/docs/clear.md +0 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/docs/cli.md +0 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/docs/images/Datatrail-logo.png +0 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/docs/index.md +0 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/docs/initialising.md +0 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/docs/pull.md +0 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/docs/scout.md +0 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/docs/unregistered.md +0 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/docs/user_guide.md +0 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/dtcli/__init__.py +0 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/dtcli/config.yaml +0 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/dtcli/scout.py +0 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/release-please-config.json +0 -0
- {datatrail_cli-0.13.0 → datatrail_cli-1.0.0}/tox.ini +0 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# For most projects, this workflow file will not need changing; you simply need
|
|
2
|
+
# to commit it to your repository.
|
|
3
|
+
#
|
|
4
|
+
# You may wish to alter this file to override the set of languages analyzed,
|
|
5
|
+
# or to provide custom queries or build logic.
|
|
6
|
+
#
|
|
7
|
+
# ******** NOTE ********
|
|
8
|
+
# We have attempted to detect the languages in your repository. Please check
|
|
9
|
+
# the `language` matrix defined below to confirm you have the correct set of
|
|
10
|
+
# supported CodeQL languages.
|
|
11
|
+
#
|
|
12
|
+
name: "CodeQL Advanced"
|
|
13
|
+
|
|
14
|
+
on:
|
|
15
|
+
push:
|
|
16
|
+
branches: [ "main" ]
|
|
17
|
+
pull_request:
|
|
18
|
+
branches: [ "main" ]
|
|
19
|
+
schedule:
|
|
20
|
+
- cron: '24 11 * * 2'
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
analyze:
|
|
24
|
+
name: Analyze (${{ matrix.language }})
|
|
25
|
+
# Runner size impacts CodeQL analysis time. To learn more, please see:
|
|
26
|
+
# - https://gh.io/recommended-hardware-resources-for-running-codeql
|
|
27
|
+
# - https://gh.io/supported-runners-and-hardware-resources
|
|
28
|
+
# - https://gh.io/using-larger-runners (GitHub.com only)
|
|
29
|
+
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
|
|
30
|
+
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
|
31
|
+
permissions:
|
|
32
|
+
# required for all workflows
|
|
33
|
+
security-events: write
|
|
34
|
+
|
|
35
|
+
# required to fetch internal or private CodeQL packs
|
|
36
|
+
packages: read
|
|
37
|
+
|
|
38
|
+
# only required for workflows in private repositories
|
|
39
|
+
actions: read
|
|
40
|
+
contents: read
|
|
41
|
+
|
|
42
|
+
strategy:
|
|
43
|
+
fail-fast: false
|
|
44
|
+
matrix:
|
|
45
|
+
include:
|
|
46
|
+
- language: actions
|
|
47
|
+
build-mode: none
|
|
48
|
+
- language: python
|
|
49
|
+
build-mode: none
|
|
50
|
+
# CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift'
|
|
51
|
+
# Use `c-cpp` to analyze code written in C, C++ or both
|
|
52
|
+
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
|
|
53
|
+
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
|
|
54
|
+
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
|
|
55
|
+
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
|
|
56
|
+
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
|
|
57
|
+
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
|
|
58
|
+
steps:
|
|
59
|
+
- name: Checkout repository
|
|
60
|
+
uses: actions/checkout@v7
|
|
61
|
+
|
|
62
|
+
# Add any setup steps before running the `github/codeql-action/init` action.
|
|
63
|
+
# This includes steps like installing compilers or runtimes (`actions/setup-node`
|
|
64
|
+
# or others). This is typically only required for manual builds.
|
|
65
|
+
# - name: Setup runtime (example)
|
|
66
|
+
# uses: actions/setup-example@v1
|
|
67
|
+
|
|
68
|
+
# Initializes the CodeQL tools for scanning.
|
|
69
|
+
- name: Initialize CodeQL
|
|
70
|
+
uses: github/codeql-action/init@v4
|
|
71
|
+
with:
|
|
72
|
+
languages: ${{ matrix.language }}
|
|
73
|
+
build-mode: ${{ matrix.build-mode }}
|
|
74
|
+
# If you wish to specify custom queries, you can do so here or in a config file.
|
|
75
|
+
# By default, queries listed here will override any specified in a config file.
|
|
76
|
+
# Prefix the list here with "+" to use these queries and those in the config file.
|
|
77
|
+
|
|
78
|
+
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
|
79
|
+
# queries: security-extended,security-and-quality
|
|
80
|
+
|
|
81
|
+
# If the analyze step fails for one of the languages you are analyzing with
|
|
82
|
+
# "We were unable to automatically build your code", modify the matrix above
|
|
83
|
+
# to set the build mode to "manual" for that language. Then modify this step
|
|
84
|
+
# to build your code.
|
|
85
|
+
# ℹ️ Command-line programs to run using the OS shell.
|
|
86
|
+
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
|
87
|
+
- name: Run manual build steps
|
|
88
|
+
if: matrix.build-mode == 'manual'
|
|
89
|
+
shell: bash
|
|
90
|
+
run: |
|
|
91
|
+
echo 'If you are using a "manual" build mode for one or more of the' \
|
|
92
|
+
'languages you are analyzing, replace this with the commands to build' \
|
|
93
|
+
'your code, for example:'
|
|
94
|
+
echo ' make bootstrap'
|
|
95
|
+
echo ' make release'
|
|
96
|
+
exit 1
|
|
97
|
+
|
|
98
|
+
- name: Perform CodeQL Analysis
|
|
99
|
+
uses: github/codeql-action/analyze@v4
|
|
100
|
+
with:
|
|
101
|
+
category: "/language:${{matrix.language}}"
|
|
@@ -1,5 +1,55 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.0.0](https://github.com/CHIMEFRB/datatrail-cli/compare/datatrail-cli-v0.13.0...datatrail-cli-v1.0.0) (2026-09-28)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### ⚠ BREAKING CHANGES
|
|
7
|
+
|
|
8
|
+
* require Python 3.10 for patched dependencies
|
|
9
|
+
|
|
10
|
+
### Features
|
|
11
|
+
|
|
12
|
+
* **doctor:** add readiness checks ([ae0565c](https://github.com/CHIMEFRB/datatrail-cli/commit/ae0565cd7963758e465889f312f0fac2d0418c3d))
|
|
13
|
+
* **doctor:** add readiness checks ([6691c31](https://github.com/CHIMEFRB/datatrail-cli/commit/6691c31cb20e5419588af7a21f62810aee1fbc02))
|
|
14
|
+
* **inventory:** add resumable manifests ([c7c4df5](https://github.com/CHIMEFRB/datatrail-cli/commit/c7c4df5d1634e8573f700ba2b1368105f4f67fb7))
|
|
15
|
+
* **inventory:** add resumable manifests ([343a28a](https://github.com/CHIMEFRB/datatrail-cli/commit/343a28a74366f91b8a0bd428250f1576cd4a752f))
|
|
16
|
+
* **ls:** add --match and --expand for dataset discovery ([bf08635](https://github.com/CHIMEFRB/datatrail-cli/commit/bf08635a75f6ec3b1415541ff1b9a1f31e9d443b))
|
|
17
|
+
* **ls:** add match and expand for dataset discovery ([31cccde](https://github.com/CHIMEFRB/datatrail-cli/commit/31cccde47ee8827aec17df7ce13ba5a7ac7b13d3))
|
|
18
|
+
* **ls:** add recursive dataset discovery ([8ea3bc4](https://github.com/CHIMEFRB/datatrail-cli/commit/8ea3bc4e5026fbb9fedb231a0bdb7b78a8f90bdf))
|
|
19
|
+
* **ls:** add recursive dataset discovery ([6f9a85e](https://github.com/CHIMEFRB/datatrail-cli/commit/6f9a85e608eea73a5b3e8b30331203a09908c71c))
|
|
20
|
+
* **ps:** expose common paths in JSON output ([3ee4238](https://github.com/CHIMEFRB/datatrail-cli/commit/3ee423828ee81fca7c9a661051975920e71e17bf))
|
|
21
|
+
* **ps:** expose per-storage-element common paths in --json output ([b748fb4](https://github.com/CHIMEFRB/datatrail-cli/commit/b748fb442589a0259b483774ed6fcf391a8eb391))
|
|
22
|
+
* **pull:** add resumable manifest transfers ([9017c11](https://github.com/CHIMEFRB/datatrail-cli/commit/9017c118450ee98082f72b4142b2c76d77c94f28))
|
|
23
|
+
* **pull:** add resumable manifest transfers ([7272daa](https://github.com/CHIMEFRB/datatrail-cli/commit/7272daa58fc76b3130181fdc1171da7453b01f82))
|
|
24
|
+
* **verify:** verify registered dataset files ([cef2ab7](https://github.com/CHIMEFRB/datatrail-cli/commit/cef2ab708b2d4f26bae4131d18f5613ba86ec0e3))
|
|
25
|
+
* **verify:** verify registered dataset files ([27f3810](https://github.com/CHIMEFRB/datatrail-cli/commit/27f3810dfe78c1f889cb94abae3836a7058ebfd5))
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
### Bug Fixes
|
|
29
|
+
|
|
30
|
+
* add stable command error metadata ([d1096ff](https://github.com/CHIMEFRB/datatrail-cli/commit/d1096ffb850b6bd1a690370318dcec5be97ce4f3))
|
|
31
|
+
* **deps:** require patched Requests on Python 3.10 and newer ([e0fb559](https://github.com/CHIMEFRB/datatrail-cli/commit/e0fb55951975d60c202181644c703f280602fa5f))
|
|
32
|
+
* **deps:** require patched Requests on Python 3.10+ ([7d1c4ba](https://github.com/CHIMEFRB/datatrail-cli/commit/7d1c4ba3ead33b46cc6c042e554464fca4e78438))
|
|
33
|
+
* **deps:** require patched urllib3 on Python 3.10+ ([5a4ad0b](https://github.com/CHIMEFRB/datatrail-cli/commit/5a4ad0bc1a29dcad305cad8ec739dd47e703ef6a))
|
|
34
|
+
* **deps:** use patched dependencies on Python 3.10 and newer ([69f0806](https://github.com/CHIMEFRB/datatrail-cli/commit/69f080682a6fa11f18c4acbc890b3c043bc22393))
|
|
35
|
+
* **doctor:** handle certificate and authentication failures ([3584b7b](https://github.com/CHIMEFRB/datatrail-cli/commit/3584b7b0d71ee9bc18479bba75e5b10b96ac8ac2))
|
|
36
|
+
* **encoding:** use ASCII status output ([a0646d7](https://github.com/CHIMEFRB/datatrail-cli/commit/a0646d7d17e66b7507a7f6019e1cd48c3faf2f9d))
|
|
37
|
+
* enforce patched urllib3 on Python 3.10 and newer ([ab12a03](https://github.com/CHIMEFRB/datatrail-cli/commit/ab12a03402cb0ecfec471b2c1941bc3513101762))
|
|
38
|
+
* **failure:** add stable command error metadata ([f52a917](https://github.com/CHIMEFRB/datatrail-cli/commit/f52a917acc05a88b4cbe1364ce3d41af8e1af4ae))
|
|
39
|
+
* **inventory:** reconcile recovered discovery checkpoints ([2a0bda5](https://github.com/CHIMEFRB/datatrail-cli/commit/2a0bda5751e849503903c96bba65fe530bb016d2))
|
|
40
|
+
* **ls:** validate discovery filters and response names ([af2de4f](https://github.com/CHIMEFRB/datatrail-cli/commit/af2de4f3526da507e54dc30f68cc139227f3381b))
|
|
41
|
+
* **ps:** preserve paths for duplicate and invalid replicas ([2dae57d](https://github.com/CHIMEFRB/datatrail-cli/commit/2dae57d4654c4a22c81aea17827a5d0f041b977c))
|
|
42
|
+
* **pull:** clean up CADC SDK partial downloads ([1b15bff](https://github.com/CHIMEFRB/datatrail-cli/commit/1b15bffaa32b2685669a74f4d18f9d6bb73ee1ef))
|
|
43
|
+
* **pull:** protect aliased directory ownership paths ([c03f284](https://github.com/CHIMEFRB/datatrail-cli/commit/c03f284d730fdf1dd9bf2f8dbe5ddda8780324ac))
|
|
44
|
+
* **pull:** publish downloads atomically ([b512e5f](https://github.com/CHIMEFRB/datatrail-cli/commit/b512e5f8ba5b6acd3a5a09c68440eb914d9e8d8e))
|
|
45
|
+
* **pull:** publish downloads atomically ([bf7846f](https://github.com/CHIMEFRB/datatrail-cli/commit/bf7846f4efb41ea55d3edd3961b19c5da7d79eb3))
|
|
46
|
+
* **pull:** report lost workers and clean up failed starts ([bfe5d91](https://github.com/CHIMEFRB/datatrail-cli/commit/bfe5d91d71d130230f5a6b232953e09e34fc8219))
|
|
47
|
+
* **pull:** validate manifest paths before creating state ([b0dc320](https://github.com/CHIMEFRB/datatrail-cli/commit/b0dc32064e1859fc90466da5ed2b4a7f62aa8ccd))
|
|
48
|
+
* require Python 3.10 for patched dependencies ([07de5af](https://github.com/CHIMEFRB/datatrail-cli/commit/07de5af18da463d514ca4b05da06a749c5c2b0dd))
|
|
49
|
+
* update TLS dependencies without raising Python minimum ([8658c58](https://github.com/CHIMEFRB/datatrail-cli/commit/8658c5828ce63772ba229ffa6f4ff93b5c9575fe))
|
|
50
|
+
* update TLS dependencies without raising Python minimum ([ec11019](https://github.com/CHIMEFRB/datatrail-cli/commit/ec110197e2f5281cd22261b605de1d1ad47405e3))
|
|
51
|
+
* **verify:** preserve reports when metadata services fail ([8dbeea3](https://github.com/CHIMEFRB/datatrail-cli/commit/8dbeea34caa8a87d94f4f4d0e3418f3bcfb2df9f))
|
|
52
|
+
|
|
3
53
|
## [0.13.0](https://github.com/CHIMEFRB/datatrail-cli/compare/datatrail-cli-v0.12.0...datatrail-cli-v0.13.0) (2026-08-25)
|
|
4
54
|
|
|
5
55
|
|
|
@@ -1,24 +1,29 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: datatrail-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.0
|
|
4
4
|
Summary: CHIME/FRB Datatrail CLI
|
|
5
5
|
Author: CHIME FRB Project Office
|
|
6
6
|
Author-email: Tarik Zegmott <tarik.zegmott@mcgill.ca>
|
|
7
7
|
License-Expression: MIT
|
|
8
8
|
License-File: LICENSE
|
|
9
|
-
Requires-Python:
|
|
9
|
+
Requires-Python: <4.0,>=3.10
|
|
10
10
|
Requires-Dist: cadcdata>=2.5.0
|
|
11
11
|
Requires-Dist: cadctap>=0.9.11
|
|
12
12
|
Requires-Dist: cadcutils>=1.5.1.1
|
|
13
13
|
Requires-Dist: click-aliasing>=1.0.0
|
|
14
14
|
Requires-Dist: click>=8.1.3
|
|
15
|
+
Requires-Dist: cryptography>=50.0.0
|
|
15
16
|
Requires-Dist: dill>=0.3.6
|
|
16
17
|
Requires-Dist: lxml>=6.1.0
|
|
17
18
|
Requires-Dist: mergedeep>=1.3.4
|
|
18
19
|
Requires-Dist: pyaml>=21.10.1
|
|
19
|
-
Requires-Dist:
|
|
20
|
+
Requires-Dist: pygments>=2.20.0
|
|
21
|
+
Requires-Dist: pyopenssl>=26.4.0
|
|
22
|
+
Requires-Dist: requests>=2.33.0
|
|
20
23
|
Requires-Dist: rich>=13.3.5
|
|
24
|
+
Requires-Dist: setuptools>=83.0.0
|
|
21
25
|
Requires-Dist: tenacity>=8.0.0
|
|
26
|
+
Requires-Dist: urllib3>=2.7.0
|
|
22
27
|
Description-Content-Type: text/markdown
|
|
23
28
|
|
|
24
29
|
<div align="center">
|
|
@@ -56,6 +61,8 @@ Description-Content-Type: text/markdown
|
|
|
56
61
|
|
|
57
62
|
## 🛠️ Installation
|
|
58
63
|
|
|
64
|
+
Python 3.10 or newer is required for the supported dependency versions.
|
|
65
|
+
|
|
59
66
|
### Install from PYPI
|
|
60
67
|
|
|
61
68
|
```shell
|
|
@@ -9,11 +9,14 @@ The commands available to you are:
|
|
|
9
9
|
- `clear`: This removes all files belonging to the 'scope' and 'dataset', only
|
|
10
10
|
available for the local and canfar sites.
|
|
11
11
|
- `config`: Edit the `.datatrail/config.yaml` configuration file.
|
|
12
|
+
- `inventory`: Recursively discover datasets and write their file replica URIs
|
|
13
|
+
to a resumable JSON manifest.
|
|
12
14
|
- `list`: This list either the 'scopes' available or all of the datasets
|
|
13
15
|
belonging to the given dataset.
|
|
14
16
|
- `ps`: This provides detailed information for the given 'scope' and 'dataset' combination.
|
|
15
17
|
- `pull`: This allows you to download all files belonging to the 'scope' and
|
|
16
18
|
'dataset' provided.
|
|
19
|
+
- `pull-manifest`: Download Minoc files from a resumable inventory manifest.
|
|
17
20
|
- `scout`: This command provides an overview of what the Datatrail database
|
|
18
21
|
thinks is the current number of files for a given dataset at each storage
|
|
19
22
|
element, compared to what is observed. If a discrepancy is found at Minoc,
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Building a durable inventory
|
|
2
|
+
|
|
3
|
+
`datatrail inventory` recursively discovers terminal datasets and records each
|
|
4
|
+
file replica URI in a versioned JSON manifest. The manifest can later drive a
|
|
5
|
+
batch download without repeating the archive crawl.
|
|
6
|
+
|
|
7
|
+
Every run must be bounded in one of these ways:
|
|
8
|
+
|
|
9
|
+
```shell
|
|
10
|
+
$> datatrail inventory chime.event.baseband.raw
|
|
11
|
+
$> datatrail inventory --match classified,baseband
|
|
12
|
+
$> datatrail inventory gbo.acquisition.processed --parent complex_gains
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
A scope limits traversal to that scope. `--match` may search across scopes but
|
|
16
|
+
only opens matching larger datasets. `--parent` requires a scope and starts at
|
|
17
|
+
one known dataset. It cannot be combined with `--match`.
|
|
18
|
+
|
|
19
|
+
Use `--output` to choose the manifest path:
|
|
20
|
+
|
|
21
|
+
```shell
|
|
22
|
+
$> datatrail inventory chime.event.baseband.raw --match classified \
|
|
23
|
+
--output baseband-inventory.json
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The command writes the manifest atomically after discovery and after every
|
|
27
|
+
dataset query. A rerun with the same selection reuses `ready` and `empty`
|
|
28
|
+
entries, then retries `pending` and `failed` entries. A different selection is
|
|
29
|
+
refused so unrelated inventories cannot be mixed.
|
|
30
|
+
|
|
31
|
+
Successful discovery replaces obsolete entries with the current terminal
|
|
32
|
+
datasets. If a failed parent lookup recovers, its placeholder is replaced by
|
|
33
|
+
the discovered descendants. A discovery outage preserves earlier checkpoints.
|
|
34
|
+
|
|
35
|
+
Only one inventory command may own an output at a time. A competing run exits
|
|
36
|
+
with an error before reading or changing the manifest, including when a symlink
|
|
37
|
+
refers to the same output. Ownership is released when the process exits. Leave
|
|
38
|
+
the hidden `.lock` file in place; its presence does not mean a run is active.
|
|
39
|
+
|
|
40
|
+
An inventory with any failed discovery branch or file query exits nonzero.
|
|
41
|
+
`--allow-incomplete` keeps the incomplete manifest but exits zero when a caller
|
|
42
|
+
wants to inspect or process the available subset.
|
|
43
|
+
|
|
44
|
+
## Manifest format
|
|
45
|
+
|
|
46
|
+
The first format is `datatrail.inventory/v1`:
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"schema": "datatrail.inventory/v1",
|
|
51
|
+
"selection": {
|
|
52
|
+
"scope": "gbo.acquisition.processed",
|
|
53
|
+
"match": [],
|
|
54
|
+
"parent": "complex_gains"
|
|
55
|
+
},
|
|
56
|
+
"complete": true,
|
|
57
|
+
"discovery_failures": [],
|
|
58
|
+
"datasets": [
|
|
59
|
+
{
|
|
60
|
+
"scope": "gbo.acquisition.processed",
|
|
61
|
+
"dataset": "20230525",
|
|
62
|
+
"parent": "complex_gains",
|
|
63
|
+
"path": ["complex_gains", "20230525"],
|
|
64
|
+
"status": "ready",
|
|
65
|
+
"replicas": [
|
|
66
|
+
{
|
|
67
|
+
"storage_element": "minoc",
|
|
68
|
+
"uri": "cadc:CHIMEFRB/example/file.h5"
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Replica rows contain only Datatrail information. Size and checksum fields may
|
|
77
|
+
be added in a later schema when they can be obtained without requiring a CADC
|
|
78
|
+
credential during inventory creation. A valid dataset with no replica URIs has
|
|
79
|
+
status `empty`; an unavailable or invalid file response has status `failed`
|
|
80
|
+
and an `error` field.
|
|
@@ -12,6 +12,12 @@ Options:
|
|
|
12
12
|
-q, --quiet Only errors shown in logs.
|
|
13
13
|
--write Write the events to file.
|
|
14
14
|
--json Output as JSON.
|
|
15
|
+
--match TEXT Comma-separated, case-insensitive terms a larger dataset must
|
|
16
|
+
all contain.
|
|
17
|
+
--expand Open each matched larger dataset one level and list its
|
|
18
|
+
children.
|
|
19
|
+
--recursive Open each matched larger dataset through all descendant
|
|
20
|
+
levels.
|
|
15
21
|
--help Show this message and exit.
|
|
16
22
|
|
|
17
23
|
```
|
|
@@ -102,6 +108,105 @@ Within Datatrail, there are two types of datasets:
|
|
|
102
108
|
Please see the CLI reference page for more information on the `list` command:
|
|
103
109
|
[datatrail list](../cli/#datatrail-list)
|
|
104
110
|
|
|
111
|
+
## Finding datasets with `--match` and `--expand`
|
|
112
|
+
|
|
113
|
+
Navigating the hierarchy one name at a time gets slow when you do not know
|
|
114
|
+
where a dataset lives. `--match` filters the larger datasets of a scope, or
|
|
115
|
+
of **every** scope when no scope is given, by one or more comma-separated,
|
|
116
|
+
case-insensitive terms, which must all appear in the combined
|
|
117
|
+
`scope dataset` text. At least one nonempty term is required; whitespace and
|
|
118
|
+
commas alone are rejected:
|
|
119
|
+
|
|
120
|
+
```shell
|
|
121
|
+
$> datatrail ls chime.acquisition.processed --match gains
|
|
122
|
+
Datatrail: Dataset Map
|
|
123
|
+
+-----------------------------+---------------+
|
|
124
|
+
| Scope | Dataset |
|
|
125
|
+
+-----------------------------+---------------+
|
|
126
|
+
| chime.acquisition.processed | complex_gains |
|
|
127
|
+
+-----------------------------+---------------+
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
A hit may be a container whose children are the datasets you actually want.
|
|
131
|
+
`--expand` opens each matched larger dataset one level and lists the children
|
|
132
|
+
it finds, recording the parent; a match whose children cannot be listed keeps
|
|
133
|
+
its own row:
|
|
134
|
+
|
|
135
|
+
```shell
|
|
136
|
+
$> datatrail ls --match gain --expand
|
|
137
|
+
Datatrail: Dataset Map
|
|
138
|
+
+-----------------------------+---------------+---------------+
|
|
139
|
+
| Scope | Dataset | Parent |
|
|
140
|
+
+-----------------------------+---------------+---------------+
|
|
141
|
+
| chime.acquisition.processed | complex_gains | |
|
|
142
|
+
+-----------------------------+---------------+---------------+
|
|
143
|
+
| gbo.acquisition.processed | 20230716 | complex_gains |
|
|
144
|
+
| gbo.acquisition.processed | 20230715 | complex_gains |
|
|
145
|
+
| ... | ... | ... |
|
|
146
|
+
+-----------------------------+---------------+---------------+
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Rows reached through a parent resolve directly with
|
|
150
|
+
`datatrail ps <scope> <dataset>`; a row kept for a matched dataset whose
|
|
151
|
+
children could not be listed (or that has none) may still be a container.
|
|
152
|
+
|
|
153
|
+
!!! warning "Incomplete maps"
|
|
154
|
+
|
|
155
|
+
If Datatrail does not answer for a scope or dataset during the walk, the
|
|
156
|
+
map is reported as **incomplete** and the unanswered queries are listed,
|
|
157
|
+
rather than silently showing them as empty. With `--json`, those queries
|
|
158
|
+
appear in the `failed` list. A partial map still exits 0; a map with **no**
|
|
159
|
+
rows and unanswered queries exits 1, since nothing was determined.
|
|
160
|
+
|
|
161
|
+
`--recursive` follows every descendant of each matched larger dataset instead
|
|
162
|
+
of stopping after one level. It emits terminal datasets and records the full
|
|
163
|
+
path used to reach each one:
|
|
164
|
+
|
|
165
|
+
```shell
|
|
166
|
+
$> datatrail ls gbo.acquisition.processed --match gains --recursive
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
The walk visits each dataset once, so shared descendants are not duplicated
|
|
170
|
+
and hierarchy cycles cannot loop forever. The first path found in sorted order
|
|
171
|
+
is retained. An answered empty child list is a terminal dataset. A branch that
|
|
172
|
+
does not answer is retained as a partial row and also listed under `failed`.
|
|
173
|
+
Like `--expand`, a recursive walk across all scopes requires `--match` to keep
|
|
174
|
+
the request bounded.
|
|
175
|
+
|
|
176
|
+
With `--json`, the map is emitted as structured rows for scripting; `parent`
|
|
177
|
+
is `null` for rows that were not reached through expansion. Recursive rows
|
|
178
|
+
also include `path`, from the matched larger dataset through the terminal row:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
$ datatrail ls --match gain --expand --json
|
|
182
|
+
{
|
|
183
|
+
"results": [
|
|
184
|
+
{
|
|
185
|
+
"scope": "gbo.acquisition.processed",
|
|
186
|
+
"dataset": "20230525",
|
|
187
|
+
"parent": "complex_gains"
|
|
188
|
+
},
|
|
189
|
+
...
|
|
190
|
+
],
|
|
191
|
+
"failed": []
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
$ datatrail ls gbo.acquisition.processed --match gains --recursive --json
|
|
197
|
+
{
|
|
198
|
+
"results": [
|
|
199
|
+
{
|
|
200
|
+
"scope": "gbo.acquisition.processed",
|
|
201
|
+
"dataset": "20230525",
|
|
202
|
+
"parent": "complex_gains",
|
|
203
|
+
"path": ["complex_gains", "20230525"]
|
|
204
|
+
}
|
|
205
|
+
],
|
|
206
|
+
"failed": []
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
105
210
|
## 🤖 Machine-readable JSON output
|
|
106
211
|
|
|
107
212
|
The `--json` flag outputs structured JSON instead of formatted tables, making it easy to parse the output in scripts and pipelines:
|
|
@@ -102,6 +102,16 @@ $ datatrail ps kko.event.baseband.raw 308892599 --json
|
|
|
102
102
|
]
|
|
103
103
|
}
|
|
104
104
|
},
|
|
105
|
+
"common_paths": {
|
|
106
|
+
"minoc": {
|
|
107
|
+
"common_path": "data/kko/baseband/raw/2023/08/07/astro_308892599",
|
|
108
|
+
"files": [
|
|
109
|
+
"baseband_308892599_129.h5",
|
|
110
|
+
"baseband_308892599_1013.h5",
|
|
111
|
+
...
|
|
112
|
+
]
|
|
113
|
+
}
|
|
114
|
+
},
|
|
105
115
|
"policies": {
|
|
106
116
|
"replication_policy": {
|
|
107
117
|
"preferred_storage_elements": ["chime"],
|
|
@@ -127,6 +137,13 @@ $ datatrail ps kko.event.baseband.raw 308892599 --json
|
|
|
127
137
|
}
|
|
128
138
|
```
|
|
129
139
|
|
|
140
|
+
The `common_paths` field gives, per storage element, the deepest common
|
|
141
|
+
directory of its file replicas and the file names relative to it, so scripts
|
|
142
|
+
do not have to re-derive the split. When no common directory exists, it is
|
|
143
|
+
`""` and the original paths are listed. Note that `minoc` paths keep any
|
|
144
|
+
collection prefix (such as `cadc:CHIMEFRB`) exactly as reported in
|
|
145
|
+
`file_replica_locations`.
|
|
146
|
+
|
|
130
147
|
### Usage in scripts
|
|
131
148
|
|
|
132
149
|
```python
|
|
@@ -145,6 +162,13 @@ data = json.loads(result.stdout)
|
|
|
145
162
|
file_locations = data["files"]["file_replica_locations"]
|
|
146
163
|
minoc_files = file_locations.get("minoc", [])
|
|
147
164
|
|
|
165
|
+
# Compose full paths from the derived common path
|
|
166
|
+
minoc = data["common_paths"].get("minoc", {})
|
|
167
|
+
full_paths = [
|
|
168
|
+
f"{minoc['common_path']}/{name}" if minoc["common_path"] else name
|
|
169
|
+
for name in minoc.get("files", [])
|
|
170
|
+
]
|
|
171
|
+
|
|
148
172
|
# Access policies
|
|
149
173
|
replication_policy = data["policies"]["replication_policy"]
|
|
150
174
|
deletion_policy = data["policies"]["deletion_policy"]
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Pulling an inventory
|
|
2
|
+
|
|
3
|
+
`datatrail pull-manifest` downloads the Minoc files in an inventory and writes
|
|
4
|
+
durable transfer state beside it:
|
|
5
|
+
|
|
6
|
+
```shell
|
|
7
|
+
$> datatrail pull-manifest baseband-inventory.json --directory ./baseband
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
The default state path is `<inventory-name>.pull.json`. Use `--state` to put it
|
|
11
|
+
elsewhere. Each completed batch is written atomically, so rerunning the same
|
|
12
|
+
command skips completed files whose recorded size still matches and retries
|
|
13
|
+
pending or failed files.
|
|
14
|
+
|
|
15
|
+
Minoc replicas may use `cadc:CHIMEFRB/...`, `data/...`, or `/...` paths, matching
|
|
16
|
+
the formats accepted by dataset downloads. Equivalent paths are downloaded
|
|
17
|
+
once. Paths that escape the destination, collide with one another, or replace
|
|
18
|
+
the inventory, transfer state, or lock files are refused before creating state.
|
|
19
|
+
|
|
20
|
+
Transfers are limited by `--cores`, which defaults to one. A larger value runs
|
|
21
|
+
only that many files at once:
|
|
22
|
+
|
|
23
|
+
```shell
|
|
24
|
+
$> datatrail pull-manifest baseband-inventory.json --directory ./baseband \
|
|
25
|
+
--cores 4 --force
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Each file is downloaded to a temporary sibling, checked against Minoc's size
|
|
29
|
+
when available, and moved into place only after it completes. An interrupted or
|
|
30
|
+
truncated download does not replace the destination.
|
|
31
|
+
|
|
32
|
+
The command exits nonzero when any file fails, the inventory is incomplete, or
|
|
33
|
+
a ready dataset has no Minoc replica. Available files are still downloaded and
|
|
34
|
+
checkpointed, so the next run can continue after the service recovers.
|
|
35
|
+
|
|
36
|
+
Only one transfer command may use a state file or destination directory at a
|
|
37
|
+
time. Competing runs exit before changing transfer state or downloading files,
|
|
38
|
+
even if they use different state files for the same destination. Symlinks to the
|
|
39
|
+
same paths share ownership. The locks are held through confirmation and all
|
|
40
|
+
download batches, and released when the process exits. Leave the hidden `.lock`
|
|
41
|
+
files in place; their presence does not mean a transfer is active.
|
|
42
|
+
Use separate destination trees for concurrent commands; these locks do not
|
|
43
|
+
coordinate a directory with a nested destination used by another command.
|
|
44
|
+
|
|
45
|
+
## Transfer state
|
|
46
|
+
|
|
47
|
+
The transfer state uses schema `datatrail.pull/v1`:
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{
|
|
51
|
+
"schema": "datatrail.pull/v1",
|
|
52
|
+
"inventory": "/data/baseband-inventory.json",
|
|
53
|
+
"directory": "/data/baseband",
|
|
54
|
+
"inventory_complete": true,
|
|
55
|
+
"unavailable_datasets": [],
|
|
56
|
+
"complete": true,
|
|
57
|
+
"files": [
|
|
58
|
+
{
|
|
59
|
+
"uri": "cadc:CHIMEFRB/example/file.h5",
|
|
60
|
+
"path": "example/file.h5",
|
|
61
|
+
"status": "complete",
|
|
62
|
+
"bytes": 4096
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Keep the state file with its inventory. A state file cannot be reused with a
|
|
69
|
+
different inventory path or destination directory.
|
|
@@ -128,9 +128,9 @@ def clear(
|
|
|
128
128
|
is_delete = True
|
|
129
129
|
else:
|
|
130
130
|
message = (
|
|
131
|
-
"
|
|
131
|
+
"WARNING: Delete files and empty parent directories?"
|
|
132
132
|
if clear_parents
|
|
133
|
-
else "
|
|
133
|
+
else "WARNING: Delete files?"
|
|
134
134
|
)
|
|
135
135
|
is_delete = Confirm.ask(message)
|
|
136
136
|
|
|
@@ -6,7 +6,19 @@ import click
|
|
|
6
6
|
from click_aliasing import ClickAliasedGroup
|
|
7
7
|
from rich import console, pretty
|
|
8
8
|
|
|
9
|
-
from dtcli import
|
|
9
|
+
from dtcli import (
|
|
10
|
+
clear,
|
|
11
|
+
config,
|
|
12
|
+
doctor,
|
|
13
|
+
inventory,
|
|
14
|
+
ls,
|
|
15
|
+
ps,
|
|
16
|
+
pull,
|
|
17
|
+
pull_manifest,
|
|
18
|
+
scout,
|
|
19
|
+
unregistered,
|
|
20
|
+
verify,
|
|
21
|
+
)
|
|
10
22
|
from dtcli.utilities import utilities
|
|
11
23
|
|
|
12
24
|
pretty.install()
|
|
@@ -43,11 +55,15 @@ def version():
|
|
|
43
55
|
|
|
44
56
|
cli.add_command(clear.clear)
|
|
45
57
|
cli.add_command(config.config)
|
|
58
|
+
cli.add_command(doctor.doctor)
|
|
59
|
+
cli.add_command(inventory.inventory)
|
|
46
60
|
cli.add_command(ls.list, aliases=["ls"])
|
|
47
61
|
cli.add_command(ps.ps)
|
|
48
62
|
cli.add_command(pull.pull)
|
|
63
|
+
cli.add_command(pull_manifest.pull_manifest)
|
|
49
64
|
cli.add_command(scout.scout)
|
|
50
65
|
cli.add_command(unregistered.unregistered)
|
|
66
|
+
cli.add_command(verify.verify)
|
|
51
67
|
|
|
52
68
|
|
|
53
69
|
def check_version() -> None:
|
|
@@ -60,7 +76,7 @@ def check_version() -> None:
|
|
|
60
76
|
current_version = package_version("datatrail-cli")
|
|
61
77
|
latest_version = utilities.get_latest_released_version()
|
|
62
78
|
terminal_stderr.print(
|
|
63
|
-
f"A new release of datatrail-cli is available: {current_version}
|
|
79
|
+
f"A new release of datatrail-cli is available: {current_version} -> {latest_version}", # noqa: E501
|
|
64
80
|
style="bold yellow",
|
|
65
81
|
)
|
|
66
82
|
terminal_stderr.print()
|