datex-studio-cli 0.4.4__tar.gz → 0.4.5__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.
Files changed (172) hide show
  1. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/PKG-INFO +1 -1
  2. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/pyproject.toml +1 -1
  3. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/__init__.py +1 -1
  4. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/cli.py +25 -16
  5. datex_studio_cli-0.4.5/src/dxs/utils/update_check.py +208 -0
  6. datex_studio_cli-0.4.4/src/dxs/utils/update_check.py +0 -310
  7. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/.gitignore +0 -0
  8. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/README.md +0 -0
  9. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/report-creator.skill +0 -0
  10. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/scripts/analyze_corpus.py +0 -0
  11. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/scripts/generate_rdlx_schema.py +0 -0
  12. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/__main__.py +0 -0
  13. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/__init__.py +0 -0
  14. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/api.py +0 -0
  15. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/auth.py +0 -0
  16. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/branch.py +0 -0
  17. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/config.py +0 -0
  18. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/configuration.py +0 -0
  19. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/crm.py +0 -0
  20. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/datasource.py +0 -0
  21. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/devops.py +0 -0
  22. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/document.py +0 -0
  23. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/endpoint.py +0 -0
  24. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/env.py +0 -0
  25. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/explore.py +0 -0
  26. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/function.py +0 -0
  27. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/marketplace.py +0 -0
  28. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/odata.py +0 -0
  29. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/organization.py +0 -0
  30. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/proxy.py +0 -0
  31. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/release_notes.py +0 -0
  32. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/repo.py +0 -0
  33. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/report/__init__.py +0 -0
  34. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/report/add_cmds.py +0 -0
  35. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/report/api.py +0 -0
  36. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/report/batch.py +0 -0
  37. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/report/create.py +0 -0
  38. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/report/data.py +0 -0
  39. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/report/dataset.py +0 -0
  40. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/report/edit.py +0 -0
  41. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/report/folder.py +0 -0
  42. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/report/preview.py +0 -0
  43. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/report/schema_cmds.py +0 -0
  44. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/schema.py +0 -0
  45. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/servicepack.py +0 -0
  46. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/source.py +0 -0
  47. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/studio.py +0 -0
  48. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/telemetry.py +0 -0
  49. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/commands/user.py +0 -0
  50. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/context.py +0 -0
  51. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/__init__.py +0 -0
  52. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/api/__init__.py +0 -0
  53. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/api/app_config.py +0 -0
  54. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/api/client.py +0 -0
  55. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/api/endpoints.py +0 -0
  56. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/api/metadata_models.py +0 -0
  57. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/api/models.py +0 -0
  58. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/auth/__init__.py +0 -0
  59. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/auth/decorators.py +0 -0
  60. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/auth/msal_client.py +0 -0
  61. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/auth/token_cache.py +0 -0
  62. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/cache.py +0 -0
  63. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/datasource/__init__.py +0 -0
  64. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/datasource/flow_generator.py +0 -0
  65. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/datasource/flow_models.py +0 -0
  66. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/datasource/generator.py +0 -0
  67. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/datasource/models.py +0 -0
  68. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/datasource/parsers.py +0 -0
  69. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/datasource/resolver.py +0 -0
  70. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/datasource/type_def_parser.py +0 -0
  71. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/datasource/validator.py +0 -0
  72. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/designer/__init__.py +0 -0
  73. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/designer/flow_models.py +0 -0
  74. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/designer/models.py +0 -0
  75. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/designer/parsers.py +0 -0
  76. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/devops/__init__.py +0 -0
  77. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/devops/client.py +0 -0
  78. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/devops/helpers.py +0 -0
  79. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/devops/models.py +0 -0
  80. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/dynamics/__init__.py +0 -0
  81. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/dynamics/client.py +0 -0
  82. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/dynamics/metadata_cache.py +0 -0
  83. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/footprint/__init__.py +0 -0
  84. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/footprint/client.py +0 -0
  85. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/footprint/edmx_parser.py +0 -0
  86. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/footprint/metadata.py +0 -0
  87. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/function/__init__.py +0 -0
  88. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/function/generator.py +0 -0
  89. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/function/models.py +0 -0
  90. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/function/validator.py +0 -0
  91. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/graph.py +0 -0
  92. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/output/__init__.py +0 -0
  93. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/output/csv_fmt.py +0 -0
  94. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/output/formatter.py +0 -0
  95. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/output/json_fmt.py +0 -0
  96. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/output/redaction.py +0 -0
  97. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/output/yaml_fmt.py +0 -0
  98. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/release_notes.py +0 -0
  99. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/responses.py +0 -0
  100. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/telemetry/__init__.py +0 -0
  101. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/telemetry/config.py +0 -0
  102. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/telemetry/identity.py +0 -0
  103. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/telemetry/recorder.py +0 -0
  104. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/telemetry/scrubber.py +0 -0
  105. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/core/telemetry/sender.py +0 -0
  106. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/models/__init__.py +0 -0
  107. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/report/__init__.py +0 -0
  108. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/report/datasource_binding.py +0 -0
  109. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/report/engine.py +0 -0
  110. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/report/field_parser.py +0 -0
  111. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/report/folder.py +0 -0
  112. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/report/manifest.py +0 -0
  113. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/report/models.py +0 -0
  114. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/report/preview.py +0 -0
  115. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/report/preview_arjs.py +0 -0
  116. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/report/schema.py +0 -0
  117. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/report/svg_renderer.py +0 -0
  118. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/report/templates/__init__.py +0 -0
  119. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/report/templates/bill_of_lading.rdlx-json +0 -0
  120. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/report/templates/shipping_label.rdlx-json +0 -0
  121. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/report/validate_arjs.py +0 -0
  122. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/report/validator.py +0 -0
  123. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/report/wrapper.py +0 -0
  124. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/utils/__init__.py +0 -0
  125. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/utils/click_options.py +0 -0
  126. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/utils/config.py +0 -0
  127. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/utils/errors.py +0 -0
  128. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/utils/filtering.py +0 -0
  129. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/utils/image.py +0 -0
  130. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/utils/paths.py +0 -0
  131. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/utils/resolvers.py +0 -0
  132. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/utils/responses.py +0 -0
  133. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/utils/restricted.py +0 -0
  134. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/utils/sorting.py +0 -0
  135. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/__init__.py +0 -0
  136. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/app.py +0 -0
  137. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/design.py +0 -0
  138. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/proxy_app.py +0 -0
  139. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/404/index.html +0 -0
  140. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/404.html +0 -0
  141. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/_next/static/UgyAMtPjH-Pt0RYWOHzIT/_buildManifest.js +0 -0
  142. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/_next/static/UgyAMtPjH-Pt0RYWOHzIT/_ssgManifest.js +0 -0
  143. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/_next/static/chunks/0b24cca5-c1e1c8810348f107.js +0 -0
  144. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/_next/static/chunks/255-102f2e5b2e3dc2ef.js +0 -0
  145. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/_next/static/chunks/4bd1b696-c023c6e3521b1417.js +0 -0
  146. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/_next/static/chunks/538-84e2e111415f1fda.js +0 -0
  147. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/_next/static/chunks/697-0e000ab410d9f470.js +0 -0
  148. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/_next/static/chunks/871-1acacdb7b4022abf.js +0 -0
  149. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/_next/static/chunks/8b8f67fc-6295949a4b5485a4.js +0 -0
  150. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/_next/static/chunks/909-c88abba3cf0caec3.js +0 -0
  151. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/_next/static/chunks/app/_not-found/page-ea1be7001c230704.js +0 -0
  152. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/_next/static/chunks/app/design/capture/page-a5e129c2d223432c.js +0 -0
  153. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/_next/static/chunks/app/design/page-21ba66a3dd3b03f0.js +0 -0
  154. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/_next/static/chunks/app/layout-2cc6eac09e476c91.js +0 -0
  155. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/_next/static/chunks/app/page-20c358395882cdac.js +0 -0
  156. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/_next/static/chunks/framework-de98b93a850cfc71.js +0 -0
  157. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/_next/static/chunks/main-0f18f91200dac003.js +0 -0
  158. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/_next/static/chunks/main-app-b69998d8941231d8.js +0 -0
  159. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/_next/static/chunks/pages/_app-7d307437aca18ad4.js +0 -0
  160. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/_next/static/chunks/pages/_error-cb2a52f75f2162e2.js +0 -0
  161. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/_next/static/chunks/polyfills-42372ed130431b0a.js +0 -0
  162. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/_next/static/chunks/webpack-2b297ada5306c17f.js +0 -0
  163. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/_next/static/css/360c657de5e04df8.css +0 -0
  164. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/design/capture/index.html +0 -0
  165. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/design/capture/index.txt +0 -0
  166. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/design/index.html +0 -0
  167. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/design/index.txt +0 -0
  168. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/index.html +0 -0
  169. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/index.txt +0 -0
  170. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/render-cli.js +0 -0
  171. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/src/dxs/web/static/report-preview.html +0 -0
  172. {datex_studio_cli-0.4.4 → datex_studio_cli-0.4.5}/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.4.4
