datex-studio-cli 0.3.4__tar.gz → 0.4.1__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.
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/PKG-INFO +1 -1
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/pyproject.toml +1 -1
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/__init__.py +1 -1
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/cli.py +64 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/context.py +1 -0
- datex_studio_cli-0.4.1/src/dxs/utils/update_check.py +221 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/.gitignore +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/README.md +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/report-creator.skill +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/scripts/analyze_corpus.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/scripts/generate_rdlx_schema.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/__main__.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/__init__.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/api.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/auth.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/branch.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/config.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/crm.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/datasource.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/devops.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/document.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/endpoint.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/env.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/explore.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/function.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/marketplace.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/odata.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/organization.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/proxy.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/release_notes.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/repo.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/report/__init__.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/report/add_cmds.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/report/api.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/report/batch.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/report/create.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/report/data.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/report/dataset.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/report/edit.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/report/folder.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/report/preview.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/report/schema_cmds.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/schema.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/servicepack.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/source.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/studio.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/commands/user.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/__init__.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/api/__init__.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/api/client.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/api/endpoints.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/api/metadata_models.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/api/models.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/auth/__init__.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/auth/decorators.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/auth/msal_client.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/auth/token_cache.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/cache.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/datasource/__init__.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/datasource/flow_generator.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/datasource/flow_models.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/datasource/generator.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/datasource/models.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/datasource/parsers.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/datasource/resolver.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/datasource/type_def_parser.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/datasource/validator.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/designer/__init__.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/designer/flow_models.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/designer/models.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/designer/parsers.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/devops/__init__.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/devops/client.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/devops/helpers.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/devops/models.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/dynamics/__init__.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/dynamics/client.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/footprint/__init__.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/footprint/client.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/footprint/edmx_parser.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/footprint/metadata.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/function/__init__.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/function/generator.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/function/models.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/function/validator.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/graph.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/output/__init__.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/output/csv_fmt.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/output/formatter.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/output/json_fmt.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/output/redaction.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/output/yaml_fmt.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/release_notes.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/responses.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/models/__init__.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/report/__init__.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/report/datasource_binding.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/report/engine.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/report/field_parser.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/report/folder.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/report/manifest.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/report/models.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/report/preview.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/report/preview_arjs.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/report/schema.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/report/svg_renderer.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/report/templates/__init__.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/report/templates/bill_of_lading.rdlx-json +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/report/templates/shipping_label.rdlx-json +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/report/validate_arjs.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/report/validator.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/report/wrapper.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/utils/__init__.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/utils/click_options.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/utils/config.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/utils/errors.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/utils/filtering.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/utils/image.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/utils/paths.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/utils/resolvers.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/utils/responses.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/utils/restricted.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/utils/sorting.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/__init__.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/app.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/design.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/proxy_app.py +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/404/index.html +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/404.html +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/_next/static/UgyAMtPjH-Pt0RYWOHzIT/_buildManifest.js +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/_next/static/UgyAMtPjH-Pt0RYWOHzIT/_ssgManifest.js +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/_next/static/chunks/0b24cca5-c1e1c8810348f107.js +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/_next/static/chunks/255-102f2e5b2e3dc2ef.js +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/_next/static/chunks/4bd1b696-c023c6e3521b1417.js +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/_next/static/chunks/538-84e2e111415f1fda.js +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/_next/static/chunks/697-0e000ab410d9f470.js +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/_next/static/chunks/871-1acacdb7b4022abf.js +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/_next/static/chunks/8b8f67fc-6295949a4b5485a4.js +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/_next/static/chunks/909-c88abba3cf0caec3.js +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/_next/static/chunks/app/_not-found/page-ea1be7001c230704.js +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/_next/static/chunks/app/design/capture/page-a5e129c2d223432c.js +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/_next/static/chunks/app/design/page-21ba66a3dd3b03f0.js +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/_next/static/chunks/app/layout-2cc6eac09e476c91.js +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/_next/static/chunks/app/page-20c358395882cdac.js +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/_next/static/chunks/framework-de98b93a850cfc71.js +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/_next/static/chunks/main-0f18f91200dac003.js +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/_next/static/chunks/main-app-b69998d8941231d8.js +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/_next/static/chunks/pages/_app-7d307437aca18ad4.js +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/_next/static/chunks/pages/_error-cb2a52f75f2162e2.js +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/_next/static/chunks/polyfills-42372ed130431b0a.js +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/_next/static/chunks/webpack-2b297ada5306c17f.js +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/_next/static/css/360c657de5e04df8.css +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/design/capture/index.html +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/design/capture/index.txt +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/design/index.html +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/design/index.txt +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/index.html +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/index.txt +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/render-cli.js +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/report-preview.html +0 -0
- {datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/report-validate.html +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: datex-studio-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Summary: CLI for Datex Studio low-code platform, designed for LLM-based AI agents
|
|
5
5
|
Project-URL: Homepage, https://github.com/datex/datex-studio-cli
|
|
6
6
|
Project-URL: Documentation, https://github.com/datex/datex-studio-cli
|
|
@@ -162,6 +162,13 @@ class DxsGroup(click.Group):
|
|
|
162
162
|
default=False,
|
|
163
163
|
help="Show authentication environment variables for debugging",
|
|
164
164
|
)
|
|
165
|
+
@click.option(
|
|
166
|
+
"--no-update-check",
|
|
167
|
+
"no_update_check",
|
|
168
|
+
is_flag=True,
|
|
169
|
+
default=False,
|
|
170
|
+
help="Skip the PyPI update check for this invocation",
|
|
171
|
+
)
|
|
165
172
|
@click.pass_context
|
|
166
173
|
def cli(
|
|
167
174
|
ctx: click.Context,
|
|
@@ -177,6 +184,7 @@ def cli(
|
|
|
177
184
|
save_path: str | None,
|
|
178
185
|
force_overwrite: bool,
|
|
179
186
|
diagnose_auth: bool,
|
|
187
|
+
no_update_check: bool,
|
|
180
188
|
) -> None:
|
|
181
189
|
"""Datex Studio CLI - Command-line interface for Datex Studio platform.
|
|
182
190
|
|
|
@@ -249,6 +257,9 @@ def cli(
|
|
|
249
257
|
if diagnose_auth:
|
|
250
258
|
_show_auth_diagnostics()
|
|
251
259
|
|
|
260
|
+
# Stash for the result_callback to honor --no-update-check
|
|
261
|
+
dxs_ctx.no_update_check = no_update_check
|
|
262
|
+
|
|
252
263
|
|
|
253
264
|
def _mask_token(token: str | None, visible_chars: int = 8) -> str:
|
|
254
265
|
"""Mask a token for display, showing only first/last few characters.
|
|
@@ -366,6 +377,59 @@ def register_commands() -> None:
|
|
|
366
377
|
cli.add_command(schema.schema)
|
|
367
378
|
|
|
368
379
|
|
|
380
|
+
@cli.result_callback()
|
|
381
|
+
@click.pass_context
|
|
382
|
+
def _after_command(ctx: click.Context, result: Any, **kwargs: Any) -> Any:
|
|
383
|
+
"""Run post-command hooks (currently: PyPI update notice)."""
|
|
384
|
+
from dxs.utils.update_check import maybe_show_update_notice
|
|
385
|
+
|
|
386
|
+
dxs_ctx: DxsContext | None = ctx.find_object(DxsContext)
|
|
387
|
+
skip = bool(dxs_ctx and dxs_ctx.no_update_check)
|
|
388
|
+
try:
|
|
389
|
+
maybe_show_update_notice(skip=skip)
|
|
390
|
+
except Exception: # noqa: BLE001 - never let the update check break the CLI
|
|
391
|
+
pass
|
|
392
|
+
return result
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
@cli.command("update")
|
|
396
|
+
@click.option(
|
|
397
|
+
"--check",
|
|
398
|
+
"check_only",
|
|
399
|
+
is_flag=True,
|
|
400
|
+
default=False,
|
|
401
|
+
help="Print whether an update is available without prompting to install",
|
|
402
|
+
)
|
|
403
|
+
def update_cmd(check_only: bool) -> None:
|
|
404
|
+
"""Check PyPI for a newer release and optionally upgrade in place."""
|
|
405
|
+
from dxs.utils.update_check import (
|
|
406
|
+
_fetch_latest_version,
|
|
407
|
+
_run_upgrade,
|
|
408
|
+
detect_upgrade_command,
|
|
409
|
+
is_newer,
|
|
410
|
+
)
|
|
411
|
+
|
|
412
|
+
click.echo(f"Current version: {__version__}", err=True)
|
|
413
|
+
click.echo("Checking PyPI...", err=True)
|
|
414
|
+
latest = _fetch_latest_version()
|
|
415
|
+
if latest is None:
|
|
416
|
+
click.echo("Could not reach PyPI. Check your network and try again.", err=True)
|
|
417
|
+
sys.exit(1)
|
|
418
|
+
click.echo(f"Latest on PyPI: {latest}", err=True)
|
|
419
|
+
|
|
420
|
+
if not is_newer(latest, __version__):
|
|
421
|
+
click.echo("You are on the latest version.", err=True)
|
|
422
|
+
return
|
|
423
|
+
|
|
424
|
+
upgrade_cmd = detect_upgrade_command()
|
|
425
|
+
click.echo(f"Upgrade command: {upgrade_cmd}", err=True)
|
|
426
|
+
if check_only:
|
|
427
|
+
return
|
|
428
|
+
|
|
429
|
+
if click.confirm("Upgrade now?", default=True, err=True):
|
|
430
|
+
sys.exit(_run_upgrade(upgrade_cmd))
|
|
431
|
+
|
|
432
|
+
|
|
369
433
|
# Register commands when module loads
|
|
370
434
|
register_commands()
|
|
371
435
|
|
|
@@ -29,6 +29,7 @@ class DxsContext:
|
|
|
29
29
|
self.save_path: str | None = None
|
|
30
30
|
self.force_overwrite: bool = False
|
|
31
31
|
self.explicit_output_format: bool = False
|
|
32
|
+
self.no_update_check: bool = False
|
|
32
33
|
|
|
33
34
|
def output(self, data: Any, include_metadata: bool = True) -> None:
|
|
34
35
|
"""Output data in the configured format.
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
"""PyPI update check.
|
|
2
|
+
|
|
3
|
+
On each invocation, reads a cached "latest version on PyPI" entry. If a newer
|
|
4
|
+
version is available and we're attached to an interactive terminal, prints a
|
|
5
|
+
banner and offers to upgrade in place. The PyPI fetch happens in a background
|
|
6
|
+
daemon thread so the user's command is never delayed.
|
|
7
|
+
|
|
8
|
+
Environment / flag controls:
|
|
9
|
+
- ``DXS_NO_UPDATE_CHECK=1`` disables both the check and the banner.
|
|
10
|
+
- ``--no-update-check`` (CLI flag) does the same per-invocation.
|
|
11
|
+
- ``DXS_UPDATE_CHECK_DEBUG=1`` surfaces sender errors (development only).
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import json
|
|
17
|
+
import os
|
|
18
|
+
import re
|
|
19
|
+
import subprocess
|
|
20
|
+
import sys
|
|
21
|
+
import threading
|
|
22
|
+
import time
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
from typing import Any
|
|
25
|
+
|
|
26
|
+
import click
|
|
27
|
+
|
|
28
|
+
from dxs import __version__
|
|
29
|
+
from dxs.utils.paths import get_datex_home
|
|
30
|
+
|
|
31
|
+
PYPI_URL = "https://pypi.org/pypi/datex-studio-cli/json"
|
|
32
|
+
PACKAGE_NAME = "datex-studio-cli"
|
|
33
|
+
CACHE_TTL_SECONDS = 24 * 60 * 60
|
|
34
|
+
PROMPT_DEDUPE_SECONDS = 60 * 60 # at most one prompt per hour per machine
|
|
35
|
+
HTTP_TIMEOUT_SECONDS = 2.0
|
|
36
|
+
|
|
37
|
+
_CI_ENV_VARS = ("CI", "CONTINUOUS_INTEGRATION", "GITHUB_ACTIONS", "BUILDKITE", "TF_BUILD")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _cache_path() -> Path:
|
|
41
|
+
return get_datex_home() / "update_check.json"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _debug(msg: str) -> None:
|
|
45
|
+
if os.environ.get("DXS_UPDATE_CHECK_DEBUG", "").lower() in ("1", "true", "yes"):
|
|
46
|
+
click.echo(f"[update-check] {msg}", err=True)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def is_disabled() -> bool:
|
|
50
|
+
"""Return True if the update check has been disabled via env var."""
|
|
51
|
+
return os.environ.get("DXS_NO_UPDATE_CHECK", "").lower() in ("1", "true", "yes")
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _is_ci() -> bool:
|
|
55
|
+
return any(os.environ.get(v) for v in _CI_ENV_VARS)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _read_cache() -> dict[str, Any] | None:
|
|
59
|
+
path = _cache_path()
|
|
60
|
+
if not path.exists():
|
|
61
|
+
return None
|
|
62
|
+
try:
|
|
63
|
+
data = json.loads(path.read_text())
|
|
64
|
+
if isinstance(data, dict):
|
|
65
|
+
return data
|
|
66
|
+
except (json.JSONDecodeError, OSError) as e:
|
|
67
|
+
_debug(f"cache read failed: {e}")
|
|
68
|
+
return None
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _write_cache(data: dict[str, Any]) -> None:
|
|
72
|
+
try:
|
|
73
|
+
_cache_path().write_text(json.dumps(data))
|
|
74
|
+
except OSError as e:
|
|
75
|
+
_debug(f"cache write failed: {e}")
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _fetch_latest_version() -> str | None:
|
|
79
|
+
"""Fetch the latest version from PyPI. Returns None on any failure."""
|
|
80
|
+
try:
|
|
81
|
+
import httpx
|
|
82
|
+
|
|
83
|
+
response = httpx.get(PYPI_URL, timeout=HTTP_TIMEOUT_SECONDS)
|
|
84
|
+
response.raise_for_status()
|
|
85
|
+
latest = response.json()["info"]["version"]
|
|
86
|
+
return str(latest) if latest else None
|
|
87
|
+
except Exception as e: # noqa: BLE001 - never let telemetry break the CLI
|
|
88
|
+
_debug(f"fetch failed: {e}")
|
|
89
|
+
return None
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _refresh_cache_worker() -> None:
|
|
93
|
+
latest = _fetch_latest_version()
|
|
94
|
+
if not latest:
|
|
95
|
+
return
|
|
96
|
+
cache = _read_cache() or {}
|
|
97
|
+
cache["latest"] = latest
|
|
98
|
+
cache["checked_at"] = time.time()
|
|
99
|
+
_write_cache(cache)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _maybe_refresh_async(cache: dict[str, Any] | None) -> None:
|
|
103
|
+
"""Spawn a daemon thread to refresh the cache if it's missing or stale."""
|
|
104
|
+
needs_refresh = cache is None or (time.time() - float(cache.get("checked_at", 0))) > CACHE_TTL_SECONDS
|
|
105
|
+
if not needs_refresh:
|
|
106
|
+
return
|
|
107
|
+
thread = threading.Thread(target=_refresh_cache_worker, daemon=True, name="dxs-update-check")
|
|
108
|
+
thread.start()
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
_VERSION_RE = re.compile(r"^(\d+)(?:\.(\d+))?(?:\.(\d+))?")
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def _parse_version(v: str) -> tuple[int, int, int]:
|
|
115
|
+
"""Parse an X.Y.Z version into a tuple. Pre-release suffixes are ignored.
|
|
116
|
+
|
|
117
|
+
Returns (0, 0, 0) on unparseable input — treated as oldest possible.
|
|
118
|
+
"""
|
|
119
|
+
m = _VERSION_RE.match(v.strip())
|
|
120
|
+
if not m:
|
|
121
|
+
return (0, 0, 0)
|
|
122
|
+
return (int(m.group(1) or 0), int(m.group(2) or 0), int(m.group(3) or 0))
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def is_newer(candidate: str, current: str) -> bool:
|
|
126
|
+
"""Return True if `candidate` is a newer version than `current`."""
|
|
127
|
+
return _parse_version(candidate) > _parse_version(current)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def detect_upgrade_command() -> str:
|
|
131
|
+
"""Best-effort detection of how dxs was installed.
|
|
132
|
+
|
|
133
|
+
Returns the shell command the user should run to upgrade.
|
|
134
|
+
"""
|
|
135
|
+
exe = sys.executable
|
|
136
|
+
# uv tool installs land under ~/.local/share/uv/tools/<pkg>/...
|
|
137
|
+
if "/uv/tools/" in exe or "\\uv\\tools\\" in exe:
|
|
138
|
+
return f"uv tool upgrade {PACKAGE_NAME}"
|
|
139
|
+
# pipx installs land under ~/.local/pipx/venvs/<pkg>/...
|
|
140
|
+
if "/pipx/" in exe or "\\pipx\\" in exe:
|
|
141
|
+
return f"pipx upgrade {PACKAGE_NAME}"
|
|
142
|
+
# Fallback: pip in whatever interpreter the user is on
|
|
143
|
+
return f"{exe} -m pip install --upgrade {PACKAGE_NAME}"
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _run_upgrade(command: str) -> int:
|
|
147
|
+
"""Run the upgrade command and stream its output to the user.
|
|
148
|
+
|
|
149
|
+
Returns the subprocess exit code.
|
|
150
|
+
"""
|
|
151
|
+
click.echo(f"Running: {command}", err=True)
|
|
152
|
+
try:
|
|
153
|
+
completed = subprocess.run(command, shell=True, check=False)
|
|
154
|
+
return completed.returncode
|
|
155
|
+
except Exception as e: # noqa: BLE001
|
|
156
|
+
click.echo(f"Upgrade failed to start: {e}", err=True)
|
|
157
|
+
return 1
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def _interactive() -> bool:
|
|
161
|
+
"""True only when stdin, stderr, and stdout are all attached to a TTY.
|
|
162
|
+
|
|
163
|
+
We require stdout TTY too, because piping/redirecting stdout is the strongest
|
|
164
|
+
signal that the user is consuming structured output programmatically and
|
|
165
|
+
won't appreciate a banner mid-stream.
|
|
166
|
+
"""
|
|
167
|
+
return all(s.isatty() for s in (sys.stdin, sys.stderr, sys.stdout))
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def maybe_show_update_notice(skip: bool = False) -> None:
|
|
171
|
+
"""Check the cache and, if a newer version is available, prompt to upgrade.
|
|
172
|
+
|
|
173
|
+
Always returns quickly — the network fetch happens in a background thread.
|
|
174
|
+
|
|
175
|
+
Args:
|
|
176
|
+
skip: If True, skip both the check and any cache refresh. Used to honor
|
|
177
|
+
``--no-update-check``.
|
|
178
|
+
"""
|
|
179
|
+
if skip or is_disabled() or _is_ci():
|
|
180
|
+
return
|
|
181
|
+
if not _interactive():
|
|
182
|
+
return
|
|
183
|
+
|
|
184
|
+
cache = _read_cache()
|
|
185
|
+
_maybe_refresh_async(cache)
|
|
186
|
+
|
|
187
|
+
if not cache:
|
|
188
|
+
return
|
|
189
|
+
|
|
190
|
+
latest = cache.get("latest")
|
|
191
|
+
if not isinstance(latest, str) or not is_newer(latest, __version__):
|
|
192
|
+
return
|
|
193
|
+
|
|
194
|
+
last_prompted = float(cache.get("last_prompted_at", 0))
|
|
195
|
+
if time.time() - last_prompted < PROMPT_DEDUPE_SECONDS:
|
|
196
|
+
return
|
|
197
|
+
|
|
198
|
+
upgrade_cmd = detect_upgrade_command()
|
|
199
|
+
click.echo("", err=True)
|
|
200
|
+
click.echo(
|
|
201
|
+
f" dxs {latest} is available (you have {__version__})",
|
|
202
|
+
err=True,
|
|
203
|
+
)
|
|
204
|
+
click.echo(f" Upgrade command: {upgrade_cmd}", err=True)
|
|
205
|
+
|
|
206
|
+
cache["last_prompted_at"] = time.time()
|
|
207
|
+
_write_cache(cache)
|
|
208
|
+
|
|
209
|
+
try:
|
|
210
|
+
if click.confirm(" Upgrade now?", default=False, err=True):
|
|
211
|
+
exit_code = _run_upgrade(upgrade_cmd)
|
|
212
|
+
if exit_code == 0:
|
|
213
|
+
click.echo(
|
|
214
|
+
" Upgrade complete. Re-run your command to use the new version.",
|
|
215
|
+
err=True,
|
|
216
|
+
)
|
|
217
|
+
else:
|
|
218
|
+
click.echo(f" Upgrade exited with code {exit_code}.", err=True)
|
|
219
|
+
except (click.Abort, EOFError):
|
|
220
|
+
click.echo("", err=True)
|
|
221
|
+
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
|
|
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
|
{datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/core/datasource/type_def_parser.py
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/report/templates/bill_of_lading.rdlx-json
RENAMED
|
File without changes
|
{datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/report/templates/shipping_label.rdlx-json
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/design/capture/index.html
RENAMED
|
File without changes
|
{datex_studio_cli-0.3.4 → datex_studio_cli-0.4.1}/src/dxs/web/static/design/capture/index.txt
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
|