tabalyst 0.7.2__tar.gz → 0.7.4__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.7.2/src/tabalyst.egg-info → tabalyst-0.7.4}/PKG-INFO +7 -2
- {tabalyst-0.7.2 → tabalyst-0.7.4}/README.md +6 -1
- {tabalyst-0.7.2 → tabalyst-0.7.4}/pyproject.toml +1 -1
- tabalyst-0.7.4/src/tabalyst/cli/generate.py +190 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/cli/sample.py +45 -3
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_anomalies.py +8 -1
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_computer.py +39 -17
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_computer_output.py +71 -23
- tabalyst-0.7.4/src/tabalyst/generate_computer_parallel.py +184 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_selection.py +170 -53
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_service.py +228 -70
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/sampling.py +154 -26
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/sampling_service.py +9 -2
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/render.py +2 -2
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/stratification.py +5 -8
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/stratmodels.py +2 -2
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/stratify.py +40 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4/src/tabalyst.egg-info}/PKG-INFO +7 -2
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst.egg-info/SOURCES.txt +3 -0
- tabalyst-0.7.4/tests/test_generate_computer_parallel.py +115 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_generate_computer_service.py +263 -0
- tabalyst-0.7.4/tests/test_sampling_stratified_balanced.py +292 -0
- tabalyst-0.7.2/src/tabalyst/cli/generate.py +0 -106
- {tabalyst-0.7.2 → tabalyst-0.7.4}/LICENSE +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/MANIFEST.in +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/examples/README.md +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/examples/config.json +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/examples/datasets/basic.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/examples/datasets/insurance-customers.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/examples/generate/README.md +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/examples/generate/cohorts-anomalies/catalog.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/examples/generate/cohorts-anomalies/dataset.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/examples/generate/cohorts-anomalies/schemas/accounts.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/examples/generate/cohorts-anomalies/schemas/contacts.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/examples/generate/common-references/catalog.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/examples/generate/common-references/dataset.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/examples/generate/common-references/schemas/contacts.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/examples/generate/generate_examples.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/setup.cfg +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/__init__.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/__main__.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/_version.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/batch.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/cache_service.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/cli/__init__.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/cli/app.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/cli/cache.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/cli/confirm.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/cli/dedup.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/cli/inspect.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/cli/report.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/cli/scan.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/cli/terminal.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/config.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/csv_records.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/dedup/__init__.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/dedup/analysis.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/dedup/batch_report.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/dedup/cache.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/dedup/calculation.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/dedup/count_only.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/dedup/discovery.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/dedup/diskstore.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/dedup/failures.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/dedup/groups.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/dedup/identity.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/dedup/pipeline.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/dedup/publish.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/dedup/report.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/dedup/settings.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/dedup/store.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/dedup/tiered.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/dedup/writer.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/dedup_service.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/deep_service.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/deep_store.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/errors.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/execution_log.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_columns_package.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_csv.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_definition.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/SOURCES.md +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/catalog.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/brand.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/color.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/computer_type.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/computer_type_form_factor.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/computer_type_product_segment.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/cpu.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/cpu_memory_weight.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/cpu_operating_system.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/display.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/extended_specs.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/form_factor.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/generation_color.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/generation_cpu.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/generation_display.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/generation_gpu.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/generation_memory.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/generation_operating_system.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/generation_profile.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/generation_profile_computer_type.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/generation_profile_segment.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/generation_storage.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/gpu.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/gpu_display.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/gpu_memory_weight.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/gpu_storage_weight.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/memory.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/model_form_factor.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/model_generation.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/operating_system.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/product_category.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/product_family.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/product_family_computer_type.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/product_family_product_segment.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/product_model.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/product_segment.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/product_segment_brand.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/product_segment_display_weight.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/product_segment_memory_weight.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/product_segment_storage_weight.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/product_subcategory.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/profile_exclusions.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/promotion_status.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/promotion_type.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/seller.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/seller_type.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/shipping_availability.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/standard_specs.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/storage.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/data/warehouse.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/dataset.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/computer_type.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/computer_type_form_factor.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/computer_type_product_segment.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/computers.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/cpu.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/cpu_memory_weight.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/cpu_operating_system.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/display.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/extended_specs.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/generation_color.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/generation_cpu.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/generation_display.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/generation_gpu.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/generation_memory.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/generation_operating_system.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/generation_profile.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/generation_profile_computer_type.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/generation_profile_segment.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/generation_storage.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/gpu.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/gpu_display.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/gpu_memory_weight.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/gpu_storage_weight.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/localized.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/memory.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/model_form_factor.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/model_generation.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/operating_system.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/product_family.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/product_family_computer_type.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/product_family_product_segment.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/product_model.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/product_segment.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/product_segment_brand.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/product_segment_display_weight.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/product_segment_memory_weight.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/product_segment_storage_weight.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/product_subcategory.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/profile_exclusions.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/seller.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/standard_specs.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/storage.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/computer/schemas/warehouse.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/crm/catalog.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/crm/dataset.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/crm/schemas/accounts.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/crm/schemas/contacts.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/insurance/SOURCES.md +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/insurance/catalog.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/insurance/data/agencies.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/insurance/data/branch_contract_weights.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/insurance/data/claim_statuses.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/insurance/data/contract_statuses.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/insurance/data/contract_types.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/insurance/data/payment_frequencies.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/insurance/data/payment_methods.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/insurance/dataset.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/insurance/schemas/agencies.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/insurance/schemas/branch_contract_weights.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/insurance/schemas/claim_statuses.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/insurance/schemas/contract_statuses.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/insurance/schemas/contract_types.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/insurance/schemas/customers.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/insurance/schemas/payment_frequencies.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_examples/insurance/schemas/payment_methods.yaml +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_insurance.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_package.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_references.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_resources/SOURCES.md +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_resources/addresses/street_directions_ca.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_resources/addresses/street_names_ca.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_resources/addresses/street_types_ca.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_resources/addresses/unit_types_ca.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_resources/contact/email_patterns.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_resources/contact/email_providers_ca.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_resources/contact/phone_area_codes_ca.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_resources/geography/cities_ca.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_resources/geography/postal_prefixes_ca.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_resources/geography/provinces_ca.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_resources/people/family_names_ca.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_resources/people/first_names_en_ca.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_resources/people/first_names_fr_qc.csv +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/generate_values.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/identifier_uniqueness/__init__.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/identifier_uniqueness/facts.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/identifier_uniqueness/models.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/identifier_uniqueness/near_unique.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/identifier_uniqueness/proof.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/identifier_uniqueness/rule.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/inspect_service.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/inspector/__init__.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/inspector/choices.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/inspector/excel_inspect/__init__.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/inspector/excel_inspect/build.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/inspector/excel_inspect/detect.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/inspector/excel_inspect/parameters.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/inspector/json_inspect/__init__.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/inspector/json_inspect/build.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/inspector/json_inspect/detect.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/inspector/json_inspect/parameters.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/inspector/models.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/inspector/persistence.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/inspector/resolution.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/json_text.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/models.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/option_notices.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/plan_service.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/progress.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/project_open_service.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/project_scan_service.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/projects/__init__.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/projects/_bounded_values.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/projects/_cache.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/projects/_codec.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/projects/_generation.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/projects/_locks.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/projects/_publication.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/projects/_queries.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/projects/_query_budget.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/projects/_recovery.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/projects/_retention.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/projects/_schema.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/projects/_session.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/projects/_staging.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/projects/_sync.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/projects/_validation.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/projects/catalog.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/projects/freshness.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/projects/identity.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/projects/index.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/projects/location.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/projects/models.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/projects/store.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/report_chain.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/report_classification.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/report_column_page.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/report_config.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/report_deep.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/report_details.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/report_finding_details.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/report_findings.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/report_insights.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/report_labels.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/report_measures.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/report_overview.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/report_plan.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/report_preview.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/report_profile.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/report_relations.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/report_schema.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/report_sections.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/report_service.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/report_signals.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/report_summary.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/report_table.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/report_uniqueness.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/report_views.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/reporting.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/result_model.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/sample_page.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scan_document.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scan_page.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scan_reuse.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scan_service.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/__init__.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/api.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/bottomk.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/cases.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/charactermap.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/characters.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/classify/__init__.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/classify/candidates.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/classify/catalog.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/classify/identifiers.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/classify/models.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/classify/names.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/classify/rules.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/config.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/convention_rule.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/correlation_ratio.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/crosstab.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/detectors/__init__.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/detectors/amount.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/detectors/base.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/detectors/boolean.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/detectors/currency.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/detectors/email.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/detectors/enumeration.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/detectors/ip.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/detectors/keys.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/detectors/names.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/detectors/number.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/detectors/pattern.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/detectors/percentage.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/detectors/phone.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/detectors/postal.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/detectors/quantity.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/detectors/registry.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/detectors/shape.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/detectors/temporal.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/detectors/url.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/detectors/uuid.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/diagnostics.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/engine.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/exposure.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/features.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/field.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/identity.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/lengthsample.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/longtext.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/measures.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/memory.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/models.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/normalization.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/observations.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/paths.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/pattern_eligibility.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/patternfacets.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/patterninfer.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/patterntree.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/pearson.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/__init__.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzer.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzers/__init__.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzers/analytical.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzers/characters.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzers/common.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzers/copies.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzers/crosstab.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzers/date_order.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzers/distinct.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzers/drift.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzers/duplicates.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzers/forms.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzers/frequencies.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzers/histogram.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzers/lengths.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzers/matrix.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzers/measures.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzers/missing_copies.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzers/parts.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzers/patterns.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzers/pearson.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzers/residuals.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzers/shape.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzers/stats.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzers/structure.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzers/temporal.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/analyzers/texts.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/categorystats.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/costmodel.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/crosstabs.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/facts.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/identifiers.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/models.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/orders.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/planner.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/reasons.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/registry.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/relations.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/samplerows.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/planner/secondpass.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/process.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/quality.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/rankcorr.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/readers/__init__.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/readers/base.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/readers/csv_reader.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/readers/excel_common.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/readers/excel_reader.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/readers/excel_table.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/readers/factory.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/readers/json_common.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/readers/json_reader.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/readers/jsonl_reader.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/records.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/rowsample.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/schema.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/__init__.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/accumulators.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/analytical.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/bins.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/boundaries.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/characters.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/copies.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/crosstab.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/document.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/drift.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/duplicates.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/exactset.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/executor.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/forms.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/frequencies.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/matrix.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/measures.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/missing_copies.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/models.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/orders.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/parallel.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/parts.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/patternreader.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/patterns.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/pearson.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/periods.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/ranks.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/replay.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/residuals.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/routing.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/schema.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/shape.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/stats.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/structure.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/secondpass/texts.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/smart/__init__.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/smart/bins.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/smart/estimate.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/smart/evaluate.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/smart/execute.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/smart/models.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/smart/near.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/smart/plan.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/smart/reasons.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/smart/render.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/smart/result.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/smart/select.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/smart/targets.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/smart/weights.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/structure.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/technical.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/validation.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/values.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/valuesample.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/scanner/workers.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/schemas/tabalyst.dedup.batch.schema.json +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/schemas/tabalyst.dedup.schema.json +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/schemas/tabalyst.report.schema.json +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/schemas/tabalyst.sample.schema.json +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/schemas/tabalyst.scan.deep.schema.json +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/schemas/tabalyst.scan.schema.json +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/service.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/shared_scan_service.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/smart_service.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/source_guard.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/static/report.js +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/static/theme.css +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/summary_models.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/templates/characters.html +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/templates/column.html +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/templates/insights.html +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/templates/patterns.html +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/templates/report.html +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst/templates/sample.html +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst.egg-info/dependency_links.txt +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst.egg-info/entry_points.txt +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst.egg-info/requires.txt +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/src/tabalyst.egg-info/top_level.txt +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_all_collections.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_cli.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_csv_records.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_examples_index.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_examples_layout.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_generate.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_generate_anomalies.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_generate_anomalies_regression.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_generate_computer_catalog.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_generate_computer_components.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_generate_computer_derivations.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_generate_computer_hierarchy.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_generate_computer_output.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_generate_crm.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_generate_crm_package.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_generate_insurance.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_generate_insurance_stress.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_generate_lot4.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_generate_package.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_generate_references.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_generate_selection.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_json_text.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_license_headers.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_make_datasets.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_option_notices.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_project_cache.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_project_database.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_project_generations.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_project_identity.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_project_index.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_project_location.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_project_open_service.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_project_queries.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_project_rescan.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_project_scan.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_project_scan_model.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_project_sessions.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_project_store.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_public_api.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_report_contrast.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_reporting.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_sampling.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_scan_command.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_scanner_amounts.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_scanner_batches.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_scanner_config.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_scanner_csv.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_scanner_email_url.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_scanner_exposure.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_scanner_paths.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_scanner_phone.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_scanner_postal.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_scanner_uuid_ip.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_shared_scan_cli.py +0 -0
- {tabalyst-0.7.2 → tabalyst-0.7.4}/tests/test_source_freshness.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tabalyst
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.4
|
|
4
4
|
Summary: Open-source toolkit for understanding and working with unfamiliar data.
|
|
5
5
|
Author: Gregory Borelli
|
|
6
6
|
License-Expression: MPL-2.0
|
|
@@ -280,10 +280,15 @@ tabalyst generate --example crm -o crm-contacts.csv
|
|
|
280
280
|
tabalyst generate --example insurance --rows 3000 -d insurance-output/
|
|
281
281
|
tabalyst generate --example computer --rows 10000 -d computer-output/
|
|
282
282
|
tabalyst generate --example insurance --rows 3000 --anomaly-profile dirty_realistic -d insurance-dirty/
|
|
283
|
+
tabalyst generate --example computer --rows 30000 -o pcs.csv --anomaly-profile dirty_realistic
|
|
283
284
|
```
|
|
284
285
|
|
|
285
286
|
An anomaly profile writes an altered CSV, a cell change log and a summary
|
|
286
|
-
beside the untouched clean CSV.
|
|
287
|
+
beside the untouched clean CSV. For Computer, `-o` writes one CSV with the
|
|
288
|
+
errors and its `.changes.csv` log, and `--anomaly-profile` accepts several
|
|
289
|
+
profiles with `-d` to get one variant of each. Computer rows are generated by
|
|
290
|
+
several processes from 5,000 rows (`--workers` sets the number), and the command
|
|
291
|
+
shows its progress and ends with a timing report.
|
|
287
292
|
|
|
288
293
|
Details: [Tabalyst Generate](https://docs.tabalyst.com/generate/),
|
|
289
294
|
[`examples/generate/README.md`](examples/generate/README.md) and the
|
|
@@ -240,10 +240,15 @@ tabalyst generate --example crm -o crm-contacts.csv
|
|
|
240
240
|
tabalyst generate --example insurance --rows 3000 -d insurance-output/
|
|
241
241
|
tabalyst generate --example computer --rows 10000 -d computer-output/
|
|
242
242
|
tabalyst generate --example insurance --rows 3000 --anomaly-profile dirty_realistic -d insurance-dirty/
|
|
243
|
+
tabalyst generate --example computer --rows 30000 -o pcs.csv --anomaly-profile dirty_realistic
|
|
243
244
|
```
|
|
244
245
|
|
|
245
246
|
An anomaly profile writes an altered CSV, a cell change log and a summary
|
|
246
|
-
beside the untouched clean CSV.
|
|
247
|
+
beside the untouched clean CSV. For Computer, `-o` writes one CSV with the
|
|
248
|
+
errors and its `.changes.csv` log, and `--anomaly-profile` accepts several
|
|
249
|
+
profiles with `-d` to get one variant of each. Computer rows are generated by
|
|
250
|
+
several processes from 5,000 rows (`--workers` sets the number), and the command
|
|
251
|
+
shows its progress and ends with a timing report.
|
|
247
252
|
|
|
248
253
|
Details: [Tabalyst Generate](https://docs.tabalyst.com/generate/),
|
|
249
254
|
[`examples/generate/README.md`](examples/generate/README.md) and the
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
|
|
5
|
+
"""CLI adapter for Tabalyst Generate."""
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Annotated
|
|
10
|
+
|
|
11
|
+
import typer
|
|
12
|
+
|
|
13
|
+
from tabalyst.cli.terminal import error_exit_code
|
|
14
|
+
from tabalyst.errors import TabalystError
|
|
15
|
+
from tabalyst.generate_service import (
|
|
16
|
+
GenerateProgress,
|
|
17
|
+
GenerateResult,
|
|
18
|
+
build_generate_plan,
|
|
19
|
+
generate_datasets,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
PHASE_NAMES = {"rows": "generating rows", "errors": "injecting errors", "publish": "writing files"}
|
|
23
|
+
# Below this, a phase is noise in the report.
|
|
24
|
+
MIN_REPORTED_SECONDS = 0.05
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def format_duration(seconds: float) -> str:
|
|
28
|
+
"""A duration for people: tenths of a second under a minute, then minutes and seconds."""
|
|
29
|
+
if seconds < 60:
|
|
30
|
+
return f"{seconds:.1f}s"
|
|
31
|
+
minutes, rest = divmod(round(seconds), 60)
|
|
32
|
+
if minutes < 60:
|
|
33
|
+
return f"{minutes}m {rest:02d}s"
|
|
34
|
+
hours, minutes = divmod(minutes, 60)
|
|
35
|
+
return f"{hours}h {minutes:02d}m"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class GenerateProgressPrinter:
|
|
39
|
+
"""One rewritten standard error line per stage, with the time left once it is known."""
|
|
40
|
+
|
|
41
|
+
def __init__(self, enabled: bool) -> None:
|
|
42
|
+
self.enabled = enabled
|
|
43
|
+
self._stage: str | None = None
|
|
44
|
+
self._stage_start = 0.0
|
|
45
|
+
self._width = 0
|
|
46
|
+
|
|
47
|
+
def __call__(self, event: GenerateProgress) -> None:
|
|
48
|
+
if not self.enabled or not event.total:
|
|
49
|
+
return
|
|
50
|
+
if event.stage != self._stage:
|
|
51
|
+
self._stage = event.stage
|
|
52
|
+
self._stage_start = event.elapsed_seconds
|
|
53
|
+
spent = event.elapsed_seconds - self._stage_start
|
|
54
|
+
message = f"{event.stage} {event.done:,}/{event.total:,} ({100 * event.done // event.total}%)"
|
|
55
|
+
if event.done >= event.total:
|
|
56
|
+
message += f" - {format_duration(spent)}"
|
|
57
|
+
elif event.done and spent >= 1:
|
|
58
|
+
message += (f" - {format_duration(spent)}, "
|
|
59
|
+
f"about {format_duration(spent * (event.total - event.done) / event.done)} left")
|
|
60
|
+
finished = event.done >= event.total
|
|
61
|
+
typer.echo(f"\r{message.ljust(self._width)}", nl=finished, err=True)
|
|
62
|
+
self._width = 0 if finished else max(self._width, len(message))
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def timing_report(result: GenerateResult) -> str:
|
|
66
|
+
"""The closing line: rows, total time, rate and where the time went."""
|
|
67
|
+
rows = sum(result.row_counts.values()) if len(result.row_counts) == 1 else None
|
|
68
|
+
text = f"Done in {format_duration(result.seconds)}"
|
|
69
|
+
if rows is not None:
|
|
70
|
+
text = f"{rows:,} rows in {format_duration(result.seconds)}"
|
|
71
|
+
if result.seconds > 0:
|
|
72
|
+
processes = f", {result.workers} processes" if result.workers > 1 else ""
|
|
73
|
+
text += f" ({rows / result.seconds:,.0f} rows/s{processes})"
|
|
74
|
+
changed = sum(result.anomaly_counts.values())
|
|
75
|
+
if changed:
|
|
76
|
+
profiles = {key.split("/", 1)[1] for key in result.anomaly_counts if "/" in key}
|
|
77
|
+
text += f", {changed:,} cells changed"
|
|
78
|
+
if len(profiles) > 1:
|
|
79
|
+
text += f" in {len(profiles)} profiles"
|
|
80
|
+
parts = [f"{PHASE_NAMES[name]} {format_duration(value)}"
|
|
81
|
+
for name, value in result.timings.items()
|
|
82
|
+
if name in PHASE_NAMES and value >= MIN_REPORTED_SECONDS]
|
|
83
|
+
return f"{text}: {', '.join(parts)}" if len(parts) > 1 else text
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def generate_command(
|
|
87
|
+
definition: Annotated[
|
|
88
|
+
Path | None,
|
|
89
|
+
typer.Argument(help="Generate definition or package directory."),
|
|
90
|
+
] = None,
|
|
91
|
+
example: Annotated[
|
|
92
|
+
str | None,
|
|
93
|
+
typer.Option("--example", help="Packaged example: crm, insurance, or computer."),
|
|
94
|
+
] = None,
|
|
95
|
+
output: Annotated[
|
|
96
|
+
Path | None,
|
|
97
|
+
typer.Option("--output", "-o", help="One CSV file (with --anomaly-profile: the CSV with errors, plus FILE.changes.csv)."),
|
|
98
|
+
] = None,
|
|
99
|
+
output_dir: Annotated[
|
|
100
|
+
Path | None,
|
|
101
|
+
typer.Option("--output-dir", "-d", help="Directory for all artifacts."),
|
|
102
|
+
] = None,
|
|
103
|
+
rows: Annotated[
|
|
104
|
+
int | None,
|
|
105
|
+
typer.Option("--rows", help="Number of generated rows."),
|
|
106
|
+
] = None,
|
|
107
|
+
seed: Annotated[
|
|
108
|
+
int | None,
|
|
109
|
+
typer.Option("--seed", help="Root random seed."),
|
|
110
|
+
] = None,
|
|
111
|
+
as_of_date: Annotated[
|
|
112
|
+
str | None,
|
|
113
|
+
typer.Option("--as-of-date", help="Reference date (YYYY-MM-DD)."),
|
|
114
|
+
] = None,
|
|
115
|
+
anomaly_profile: Annotated[
|
|
116
|
+
str | None,
|
|
117
|
+
typer.Option("--anomaly-profile", help="Inject errors. Computer: dirty_realistic, dirty_stress, unit_variants, unit_variants_extended; several, comma separated, with -d."),
|
|
118
|
+
] = None,
|
|
119
|
+
request: Annotated[
|
|
120
|
+
Path | None,
|
|
121
|
+
typer.Option("--request", help="JSON generation request."),
|
|
122
|
+
] = None,
|
|
123
|
+
generation_profile: Annotated[
|
|
124
|
+
str | None,
|
|
125
|
+
typer.Option("--generation-profile", help="Catalog selection profile."),
|
|
126
|
+
] = None,
|
|
127
|
+
output_profile: Annotated[
|
|
128
|
+
str | None,
|
|
129
|
+
typer.Option("--output-profile", help="Output column profile."),
|
|
130
|
+
] = None,
|
|
131
|
+
market: Annotated[
|
|
132
|
+
str | None,
|
|
133
|
+
typer.Option("--market", help="Offer market: ca or us."),
|
|
134
|
+
] = None,
|
|
135
|
+
locales: Annotated[
|
|
136
|
+
str | None,
|
|
137
|
+
typer.Option("--locales", help="Computer locales: en, fr or en,fr (default en with -o, en,fr with -d)."),
|
|
138
|
+
] = None,
|
|
139
|
+
unit_style: Annotated[
|
|
140
|
+
str | None,
|
|
141
|
+
typer.Option("--unit-style", help="Computer values: numeric or localized units."),
|
|
142
|
+
] = None,
|
|
143
|
+
unit_columns: Annotated[
|
|
144
|
+
str | None,
|
|
145
|
+
typer.Option("--unit-columns", help="Comma-separated Computer measurement columns to format with units."),
|
|
146
|
+
] = None,
|
|
147
|
+
validate_only: Annotated[
|
|
148
|
+
bool,
|
|
149
|
+
typer.Option("--validate-only", help="Validate a package without writing."),
|
|
150
|
+
] = False,
|
|
151
|
+
force: Annotated[
|
|
152
|
+
bool,
|
|
153
|
+
typer.Option("--force", "-f", help="Replace existing artifacts."),
|
|
154
|
+
] = False,
|
|
155
|
+
no_progress: Annotated[
|
|
156
|
+
bool,
|
|
157
|
+
typer.Option("--no-progress", help="Hide the progress line. It is also hidden outside a terminal."),
|
|
158
|
+
] = False,
|
|
159
|
+
workers: Annotated[
|
|
160
|
+
int | None,
|
|
161
|
+
typer.Option(
|
|
162
|
+
"--workers", min=1,
|
|
163
|
+
help=("Computer: processes that generate the rows, 1 for one process. By default, "
|
|
164
|
+
"5,000 rows or more use one per spare processor, at most 6."),
|
|
165
|
+
),
|
|
166
|
+
] = None,
|
|
167
|
+
) -> None:
|
|
168
|
+
"""Validate and generate datasets from a definition or package."""
|
|
169
|
+
try:
|
|
170
|
+
plan = build_generate_plan(
|
|
171
|
+
definition, example=example, output=output, output_dir=output_dir,
|
|
172
|
+
rows=rows, seed=seed, as_of_date=as_of_date,
|
|
173
|
+
anomaly_profile=anomaly_profile, force=force, request=request,
|
|
174
|
+
generation_profile=generation_profile, output_profile=output_profile,
|
|
175
|
+
market=market, locales=locales, unit_style=unit_style,
|
|
176
|
+
unit_columns=unit_columns,
|
|
177
|
+
validate_only=validate_only, workers=workers,
|
|
178
|
+
)
|
|
179
|
+
if validate_only:
|
|
180
|
+
typer.echo("Valid Generate package.", err=True)
|
|
181
|
+
return
|
|
182
|
+
result = generate_datasets(
|
|
183
|
+
plan, on_progress=GenerateProgressPrinter(not no_progress and sys.stderr.isatty()),
|
|
184
|
+
)
|
|
185
|
+
except TabalystError as exc:
|
|
186
|
+
typer.echo(f"Error: {exc}", err=True)
|
|
187
|
+
raise typer.Exit(error_exit_code(exc)) from exc
|
|
188
|
+
for path in result.paths:
|
|
189
|
+
typer.echo(f"Created: {path}", err=True)
|
|
190
|
+
typer.echo(timing_report(result), err=True)
|
|
@@ -32,6 +32,8 @@ def _print_result(result: SampleResult) -> None:
|
|
|
32
32
|
typer.echo(f"Source rows: {result.source_rows:,}", err=True)
|
|
33
33
|
typer.echo(f"Sample rows: {result.sample_rows:,}", err=True)
|
|
34
34
|
typer.echo(f"Sample rate: {result.sample_rate:.2f}%", err=True)
|
|
35
|
+
if result.per_value is not None:
|
|
36
|
+
typer.echo(f"Per value: up to {result.per_value:,} rows", err=True)
|
|
35
37
|
if result.strata_known is not None:
|
|
36
38
|
typer.echo(
|
|
37
39
|
f"Strata: {result.strata_known:,} known, "
|
|
@@ -39,9 +41,23 @@ def _print_result(result: SampleResult) -> None:
|
|
|
39
41
|
f"{result.strata_uncovered:,} without rows",
|
|
40
42
|
err=True,
|
|
41
43
|
)
|
|
44
|
+
if result.strata_capped is not None:
|
|
45
|
+
typer.echo(
|
|
46
|
+
f"Drawn from: {result.strata_capped:,} strata with more rows than "
|
|
47
|
+
f"the quota; the other {result.strata_known - result.strata_capped:,} "
|
|
48
|
+
"are kept whole",
|
|
49
|
+
err=True,
|
|
50
|
+
)
|
|
51
|
+
if result.source_rows and result.sample_rows * 2 >= result.source_rows:
|
|
52
|
+
typer.echo(
|
|
53
|
+
"Note: the sample holds half of the file or more: the "
|
|
54
|
+
"strata are many or the quota is large.",
|
|
55
|
+
err=True,
|
|
56
|
+
)
|
|
42
57
|
if result.seed is not None and result.method in {
|
|
43
58
|
SampleMethod.RANDOM,
|
|
44
59
|
SampleMethod.STRATIFIED,
|
|
60
|
+
SampleMethod.STRATIFIED_BALANCED,
|
|
45
61
|
}:
|
|
46
62
|
typer.echo(f"Seed: {result.seed}", err=True)
|
|
47
63
|
smart = result.smart
|
|
@@ -144,18 +160,32 @@ def _reject_unused_options(
|
|
|
144
160
|
seed: int | None,
|
|
145
161
|
yes: bool,
|
|
146
162
|
no_html: bool,
|
|
163
|
+
per_value: int | None,
|
|
164
|
+
rows: int | None,
|
|
165
|
+
percent: float | None,
|
|
147
166
|
) -> None:
|
|
148
167
|
"""Refuse an option the method does not read: none is ignored without an error."""
|
|
149
168
|
smart = method is SampleMethod.SMART
|
|
150
169
|
for name, given in (("--yes", yes), ("--no-html", no_html)):
|
|
151
170
|
if given and not smart:
|
|
152
171
|
raise typer.BadParameter(f"{name} only goes with the smart method.")
|
|
153
|
-
|
|
172
|
+
balanced = method is SampleMethod.STRATIFIED_BALANCED
|
|
173
|
+
stratified = balanced or method is SampleMethod.STRATIFIED
|
|
154
174
|
for name, given in (("--field", bool(field)), ("--max-strata", max_strata is not None)):
|
|
155
175
|
if given and not stratified:
|
|
156
176
|
raise typer.BadParameter(
|
|
157
|
-
f"{name} only goes with --sample-method stratified
|
|
177
|
+
f"{name} only goes with --sample-method stratified or "
|
|
178
|
+
f"stratified-balanced, not {method.value}."
|
|
158
179
|
)
|
|
180
|
+
if per_value is not None and not balanced:
|
|
181
|
+
raise typer.BadParameter(
|
|
182
|
+
f"--per-value only goes with --sample-method stratified-balanced, not {method.value}."
|
|
183
|
+
)
|
|
184
|
+
if balanced and (rows is not None or percent is not None):
|
|
185
|
+
raise typer.BadParameter(
|
|
186
|
+
"--rows and --percent do not go with stratified-balanced: use --per-value "
|
|
187
|
+
"for the quota of each stratum."
|
|
188
|
+
)
|
|
159
189
|
if seed is not None and method in {SampleMethod.FIRST, SampleMethod.LAST}:
|
|
160
190
|
raise typer.BadParameter(
|
|
161
191
|
f"--seed has no effect with {method.value}: it keeps the rows in file order."
|
|
@@ -197,10 +227,18 @@ def sample_command(
|
|
|
197
227
|
list[str] | None,
|
|
198
228
|
typer.Option(
|
|
199
229
|
"--field",
|
|
200
|
-
help="Field used for stratified sampling; repeat it to stratify "
|
|
230
|
+
help="Field used for stratified sampling (stratified, stratified-balanced); repeat it to stratify "
|
|
201
231
|
"by the combinations of several fields.",
|
|
202
232
|
),
|
|
203
233
|
] = None,
|
|
234
|
+
per_value: Annotated[
|
|
235
|
+
int | None,
|
|
236
|
+
typer.Option(
|
|
237
|
+
"--per-value",
|
|
238
|
+
help="With stratified-balanced, the most rows kept from each stratum "
|
|
239
|
+
"(all of a smaller one). The size of the sample follows from the data.",
|
|
240
|
+
),
|
|
241
|
+
] = None,
|
|
204
242
|
max_strata: Annotated[
|
|
205
243
|
int | None,
|
|
206
244
|
typer.Option(
|
|
@@ -273,6 +311,9 @@ def sample_command(
|
|
|
273
311
|
seed=seed,
|
|
274
312
|
yes=yes,
|
|
275
313
|
no_html=no_html,
|
|
314
|
+
per_value=per_value,
|
|
315
|
+
rows=rows,
|
|
316
|
+
percent=percent,
|
|
276
317
|
)
|
|
277
318
|
try:
|
|
278
319
|
if method is SampleMethod.SMART:
|
|
@@ -305,6 +346,7 @@ def sample_command(
|
|
|
305
346
|
encoding=encoding,
|
|
306
347
|
force=force,
|
|
307
348
|
max_strata=max_strata,
|
|
349
|
+
per_value=per_value,
|
|
308
350
|
)
|
|
309
351
|
except TabalystError as exc:
|
|
310
352
|
typer.echo(f"Error: {exc}", err=True)
|
|
@@ -354,7 +354,8 @@ def _choose_rows(clean: Path, delimiter: str, operations: Sequence[Mapping[str,
|
|
|
354
354
|
def inject_anomalies(clean: Path, altered: Path, changes: Path, *,
|
|
355
355
|
dataset: str, profile: Mapping[str, object], seed: int, count: int,
|
|
356
356
|
delimiter: str, locale: str = "en",
|
|
357
|
-
unit_suffixes: Mapping[str, tuple[str, str]] | None = None
|
|
357
|
+
unit_suffixes: Mapping[str, tuple[str, str]] | None = None,
|
|
358
|
+
on_row: Callable[[int], None] | None = None) -> dict[str, object]:
|
|
358
359
|
"""Write altered CSV and cell log; return requested and actual counts.
|
|
359
360
|
|
|
360
361
|
Computer unit suffixes are supplied by its output register. An operation
|
|
@@ -369,6 +370,7 @@ def inject_anomalies(clean: Path, altered: Path, changes: Path, *,
|
|
|
369
370
|
row had already received are then gone from the file, so their journal
|
|
370
371
|
entries are dropped and their operations count the row as skipped: the
|
|
371
372
|
journal always describes the file.
|
|
373
|
+
``on_row`` receives the number of rows written, about 200 times per file and at the end.
|
|
372
374
|
"""
|
|
373
375
|
# Imported here because generate_values reaches generate_definition, which
|
|
374
376
|
# imports this module for the operation rules.
|
|
@@ -416,8 +418,11 @@ def inject_anomalies(clean: Path, altered: Path, changes: Path, *,
|
|
|
416
418
|
writer.writeheader()
|
|
417
419
|
log.writeheader()
|
|
418
420
|
observed = 0
|
|
421
|
+
report_every = max(1, count // 200)
|
|
419
422
|
for row_index, clean_row in enumerate(reader):
|
|
420
423
|
observed += 1
|
|
424
|
+
if on_row is not None and row_index % report_every == 0:
|
|
425
|
+
on_row(row_index)
|
|
421
426
|
row = clean_row.copy()
|
|
422
427
|
# (operation index, cell updates) of this row, written once it is final.
|
|
423
428
|
pending: list[tuple[int, list[tuple[str, str, str, str]]]] = []
|
|
@@ -488,6 +493,8 @@ def inject_anomalies(clean: Path, altered: Path, changes: Path, *,
|
|
|
488
493
|
history[field].append(value)
|
|
489
494
|
if observed != count:
|
|
490
495
|
raise ValueError(f"Clean row count changed for {dataset}: {observed} != {count}")
|
|
496
|
+
if on_row is not None:
|
|
497
|
+
on_row(observed)
|
|
491
498
|
return {
|
|
492
499
|
"dataset": dataset, "profile": profile_id, "seed": seed,
|
|
493
500
|
"total_rows": count, "affected_rows": affected_rows,
|
|
@@ -26,12 +26,11 @@ MARKET_CURRENCY = {"ca": "CAD", "us": "USD"}
|
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
def _digest(parts: tuple[str, ...]) -> str:
|
|
29
|
-
|
|
30
|
-
for part in parts
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
return digest.hexdigest()[:40]
|
|
29
|
+
# One hash call over the same length-prefixed bytes: parts hashed one by one would cost more.
|
|
30
|
+
encoded = [part.encode("utf-8") for part in parts]
|
|
31
|
+
return hashlib.sha256(b"".join(
|
|
32
|
+
[len(item).to_bytes(8, "big") + item for item in encoded]
|
|
33
|
+
)).hexdigest()[:40]
|
|
35
34
|
|
|
36
35
|
|
|
37
36
|
def _stream(seed: int, dataset_id: str, row_index: int, decision: str,
|
|
@@ -39,13 +38,45 @@ def _stream(seed: int, dataset_id: str, row_index: int, decision: str,
|
|
|
39
38
|
return random.Random(int(_digest((str(seed), dataset_id, str(row_index), decision, *context)), 16))
|
|
40
39
|
|
|
41
40
|
|
|
41
|
+
_ID_INDEXES: dict[tuple[int, str], tuple[DatasetPackage, dict[Cell, list[dict[str, Cell]]]]] = {}
|
|
42
|
+
_MARKET_CHOICES: dict[tuple[int, str, str], tuple[DatasetPackage, tuple[str, ...], tuple[str, ...]]] = {}
|
|
43
|
+
|
|
44
|
+
|
|
42
45
|
def _entry(package: DatasetPackage, table_id: str, selected_id: Cell) -> dict[str, Cell]:
|
|
43
|
-
|
|
46
|
+
key = (id(package), table_id)
|
|
47
|
+
cached = _ID_INDEXES.get(key)
|
|
48
|
+
# The cache keeps the package alive, so a matching id is always the same object.
|
|
49
|
+
if cached is None or cached[0] is not package:
|
|
50
|
+
index: dict[Cell, list[dict[str, Cell]]] = {}
|
|
51
|
+
for row in package.tables[table_id].rows:
|
|
52
|
+
index.setdefault(row["id"], []).append(row)
|
|
53
|
+
cached = _ID_INDEXES[key] = (package, index)
|
|
54
|
+
matches = cached[1].get(selected_id, [])
|
|
44
55
|
if len(matches) != 1:
|
|
45
56
|
raise ConfigurationError(f"PACKAGE_STEP_REFERENCE: unknown {table_id} ID {selected_id!r}")
|
|
46
57
|
return matches[0]
|
|
47
58
|
|
|
48
59
|
|
|
60
|
+
def _market_choices(package: DatasetPackage, market: str, brand_id: str
|
|
61
|
+
) -> tuple[tuple[str, ...], tuple[str, ...]]:
|
|
62
|
+
"""Sellers a brand may use and warehouses of a market, in the order the draws index them."""
|
|
63
|
+
key = (id(package), market, brand_id)
|
|
64
|
+
cached = _MARKET_CHOICES.get(key)
|
|
65
|
+
if cached is None or cached[0] is not package:
|
|
66
|
+
sellers = tuple(sorted(
|
|
67
|
+
str(row["id"]) for row in package.tables["seller"].rows
|
|
68
|
+
if row["market"] == market
|
|
69
|
+
and (row["seller_type_id"] != "manufacturer"
|
|
70
|
+
or row["id"] == f"{brand_id}_direct_{market}")
|
|
71
|
+
))
|
|
72
|
+
warehouses = tuple(sorted(
|
|
73
|
+
str(row["id"]) for row in package.tables["warehouse"].rows
|
|
74
|
+
if row["market"] == market
|
|
75
|
+
))
|
|
76
|
+
cached = _MARKET_CHOICES[key] = (package, sellers, warehouses)
|
|
77
|
+
return cached[1], cached[2]
|
|
78
|
+
|
|
79
|
+
|
|
49
80
|
def _integer(value: Cell, field: str) -> int:
|
|
50
81
|
if type(value) is not int:
|
|
51
82
|
raise ConfigurationError(f"PACKAGE_STEP_REFERENCE: expected integer Computer field {field!r}")
|
|
@@ -274,18 +305,9 @@ def derive_computer_row(package: DatasetPackage, selected: dict[str, Cell],
|
|
|
274
305
|
return_rate = (Decimal("0.10") - (rating_value - 3) * Decimal("0.02")
|
|
275
306
|
+ Decimal(_stream(seed, dataset_id, row_index, "returns", context).randrange(0, 6))
|
|
276
307
|
/ 1000).quantize(Decimal("0.001"))
|
|
277
|
-
seller_ids =
|
|
278
|
-
str(row["id"]) for row in package.tables["seller"].rows
|
|
279
|
-
if row["market"] == market
|
|
280
|
-
and (row["seller_type_id"] != "manufacturer"
|
|
281
|
-
or row["id"] == f"{values['brand_id']}_direct_{market}")
|
|
282
|
-
))
|
|
308
|
+
seller_ids, warehouse_ids = _market_choices(package, market, str(values["brand_id"]))
|
|
283
309
|
seller_id = _stream(seed, dataset_id, row_index, "seller", context).choice(seller_ids)
|
|
284
310
|
seller = _entry(package, "seller", seller_id)
|
|
285
|
-
warehouse_ids = tuple(sorted(
|
|
286
|
-
str(row["id"]) for row in package.tables["warehouse"].rows
|
|
287
|
-
if row["market"] == market
|
|
288
|
-
))
|
|
289
311
|
warehouse_id = _stream(seed, dataset_id, row_index, "warehouse", context).choice(
|
|
290
312
|
warehouse_ids
|
|
291
313
|
)
|
|
@@ -8,8 +8,11 @@ from __future__ import annotations
|
|
|
8
8
|
|
|
9
9
|
import csv
|
|
10
10
|
import hashlib
|
|
11
|
+
import io
|
|
11
12
|
import json
|
|
12
13
|
import sys
|
|
14
|
+
import tempfile
|
|
15
|
+
from collections.abc import Callable
|
|
13
16
|
from contextlib import ExitStack
|
|
14
17
|
from datetime import date
|
|
15
18
|
from pathlib import Path
|
|
@@ -209,6 +212,33 @@ def render_computer_row(package: DatasetPackage, row: dict[str, Cell],
|
|
|
209
212
|
return rendered
|
|
210
213
|
|
|
211
214
|
|
|
215
|
+
def _write_rows_in_workers(
|
|
216
|
+
package: DatasetPackage, outputs: dict[str, Path], locales: tuple[str, ...],
|
|
217
|
+
columns: tuple[str, ...], dataset_id: str, rows: int, seed: int, as_of_date: date,
|
|
218
|
+
generation_profile: str, output_profile: str, market: str, unit_style: str,
|
|
219
|
+
selected_units: tuple[str, ...], workers: int, on_rows: Callable[[int], None] | None,
|
|
220
|
+
) -> None:
|
|
221
|
+
"""Write the CSVs from rows rendered by worker processes."""
|
|
222
|
+
# Imported here because the workers module imports this one.
|
|
223
|
+
from tabalyst.generate_computer_parallel import SpanSettings, write_rows
|
|
224
|
+
|
|
225
|
+
header = io.StringIO()
|
|
226
|
+
csv.writer(header, lineterminator="\n").writerow(columns)
|
|
227
|
+
with ExitStack() as stack:
|
|
228
|
+
# The parts sit beside the outputs: millions of rows would fill a small system temp.
|
|
229
|
+
directory = Path(stack.enter_context(tempfile.TemporaryDirectory(
|
|
230
|
+
prefix=".generate-parts-", dir=outputs[locales[0]].parent)))
|
|
231
|
+
streams = {locale: stack.enter_context(outputs[locale].open("wb")) for locale in locales}
|
|
232
|
+
for stream in streams.values():
|
|
233
|
+
stream.write(header.getvalue().encode("utf-8"))
|
|
234
|
+
write_rows(
|
|
235
|
+
SpanSettings(package.root, dataset_id, seed, as_of_date, generation_profile,
|
|
236
|
+
output_profile, market, unit_style, selected_units, locales,
|
|
237
|
+
columns, directory),
|
|
238
|
+
rows, workers, streams, on_rows,
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
|
|
212
242
|
def write_computer_csvs(package: DatasetPackage, outputs: dict[str, Path],
|
|
213
243
|
metadata_path: Path, *, dataset_id: str = "computers",
|
|
214
244
|
rows: int = 10, seed: int = 42,
|
|
@@ -216,15 +246,23 @@ def write_computer_csvs(package: DatasetPackage, outputs: dict[str, Path],
|
|
|
216
246
|
generation_profile: str = "balanced",
|
|
217
247
|
output_profile: str = "compact", market: str = "ca",
|
|
218
248
|
unit_style: str = "numeric",
|
|
219
|
-
unit_columns: tuple[str, ...] | None = None
|
|
249
|
+
unit_columns: tuple[str, ...] | None = None,
|
|
250
|
+
on_rows: Callable[[int], None] | None = None,
|
|
251
|
+
workers: int = 1) -> dict[str, object]:
|
|
220
252
|
"""Write paired CSVs and reproducible metadata to caller supplied paths.
|
|
221
253
|
|
|
222
254
|
The caller owns path planning, staging, collision checks, and publication.
|
|
223
|
-
One selected and derived record feeds
|
|
255
|
+
One selected and derived record feeds every requested locale writer per iteration.
|
|
256
|
+
`outputs` holds `en`, `fr` or both; a single locale writes only that file.
|
|
257
|
+
`on_rows` receives the number of rows written, about 200 times and at the end.
|
|
258
|
+
With `workers` above 1 the rows are rendered by that many processes and the
|
|
259
|
+
files are byte for byte those of one process; `on_rows` then moves by span.
|
|
224
260
|
Localized units are recorded with the effective column selection.
|
|
225
261
|
"""
|
|
226
|
-
|
|
227
|
-
|
|
262
|
+
locales = tuple(locale for locale in ("en", "fr") if locale in outputs)
|
|
263
|
+
if (not locales or len(locales) != len(outputs)
|
|
264
|
+
or len(set(outputs.values()) | {metadata_path}) != len(outputs) + 1):
|
|
265
|
+
raise ValueError("Computer outputs need distinct en or fr paths and a metadata path")
|
|
228
266
|
if type(rows) is not int or rows < 1:
|
|
229
267
|
raise ValueError("rows must be positive")
|
|
230
268
|
if output_profile not in PROFILE_COLUMNS:
|
|
@@ -241,23 +279,33 @@ def write_computer_csvs(package: DatasetPackage, outputs: dict[str, Path],
|
|
|
241
279
|
or any(column not in columns or column not in UNIT_COLUMNS for column in selected_units)
|
|
242
280
|
or unit_style == "numeric" and unit_columns is not None):
|
|
243
281
|
raise ValueError("invalid Computer unit columns")
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
282
|
+
if workers > 1:
|
|
283
|
+
_write_rows_in_workers(package, outputs, locales, columns, dataset_id, rows, seed,
|
|
284
|
+
as_of_date, generation_profile, output_profile, market,
|
|
285
|
+
unit_style, selected_units, workers, on_rows)
|
|
286
|
+
else:
|
|
287
|
+
with ExitStack() as stack:
|
|
288
|
+
writers: dict[str, csv.DictWriter] = {}
|
|
289
|
+
for locale in locales:
|
|
290
|
+
stream = stack.enter_context(outputs[locale].open("w", encoding="utf-8", newline=""))
|
|
291
|
+
writer = csv.DictWriter(stream, fieldnames=columns,
|
|
292
|
+
extrasaction="raise", lineterminator="\n")
|
|
293
|
+
writer.writeheader()
|
|
294
|
+
writers[locale] = writer
|
|
295
|
+
report_every = max(1, rows // 200)
|
|
296
|
+
for index in range(rows):
|
|
297
|
+
if on_rows is not None and index % report_every == 0:
|
|
298
|
+
on_rows(index)
|
|
299
|
+
selected = select_catalog_row(package, dataset_id, seed, index,
|
|
300
|
+
generation_profile)
|
|
301
|
+
internal = derive_computer_row(package, selected, dataset_id, seed,
|
|
302
|
+
index, as_of_date, market)
|
|
303
|
+
for locale in locales:
|
|
304
|
+
writers[locale].writerow(render_computer_row(
|
|
305
|
+
package, internal, locale, output_profile, unit_style, selected_units,
|
|
306
|
+
))
|
|
307
|
+
if on_rows is not None:
|
|
308
|
+
on_rows(rows)
|
|
261
309
|
resources: dict[str, str] = {}
|
|
262
310
|
for path in sorted(package.input_paths):
|
|
263
311
|
with path.open("rb") as source:
|
|
@@ -273,10 +321,10 @@ def write_computer_csvs(package: DatasetPackage, outputs: dict[str, Path],
|
|
|
273
321
|
"request": {"dataset": dataset_id, "rows": rows, "seed": seed,
|
|
274
322
|
"as_of_date": as_of_date.isoformat(),
|
|
275
323
|
"generation_profile": generation_profile,
|
|
276
|
-
"output_profile": output_profile, "locales":
|
|
324
|
+
"output_profile": output_profile, "locales": list(locales),
|
|
277
325
|
"market": market},
|
|
278
326
|
"outputs": {locale: {"rows": rows, "profile": output_profile,
|
|
279
|
-
"columns": len(columns)} for locale in
|
|
327
|
+
"columns": len(columns)} for locale in locales},
|
|
280
328
|
"engine_version": __version__,
|
|
281
329
|
"python_version": f"{sys.version_info.major}.{sys.version_info.minor}",
|
|
282
330
|
}
|