3
+ Version: 0.4.5
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
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "datex-studio-cli"
7
- version = "0.4.4"
7
+ version = "0.4.5"
8
8
  description = "CLI for Datex Studio low-code platform, designed for LLM-based AI agents"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -1,4 +1,4 @@
1
1
  """Datex Studio CLI - Command-line interface for Datex Studio platform."""
2
2
 
3
- __version__ = "0.4.4"
3
+ __version__ = "0.4.5"
4
4
  __app_name__ = "dxs"
@@ -507,18 +507,20 @@ def _ctx_extras(dxs_ctx: "DxsContext | None") -> dict[str, Any]:
507
507
 
508
508
 
509
509
  @cli.command("update")
510
- @click.option(
511
- "--check",
512
- "check_only",
513
- is_flag=True,
514
- default=False,
515
- help="Print whether an update is available without prompting to install",
516
- )
517
- def update_cmd(check_only: bool) -> None:
518
- """Check PyPI for a newer release and optionally upgrade in place."""
510
+ def update_cmd() -> None:
511
+ """Check PyPI for a newer release and print the upgrade command.
512
+
513
+ This command never performs the upgrade itself — run the printed
514
+ command in a fresh shell. This avoids the running-binary file-lock
515
+ issues that any in-process upgrade hits on Windows.
516
+ """
517
+ import time
518
+
519
519
  from dxs.utils.update_check import (
520
+ PACKAGE_NAME,
520
521
  _fetch_latest_version,
521
- _run_upgrade,
522
+ _read_cache,
523
+ _write_cache,
522
524
  detect_upgrade_command,
523
525
  is_newer,
524
526
  )
@@ -536,12 +538,19 @@ def update_cmd(check_only: bool) -> None:
536
538
  return
537
539
 
538
540
  upgrade_cmd = detect_upgrade_command()
539
- click.echo(f"Upgrade command: {upgrade_cmd}", err=True)
540
- if check_only:
541
- return
542
-
543
- if click.confirm("Upgrade now?", default=True, err=True):
544
- sys.exit(_run_upgrade(upgrade_cmd))
541
+ click.echo("", err=True)
542
+ click.echo(f" A new release of dxs is available: {__version__} → {latest}", err=True)
543
+ click.echo(f" To upgrade, run: {upgrade_cmd}", err=True)
544
+ click.echo(f" https://pypi.org/project/{PACKAGE_NAME}/{latest}/", err=True)
545
+
546
+ # Refresh the cache and suppress the auto-banner for the next dedupe
547
+ # window — the user has explicitly seen the news.
548
+ now = time.time()
549
+ cache = _read_cache() or {}
550
+ cache["latest"] = latest
551
+ cache["checked_at"] = now
552
+ cache["last_notified_at"] = now
553
+ _write_cache(cache)
545
554
 
546
555
 
547
556
  # Register commands when module loads
@@ -0,0 +1,208 @@
1
+ """PyPI update notifier.
2
+
3
+ After each command, if the on-disk cache says a newer version exists on
4
+ PyPI, print a one-time banner to stderr telling the user how to upgrade.
5
+ The actual upgrade is the user's responsibility — we never exec, spawn,
6
+ or otherwise touch the running install. This sidesteps every file-lock,
7
+ process-replacement, and platform-specific upgrade problem.
8
+
9
+ The PyPI fetch happens in a background daemon thread, so a stale cache is
10
+ refreshed for *next* time. The current run never blocks on the network.
11
+
12
+ Environment / flag controls:
13
+ - ``DXS_NO_UPDATE_CHECK=1`` disables both the check and the banner.
14
+ - ``--no-update-check`` (CLI flag) does the same per-invocation.
15
+ - ``DXS_UPDATE_CHECK_DEBUG=1`` surfaces sender errors (development only).
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import json
21
+ import os
22
+ import re
23
+ import sys
24
+ import threading
25
+ import time
26
+ from pathlib import Path
27
+ from typing import Any
28
+
29
+ import click
30
+
31
+ from dxs import __version__
32
+ from dxs.utils.paths import get_datex_home
33
+
34
+ PYPI_URL = "https://pypi.org/pypi/datex-studio-cli/json"
35
+ PACKAGE_NAME = "datex-studio-cli"
36
+ CACHE_TTL_SECONDS = 24 * 60 * 60
37
+ NOTIFY_DEDUPE_SECONDS = 60 * 60 # at most one banner per hour per machine
38
+ HTTP_TIMEOUT_SECONDS = 2.0
39
+
40
+ _CI_ENV_VARS = ("CI", "CONTINUOUS_INTEGRATION", "GITHUB_ACTIONS", "BUILDKITE", "TF_BUILD")
41
+
42
+
43
+ def _cache_path() -> Path:
44
+ return get_datex_home() / "update_check.json"
45
+
46
+
47
+ def _debug(msg: str) -> None:
48
+ if os.environ.get("DXS_UPDATE_CHECK_DEBUG", "").lower() in ("1", "true", "yes"):
49
+ click.echo(f"[update-check] {msg}", err=True)
50
+
51
+
52
+ def is_disabled() -> bool:
53
+ """Return True if the update check has been disabled via env var."""
54
+ return os.environ.get("DXS_NO_UPDATE_CHECK", "").lower() in ("1", "true", "yes")
55
+
56
+
57
+ def _is_ci() -> bool:
58
+ return any(os.environ.get(v) for v in _CI_ENV_VARS)
59
+
60
+
61
+ def _read_cache() -> dict[str, Any] | None:
62
+ path = _cache_path()
63
+ if not path.exists():
64
+ return None
65
+ try:
66
+ data = json.loads(path.read_text())
67
+ if isinstance(data, dict):
68
+ return data
69
+ except (json.JSONDecodeError, OSError) as e:
70
+ _debug(f"cache read failed: {e}")
71
+ return None
72
+
73
+
74
+ def _write_cache(data: dict[str, Any]) -> None:
75
+ try:
76
+ _cache_path().write_text(json.dumps(data))
77
+ except OSError as e:
78
+ _debug(f"cache write failed: {e}")
79
+
80
+
81
+ def _fetch_latest_version() -> str | None:
82
+ """Fetch the latest version from PyPI. Returns None on any failure."""
83
+ try:
84
+ import httpx
85
+
86
+ response = httpx.get(PYPI_URL, timeout=HTTP_TIMEOUT_SECONDS)
87
+ response.raise_for_status()
88
+ latest = response.json()["info"]["version"]
89
+ return str(latest) if latest else None
90
+ except Exception as e: # noqa: BLE001 - never let telemetry break the CLI
91
+ _debug(f"fetch failed: {e}")
92
+ return None
93
+
94
+
95
+ def _refresh_cache_worker() -> None:
96
+ latest = _fetch_latest_version()
97
+ if not latest:
98
+ return
99
+ cache = _read_cache() or {}
100
+ cache["latest"] = latest
101
+ cache["checked_at"] = time.time()
102
+ _write_cache(cache)
103
+
104
+
105
+ def _maybe_refresh_async(cache: dict[str, Any] | None) -> None:
106
+ """Spawn a daemon thread to refresh the cache if it's missing or stale."""
107
+ needs_refresh = (
108
+ cache is None or (time.time() - float(cache.get("checked_at", 0))) > CACHE_TTL_SECONDS
109
+ )
110
+ if not needs_refresh:
111
+ return
112
+ thread = threading.Thread(target=_refresh_cache_worker, daemon=True, name="dxs-update-check")
113
+ thread.start()
114
+
115
+
116
+ _VERSION_RE = re.compile(r"^(\d+)(?:\.(\d+))?(?:\.(\d+))?")
117
+
118
+
119
+ def _parse_version(v: str) -> tuple[int, int, int]:
120
+ """Parse an X.Y.Z version into a tuple. Pre-release suffixes are ignored.
121
+
122
+ Returns (0, 0, 0) on unparseable input — treated as oldest possible.
123
+ """
124
+ m = _VERSION_RE.match(v.strip())
125
+ if not m:
126
+ return (0, 0, 0)
127
+ return (int(m.group(1) or 0), int(m.group(2) or 0), int(m.group(3) or 0))
128
+
129
+
130
+ def is_newer(candidate: str, current: str) -> bool:
131
+ """Return True if `candidate` is a newer version than `current`."""
132
+ return _parse_version(candidate) > _parse_version(current)
133
+
134
+
135
+ def detect_upgrade_command() -> str:
136
+ """Best-effort detection of how dxs was installed.
137
+
138
+ Returns the shell command the user should run to upgrade.
139
+ """
140
+ exe = sys.executable
141
+ # uv tool installs land under ~/.local/share/uv/tools/<pkg>/...
142
+ if "/uv/tools/" in exe or "\\uv\\tools\\" in exe:
143
+ return f"uv tool upgrade {PACKAGE_NAME}"
144
+ # pipx installs land under ~/.local/pipx/venvs/<pkg>/...
145
+ if "/pipx/" in exe or "\\pipx\\" in exe:
146
+ return f"pipx upgrade {PACKAGE_NAME}"
147
+ # Fallback: pip in whatever interpreter the user is on
148
+ return f"{exe} -m pip install --upgrade {PACKAGE_NAME}"
149
+
150
+
151
+ def _stderr_is_tty() -> bool:
152
+ """True when stderr is attached to a TTY.
153
+
154
+ Only stderr matters — the banner is written there. Piping stdout (e.g.
155
+ ``dxs odata ... | jq``) leaves stderr untouched, so the user still sees
156
+ the banner in their terminal. Redirecting stderr (``2>log``) suppresses
157
+ it, as intended.
158
+ """
159
+ return sys.stderr.isatty()
160
+
161
+
162
+ def _print_banner(latest: str, upgrade_cmd: str) -> None:
163
+ """Print the update banner to stderr."""
164
+ click.echo("", err=True)
165
+ click.echo(
166
+ f" A new release of dxs is available: {__version__} → {latest}",
167
+ err=True,
168
+ )
169
+ click.echo(f" To upgrade, run: {upgrade_cmd}", err=True)
170
+ click.echo(f" https://pypi.org/project/{PACKAGE_NAME}/{latest}/", err=True)
171
+
172
+
173
+ def maybe_show_update_notice(skip: bool = False) -> None:
174
+ """If the cache shows a newer version, print a one-time banner to stderr.
175
+
176
+ Always returns quickly — the PyPI fetch happens in a background thread
177
+ that only writes to the cache. The first run on a stale cache prints
178
+ nothing; the next run sees the refreshed cache and prints the banner.
179
+ Dedupe keeps it to one banner per ``NOTIFY_DEDUPE_SECONDS`` window so
180
+ fast-fire commands don't spam.
181
+
182
+ Args:
183
+ skip: If True, skip both the check and any cache refresh. Used to
184
+ honor ``--no-update-check``.
185
+ """
186
+ if skip or is_disabled() or _is_ci():
187
+ return
188
+ if not _stderr_is_tty():
189
+ return
190
+
191
+ cache = _read_cache()
192
+ _maybe_refresh_async(cache)
193
+
194
+ if not cache:
195
+ return
196
+
197
+ latest = cache.get("latest")
198
+ if not isinstance(latest, str) or not is_newer(latest, __version__):
199
+ return
200
+
201
+ last_notified = float(cache.get("last_notified_at", 0))
202
+ if time.time() - last_notified < NOTIFY_DEDUPE_SECONDS:
203
+ return
204
+
205
+ _print_banner(latest, detect_upgrade_command())
206
+
207
+ cache["last_notified_at"] = time.time()
208
+ _write_cache(cache)
@@ -1,310 +0,0 @@
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 platform
19
- import re
20
- import shlex
21
- import subprocess
22
- import sys
23
- import tempfile
24
- import threading
25
- import time
26
- from pathlib import Path
27
- from typing import Any
28
-
29
- import click
30
-
31
- from dxs import __version__
32
- from dxs.utils.paths import get_datex_home
33
-
34
- PYPI_URL = "https://pypi.org/pypi/datex-studio-cli/json"
35
- PACKAGE_NAME = "datex-studio-cli"
36
- CACHE_TTL_SECONDS = 24 * 60 * 60
37
- PROMPT_DEDUPE_SECONDS = 60 * 60 # at most one prompt per hour per machine
38
- HTTP_TIMEOUT_SECONDS = 2.0
39
-
40
- _CI_ENV_VARS = ("CI", "CONTINUOUS_INTEGRATION", "GITHUB_ACTIONS", "BUILDKITE", "TF_BUILD")
41
-
42
-
43
- def _cache_path() -> Path:
44
- return get_datex_home() / "update_check.json"
45
-
46
-
47
- def _debug(msg: str) -> None:
48
- if os.environ.get("DXS_UPDATE_CHECK_DEBUG", "").lower() in ("1", "true", "yes"):
49
- click.echo(f"[update-check] {msg}", err=True)
50
-
51
-
52
- def is_disabled() -> bool:
53
- """Return True if the update check has been disabled via env var."""
54
- return os.environ.get("DXS_NO_UPDATE_CHECK", "").lower() in ("1", "true", "yes")
55
-
56
-
57
- def _is_ci() -> bool:
58
- return any(os.environ.get(v) for v in _CI_ENV_VARS)
59
-
60
-
61
- def _read_cache() -> dict[str, Any] | None:
62
- path = _cache_path()
63
- if not path.exists():
64
- return None
65
- try:
66
- data = json.loads(path.read_text())
67
- if isinstance(data, dict):
68
- return data
69
- except (json.JSONDecodeError, OSError) as e:
70
- _debug(f"cache read failed: {e}")
71
- return None
72
-
73
-
74
- def _write_cache(data: dict[str, Any]) -> None:
75
- try:
76
- _cache_path().write_text(json.dumps(data))
77
- except OSError as e:
78
- _debug(f"cache write failed: {e}")
79
-
80
-
81
- def _fetch_latest_version() -> str | None:
82
- """Fetch the latest version from PyPI. Returns None on any failure."""
83
- try:
84
- import httpx
85
-
86
- response = httpx.get(PYPI_URL, timeout=HTTP_TIMEOUT_SECONDS)
87
- response.raise_for_status()
88
- latest = response.json()["info"]["version"]
89
- return str(latest) if latest else None
90
- except Exception as e: # noqa: BLE001 - never let telemetry break the CLI
91
- _debug(f"fetch failed: {e}")
92
- return None
93
-
94
-
95
- def _refresh_cache_worker() -> None:
96
- latest = _fetch_latest_version()
97
- if not latest:
98
- return
99
- cache = _read_cache() or {}
100
- cache["latest"] = latest
101
- cache["checked_at"] = time.time()
102
- _write_cache(cache)
103
-
104
-
105
- def _maybe_refresh_async(cache: dict[str, Any] | None) -> None:
106
- """Spawn a daemon thread to refresh the cache if it's missing or stale."""
107
- needs_refresh = (
108
- cache is None or (time.time() - float(cache.get("checked_at", 0))) > CACHE_TTL_SECONDS
109
- )
110
- if not needs_refresh:
111
- return
112
- thread = threading.Thread(target=_refresh_cache_worker, daemon=True, name="dxs-update-check")
113
- thread.start()
114
-
115
-
116
- _VERSION_RE = re.compile(r"^(\d+)(?:\.(\d+))?(?:\.(\d+))?")
117
-
118
-
119
- def _parse_version(v: str) -> tuple[int, int, int]:
120
- """Parse an X.Y.Z version into a tuple. Pre-release suffixes are ignored.
121
-
122
- Returns (0, 0, 0) on unparseable input — treated as oldest possible.
123
- """
124
- m = _VERSION_RE.match(v.strip())
125
- if not m:
126
- return (0, 0, 0)
127
- return (int(m.group(1) or 0), int(m.group(2) or 0), int(m.group(3) or 0))
128
-
129
-
130
- def is_newer(candidate: str, current: str) -> bool:
131
- """Return True if `candidate` is a newer version than `current`."""
132
- return _parse_version(candidate) > _parse_version(current)
133
-
134
-
135
- def detect_upgrade_command() -> str:
136
- """Best-effort detection of how dxs was installed.
137
-
138
- Returns the shell command the user should run to upgrade.
139
- """
140
- exe = sys.executable
141
- # uv tool installs land under ~/.local/share/uv/tools/<pkg>/...
142
- if "/uv/tools/" in exe or "\\uv\\tools\\" in exe:
143
- return f"uv tool upgrade {PACKAGE_NAME}"
144
- # pipx installs land under ~/.local/pipx/venvs/<pkg>/...
145
- if "/pipx/" in exe or "\\pipx\\" in exe:
146
- return f"pipx upgrade {PACKAGE_NAME}"
147
- # Fallback: pip in whatever interpreter the user is on
148
- return f"{exe} -m pip install --upgrade {PACKAGE_NAME}"
149
-
150
-
151
- def _run_upgrade(command: str) -> int:
152
- """Hand off to the upgrade command, tearing down this process first.
153
-
154
- POSIX uses ``os.execvp``, which truly replaces the process image and
155
- frees all file handles before the upgrader (uv/pipx/pip) starts rewriting
156
- the venv.
157
-
158
- Windows is different: ``os.execvp`` there spawns a child and exits, but
159
- Windows holds an exclusive image-file lock on the running ``dxs.exe``
160
- launcher (e.g. ``~/.local/bin/dxs.exe``) until the launcher process fully
161
- terminates — uv races ahead and fails to overwrite the entry-point shim
162
- with "os error 32: file in use". So on Windows we write a small batch
163
- helper that waits briefly for the launcher to exit, then runs the
164
- upgrade in a fresh console window, and we exit immediately to release
165
- the lock.
166
-
167
- On success this function does not return. Returns 1 only when the
168
- upgrade fails to start.
169
- """
170
- command = command.strip()
171
- if not command:
172
- click.echo("Upgrade command was empty.", err=True)
173
- return 1
174
-
175
- click.echo(f"Running: {command}", err=True)
176
- try:
177
- sys.stdout.flush()
178
- sys.stderr.flush()
179
- except Exception: # noqa: BLE001
180
- pass
181
-
182
- if platform.system() == "Windows":
183
- return _spawn_windows_upgrade(command)
184
-
185
- args = shlex.split(command)
186
- try:
187
- os.execvp(args[0], args)
188
- except OSError as e:
189
- click.echo(f"Upgrade failed to start: {e}", err=True)
190
- return 1
191
- return 1 # unreachable on success
192
-
193
-
194
- def _spawn_windows_upgrade(command: str) -> int:
195
- """Spawn the upgrade in a new console window detached from this process.
196
-
197
- Writes a temporary ``.cmd`` file that waits ~3 seconds for ``dxs.exe`` to
198
- fully terminate (releasing Windows' image-file lock on the launcher),
199
- then runs the upgrade with one short retry if the first attempt still
200
- hits a file-in-use error. The current process exits immediately so the
201
- lock is released as quickly as possible.
202
- """
203
- script = (
204
- "@echo off\r\n"
205
- "echo Waiting for dxs to exit so its files can be replaced...\r\n"
206
- # ping -n N sleeps roughly (N-1) seconds; portable across all
207
- # Windows versions where `timeout` may not be available.
208
- "ping -n 4 127.0.0.1 > nul\r\n"
209
- f"echo Running: {command}\r\n"
210
- f"{command}\r\n"
211
- "if %ERRORLEVEL% NEQ 0 (\r\n"
212
- " echo.\r\n"
213
- " echo First attempt failed; waiting and retrying once...\r\n"
214
- " ping -n 6 127.0.0.1 > nul\r\n"
215
- f" {command}\r\n"
216
- ")\r\n"
217
- "echo.\r\n"
218
- "if %ERRORLEVEL% NEQ 0 (echo Upgrade failed.) else (echo Upgrade complete.)\r\n"
219
- "echo.\r\n"
220
- "pause\r\n"
221
- )
222
-
223
- try:
224
- fd, script_path = tempfile.mkstemp(prefix="dxs-upgrade-", suffix=".cmd")
225
- with os.fdopen(fd, "w", newline="") as f:
226
- f.write(script)
227
- except OSError as e:
228
- click.echo(f"Failed to write upgrade helper script: {e}", err=True)
229
- return 1
230
-
231
- click.echo(
232
- "Spawning the upgrade in a new console window so dxs can exit and release its files.",
233
- err=True,
234
- )
235
-
236
- CREATE_NEW_CONSOLE = 0x00000010
237
- try:
238
- subprocess.Popen(
239
- ["cmd.exe", "/c", script_path],
240
- creationflags=CREATE_NEW_CONSOLE,
241
- close_fds=True,
242
- )
243
- except OSError as e:
244
- click.echo(f"Failed to spawn upgrade: {e}", err=True)
245
- return 1
246
-
247
- sys.exit(0)
248
-
249
-
250
- def _interactive() -> bool:
251
- """True only when stdin, stderr, and stdout are all attached to a TTY.
252
-
253
- We require stdout TTY too, because piping/redirecting stdout is the strongest
254
- signal that the user is consuming structured output programmatically and
255
- won't appreciate a banner mid-stream.
256
- """
257
- return all(s.isatty() for s in (sys.stdin, sys.stderr, sys.stdout))
258
-
259
-
260
- def maybe_show_update_notice(skip: bool = False) -> None:
261
- """Check the cache and, if a newer version is available, prompt to upgrade.
262
-
263
- Always returns quickly — the network fetch happens in a background thread.
264
-
265
- Args:
266
- skip: If True, skip both the check and any cache refresh. Used to honor
267
- ``--no-update-check``.
268
- """
269
- if skip or is_disabled() or _is_ci():
270
- return
271
- if not _interactive():
272
- return
273
-
274
- cache = _read_cache()
275
- _maybe_refresh_async(cache)
276
-
277
- if not cache:
278
- return
279
-
280
- latest = cache.get("latest")
281
- if not isinstance(latest, str) or not is_newer(latest, __version__):
282
- return
283
-
284
- last_prompted = float(cache.get("last_prompted_at", 0))
285
- if time.time() - last_prompted < PROMPT_DEDUPE_SECONDS:
286
- return
287
-
288
- upgrade_cmd = detect_upgrade_command()
289
- click.echo("", err=True)
290
- click.echo(
291
- f" dxs {latest} is available (you have {__version__})",
292
- err=True,
293
- )
294
- click.echo(f" Upgrade command: {upgrade_cmd}", err=True)
295
-
296
- cache["last_prompted_at"] = time.time()
297
- _write_cache(cache)
298
-
299
- try:
300
- if click.confirm(" Upgrade now?", default=False, err=True):
301
- click.echo(
302
- " After upgrade completes, re-run your dxs command to use the new version.",
303
- err=True,
304
- )
305
- exit_code = _run_upgrade(upgrade_cmd)
306
- # _run_upgrade only returns when the upgrade failed to start.
307
- click.echo(f" Upgrade failed to start (code {exit_code}).", err=True)
308
- except (click.Abort, EOFError):
309
- click.echo("", err=True)
310
- return