classifyre-cli 0.6.3__tar.gz → 0.6.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/.turbo/turbo-build.log +1 -1
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/PKG-INFO +1 -1
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/package.json +1 -1
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/pyproject.toml +1 -1
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/scripts/generate_models.py +12 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/scripts/generate_sdk_completions.py +12 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/augmentation/sdk.py +34 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/augmentation/session.py +24 -162
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/runners/__init__.py +2 -0
- classifyre_cli-0.6.5/src/detectors/custom/runners/_custom_detector.py +72 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/runners/_factory.py +6 -0
- classifyre_cli-0.6.5/src/detectors/custom_detector/__init__.py +9 -0
- classifyre_cli-0.6.5/src/detectors/custom_detector/contract.py +45 -0
- classifyre_cli-0.6.5/src/detectors/custom_detector/files.py +102 -0
- classifyre_cli-0.6.5/src/detectors/custom_detector/preview.py +283 -0
- classifyre_cli-0.6.5/src/detectors/custom_detector/results.py +266 -0
- classifyre_cli-0.6.5/src/detectors/custom_detector/runner.py +258 -0
- classifyre_cli-0.6.5/src/detectors/custom_detector/sdk.py +334 -0
- classifyre_cli-0.6.5/src/detectors/custom_detector/session.py +443 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/engine_version.py +41 -1
- classifyre_cli-0.6.5/src/file_evaluation/asset_fixture.py +142 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/file_evaluation/runner.py +110 -6
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/graph/__init__.py +2 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/graph/edges.py +51 -2
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/main.py +26 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/models/generated_detectors.py +250 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/models/generated_single_asset_scan_results.py +6 -1
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/child.py +5 -1
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/cli.py +54 -4
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/protocol.py +24 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/sdk.py +129 -1
- classifyre_cli-0.6.5/src/pipeline/asset_payload_server.py +242 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/pipeline/detector_pipeline.py +121 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/pipeline/scan_cache.py +66 -15
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/redaction.py +22 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/urn.py +28 -1
- classifyre_cli-0.6.5/tests/detectors/test_custom_detector_session.py +303 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_augmentation_sdk.py +1 -0
- classifyre_cli-0.6.5/tests/test_custom_detector_end_to_end.py +152 -0
- classifyre_cli-0.6.5/tests/test_custom_detector_evaluation.py +75 -0
- classifyre_cli-0.6.5/tests/test_custom_detector_notebook.py +136 -0
- classifyre_cli-0.6.5/tests/test_custom_detector_templates.py +86 -0
- classifyre_cli-0.6.5/tests/test_notebook_asset_entity.py +82 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_scan_cache.py +46 -0
- classifyre_cli-0.6.5/tests/test_semantic_declarations.py +96 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/uv.lock +722 -681
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/.gitignore +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/.python-version +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/README.md +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/main.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/scripts/generate_runtime_packages.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/augmentation/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/augmentation/contract.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/augmentation/preview.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/augmentation/runner.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/config.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/base.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/broken_links/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/broken_links/detector.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/config.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/content/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/detector.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/extractor.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/runners/_base.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/runners/_gliner2.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/runners/_image_classification.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/runners/_llm.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/runners/_object_detection.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/runners/_regex.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/runners/_tag.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/runners/_text_classification.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/custom/trainer.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/dependencies.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/errors.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/pii/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/pii/detector.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/secrets/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/secrets/detector.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/threat/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/threat/code_security_detector.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/detectors/threat/yara_detector.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/file_evaluation/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/models/generated_input.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/cohort.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/contract.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/execute.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/files.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/groups.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/outputs.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/packages.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/redact.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/scaffold.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/notebook/serialize.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/outputs/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/outputs/base.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/outputs/console.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/outputs/factory.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/outputs/file.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/outputs/rest.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/pipeline/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/pipeline/content_provider.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/pipeline/detector_breaker.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/pipeline/parsed_content_provider.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/pipeline/payload_window.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/pipeline/text_artifact.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/pipeline/worker_pool.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/asset_metadata.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/atlassian_common.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/azure_blob_storage/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/azure_blob_storage/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/base.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/confluence/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/confluence/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/custom/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/custom/env.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/custom/runner.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/custom/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/databricks/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/databricks/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/delta_lake/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/delta_lake/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/dependencies.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/dropbox/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/dropbox/auth.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/dropbox/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/elasticsearch/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/elasticsearch/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/email/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/email/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/git/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/git/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/google_cloud_storage/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/google_cloud_storage/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/google_workspace/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/google_workspace/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/hive/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/hive/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/hugging_face/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/hugging_face/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/iceberg/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/iceberg/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/jira/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/jira/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/kafka/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/kafka/rest.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/kafka/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/lakehouse_base.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/local_folder/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/local_folder/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/meilisearch/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/meilisearch/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/microsoft_365/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/microsoft_365/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/mongodb/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/mongodb/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/mssql/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/mssql/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/mysql/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/mysql/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/neo4j/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/neo4j/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/notion/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/notion/client.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/notion/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/object_storage/base.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/opensearch/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/opensearch/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/oracle/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/oracle/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/postgresql/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/postgresql/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/powerbi/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/powerbi/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/recipe_normalizer.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/reddit/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/reddit/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/s3_client.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/s3_compatible_storage/README.md +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/s3_compatible_storage/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/s3_compatible_storage/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/sandbox/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/sandbox/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/search_engine_base.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/servicedesk/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/servicedesk/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/slack/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/slack/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/snowflake/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/snowflake/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/sqlite/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/sqlite/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/tableau/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/tableau/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/tabular_base.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/tabular_utils.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/wordpress/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/wordpress/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/youtube/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/sources/youtube/source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/telemetry.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/archive_extraction.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/content_extraction.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/dependency_groups.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/embedded_files.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/external_video.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/file_metadata.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/file_parser.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/file_to_images.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/hashing.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/legacy_office.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/payload.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/range_reader.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/resources.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/source_files.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/sql_lineage.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/torch_runtime.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/transcription.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/uv_sync.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/validation.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/src/utils/video_processing.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/_lakehouse_fakes.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/conftest.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/broken_links/test_broken_links_detector.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/conftest.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/content/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/custom/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/custom/conftest.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/custom/test_gliner2_classification.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/custom/test_invoice_extraction.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/custom/test_llm_runner.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/custom/test_pipeline_integration.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/custom/test_regex_runner.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/custom/test_runner_hardening.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/custom/test_transformer_runners.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/pii/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/pii/conftest.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/pii/sample_invoice.pdf +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/pii/test_pii_chunking.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/pii/test_pii_detector.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/pii/test_pii_detector_extended.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/pii/test_pii_regional_entities.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/pii/test_pii_severity.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/secrets/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/secrets/test_secrets_detector.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/secrets/test_secrets_detector_extended.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/test_base_detector.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/test_custom_detector_examples_runtime.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/test_detector_catalog_commercial.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/test_detector_pipeline_types.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/test_detector_schema_examples.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/test_detector_types.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/test_phase2_detectors.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/test_registry.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/test_tag_runner.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/threat/__init__.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/threat/test_code_security_detector.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/detectors/threat/test_yara_detector.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/integration/test_wordpress_broken_links_detector.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/integration/test_wordpress_links_assets.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/pipeline/test_detector_breaker.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/pipeline/test_detector_outcomes.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/pipeline/test_detector_pipeline.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/pipeline/test_worker_pool.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_arrow_ipc_payloads.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_assets_metadata_catalog.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_augmentation_contract.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_augmentation_edges.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_augmentation_patch.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_augmentation_scan_cache.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_augmentation_session.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_augmentation_tags_end_to_end.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_azure_blob_storage_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_base_source_attachment.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_base_source_sampling.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_byte_valued_fields.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_config.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_confluence_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_custom_extractor.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_custom_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_custom_source_relationships.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_custom_source_tags_end_to_end.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_databricks_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_delta_lake_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_dependency_groups.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_detector_scope.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_dropbox_auth_command.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_dropbox_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_elasticsearch_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_email_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_file_evaluation_runner.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_git_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_google_cloud_storage_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_google_workspace_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_graph_edges.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_hashing.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_hive_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_hugging_face_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_iceberg_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_jira_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_kafka_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_lineage_loss_reporting.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_local_folder_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_main.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_meilisearch_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_microsoft_365_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_mongodb_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_mssql_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_mysql_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_neo4j_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_notebook_asset_extract.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_notebook_asset_tags.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_notebook_cohort.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_notebook_execute.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_notebook_files.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_notebook_groups.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_notebook_log_levels.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_notebook_packages.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_notebook_query_assets.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_notebook_sdk_exports.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_notebook_serialize.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_notebook_templates.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_notion_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_object_storage_download_efficiency.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_opensearch_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_oracle_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_outputs.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_payload_window.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_payload_window_parquet.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_postgresql_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_powerbi_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_range_reading.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_recipe_normalizer.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_reddit_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_rest_backpressure.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_runtime_packages.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_s3_compatible_storage_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_sampling_automatic.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_sandbox_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_sdk_completions.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_secret_redaction.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_servicedesk_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_slack_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_snowflake_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_source_dependency_groups.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_source_strategy_conformance.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_sqlite_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_tableau_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_tabular_automatic_sampling.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_tabular_lineage.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_tabular_utils.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_torch_runtime.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_urn.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_uv_sync.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_wordpress_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_youtube_source.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/test_youtube_source_integration.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/utils/test_archive_extraction.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/utils/test_content_extraction.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/utils/test_embedded_files.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/utils/test_file_metadata.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/utils/test_file_parser.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/utils/test_file_to_images.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/utils/test_legacy_office.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/utils/test_payload.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/utils/test_transcription.py +0 -0
- {classifyre_cli-0.6.3 → classifyre_cli-0.6.5}/tests/utils/test_video_processing.py +0 -0
|
@@ -15,6 +15,7 @@ _PIPELINE_TYPE_DEFAULTS: dict[str, str] = {
|
|
|
15
15
|
"RegexPipelineSchema": "REGEX",
|
|
16
16
|
"LLMPipelineSchema": "LLM",
|
|
17
17
|
"TagPipelineSchema": "TAG",
|
|
18
|
+
"CodeDetectorPipelineSchema": "CODE_DETECTOR",
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
# Pipeline schema classes whose `severity` field has a string default from JSON schema
|
|
@@ -27,6 +28,7 @@ _SEVERITY_ENUM_DEFAULT_CLASSES = {
|
|
|
27
28
|
"LLMPipelineSchema": "info",
|
|
28
29
|
"TextClassificationPipelineSchema": "info",
|
|
29
30
|
"TagPipelineSchema": "medium",
|
|
31
|
+
"CodeDetectorPipelineSchema": "medium",
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
|
|
@@ -60,6 +62,15 @@ def _patch_severity_enum_defaults(source: str) -> str:
|
|
|
60
62
|
return source
|
|
61
63
|
|
|
62
64
|
|
|
65
|
+
def _patch_category_enum_defaults(source: str) -> str:
|
|
66
|
+
"""Same fix as the severity one, for the code detector's ``category`` default."""
|
|
67
|
+
pattern = (
|
|
68
|
+
r"(class CodeDetectorPipelineSchema\(.*?category: DetectorCategory \| None = Field\(\n\s+)"
|
|
69
|
+
r"'QUALITY'(\s*,)"
|
|
70
|
+
)
|
|
71
|
+
return re.sub(pattern, r"\1DetectorCategory.QUALITY\2", source, flags=re.DOTALL)
|
|
72
|
+
|
|
73
|
+
|
|
63
74
|
def run_codegen(input_file):
|
|
64
75
|
"""Generate Pydantic models from a single JSON schema file."""
|
|
65
76
|
cmd = [
|
|
@@ -107,6 +118,7 @@ def main():
|
|
|
107
118
|
content = run_codegen(detector_schema)
|
|
108
119
|
content = _patch_pipeline_type_defaults(content)
|
|
109
120
|
content = _patch_severity_enum_defaults(content)
|
|
121
|
+
content = _patch_category_enum_defaults(content)
|
|
110
122
|
(MODEL_DIR / "generated_detectors.py").write_text(content)
|
|
111
123
|
print("Wrote src/models/generated_detectors.py")
|
|
112
124
|
|
|
@@ -35,6 +35,7 @@ from src.notebook.contract import ( # noqa: E402
|
|
|
35
35
|
from src.notebook.sdk import ( # noqa: E402
|
|
36
36
|
Asset,
|
|
37
37
|
Context,
|
|
38
|
+
Entity,
|
|
38
39
|
FieldMapping,
|
|
39
40
|
FlowType,
|
|
40
41
|
NotebookFile,
|
|
@@ -259,6 +260,13 @@ def build() -> dict[str, Any]:
|
|
|
259
260
|
"documentation": _summary(Tag),
|
|
260
261
|
"insertText": "Tag",
|
|
261
262
|
},
|
|
263
|
+
{
|
|
264
|
+
"label": "Entity",
|
|
265
|
+
"kind": "class",
|
|
266
|
+
"detail": 'Entity(name, type="ORGANIZATION", identifiers={...})',
|
|
267
|
+
"documentation": _summary(Entity),
|
|
268
|
+
"insertText": "Entity",
|
|
269
|
+
},
|
|
262
270
|
{
|
|
263
271
|
"label": "Ref",
|
|
264
272
|
"kind": "class",
|
|
@@ -304,6 +312,10 @@ def build() -> dict[str, Any]:
|
|
|
304
312
|
"documentation": _summary(Tag),
|
|
305
313
|
"fields": _fields(Tag),
|
|
306
314
|
},
|
|
315
|
+
"Entity": {
|
|
316
|
+
"documentation": _summary(Entity),
|
|
317
|
+
"fields": _fields(Entity),
|
|
318
|
+
},
|
|
307
319
|
"AugmentedAsset": {
|
|
308
320
|
"documentation": _summary(augmentation_sdk.AugmentedAsset),
|
|
309
321
|
"members": _members(augmentation_sdk.AugmentedAsset),
|
|
@@ -44,11 +44,13 @@ from ..graph.edges import (
|
|
|
44
44
|
FlowType,
|
|
45
45
|
Ref,
|
|
46
46
|
contains,
|
|
47
|
+
edge_to_payload,
|
|
47
48
|
flow,
|
|
48
49
|
references,
|
|
49
50
|
same_as,
|
|
50
51
|
uses,
|
|
51
52
|
)
|
|
53
|
+
from ..graph.edges import means as means_edge
|
|
52
54
|
from ..notebook.files import ParsedContent, pages, parse
|
|
53
55
|
from ..notebook.sdk import (
|
|
54
56
|
MODULE_NAME,
|
|
@@ -141,6 +143,7 @@ class AugmentedAsset:
|
|
|
141
143
|
self._added_metadata: dict[str, Any] = {}
|
|
142
144
|
self._tags: dict[str, str] = {}
|
|
143
145
|
self._links: list[str] = []
|
|
146
|
+
self._means: list[dict[str, Any]] = []
|
|
144
147
|
self._new_urn: str | None = None
|
|
145
148
|
self.warnings: list[str] = []
|
|
146
149
|
|
|
@@ -313,6 +316,33 @@ class AugmentedAsset:
|
|
|
313
316
|
if target not in self._links:
|
|
314
317
|
self._links.append(target)
|
|
315
318
|
|
|
319
|
+
def means(
|
|
320
|
+
self,
|
|
321
|
+
key: str,
|
|
322
|
+
*,
|
|
323
|
+
evidence: Mapping[str, Any] | None = None,
|
|
324
|
+
confidence: float | None = None,
|
|
325
|
+
) -> None:
|
|
326
|
+
"""Declare that this asset is about a glossary concept or entity, by key.
|
|
327
|
+
|
|
328
|
+
Additive, like ``tag()`` and ``link()``: a DECLARED semantic link. The
|
|
329
|
+
term need not exist yet; the declaration links once it is defined. An
|
|
330
|
+
invalid key is skipped with a warning.
|
|
331
|
+
"""
|
|
332
|
+
try:
|
|
333
|
+
edge = means_edge(
|
|
334
|
+
Ref.asset(self._hash),
|
|
335
|
+
Ref.term(str(key or "")),
|
|
336
|
+
evidence=dict(evidence or {}),
|
|
337
|
+
confidence=confidence,
|
|
338
|
+
)
|
|
339
|
+
except ValueError as exc:
|
|
340
|
+
self.warnings.append(f"Ignoring asset.means({key!r}): {exc}")
|
|
341
|
+
return
|
|
342
|
+
payload = edge_to_payload(edge)
|
|
343
|
+
if payload not in self._means:
|
|
344
|
+
self._means.append(payload)
|
|
345
|
+
|
|
316
346
|
def set_urn(self, urn: str) -> None:
|
|
317
347
|
"""Set the asset's cross-system identity, only if the connector left it empty.
|
|
318
348
|
|
|
@@ -337,6 +367,7 @@ class AugmentedAsset:
|
|
|
337
367
|
"metadata": dict(self._added_metadata),
|
|
338
368
|
"tags": dict(self._tags),
|
|
339
369
|
"links": list(self._links),
|
|
370
|
+
"means": list(self._means),
|
|
340
371
|
"urn": self._new_urn,
|
|
341
372
|
"warnings": list(self.warnings),
|
|
342
373
|
}
|
|
@@ -418,6 +449,7 @@ def build_augmentation_module(context: AugmentContext) -> types.ModuleType:
|
|
|
418
449
|
module.flow = flow # type: ignore[attr-defined]
|
|
419
450
|
module.contains = contains # type: ignore[attr-defined]
|
|
420
451
|
module.references = references # type: ignore[attr-defined]
|
|
452
|
+
module.means = means_edge # type: ignore[attr-defined]
|
|
421
453
|
module.same_as = same_as # type: ignore[attr-defined]
|
|
422
454
|
module.uses = uses # type: ignore[attr-defined]
|
|
423
455
|
module.urn_for = urn_for # type: ignore[attr-defined]
|
|
@@ -439,6 +471,7 @@ def build_augmentation_module(context: AugmentContext) -> types.ModuleType:
|
|
|
439
471
|
"contains",
|
|
440
472
|
"ctx",
|
|
441
473
|
"flow",
|
|
474
|
+
"means",
|
|
442
475
|
"pages",
|
|
443
476
|
"parse",
|
|
444
477
|
"references",
|
|
@@ -470,6 +503,7 @@ def augmentation_namespace(context: AugmentContext) -> dict[str, Any]:
|
|
|
470
503
|
"flow": flow,
|
|
471
504
|
"contains": contains,
|
|
472
505
|
"references": references,
|
|
506
|
+
"means": means_edge,
|
|
473
507
|
"same_as": same_as,
|
|
474
508
|
"uses": uses,
|
|
475
509
|
"urn_for": urn_for,
|
|
@@ -18,7 +18,6 @@ silently-degraded run visible.
|
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
20
|
import asyncio
|
|
21
|
-
import base64
|
|
22
21
|
import json
|
|
23
22
|
import logging
|
|
24
23
|
from collections.abc import Mapping
|
|
@@ -29,6 +28,7 @@ from ..graph.edges import edge_from_payload
|
|
|
29
28
|
from ..notebook.child import ChildProcessError, NotebookChildProcess
|
|
30
29
|
from ..notebook.groups import warm_declared_groups
|
|
31
30
|
from ..notebook.packages import install as install_packages
|
|
31
|
+
from ..pipeline.asset_payload_server import AssetPayloadServer
|
|
32
32
|
from ..utils.hashing import unhash_id
|
|
33
33
|
from ..utils.urn import normalize_urn_or_none
|
|
34
34
|
from .contract import validate_augmentation_notebook
|
|
@@ -143,10 +143,6 @@ class AugmentationSession:
|
|
|
143
143
|
self._warnings: list[str] = []
|
|
144
144
|
self._warning_set: set[str] = set()
|
|
145
145
|
self.stats = AugmentationStats()
|
|
146
|
-
# Run-scoped memo of fetched payloads, keyed by fetch candidate id.
|
|
147
|
-
# Bounded: one in-flight asset's worth per entry, each capped at
|
|
148
|
-
# max_payload_bytes, dropped by evict_asset_cache().
|
|
149
|
-
self._memo: dict[str, dict[str, Any]] = {}
|
|
150
146
|
|
|
151
147
|
# -- construction ----------------------------------------------------------
|
|
152
148
|
|
|
@@ -295,7 +291,6 @@ class AugmentationSession:
|
|
|
295
291
|
slot.child.terminate()
|
|
296
292
|
except Exception:
|
|
297
293
|
pass
|
|
298
|
-
self._memo.clear()
|
|
299
294
|
|
|
300
295
|
# -- per asset -----------------------------------------------------------------
|
|
301
296
|
|
|
@@ -314,163 +309,34 @@ class AugmentationSession:
|
|
|
314
309
|
"mime_type": None,
|
|
315
310
|
}
|
|
316
311
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
312
|
+
@property
|
|
313
|
+
def _payloads(self) -> AssetPayloadServer:
|
|
314
|
+
"""The source's shared payload server.
|
|
315
|
+
|
|
316
|
+
Shared with the code detectors that run on the same asset later in the
|
|
317
|
+
scan, so a payload augmentation fetched is not fetched again (G1 R20).
|
|
318
|
+
"""
|
|
319
|
+
return AssetPayloadServer.shared(
|
|
320
|
+
self._source, max_payload_bytes=self._limits["max_payload_bytes"]
|
|
321
|
+
)
|
|
324
322
|
|
|
325
323
|
async def _serve_need(self, asset: Any, memo_key: str, frame: dict[str, Any]) -> Any:
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
return {"bytes_b64": None, "mime": None}
|
|
331
|
-
raw, mime = fetched
|
|
332
|
-
return {"bytes_b64": base64.b64encode(raw).decode("ascii"), "mime": mime}
|
|
333
|
-
if op == "raw_pages":
|
|
334
|
-
pages = await self._fetch_raw_pages(asset)
|
|
335
|
-
return {"pages": pages}
|
|
336
|
-
if op == "text":
|
|
337
|
-
pages = await self._fetch_text_pages(asset)
|
|
338
|
-
whole = "".join(pages)
|
|
339
|
-
return {"text": whole, "pages": pages}
|
|
340
|
-
raise ChildProcessError(f"Unknown payload op {op!r}")
|
|
324
|
+
try:
|
|
325
|
+
return await self._payloads.serve(asset, frame)
|
|
326
|
+
except ValueError as exc:
|
|
327
|
+
raise ChildProcessError(str(exc)) from exc
|
|
341
328
|
|
|
342
329
|
async def _fetch_payload(self, asset: Any) -> tuple[bytes, str] | None:
|
|
343
330
|
"""Raw bytes for file-shaped sources; None for row-shaped ones."""
|
|
344
|
-
|
|
345
|
-
if "payload" in memo:
|
|
346
|
-
cached = memo["payload"]
|
|
347
|
-
return cached if cached is None else (bytes(cached[0]), str(cached[1]))
|
|
348
|
-
fetch = getattr(self._source, "fetch_content_bytes", None)
|
|
349
|
-
result: tuple[bytes, str] | None = None
|
|
350
|
-
if callable(fetch):
|
|
351
|
-
for candidate in self._candidates(asset):
|
|
352
|
-
try:
|
|
353
|
-
result = await fetch(candidate)
|
|
354
|
-
except Exception as exc:
|
|
355
|
-
logger.debug("Augmentation payload fetch failed for %s: %s", candidate, exc)
|
|
356
|
-
continue
|
|
357
|
-
if result is not None:
|
|
358
|
-
break
|
|
359
|
-
if result is not None:
|
|
360
|
-
raw, mime = result
|
|
361
|
-
cap = self._limits["max_payload_bytes"]
|
|
362
|
-
if len(raw) > cap:
|
|
363
|
-
logger.debug("Augmentation payload for %s truncated to %d bytes", candidate, cap)
|
|
364
|
-
raw = raw[:cap]
|
|
365
|
-
result = (raw, mime)
|
|
366
|
-
self._remember_bytes(asset, raw, mime)
|
|
367
|
-
memo["payload"] = result
|
|
368
|
-
return result
|
|
331
|
+
return await self._payloads.payload(asset)
|
|
369
332
|
|
|
370
333
|
async def _fetch_raw_pages(self, asset: Any) -> list[str]:
|
|
371
334
|
"""The connector's own raw representation, page by page (capped)."""
|
|
372
|
-
|
|
373
|
-
if "raw_pages" in memo:
|
|
374
|
-
return [str(page) for page in memo["raw_pages"]]
|
|
375
|
-
pages: list[str] = []
|
|
376
|
-
fetch = getattr(self._source, "fetch_content_pages", None)
|
|
377
|
-
cap = self._limits["max_payload_bytes"]
|
|
378
|
-
used = 0
|
|
379
|
-
if callable(fetch):
|
|
380
|
-
for candidate in self._candidates(asset):
|
|
381
|
-
try:
|
|
382
|
-
async for raw, _text in fetch(candidate):
|
|
383
|
-
if not raw:
|
|
384
|
-
continue
|
|
385
|
-
chunk = str(raw)
|
|
386
|
-
if used + len(chunk) > cap:
|
|
387
|
-
chunk = chunk[: max(0, cap - used)]
|
|
388
|
-
if chunk:
|
|
389
|
-
pages.append(chunk)
|
|
390
|
-
used += len(chunk)
|
|
391
|
-
if used >= cap or len(pages) >= 50:
|
|
392
|
-
break
|
|
393
|
-
if pages:
|
|
394
|
-
break
|
|
395
|
-
except Exception as exc:
|
|
396
|
-
logger.debug("Augmentation raw fetch failed for %s: %s", candidate, exc)
|
|
397
|
-
continue
|
|
398
|
-
memo["raw_pages"] = pages
|
|
399
|
-
return pages
|
|
335
|
+
return await self._payloads.raw_pages(asset)
|
|
400
336
|
|
|
401
337
|
async def _fetch_text_pages(self, asset: Any) -> list[str]:
|
|
402
338
|
"""Extracted text, page by page (capped)."""
|
|
403
|
-
|
|
404
|
-
if "text_pages" in memo:
|
|
405
|
-
return [str(page) for page in memo["text_pages"]]
|
|
406
|
-
pages: list[str] = []
|
|
407
|
-
fetch = getattr(self._source, "fetch_content_pages", None)
|
|
408
|
-
cap = self._limits["max_payload_bytes"]
|
|
409
|
-
used = 0
|
|
410
|
-
if callable(fetch):
|
|
411
|
-
for candidate in self._candidates(asset):
|
|
412
|
-
try:
|
|
413
|
-
async for _raw, text in fetch(candidate):
|
|
414
|
-
if not text:
|
|
415
|
-
continue
|
|
416
|
-
chunk = str(text)
|
|
417
|
-
if used + len(chunk) > cap:
|
|
418
|
-
chunk = chunk[: max(0, cap - used)]
|
|
419
|
-
if chunk:
|
|
420
|
-
pages.append(chunk)
|
|
421
|
-
used += len(chunk)
|
|
422
|
-
if used >= cap or len(pages) >= 50:
|
|
423
|
-
break
|
|
424
|
-
if pages:
|
|
425
|
-
break
|
|
426
|
-
except Exception as exc:
|
|
427
|
-
logger.debug("Augmentation text fetch failed for %s: %s", candidate, exc)
|
|
428
|
-
continue
|
|
429
|
-
if not pages:
|
|
430
|
-
provider = getattr(self._source, "fetch_content_bytes", None)
|
|
431
|
-
if callable(provider):
|
|
432
|
-
fetched = await self._fetch_payload(asset)
|
|
433
|
-
if fetched is not None:
|
|
434
|
-
raw, mime = fetched
|
|
435
|
-
try:
|
|
436
|
-
text_pages = await asyncio.to_thread(
|
|
437
|
-
list, self._source.iter_asset_pages(raw, mime)
|
|
438
|
-
)
|
|
439
|
-
for page in text_pages[:50]:
|
|
440
|
-
chunk = str(page)
|
|
441
|
-
if used + len(chunk) > cap:
|
|
442
|
-
chunk = chunk[: max(0, cap - used)]
|
|
443
|
-
if chunk:
|
|
444
|
-
pages.append(chunk)
|
|
445
|
-
used += len(chunk)
|
|
446
|
-
if used >= cap:
|
|
447
|
-
break
|
|
448
|
-
except Exception as exc:
|
|
449
|
-
logger.debug("Augmentation text fallback failed: %s", exc)
|
|
450
|
-
memo["text_pages"] = pages
|
|
451
|
-
return pages
|
|
452
|
-
|
|
453
|
-
def _memo_for(self, asset: Any) -> dict[str, Any]:
|
|
454
|
-
key = str(getattr(asset, "hash", "") or "")
|
|
455
|
-
return self._memo.setdefault(key, {})
|
|
456
|
-
|
|
457
|
-
def _remember_bytes(self, asset: Any, raw: bytes, mime: str) -> None:
|
|
458
|
-
"""Mirror fetched bytes onto the source so the pipeline reuses them.
|
|
459
|
-
|
|
460
|
-
``ParsedContentProvider.fetch_bytes`` consults this memo first instead
|
|
461
|
-
of re-downloading — the fetch augmentation already paid for is not
|
|
462
|
-
paid twice. Registered under every candidate id the pipeline tries
|
|
463
|
-
(external URL, then hash), and dropped by ``evict`` at the end of the
|
|
464
|
-
asset.
|
|
465
|
-
"""
|
|
466
|
-
remember = getattr(self._source, "remember_augmentation_bytes", None)
|
|
467
|
-
if not callable(remember):
|
|
468
|
-
return
|
|
469
|
-
for candidate in self._candidates(asset):
|
|
470
|
-
try:
|
|
471
|
-
remember(candidate, raw, mime)
|
|
472
|
-
except Exception:
|
|
473
|
-
pass
|
|
339
|
+
return await self._payloads.text_pages(asset)
|
|
474
340
|
|
|
475
341
|
async def augment(self, asset: Any) -> Any:
|
|
476
342
|
"""Enrich one asset. Never raises: failure degrades to a warning."""
|
|
@@ -597,6 +463,11 @@ class AugmentationSession:
|
|
|
597
463
|
|
|
598
464
|
self._ingest_edges(patch, asset_hash=asset_hash or None)
|
|
599
465
|
|
|
466
|
+
# asset.means(): declarations, already built as MEANS edges by the SDK.
|
|
467
|
+
declared = patch.get("means")
|
|
468
|
+
if isinstance(declared, list) and declared:
|
|
469
|
+
self._ingest_edges({"edges": declared}, asset_hash=asset_hash or None)
|
|
470
|
+
|
|
600
471
|
for message in patch.get("warnings") or []:
|
|
601
472
|
self._warn(f"Augmentation on {getattr(asset, 'name', asset_hash)}: {message}")
|
|
602
473
|
|
|
@@ -718,13 +589,4 @@ class AugmentationSession:
|
|
|
718
589
|
|
|
719
590
|
def evict(self, asset: Any) -> None:
|
|
720
591
|
"""Drop one asset's payload memo. Called alongside evict_asset_cache."""
|
|
721
|
-
self.
|
|
722
|
-
forget = getattr(self._source, "forget_augmentation_bytes", None)
|
|
723
|
-
if not callable(forget):
|
|
724
|
-
return
|
|
725
|
-
# The bytes were mirrored under every candidate id; drop them all.
|
|
726
|
-
for candidate in self._candidates(asset):
|
|
727
|
-
try:
|
|
728
|
-
forget(candidate)
|
|
729
|
-
except Exception:
|
|
730
|
-
pass
|
|
592
|
+
self._payloads.evict(asset)
|
|
@@ -13,6 +13,7 @@ from ._base import (
|
|
|
13
13
|
BaseRunner,
|
|
14
14
|
_resolve_pipeline_severity,
|
|
15
15
|
)
|
|
16
|
+
from ._custom_detector import CustomDetectorRunner
|
|
16
17
|
from ._factory import create_runner
|
|
17
18
|
from ._gliner2 import (
|
|
18
19
|
GLiNER2Runner,
|
|
@@ -35,6 +36,7 @@ __all__ = [
|
|
|
35
36
|
"_IMAGE_CONTENT_TYPES",
|
|
36
37
|
"_TEXT_CONTENT_TYPES",
|
|
37
38
|
"BaseRunner",
|
|
39
|
+
"CustomDetectorRunner",
|
|
38
40
|
"GLiNER2Runner",
|
|
39
41
|
"ImageClassificationRunner",
|
|
40
42
|
"LLMRunner",
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""Runner for the ``CODE_DETECTOR`` pipeline type: a code detector.
|
|
2
|
+
|
|
3
|
+
Like ``TAG`` it never runs over a page of text: ``detect()`` returns nothing and
|
|
4
|
+
no content type is advertised, so the text, binary and link passes never
|
|
5
|
+
schedule it and the worker pool never receives it. The detector pipeline
|
|
6
|
+
recognises it by this class and calls it once per asset, after every other
|
|
7
|
+
detector, through the :class:`CustomDetectorSession` it owns.
|
|
8
|
+
|
|
9
|
+
The session is created lazily on first use and bound to the scan's source,
|
|
10
|
+
because it needs the source to serve payload and holds child processes that
|
|
11
|
+
must not exist in the worker pool's processes.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
from typing import Any
|
|
17
|
+
|
|
18
|
+
from ....models.generated_detectors import CodeDetectorPipelineSchema, PipelineResult
|
|
19
|
+
from ....models.generated_single_asset_scan_results import DetectionResult
|
|
20
|
+
from ._base import BaseRunner
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class CustomDetectorRunner(BaseRunner):
|
|
24
|
+
"""Asset-scoped runner: judged per asset by a notebook, never per page."""
|
|
25
|
+
|
|
26
|
+
asset_scoped = True
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
schema: CodeDetectorPipelineSchema,
|
|
31
|
+
detector_key: str = "",
|
|
32
|
+
detector_name: str = "",
|
|
33
|
+
) -> None:
|
|
34
|
+
self.schema = schema
|
|
35
|
+
self._detector_key = detector_key
|
|
36
|
+
self._detector_name = detector_name
|
|
37
|
+
self._session: Any = None
|
|
38
|
+
|
|
39
|
+
def run(self, text: str) -> PipelineResult:
|
|
40
|
+
return PipelineResult(metadata={"runner": "CODE_DETECTOR"})
|
|
41
|
+
|
|
42
|
+
def detect(self, content: str | bytes, content_type: str) -> list[DetectionResult]:
|
|
43
|
+
"""Never called per page. The pipeline calls ``session().detect(asset)``."""
|
|
44
|
+
return []
|
|
45
|
+
|
|
46
|
+
def get_supported_content_types(self) -> list[str]:
|
|
47
|
+
return []
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
def deterministic(self) -> bool:
|
|
51
|
+
return self.schema.deterministic is not False
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def needs_findings(self) -> bool:
|
|
55
|
+
return bool(self.schema.needs_findings)
|
|
56
|
+
|
|
57
|
+
def session(self, source: Any) -> Any:
|
|
58
|
+
"""The run's session, created on first use."""
|
|
59
|
+
if self._session is None:
|
|
60
|
+
from ...custom_detector.session import CustomDetectorSession
|
|
61
|
+
|
|
62
|
+
self._session = CustomDetectorSession(
|
|
63
|
+
key=self._detector_key,
|
|
64
|
+
name=self._detector_name,
|
|
65
|
+
schema=self.schema,
|
|
66
|
+
source=source,
|
|
67
|
+
)
|
|
68
|
+
return self._session
|
|
69
|
+
|
|
70
|
+
def close(self) -> None:
|
|
71
|
+
if self._session is not None:
|
|
72
|
+
self._session.close()
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from ....models.generated_detectors import (
|
|
6
|
+
CodeDetectorPipelineSchema,
|
|
6
7
|
GLiNER2PipelineSchema,
|
|
7
8
|
ImageClassificationPipelineSchema,
|
|
8
9
|
LLMPipelineSchema,
|
|
@@ -12,6 +13,7 @@ from ....models.generated_detectors import (
|
|
|
12
13
|
TextClassificationPipelineSchema,
|
|
13
14
|
)
|
|
14
15
|
from ._base import BaseRunner
|
|
16
|
+
from ._custom_detector import CustomDetectorRunner
|
|
15
17
|
from ._gliner2 import GLiNER2Runner
|
|
16
18
|
from ._image_classification import ImageClassificationRunner
|
|
17
19
|
from ._llm import LLMRunner
|
|
@@ -30,6 +32,7 @@ def create_runner(
|
|
|
30
32
|
| ImageClassificationPipelineSchema
|
|
31
33
|
| ObjectDetectionPipelineSchema
|
|
32
34
|
| TagPipelineSchema
|
|
35
|
+
| CodeDetectorPipelineSchema
|
|
33
36
|
),
|
|
34
37
|
detector_key: str = "",
|
|
35
38
|
detector_name: str = "",
|
|
@@ -50,5 +53,8 @@ def create_runner(
|
|
|
50
53
|
# detector that is not supposed to run anything at all.
|
|
51
54
|
if isinstance(schema, TagPipelineSchema):
|
|
52
55
|
return TagRunner(schema, detector_key, detector_name)
|
|
56
|
+
# Same reason as TAG: a code detector must never fall through to GLiNER2.
|
|
57
|
+
if isinstance(schema, CodeDetectorPipelineSchema):
|
|
58
|
+
return CustomDetectorRunner(schema, detector_key, detector_name)
|
|
53
59
|
# GLiNER2PipelineSchema is the default / backward-compat path
|
|
54
60
|
return GLiNER2Runner(schema, detector_key, detector_name)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""Code detectors: the ``CODE_DETECTOR`` pipeline type.
|
|
2
|
+
|
|
3
|
+
A notebook that defines ``detect(asset, ctx)`` and yields ``Finding`` objects,
|
|
4
|
+
run in an isolated child process once per asset, after every other detector.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .session import CustomDetectorSession, DetectOutcome
|
|
8
|
+
|
|
9
|
+
__all__ = ["CustomDetectorSession", "DetectOutcome"]
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""The interface a code detector's notebook must cover.
|
|
2
|
+
|
|
3
|
+
A code detector answers one question -- "what is wrong with this asset?" -- so
|
|
4
|
+
``detect(asset, ctx)`` is required and ``setup(ctx)`` optional. Checked at the
|
|
5
|
+
three moments the connector contract is: on save (the API's cheap check),
|
|
6
|
+
before a preview, and before every scan, because the recipe travels to a job
|
|
7
|
+
that has to defend itself.
|
|
8
|
+
|
|
9
|
+
Only the shape is checked, through the shared ``validate_module`` /
|
|
10
|
+
``validate_notebook``. Isolation is the child process and its scrubbed
|
|
11
|
+
environment, not anything an AST can decide.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
from collections.abc import Iterable, Mapping
|
|
17
|
+
|
|
18
|
+
from ...notebook.contract import ContractReport, validate_module, validate_notebook
|
|
19
|
+
from ...notebook.serialize import ModuleSource
|
|
20
|
+
|
|
21
|
+
REQUIRED_FUNCTIONS = ("detect",)
|
|
22
|
+
|
|
23
|
+
#: ``setup(ctx)`` runs once per worker before the first asset: load a list,
|
|
24
|
+
#: a model, a lookup table into ``ctx.state``.
|
|
25
|
+
OPTIONAL_FUNCTIONS = ("setup",)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def validate_detector_module(module: ModuleSource) -> ContractReport:
|
|
29
|
+
"""Parse the assembled module and check ``detect()`` exists."""
|
|
30
|
+
return validate_module(module, required=REQUIRED_FUNCTIONS)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def validate_detector_notebook(
|
|
34
|
+
cells: Iterable[Mapping[str, object] | object],
|
|
35
|
+
) -> ContractReport:
|
|
36
|
+
"""Validate a code detector's cells."""
|
|
37
|
+
return validate_notebook(cells, required=REQUIRED_FUNCTIONS)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
__all__ = [
|
|
41
|
+
"OPTIONAL_FUNCTIONS",
|
|
42
|
+
"REQUIRED_FUNCTIONS",
|
|
43
|
+
"validate_detector_module",
|
|
44
|
+
"validate_detector_notebook",
|
|
45
|
+
]
|