tabalyst 0.5.0__tar.gz → 0.5.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.
Files changed (155) hide show
  1. {tabalyst-0.5.0/src/tabalyst.egg-info → tabalyst-0.5.1}/PKG-INFO +9 -7
  2. {tabalyst-0.5.0 → tabalyst-0.5.1}/README.md +8 -6
  3. {tabalyst-0.5.0 → tabalyst-0.5.1}/pyproject.toml +1 -1
  4. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/cli/inspect.py +20 -0
  5. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/cli/report.py +12 -1
  6. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/cli/scan.py +9 -3
  7. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/cli/terminal.py +30 -0
  8. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/report_service.py +10 -1
  9. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/paths.py +9 -4
  10. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/service.py +2 -0
  11. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/static/report.js +20 -11
  12. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/templates/column.html +2 -2
  13. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/templates/report.html +2 -2
  14. {tabalyst-0.5.0 → tabalyst-0.5.1/src/tabalyst.egg-info}/PKG-INFO +9 -7
  15. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_cli.py +2 -2
  16. {tabalyst-0.5.0 → tabalyst-0.5.1}/LICENSE +0 -0
  17. {tabalyst-0.5.0 → tabalyst-0.5.1}/MANIFEST.in +0 -0
  18. {tabalyst-0.5.0 → tabalyst-0.5.1}/examples/README.md +0 -0
  19. {tabalyst-0.5.0 → tabalyst-0.5.1}/examples/config.json +0 -0
  20. {tabalyst-0.5.0 → tabalyst-0.5.1}/examples/input/basic.csv +0 -0
  21. {tabalyst-0.5.0 → tabalyst-0.5.1}/examples/input/insurance-customers.csv +0 -0
  22. {tabalyst-0.5.0 → tabalyst-0.5.1}/setup.cfg +0 -0
  23. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/__init__.py +0 -0
  24. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/__main__.py +0 -0
  25. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/_version.py +0 -0
  26. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/batch.py +0 -0
  27. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/cache_service.py +0 -0
  28. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/cli/__init__.py +0 -0
  29. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/cli/app.py +0 -0
  30. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/cli/cache.py +0 -0
  31. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/cli/sample.py +0 -0
  32. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/config.py +0 -0
  33. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/errors.py +0 -0
  34. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/execution_log.py +0 -0
  35. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/inspect_service.py +0 -0
  36. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/inspector/__init__.py +0 -0
  37. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/inspector/json_inspect/__init__.py +0 -0
  38. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/inspector/json_inspect/build.py +0 -0
  39. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/inspector/json_inspect/detect.py +0 -0
  40. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/inspector/json_inspect/parameters.py +0 -0
  41. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/inspector/models.py +0 -0
  42. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/inspector/persistence.py +0 -0
  43. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/inspector/resolution.py +0 -0
  44. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/models.py +0 -0
  45. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/progress.py +0 -0
  46. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/project_open_service.py +0 -0
  47. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/project_scan_service.py +0 -0
  48. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/__init__.py +0 -0
  49. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_bounded_values.py +0 -0
  50. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_cache.py +0 -0
  51. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_codec.py +0 -0
  52. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_generation.py +0 -0
  53. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_locks.py +0 -0
  54. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_publication.py +0 -0
  55. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_queries.py +0 -0
  56. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_query_budget.py +0 -0
  57. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_recovery.py +0 -0
  58. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_retention.py +0 -0
  59. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_schema.py +0 -0
  60. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_session.py +0 -0
  61. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_staging.py +0 -0
  62. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_sync.py +0 -0
  63. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_validation.py +0 -0
  64. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/catalog.py +0 -0
  65. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/freshness.py +0 -0
  66. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/identity.py +0 -0
  67. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/index.py +0 -0
  68. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/location.py +0 -0
  69. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/models.py +0 -0
  70. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/store.py +0 -0
  71. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/report_config.py +0 -0
  72. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/report_profile.py +0 -0
  73. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/reporting.py +0 -0
  74. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/sampling.py +0 -0
  75. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/sampling_service.py +0 -0
  76. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scan_reuse.py +0 -0
  77. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scan_service.py +0 -0
  78. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/__init__.py +0 -0
  79. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/api.py +0 -0
  80. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/config.py +0 -0
  81. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/__init__.py +0 -0
  82. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/amount.py +0 -0
  83. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/base.py +0 -0
  84. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/boolean.py +0 -0
  85. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/currency.py +0 -0
  86. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/email.py +0 -0
  87. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/enumeration.py +0 -0
  88. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/ip.py +0 -0
  89. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/names.py +0 -0
  90. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/number.py +0 -0
  91. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/pattern.py +0 -0
  92. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/percentage.py +0 -0
  93. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/phone.py +0 -0
  94. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/postal.py +0 -0
  95. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/quantity.py +0 -0
  96. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/registry.py +0 -0
  97. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/shape.py +0 -0
  98. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/temporal.py +0 -0
  99. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/url.py +0 -0
  100. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/uuid.py +0 -0
  101. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/diagnostics.py +0 -0
  102. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/engine.py +0 -0
  103. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/exposure.py +0 -0
  104. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/field.py +0 -0
  105. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/identity.py +0 -0
  106. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/measures.py +0 -0
  107. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/models.py +0 -0
  108. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/normalization.py +0 -0
  109. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/observations.py +0 -0
  110. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/readers/__init__.py +0 -0
  111. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/readers/base.py +0 -0
  112. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/readers/csv_reader.py +0 -0
  113. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/readers/json_common.py +0 -0
  114. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/readers/json_reader.py +0 -0
  115. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/readers/jsonl_reader.py +0 -0
  116. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/records.py +0 -0
  117. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/structure.py +0 -0
  118. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/technical.py +0 -0
  119. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/values.py +0 -0
  120. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/workers.py +0 -0
  121. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/shared_scan_service.py +0 -0
  122. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/static/theme.css +0 -0
  123. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst.egg-info/SOURCES.txt +0 -0
  124. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst.egg-info/dependency_links.txt +0 -0
  125. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst.egg-info/entry_points.txt +0 -0
  126. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst.egg-info/requires.txt +0 -0
  127. {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst.egg-info/top_level.txt +0 -0
  128. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_project_cache.py +0 -0
  129. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_project_database.py +0 -0
  130. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_project_generations.py +0 -0
  131. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_project_identity.py +0 -0
  132. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_project_index.py +0 -0
  133. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_project_location.py +0 -0
  134. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_project_open_service.py +0 -0
  135. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_project_queries.py +0 -0
  136. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_project_rescan.py +0 -0
  137. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_project_scan.py +0 -0
  138. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_project_sessions.py +0 -0
  139. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_project_store.py +0 -0
  140. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_public_api.py +0 -0
  141. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_reporting.py +0 -0
  142. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_sampling.py +0 -0
  143. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_scan_command.py +0 -0
  144. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_scanner_amounts.py +0 -0
  145. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_scanner_batches.py +0 -0
  146. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_scanner_config.py +0 -0
  147. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_scanner_csv.py +0 -0
  148. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_scanner_email_url.py +0 -0
  149. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_scanner_exposure.py +0 -0
  150. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_scanner_paths.py +0 -0
  151. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_scanner_phone.py +0 -0
  152. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_scanner_postal.py +0 -0
  153. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_scanner_uuid_ip.py +0 -0
  154. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_shared_scan_cli.py +0 -0
  155. {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_source_freshness.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tabalyst
3
- Version: 0.5.0
3
+ Version: 0.5.1
4
4
  Summary: Open-source toolkit for understanding and working with unfamiliar data.
5
5
  Author: Gregory Borelli
6
6
  License-Expression: MIT
@@ -270,9 +270,10 @@ Inspect is optional: `tabalyst scan` and `tabalyst report` inspect a JSON file
270
270
  themselves when it has no Inspect file. When several arrays are equally
271
271
  plausible, or none holds objects, they stop with exit code `2` before analyzing
272
272
  anything and list the candidates; set `config.structure.dataset_path` in the
273
- Inspect file, or pass `--collection`. See
274
- [Inspect JSON and JSONL files](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/how-to/inspect-json-files.md)
275
- and the [Inspect format](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/reference/inspect-format.md).
273
+ Inspect file, or pass `--collection` (`--collection customers` or
274
+ `--collection '$.customers[]'`). See
275
+ [Inspect JSON and JSONL files](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/inspect/json.md)
276
+ and the [Inspect format](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/inspect/format.md).
276
277
 
277
278
  ## Tabalyst Scan
278
279
 
@@ -328,8 +329,8 @@ tabalyst cache clean customers.csv
328
329
  `cache clean` leaves project scans and databases in place. Ordinary scans and
329
330
  reports do not create these query caches.
330
331
 
331
- See [Scan CSV and JSON files](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/how-to/scan-files.md)
332
- and the [scan format](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/reference/scan-format.md).
332
+ See [Scan CSV and JSON files](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/scan/files.md)
333
+ and the [scan format](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/scan/format.md).
333
334
 
334
335
  ## What the report analyzes
335
336
 
@@ -452,7 +453,8 @@ Additional documentation:
452
453
 
453
454
  - [Architecture](https://github.com/loribel-labs/tabalyst/blob/main/docs/dev/architecture.md)
454
455
  - [Configuration](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/reference/configuration.md)
455
- - [Inspect JSON and JSONL files](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/how-to/inspect-json-files.md)
456
+ - [Inspect JSON and JSONL files](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/inspect/json.md)
457
+ - [Documentation site](https://docs.tabalyst.com/)
456
458
  - [Release procedure](https://github.com/loribel-labs/tabalyst/blob/main/RELEASING.md)
457
459
 
458
460
  Please report defects and feature requests through the
@@ -234,9 +234,10 @@ Inspect is optional: `tabalyst scan` and `tabalyst report` inspect a JSON file
234
234
  themselves when it has no Inspect file. When several arrays are equally
235
235
  plausible, or none holds objects, they stop with exit code `2` before analyzing
236
236
  anything and list the candidates; set `config.structure.dataset_path` in the
237
- Inspect file, or pass `--collection`. See
238
- [Inspect JSON and JSONL files](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/how-to/inspect-json-files.md)
239
- and the [Inspect format](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/reference/inspect-format.md).
237
+ Inspect file, or pass `--collection` (`--collection customers` or
238
+ `--collection '$.customers[]'`). See
239
+ [Inspect JSON and JSONL files](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/inspect/json.md)
240
+ and the [Inspect format](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/inspect/format.md).
240
241
 
241
242
  ## Tabalyst Scan
242
243
 
@@ -292,8 +293,8 @@ tabalyst cache clean customers.csv
292
293
  `cache clean` leaves project scans and databases in place. Ordinary scans and
293
294
  reports do not create these query caches.
294
295
 
295
- See [Scan CSV and JSON files](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/how-to/scan-files.md)
296
- and the [scan format](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/reference/scan-format.md).
296
+ See [Scan CSV and JSON files](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/scan/files.md)
297
+ and the [scan format](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/scan/format.md).
297
298
 
298
299
  ## What the report analyzes
299
300
 
@@ -416,7 +417,8 @@ Additional documentation:
416
417
 
417
418
  - [Architecture](https://github.com/loribel-labs/tabalyst/blob/main/docs/dev/architecture.md)
418
419
  - [Configuration](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/reference/configuration.md)
419
- - [Inspect JSON and JSONL files](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/how-to/inspect-json-files.md)
420
+ - [Inspect JSON and JSONL files](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/inspect/json.md)
421
+ - [Documentation site](https://docs.tabalyst.com/)
420
422
  - [Release procedure](https://github.com/loribel-labs/tabalyst/blob/main/RELEASING.md)
421
423
 
422
424
  Please report defects and feature requests through the
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tabalyst"
7
- version = "0.5.0"
7
+ version = "0.5.1"
8
8
  description = "Open-source toolkit for understanding and working with unfamiliar data."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -40,6 +40,24 @@ def _configured(success: InspectResult) -> str | None:
40
40
  return f"Configured collection: {chosen} (kept from the existing file)"
41
41
 
42
42
 
43
+ def _choices(success: InspectResult) -> list[str]:
44
+ """Ready-to-run report commands, one per eligible collection, when the
45
+ detection could not choose between them."""
46
+ detection = success.document.detection
47
+ if detection.selection.basis != "ambiguous":
48
+ return []
49
+ source = str(success.source)
50
+ if " " in source:
51
+ source = f'"{source}"'
52
+ lines = ["Choose the collection to analyze:"]
53
+ lines.extend(
54
+ f" tabalyst report {source} --collection '{candidate.path}'"
55
+ for candidate in detection.candidates
56
+ if candidate.eligible
57
+ )
58
+ return lines
59
+
60
+
43
61
  def _print_success(success: InspectResult, *, verbose: bool) -> None:
44
62
  typer.echo(f"Inspect: {success.path.resolve()}", err=True)
45
63
  typer.echo(_selection(success), err=True)
@@ -81,6 +99,8 @@ def _print_batch_result(
81
99
  for warning in success.document.warnings:
82
100
  if warning.level == "warning" or verbose:
83
101
  typer.echo(f"Warning [{success.source}]: {warning.message}", err=True)
102
+ for line in _choices(success):
103
+ typer.echo(line, err=True)
84
104
  for failure in batch.failures:
85
105
  typer.echo(f"Error [{failure.job.source}]: {failure.error}", err=True)
86
106
 
@@ -6,7 +6,13 @@ from typing import Annotated
6
6
 
7
7
  import typer
8
8
 
9
- from tabalyst.cli.terminal import ProgressPrinter, batch_exit_code, error_exit_code
9
+ from tabalyst.cli.terminal import (
10
+ COLLECTION_HELP,
11
+ ProgressPrinter,
12
+ batch_exit_code,
13
+ collection_paths,
14
+ error_exit_code,
15
+ )
10
16
  from tabalyst.errors import TabalystError
11
17
  from tabalyst.report_service import BatchReportResult, ReportSuccess, generate_reports
12
18
 
@@ -116,6 +122,10 @@ def report_command(
116
122
  Path | None,
117
123
  typer.Option("--config", "-c", help="JSON configuration file."),
118
124
  ] = None,
125
+ collection: Annotated[
126
+ list[str] | None,
127
+ typer.Option("--collection", help=COLLECTION_HELP),
128
+ ] = None,
119
129
  from_scan: Annotated[
120
130
  bool,
121
131
  typer.Option(
@@ -178,6 +188,7 @@ def report_command(
178
188
  output_dir=output_dir,
179
189
  separator=delimiter,
180
190
  encoding=encoding,
191
+ collections=collection_paths(collection),
181
192
  config_path=config,
182
193
  force=force,
183
194
  details=details,
@@ -6,7 +6,13 @@ from typing import Annotated
6
6
 
7
7
  import typer
8
8
 
9
- from tabalyst.cli.terminal import ProgressPrinter, batch_exit_code, error_exit_code
9
+ from tabalyst.cli.terminal import (
10
+ COLLECTION_HELP,
11
+ ProgressPrinter,
12
+ batch_exit_code,
13
+ collection_paths,
14
+ error_exit_code,
15
+ )
10
16
  from tabalyst.errors import TabalystError
11
17
  from tabalyst.scan_service import BatchScanResult, ScanSuccess, generate_scans
12
18
 
@@ -124,7 +130,7 @@ def scan_command(
124
130
  list[str] | None,
125
131
  typer.Option(
126
132
  "--collection",
127
- help="JSON collection path such as '$.customers[]'; repeatable.",
133
+ help=COLLECTION_HELP,
128
134
  ),
129
135
  ] = None,
130
136
  delimiter: Annotated[
@@ -178,7 +184,7 @@ def scan_command(
178
184
  config_path=config,
179
185
  delimiter=delimiter,
180
186
  encoding=encoding,
181
- collections=collection,
187
+ collections=collection_paths(collection),
182
188
  force=force,
183
189
  on_progress=progress,
184
190
  workers=workers,
@@ -7,6 +7,36 @@ import typer
7
7
 
8
8
  from tabalyst.errors import ConfigurationError, InputError, TabalystError
9
9
  from tabalyst.progress import ProgressEvent, ProgressPhase
10
+ from tabalyst.scanner.paths import ITEMS, format_absolute, parse_path
11
+
12
+ COLLECTION_HELP = (
13
+ "JSON collection: an array path such as '$.data.items[]', or its short "
14
+ "form data.items; repeatable."
15
+ )
16
+
17
+
18
+ def collection_paths(values: list[str] | None) -> list[str] | None:
19
+ """``--collection`` values as absolute paths. Without the leading ``$``, the
20
+ value is the keys leading to the array, so ``data.items`` is
21
+ ``$.data.items[]``, and ``.`` is the root array, ``$[]``; a collection is always an array, so ``[]`` is implied."""
22
+ if values is None:
23
+ return None
24
+ paths = []
25
+ for value in values:
26
+ if value.startswith("$"):
27
+ paths.append(value)
28
+ continue
29
+ if value == ".":
30
+ paths.append(format_absolute((ITEMS,)))
31
+ continue
32
+ try:
33
+ path = parse_path(value, numeric_keys=True)
34
+ except ValueError as exc:
35
+ raise typer.BadParameter(str(exc), param_hint="--collection") from exc
36
+ if not path or path[-1] != ITEMS:
37
+ path = (*path, ITEMS)
38
+ paths.append(format_absolute(path))
39
+ return paths
10
40
 
11
41
 
12
42
  def error_exit_code(error: TabalystError) -> int:
@@ -174,6 +174,7 @@ def generate_reports(
174
174
  output_dir: str | Path | None = None,
175
175
  separator: str | None = None,
176
176
  encoding: str | None = None,
177
+ collections: Sequence[str] | None = None,
177
178
  config_path: ConfigPath | None = None,
178
179
  force: bool = False,
179
180
  details: bool = False,
@@ -186,7 +187,9 @@ def generate_reports(
186
187
  With ``from_scan``, the inputs are scan documents written by
187
188
  ``tabalyst scan``: each report is built from its document without reading
188
189
  the source again, after the staleness checks of ``tabalyst.scan_reuse``.
189
- Otherwise ``workers`` is passed to ``tabalyst.scan()``.
190
+ Otherwise ``workers`` is passed to ``tabalyst.scan()``, and ``collections``
191
+ (absolute paths such as ``$.products[]``) choose the JSON collections to
192
+ analyze, over the Inspect file and the configuration.
190
193
  Set ``details=True`` to write a standalone HTML page for each column.
191
194
  """
192
195
  if from_scan and (separator is not None or encoding is not None):
@@ -199,6 +202,11 @@ def generate_reports(
199
202
  "--workers cannot be used with --scan: the report reads the scan "
200
203
  "document, not its source."
201
204
  )
205
+ if from_scan and collections:
206
+ raise ConfigurationError(
207
+ "--collection cannot be used with --scan: the scan document records "
208
+ "which collection it analyzed."
209
+ )
202
210
  plan = build_report_plan(
203
211
  input_specs,
204
212
  output=output,
@@ -265,6 +273,7 @@ def generate_reports(
265
273
  scan_layer=report_scan_layer,
266
274
  separator=separator,
267
275
  encoding=encoding,
276
+ collections=collections,
268
277
  )
269
278
  except TabalystError as exc:
270
279
  failures.append(ReportFailure(job=job, error=exc))
@@ -41,6 +41,7 @@ ROOT: FieldPath = ()
41
41
  ROOT_DISPLAY = "$"
42
42
 
43
43
  _IDENTIFIER = re.compile(r"[A-Za-z_][A-Za-z0-9_]*")
44
+ _NUMERIC_KEY = re.compile(r"[A-Za-z0-9_]+")
44
45
  _DECODER = json.JSONDecoder()
45
46
 
46
47
 
@@ -92,19 +93,23 @@ def format_relative(path: FieldPath, separator: str = ".") -> str:
92
93
  return _segments_display(path, leading=True, separator=separator)
93
94
 
94
95
 
95
- def parse_path(text: str, *, separator: str = ".") -> FieldPath:
96
+ def parse_path(
97
+ text: str, *, separator: str = ".", numeric_keys: bool = False
98
+ ) -> FieldPath:
96
99
  """Parse the absolute (``$...``) or relative display syntax into segments.
97
100
 
98
101
  ``separator`` applies to relative texts only: an absolute path (starting
99
- with ``$``) always uses ``.``.
102
+ with ``$``) always uses ``.``. With ``numeric_keys``, a bare key may start
103
+ with a digit, such as ``categories.121``.
100
104
  """
105
+ key = _NUMERIC_KEY if numeric_keys else _IDENTIFIER
101
106
  position = 0
102
107
  segments: list[Segment] = []
103
108
  if text.startswith(ROOT_DISPLAY):
104
109
  position = 1
105
110
  separator = "."
106
111
  elif text:
107
- identifier = _IDENTIFIER.match(text)
112
+ identifier = key.match(text)
108
113
  if identifier is not None:
109
114
  segments.append(Key(identifier.group()))
110
115
  position = identifier.end()
@@ -116,7 +121,7 @@ def parse_path(text: str, *, separator: str = ".") -> FieldPath:
116
121
  while position < len(text):
117
122
  if text.startswith(separator, position):
118
123
  start = position + len(separator)
119
- identifier = _IDENTIFIER.match(text, start)
124
+ identifier = key.match(text, start)
120
125
  if identifier is None:
121
126
  raise ValueError(
122
127
  f"Invalid path {text!r}: expected a key at position {start}"
@@ -228,6 +228,7 @@ def _analyze_resolved(
228
228
  scan_layer: dict | None = None,
229
229
  separator: str | None = None,
230
230
  encoding: str | None = None,
231
+ collections: Sequence[str] | None = None,
231
232
  ) -> tuple[dict[str, Any], tuple[str, ...]]:
232
233
  started = perf_counter()
233
234
  json_report, execution_report = _validate_paths(
@@ -251,6 +252,7 @@ def _analyze_resolved(
251
252
  interpretation = resolve_interpretation(
252
253
  source,
253
254
  scan_layer=scan_layer,
255
+ collections=collections,
254
256
  delimiter=separator,
255
257
  encoding=encoding,
256
258
  )
@@ -4,22 +4,31 @@
4
4
  const $ = (s, c = document) => c.querySelector(s);
5
5
  const $$ = (s, c = document) => Array.from(c.querySelectorAll(s));
6
6
 
7
- /* theme */
7
+ /* theme: auto (system preference) -> light -> dark */
8
8
  const themeBtn = $('#theme-toggle');
9
- const setTheme = (t) => {
10
- root.dataset.theme = t;
9
+ const modes = ['auto', 'light', 'dark'];
10
+ const media = window.matchMedia ? window.matchMedia('(prefers-color-scheme: light)') : null;
11
+ const setMode = (m) => {
12
+ root.dataset.themeMode = m;
13
+ root.dataset.theme = m === 'auto' ? (media && media.matches ? 'light' : 'dark') : m;
11
14
  if (themeBtn) {
12
- const next = t === 'dark' ? 'light' : 'dark';
13
- themeBtn.setAttribute('aria-label', 'Switch to ' + next + ' theme');
14
- themeBtn.title = 'Switch to ' + next + ' theme';
15
- $$('[data-icon]', themeBtn).forEach((el) => { el.toggleAttribute('hidden', el.dataset.icon !== t); });
15
+ const label = 'Theme: ' + (m === 'auto' ? 'auto (system)' : m) + '. Click to change.';
16
+ themeBtn.setAttribute('aria-label', label);
17
+ themeBtn.title = label;
18
+ $$('[data-icon]', themeBtn).forEach((el) => { el.toggleAttribute('hidden', el.dataset.icon !== m); });
16
19
  }
17
20
  };
18
- setTheme(root.dataset.theme || 'dark');
21
+ setMode(root.dataset.themeMode || 'auto');
22
+ media && media.addEventListener && media.addEventListener('change', () => {
23
+ if (root.dataset.themeMode === 'auto') setMode('auto');
24
+ });
19
25
  themeBtn && themeBtn.addEventListener('click', () => {
20
- const t = root.dataset.theme === 'dark' ? 'light' : 'dark';
21
- setTheme(t);
22
- try { localStorage.setItem('tabalyst-theme', t); } catch (e) { /* storage unavailable */ }
26
+ const m = modes[(modes.indexOf(root.dataset.themeMode) + 1) % modes.length];
27
+ setMode(m);
28
+ try {
29
+ if (m === 'auto') localStorage.removeItem('tabalyst-theme');
30
+ else localStorage.setItem('tabalyst-theme', m);
31
+ } catch (e) { /* storage unavailable */ }
23
32
  });
24
33
 
25
34
  /* print: show every section */
@@ -8,7 +8,7 @@
8
8
  <meta name="generator" content="Tabalyst column report">
9
9
  <meta name="theme-color" content="#00051A">
10
10
  <link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2064%2064'%3E%3Crect%20width='64'%20height='64'%20rx='14'%20fill='%2300051a'/%3E%3Cpath%20d='M14%2015h36v10H37v25H27V25H14z'%20fill='%23f98510'/%3E%3C/svg%3E">
11
- <script>(()=>{let t="dark";try{const s=localStorage.getItem("tabalyst-theme");if(s==="light"||s==="dark")t=s}catch(e){}document.documentElement.dataset.theme=t})();</script>
11
+ <script>(()=>{let m="auto";try{const s=localStorage.getItem("tabalyst-theme");if(s==="light"||s==="dark")m=s}catch(e){}const r=document.documentElement;r.dataset.themeMode=m;r.dataset.theme=m==="auto"?(window.matchMedia&&matchMedia("(prefers-color-scheme: light)").matches?"light":"dark"):m})();</script>
12
12
  <style>{{ theme_css | safe }}</style>
13
13
  </head>
14
14
  <body>
@@ -32,7 +32,7 @@
32
32
  <p class="side-group">Navigation</p>
33
33
  <a class="rep-tab" href="{{ report_href }}"><small>↖</small>Full report</a>
34
34
  </nav>
35
- <div class="side-foot"><div class="row"><button type="button" id="theme-toggle" class="btn btn-icon" aria-label="Switch to light theme" title="Switch to light theme"><svg data-icon="dark" viewBox="0 0 16 16" aria-hidden="true"><circle cx="8" cy="8" r="3"/><path d="M8 1.5v1.5M8 13v1.5M1.5 8H3M13 8h1.5M3.4 3.4l1 1M11.6 11.6l1 1M3.4 12.6l1-1M11.6 4.4l1-1"/></svg><svg data-icon="light" viewBox="0 0 16 16" aria-hidden="true" hidden><path d="M13.5 9.5A5.5 5.5 0 0 1 6.5 2.5a5.5 5.5 0 1 0 7 7z"/></svg></button><button type="button" class="btn print" data-print style="flex:1">Print / PDF</button></div></div>
35
+ <div class="side-foot"><div class="row"><button type="button" id="theme-toggle" class="btn btn-icon" aria-label="Theme: auto (system)" title="Theme: auto (system)"><svg data-icon="auto" viewBox="0 0 16 16" aria-hidden="true"><rect x="2" y="2.5" width="12" height="8.5" rx="1"/><path d="M5.5 14h5M8 11v3"/></svg><svg data-icon="light" viewBox="0 0 16 16" aria-hidden="true" hidden><circle cx="8" cy="8" r="3"/><path d="M8 1.5v1.5M8 13v1.5M1.5 8H3M13 8h1.5M3.4 3.4l1 1M11.6 11.6l1 1M3.4 12.6l1-1M11.6 4.4l1-1"/></svg><svg data-icon="dark" viewBox="0 0 16 16" aria-hidden="true" hidden><path d="M13.5 9.5A5.5 5.5 0 0 1 6.5 2.5a5.5 5.5 0 1 0 7 7z"/></svg></button><button type="button" class="btn print" data-print style="flex:1">Print / PDF</button></div></div>
36
36
  </aside>
37
37
  <div class="main"><div class="ds" data-ds="0">
38
38
  <header class="rhead"><div class="wrap"><p class="eyebrow">Column report · {{ report.source.filename }}{% if report.source.format in ('json', 'jsonl') %} · {{ ds.id }}{% endif %}</p><div class="rhead-top"><div><h1>{{ column.name or '(unnamed)' }}</h1><ul class="facts"><li><b>Column {{ column.position }}</b> of {{ ds.summary.column_count }}</li><li><code>{{ column.path }}</code></li><li>{{ ds.summary.row_count | count }} {{ 'records' if report.source.format in ('json', 'jsonl') else 'rows' }}</li></ul></div><a class="btn" href="{{ report_href }}">← Full report</a></div></div></header>
@@ -7,7 +7,7 @@
7
7
  <meta name="description" content="Tabalyst profiling report for {{ report.source.filename }}">
8
8
  <meta name="theme-color" content="#00051A">
9
9
  <link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2064%2064'%3E%3Crect%20width='64'%20height='64'%20rx='14'%20fill='%2300051a'/%3E%3Cpath%20d='M14%2015h36v10H37v25H27V25H14z'%20fill='%23f98510'/%3E%3C/svg%3E">
10
- <script>(()=>{let t="dark";try{const s=localStorage.getItem("tabalyst-theme");if(s==="light"||s==="dark")t=s}catch(e){}document.documentElement.dataset.theme=t})();</script>
10
+ <script>(()=>{let m="auto";try{const s=localStorage.getItem("tabalyst-theme");if(s==="light"||s==="dark")m=s}catch(e){}const r=document.documentElement;r.dataset.themeMode=m;r.dataset.theme=m==="auto"?(window.matchMedia&&matchMedia("(prefers-color-scheme: light)").matches?"light":"dark"):m})();</script>
11
11
  <style>{{ theme_css | safe }}</style>
12
12
  </head>
13
13
  <body>
@@ -77,7 +77,7 @@
77
77
  {% endfor %}
78
78
  <div class="side-foot">
79
79
  <button type="button" class="btn reset-all" id="reset-all" hidden><svg viewBox="0 0 16 16" aria-hidden="true"><path d="M3 8a5 5 0 1 0 1.5-3.5M3 2.5V5h2.5"/></svg>Reset all filters<span class="c" id="reset-all-count"></span></button>
80
- <div class="row"><button type="button" id="theme-toggle" class="btn btn-icon" aria-label="Switch to light theme" title="Switch to light theme"><svg data-icon="dark" viewBox="0 0 16 16" aria-hidden="true"><circle cx="8" cy="8" r="3"/><path d="M8 1.5v1.5M8 13v1.5M1.5 8H3M13 8h1.5M3.4 3.4l1 1M11.6 11.6l1 1M3.4 12.6l1-1M11.6 4.4l1-1"/></svg><svg data-icon="light" viewBox="0 0 16 16" aria-hidden="true" hidden><path d="M13.5 9.5A5.5 5.5 0 0 1 6.5 2.5a5.5 5.5 0 1 0 7 7z"/></svg></button><button type="button" class="btn print" data-print style="flex:1"><svg viewBox="0 0 16 16" aria-hidden="true"><path d="M4 6V2h8v4M4 12H2.5V6.5h11V12H12M4 10h8v4H4z"/></svg>Print / PDF</button></div>
80
+ <div class="row"><button type="button" id="theme-toggle" class="btn btn-icon" aria-label="Theme: auto (system)" title="Theme: auto (system)"><svg data-icon="auto" viewBox="0 0 16 16" aria-hidden="true"><rect x="2" y="2.5" width="12" height="8.5" rx="1"/><path d="M5.5 14h5M8 11v3"/></svg><svg data-icon="light" viewBox="0 0 16 16" aria-hidden="true" hidden><circle cx="8" cy="8" r="3"/><path d="M8 1.5v1.5M8 13v1.5M1.5 8H3M13 8h1.5M3.4 3.4l1 1M11.6 11.6l1 1M3.4 12.6l1-1M11.6 4.4l1-1"/></svg><svg data-icon="dark" viewBox="0 0 16 16" aria-hidden="true" hidden><path d="M13.5 9.5A5.5 5.5 0 0 1 6.5 2.5a5.5 5.5 0 1 0 7 7z"/></svg></button><button type="button" class="btn print" data-print style="flex:1"><svg viewBox="0 0 16 16" aria-hidden="true"><path d="M4 6V2h8v4M4 12H2.5V6.5h11V12H12M4 10h8v4H4z"/></svg>Print / PDF</button></div>
81
81
  </div>
82
82
  </aside>
83
83
  <div class="main">
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tabalyst
3
- Version: 0.5.0
3
+ Version: 0.5.1
4
4
  Summary: Open-source toolkit for understanding and working with unfamiliar data.
5
5
  Author: Gregory Borelli
6
6
  License-Expression: MIT
@@ -270,9 +270,10 @@ Inspect is optional: `tabalyst scan` and `tabalyst report` inspect a JSON file
270
270
  themselves when it has no Inspect file. When several arrays are equally
271
271
  plausible, or none holds objects, they stop with exit code `2` before analyzing
272
272
  anything and list the candidates; set `config.structure.dataset_path` in the
273
- Inspect file, or pass `--collection`. See
274
- [Inspect JSON and JSONL files](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/how-to/inspect-json-files.md)
275
- and the [Inspect format](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/reference/inspect-format.md).
273
+ Inspect file, or pass `--collection` (`--collection customers` or
274
+ `--collection '$.customers[]'`). See
275
+ [Inspect JSON and JSONL files](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/inspect/json.md)
276
+ and the [Inspect format](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/inspect/format.md).
276
277
 
277
278
  ## Tabalyst Scan
278
279
 
@@ -328,8 +329,8 @@ tabalyst cache clean customers.csv
328
329
  `cache clean` leaves project scans and databases in place. Ordinary scans and
329
330
  reports do not create these query caches.
330
331
 
331
- See [Scan CSV and JSON files](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/how-to/scan-files.md)
332
- and the [scan format](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/reference/scan-format.md).
332
+ See [Scan CSV and JSON files](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/scan/files.md)
333
+ and the [scan format](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/scan/format.md).
333
334
 
334
335
  ## What the report analyzes
335
336
 
@@ -452,7 +453,8 @@ Additional documentation:
452
453
 
453
454
  - [Architecture](https://github.com/loribel-labs/tabalyst/blob/main/docs/dev/architecture.md)
454
455
  - [Configuration](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/reference/configuration.md)
455
- - [Inspect JSON and JSONL files](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/how-to/inspect-json-files.md)
456
+ - [Inspect JSON and JSONL files](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/inspect/json.md)
457
+ - [Documentation site](https://docs.tabalyst.com/)
456
458
  - [Release procedure](https://github.com/loribel-labs/tabalyst/blob/main/RELEASING.md)
457
459
 
458
460
  Please report defects and feature requests through the
@@ -16,7 +16,7 @@ def _isolated_project_home(tmp_path, monkeypatch):
16
16
 
17
17
 
18
18
  def test_source_checkout_reports_pyproject_version():
19
- assert tabalyst_version() == "0.5.0"
19
+ assert tabalyst_version() == "0.5.1"
20
20
 
21
21
 
22
22
  def test_root_help_and_version_describe_the_toolkit():
@@ -27,7 +27,7 @@ def test_root_help_and_version_describe_the_toolkit():
27
27
 
28
28
  version_result = runner.invoke(app, ["--version"])
29
29
  assert version_result.exit_code == 0
30
- assert version_result.output.strip() == "0.5.0"
30
+ assert version_result.output.strip() == "0.5.1"
31
31
 
32
32
 
33
33
  def test_report_generates_html_json_and_history(tmp_path):
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes