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.
- {tabalyst-0.5.0/src/tabalyst.egg-info → tabalyst-0.5.1}/PKG-INFO +9 -7
- {tabalyst-0.5.0 → tabalyst-0.5.1}/README.md +8 -6
- {tabalyst-0.5.0 → tabalyst-0.5.1}/pyproject.toml +1 -1
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/cli/inspect.py +20 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/cli/report.py +12 -1
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/cli/scan.py +9 -3
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/cli/terminal.py +30 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/report_service.py +10 -1
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/paths.py +9 -4
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/service.py +2 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/static/report.js +20 -11
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/templates/column.html +2 -2
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/templates/report.html +2 -2
- {tabalyst-0.5.0 → tabalyst-0.5.1/src/tabalyst.egg-info}/PKG-INFO +9 -7
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_cli.py +2 -2
- {tabalyst-0.5.0 → tabalyst-0.5.1}/LICENSE +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/MANIFEST.in +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/examples/README.md +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/examples/config.json +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/examples/input/basic.csv +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/examples/input/insurance-customers.csv +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/setup.cfg +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/__init__.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/__main__.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/_version.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/batch.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/cache_service.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/cli/__init__.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/cli/app.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/cli/cache.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/cli/sample.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/config.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/errors.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/execution_log.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/inspect_service.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/inspector/__init__.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/inspector/json_inspect/__init__.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/inspector/json_inspect/build.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/inspector/json_inspect/detect.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/inspector/json_inspect/parameters.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/inspector/models.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/inspector/persistence.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/inspector/resolution.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/models.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/progress.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/project_open_service.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/project_scan_service.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/__init__.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_bounded_values.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_cache.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_codec.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_generation.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_locks.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_publication.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_queries.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_query_budget.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_recovery.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_retention.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_schema.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_session.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_staging.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_sync.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/_validation.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/catalog.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/freshness.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/identity.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/index.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/location.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/models.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/projects/store.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/report_config.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/report_profile.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/reporting.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/sampling.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/sampling_service.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scan_reuse.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scan_service.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/__init__.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/api.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/config.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/__init__.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/amount.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/base.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/boolean.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/currency.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/email.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/enumeration.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/ip.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/names.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/number.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/pattern.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/percentage.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/phone.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/postal.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/quantity.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/registry.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/shape.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/temporal.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/url.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/detectors/uuid.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/diagnostics.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/engine.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/exposure.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/field.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/identity.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/measures.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/models.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/normalization.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/observations.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/readers/__init__.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/readers/base.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/readers/csv_reader.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/readers/json_common.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/readers/json_reader.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/readers/jsonl_reader.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/records.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/structure.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/technical.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/values.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/scanner/workers.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/shared_scan_service.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst/static/theme.css +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst.egg-info/SOURCES.txt +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst.egg-info/dependency_links.txt +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst.egg-info/entry_points.txt +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst.egg-info/requires.txt +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/src/tabalyst.egg-info/top_level.txt +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_project_cache.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_project_database.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_project_generations.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_project_identity.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_project_index.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_project_location.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_project_open_service.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_project_queries.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_project_rescan.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_project_scan.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_project_sessions.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_project_store.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_public_api.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_reporting.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_sampling.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_scan_command.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_scanner_amounts.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_scanner_batches.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_scanner_config.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_scanner_csv.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_scanner_email_url.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_scanner_exposure.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_scanner_paths.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_scanner_phone.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_scanner_postal.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_scanner_uuid_ip.py +0 -0
- {tabalyst-0.5.0 → tabalyst-0.5.1}/tests/test_shared_scan_cli.py +0 -0
- {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.
|
|
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
|
|
274
|
-
[
|
|
275
|
-
and
|
|
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/
|
|
332
|
-
and the [scan format](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/
|
|
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/
|
|
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
|
|
238
|
-
[
|
|
239
|
-
and
|
|
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/
|
|
296
|
-
and the [scan format](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/
|
|
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/
|
|
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
|
|
@@ -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
|
|
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
|
|
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=
|
|
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(
|
|
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 =
|
|
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 =
|
|
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
|
|
10
|
-
|
|
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
|
|
13
|
-
themeBtn.setAttribute('aria-label',
|
|
14
|
-
themeBtn.title =
|
|
15
|
-
$$('[data-icon]', themeBtn).forEach((el) => { el.toggleAttribute('hidden', el.dataset.icon !==
|
|
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
|
-
|
|
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
|
|
21
|
-
|
|
22
|
-
try {
|
|
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
|
|
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="
|
|
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
|
|
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="
|
|
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.
|
|
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
|
|
274
|
-
[
|
|
275
|
-
and
|
|
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/
|
|
332
|
-
and the [scan format](https://github.com/loribel-labs/tabalyst/blob/main/docs/en/
|
|
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/
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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
|