classifyre-cli 0.4.121__tar.gz → 0.4.123__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.4.121 → classifyre_cli-0.4.123}/.turbo/turbo-build.log +1 -1
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/PKG-INFO +1 -1
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/package.json +1 -1
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/pyproject.toml +14 -1
- classifyre_cli-0.4.123/scripts/generate_sdk_completions.py +206 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/main.py +17 -2
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/models/generated_input.py +193 -0
- classifyre_cli-0.4.123/src/notebook/__init__.py +29 -0
- classifyre_cli-0.4.123/src/notebook/cli.py +217 -0
- classifyre_cli-0.4.123/src/notebook/contract.py +216 -0
- classifyre_cli-0.4.123/src/notebook/execute.py +554 -0
- classifyre_cli-0.4.123/src/notebook/outputs.py +160 -0
- classifyre_cli-0.4.123/src/notebook/packages.py +166 -0
- classifyre_cli-0.4.123/src/notebook/protocol.py +191 -0
- classifyre_cli-0.4.123/src/notebook/redact.py +119 -0
- classifyre_cli-0.4.123/src/notebook/scaffold.py +61 -0
- classifyre_cli-0.4.123/src/notebook/sdk.py +298 -0
- classifyre_cli-0.4.123/src/notebook/serialize.py +136 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/asset_metadata.py +32 -11
- classifyre_cli-0.4.123/src/sources/custom/__init__.py +3 -0
- classifyre_cli-0.4.123/src/sources/custom/env.py +80 -0
- classifyre_cli-0.4.123/src/sources/custom/runner.py +345 -0
- classifyre_cli-0.4.123/src/sources/custom/source.py +652 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/utils/dependency_groups.py +3 -0
- classifyre_cli-0.4.123/tests/test_custom_source.py +590 -0
- classifyre_cli-0.4.123/tests/test_notebook_execute.py +366 -0
- classifyre_cli-0.4.123/tests/test_notebook_packages.py +142 -0
- classifyre_cli-0.4.123/tests/test_notebook_serialize.py +80 -0
- classifyre_cli-0.4.123/tests/test_sdk_completions.py +85 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/uv.lock +328 -136
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/.gitignore +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/.python-version +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/README.md +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/main.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/scripts/generate_models.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/config.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/base.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/broken_links/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/broken_links/detector.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/config.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/content/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/custom/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/custom/detector.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/custom/extractor.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/custom/runners/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/custom/runners/_base.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/custom/runners/_factory.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/custom/runners/_gliner2.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/custom/runners/_image_classification.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/custom/runners/_llm.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/custom/runners/_object_detection.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/custom/runners/_regex.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/custom/runners/_text_classification.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/custom/trainer.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/dependencies.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/engine_version.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/pii/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/pii/detector.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/secrets/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/secrets/detector.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/threat/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/threat/code_security_detector.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/detectors/threat/yara_detector.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/file_evaluation/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/file_evaluation/runner.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/models/generated_detectors.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/models/generated_single_asset_scan_results.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/outputs/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/outputs/base.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/outputs/console.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/outputs/factory.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/outputs/file.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/outputs/rest.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/pipeline/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/pipeline/content_provider.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/pipeline/detector_pipeline.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/pipeline/parsed_content_provider.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/pipeline/payload_window.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/pipeline/scan_cache.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/pipeline/text_artifact.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/pipeline/worker_pool.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/atlassian_common.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/azure_blob_storage/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/azure_blob_storage/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/base.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/confluence/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/confluence/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/databricks/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/databricks/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/delta_lake/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/delta_lake/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/dependencies.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/dropbox/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/dropbox/auth.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/dropbox/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/elasticsearch/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/elasticsearch/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/email/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/email/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/git/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/git/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/google_cloud_storage/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/google_cloud_storage/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/google_workspace/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/google_workspace/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/hive/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/hive/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/hugging_face/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/hugging_face/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/iceberg/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/iceberg/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/jira/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/jira/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/kafka/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/kafka/rest.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/kafka/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/lakehouse_base.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/local_folder/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/local_folder/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/meilisearch/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/meilisearch/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/microsoft_365/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/microsoft_365/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/mongodb/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/mongodb/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/mssql/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/mssql/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/mysql/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/mysql/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/neo4j/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/neo4j/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/notion/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/notion/client.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/notion/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/object_storage/base.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/opensearch/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/opensearch/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/oracle/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/oracle/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/postgresql/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/postgresql/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/powerbi/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/powerbi/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/recipe_normalizer.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/reddit/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/reddit/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/s3_client.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/s3_compatible_storage/README.md +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/s3_compatible_storage/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/s3_compatible_storage/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/sandbox/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/sandbox/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/search_engine_base.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/servicedesk/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/servicedesk/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/slack/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/slack/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/snowflake/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/snowflake/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/sqlite/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/sqlite/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/tableau/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/tableau/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/tabular_base.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/tabular_utils.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/wordpress/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/wordpress/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/youtube/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/sources/youtube/source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/telemetry.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/utils/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/utils/archive_extraction.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/utils/content_extraction.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/utils/embedded_files.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/utils/external_video.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/utils/file_metadata.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/utils/file_parser.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/utils/file_to_images.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/utils/hashing.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/utils/legacy_office.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/utils/payload.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/utils/range_reader.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/utils/resources.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/utils/torch_runtime.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/utils/transcription.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/utils/uv_sync.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/utils/validation.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/src/utils/video_processing.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/_lakehouse_fakes.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/conftest.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/broken_links/test_broken_links_detector.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/conftest.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/content/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/custom/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/custom/conftest.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/custom/test_gliner2_classification.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/custom/test_invoice_extraction.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/custom/test_llm_runner.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/custom/test_pipeline_integration.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/custom/test_regex_runner.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/custom/test_runner_hardening.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/custom/test_transformer_runners.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/pii/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/pii/conftest.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/pii/sample_invoice.pdf +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/pii/test_pii_chunking.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/pii/test_pii_detector.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/pii/test_pii_detector_extended.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/pii/test_pii_regional_entities.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/pii/test_pii_severity.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/secrets/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/secrets/test_secrets_detector.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/secrets/test_secrets_detector_extended.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/test_base_detector.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/test_custom_detector_examples_runtime.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/test_detector_catalog_commercial.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/test_detector_pipeline_types.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/test_detector_schema_examples.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/test_detector_types.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/test_phase2_detectors.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/test_registry.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/threat/__init__.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/threat/test_code_security_detector.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/detectors/threat/test_yara_detector.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/integration/test_wordpress_broken_links_detector.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/integration/test_wordpress_links_assets.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/pipeline/test_detector_outcomes.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/pipeline/test_detector_pipeline.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/pipeline/test_worker_pool.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_arrow_ipc_payloads.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_assets_metadata_catalog.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_azure_blob_storage_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_base_source_attachment.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_base_source_sampling.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_byte_valued_fields.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_config.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_confluence_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_custom_extractor.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_databricks_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_delta_lake_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_dependency_groups.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_dropbox_auth_command.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_dropbox_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_elasticsearch_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_email_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_file_evaluation_runner.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_git_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_google_cloud_storage_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_google_workspace_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_hashing.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_hive_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_hugging_face_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_iceberg_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_jira_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_kafka_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_local_folder_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_main.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_meilisearch_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_microsoft_365_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_mongodb_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_mssql_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_mysql_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_neo4j_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_notion_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_object_storage_download_efficiency.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_opensearch_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_oracle_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_outputs.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_payload_window.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_payload_window_parquet.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_postgresql_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_powerbi_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_range_reading.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_recipe_normalizer.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_reddit_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_rest_backpressure.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_s3_compatible_storage_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_sampling_automatic.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_sandbox_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_scan_cache.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_servicedesk_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_slack_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_snowflake_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_source_dependency_groups.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_source_strategy_conformance.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_sqlite_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_tableau_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_tabular_automatic_sampling.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_tabular_utils.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_torch_runtime.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_uv_sync.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_wordpress_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_youtube_source.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/test_youtube_source_integration.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/utils/test_archive_extraction.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/utils/test_content_extraction.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/utils/test_embedded_files.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/utils/test_file_metadata.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/utils/test_file_parser.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/utils/test_file_to_images.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/utils/test_legacy_office.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/utils/test_payload.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/utils/test_transcription.py +0 -0
- {classifyre_cli-0.4.121 → classifyre_cli-0.4.123}/tests/utils/test_video_processing.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "classifyre-cli"
|
|
3
|
-
version = "0.4.
|
|
3
|
+
version = "0.4.123"
|
|
4
4
|
description = "Classifyre CLI — scan and classify unstructured data sources"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.12"
|
|
@@ -45,6 +45,13 @@ build-backend = "hatchling.build"
|
|
|
45
45
|
packages = ["src"]
|
|
46
46
|
|
|
47
47
|
[dependency-groups]
|
|
48
|
+
# Notebook authoring only. `run_cell` is what makes a bare `df` on a cell's last
|
|
49
|
+
# line display as a table instead of being discarded, and what gives rich
|
|
50
|
+
# outputs a display protocol. Production never installs this: a productized
|
|
51
|
+
# notebook is an ordinary Python module run with `python workflow.py`.
|
|
52
|
+
interactive = [
|
|
53
|
+
"ipython>=8.30.0",
|
|
54
|
+
]
|
|
48
55
|
dev = [
|
|
49
56
|
"ruff>=0.15.13",
|
|
50
57
|
"mypy>=1.13.0",
|
|
@@ -340,6 +347,12 @@ ignore_missing_imports = true
|
|
|
340
347
|
module = ["bs4.*", "lxml.*"]
|
|
341
348
|
ignore_missing_imports = true
|
|
342
349
|
|
|
350
|
+
# Notebook authoring extras: present only when the `interactive` group is
|
|
351
|
+
# installed, so the executor imports them defensively.
|
|
352
|
+
[[tool.mypy.overrides]]
|
|
353
|
+
module = ["IPython.*", "matplotlib.*"]
|
|
354
|
+
ignore_missing_imports = true
|
|
355
|
+
|
|
343
356
|
[[tool.mypy.overrides]]
|
|
344
357
|
module = [
|
|
345
358
|
"neo4j.*",
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"""Generate the notebook editor's SDK completions from the SDK itself.
|
|
2
|
+
|
|
3
|
+
The editor has to offer `ctx.secret(...)` and `Asset(...)` with the right
|
|
4
|
+
arguments, and a hand-written list of those would be wrong the first time
|
|
5
|
+
someone adds a parameter. So the list is derived by introspecting the runtime
|
|
6
|
+
objects a notebook actually receives -- add a method to ``Context`` and the
|
|
7
|
+
editor offers it, with its real signature and its real docstring.
|
|
8
|
+
|
|
9
|
+
Run from apps/cli:
|
|
10
|
+
|
|
11
|
+
uv run python scripts/generate_sdk_completions.py
|
|
12
|
+
|
|
13
|
+
``tests/test_sdk_completions.py`` fails when the checked-in file drifts from
|
|
14
|
+
what this would produce, so the two cannot silently diverge.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
import dataclasses
|
|
20
|
+
import inspect
|
|
21
|
+
import json
|
|
22
|
+
import sys
|
|
23
|
+
from pathlib import Path
|
|
24
|
+
from typing import Any
|
|
25
|
+
|
|
26
|
+
CLI_ROOT = Path(__file__).resolve().parents[1]
|
|
27
|
+
sys.path.insert(0, str(CLI_ROOT))
|
|
28
|
+
|
|
29
|
+
from src.notebook.contract import ( # noqa: E402
|
|
30
|
+
OPTIONAL_FUNCTIONS,
|
|
31
|
+
REQUIRED_FUNCTIONS,
|
|
32
|
+
)
|
|
33
|
+
from src.notebook.sdk import Asset, Context # noqa: E402
|
|
34
|
+
|
|
35
|
+
OUTPUT_PATH = (
|
|
36
|
+
CLI_ROOT.parents[1] / "packages" / "schemas" / "src" / "schemas" / "notebook_completions.json"
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _summary(obj: Any) -> str:
|
|
41
|
+
"""The whole docstring, which is what the editor shows on demand.
|
|
42
|
+
|
|
43
|
+
Not just the first paragraph: the part of a docstring that changes what an
|
|
44
|
+
author writes is often the caveat below it -- that reading ``ctx.offset``
|
|
45
|
+
hands paging to the notebook, say -- and truncating to a one-liner is
|
|
46
|
+
exactly how that gets lost.
|
|
47
|
+
"""
|
|
48
|
+
return (inspect.getdoc(obj) or "").strip()
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _signature(func: Any, *, drop_self: bool = True) -> str:
|
|
52
|
+
try:
|
|
53
|
+
signature = inspect.signature(func)
|
|
54
|
+
except (TypeError, ValueError):
|
|
55
|
+
return "()"
|
|
56
|
+
parameters = [
|
|
57
|
+
parameter
|
|
58
|
+
for name, parameter in signature.parameters.items()
|
|
59
|
+
if not (drop_self and name == "self")
|
|
60
|
+
]
|
|
61
|
+
return str(signature.replace(parameters=parameters))
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _return_type(func: Any) -> str:
|
|
65
|
+
"""The annotated return type, rendered as it appears in the source."""
|
|
66
|
+
try:
|
|
67
|
+
annotation = inspect.signature(func).return_annotation
|
|
68
|
+
except (TypeError, ValueError):
|
|
69
|
+
return ""
|
|
70
|
+
if annotation is inspect.Signature.empty:
|
|
71
|
+
return ""
|
|
72
|
+
return str(annotation).strip("'")
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _snippet(name: str, func: Any) -> str:
|
|
76
|
+
"""A tab-stop snippet, so calling a method lands the cursor in its first arg."""
|
|
77
|
+
try:
|
|
78
|
+
signature = inspect.signature(func)
|
|
79
|
+
except (TypeError, ValueError):
|
|
80
|
+
return f"{name}()"
|
|
81
|
+
required = [
|
|
82
|
+
parameter_name
|
|
83
|
+
for parameter_name, parameter in signature.parameters.items()
|
|
84
|
+
if parameter_name != "self"
|
|
85
|
+
and parameter.default is inspect.Parameter.empty
|
|
86
|
+
and parameter.kind not in (inspect.Parameter.VAR_POSITIONAL, inspect.Parameter.VAR_KEYWORD)
|
|
87
|
+
]
|
|
88
|
+
if not required:
|
|
89
|
+
return f"{name}()"
|
|
90
|
+
placeholders = ", ".join(
|
|
91
|
+
f"${{{index}:{parameter}}}" for index, parameter in enumerate(required, start=1)
|
|
92
|
+
)
|
|
93
|
+
return f"{name}({placeholders})"
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
#: Public on Context because the runtime reads them, but not part of what a
|
|
97
|
+
#: notebook author writes -- offering them would be noise at best and a
|
|
98
|
+
#: misleading suggestion at worst.
|
|
99
|
+
RUNTIME_ONLY_MEMBERS = frozenset({"set_offset", "offset_consumed", "next_cursor"})
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _members(cls: type) -> list[dict[str, Any]]:
|
|
103
|
+
members: list[dict[str, Any]] = []
|
|
104
|
+
for name, member in sorted(vars(cls).items()):
|
|
105
|
+
if name.startswith("_") or name in RUNTIME_ONLY_MEMBERS:
|
|
106
|
+
continue
|
|
107
|
+
if isinstance(member, property):
|
|
108
|
+
members.append(
|
|
109
|
+
{
|
|
110
|
+
"label": name,
|
|
111
|
+
"kind": "property",
|
|
112
|
+
# A property is read, not called, so showing its getter's
|
|
113
|
+
# "()" would suggest otherwise. Only the type it yields.
|
|
114
|
+
"detail": _return_type(member.fget) if member.fget else "",
|
|
115
|
+
"documentation": _summary(member),
|
|
116
|
+
"insertText": name,
|
|
117
|
+
}
|
|
118
|
+
)
|
|
119
|
+
elif inspect.isfunction(member) or isinstance(member, staticmethod):
|
|
120
|
+
func = member.__func__ if isinstance(member, staticmethod) else member
|
|
121
|
+
members.append(
|
|
122
|
+
{
|
|
123
|
+
"label": name,
|
|
124
|
+
"kind": "method",
|
|
125
|
+
"detail": _signature(func),
|
|
126
|
+
"documentation": _summary(func),
|
|
127
|
+
"insertText": _snippet(name, func),
|
|
128
|
+
}
|
|
129
|
+
)
|
|
130
|
+
return members
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def _fields(cls: type) -> list[dict[str, Any]]:
|
|
134
|
+
"""Dataclass fields, offered as keyword arguments when constructing one."""
|
|
135
|
+
annotations = getattr(cls, "__annotations__", {})
|
|
136
|
+
dataclass_fields = getattr(cls, "__dataclass_fields__", {})
|
|
137
|
+
fields: list[dict[str, Any]] = []
|
|
138
|
+
for name in annotations:
|
|
139
|
+
if name.startswith("_"):
|
|
140
|
+
continue
|
|
141
|
+
field = dataclass_fields.get(name)
|
|
142
|
+
# dataclasses signal "no default" with MISSING, not Parameter.empty --
|
|
143
|
+
# the wrong sentinel marks every field optional.
|
|
144
|
+
required = field is not None and (
|
|
145
|
+
field.default is dataclasses.MISSING and field.default_factory is dataclasses.MISSING
|
|
146
|
+
)
|
|
147
|
+
fields.append(
|
|
148
|
+
{
|
|
149
|
+
"label": name,
|
|
150
|
+
"kind": "field",
|
|
151
|
+
"detail": str(annotations[name]),
|
|
152
|
+
"required": required,
|
|
153
|
+
"insertText": f"{name}=",
|
|
154
|
+
}
|
|
155
|
+
)
|
|
156
|
+
return fields
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def build() -> dict[str, Any]:
|
|
160
|
+
return {
|
|
161
|
+
"$comment": (
|
|
162
|
+
"Generated by apps/cli/scripts/generate_sdk_completions.py from "
|
|
163
|
+
"apps/cli/src/notebook/sdk.py. Do not edit by hand."
|
|
164
|
+
),
|
|
165
|
+
"module": "classifyre",
|
|
166
|
+
"globals": [
|
|
167
|
+
{
|
|
168
|
+
"label": "ctx",
|
|
169
|
+
"kind": "variable",
|
|
170
|
+
"detail": "Context",
|
|
171
|
+
"documentation": _summary(Context),
|
|
172
|
+
"insertText": "ctx",
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"label": "Asset",
|
|
176
|
+
"kind": "class",
|
|
177
|
+
"detail": "Asset(...)",
|
|
178
|
+
"documentation": _summary(Asset),
|
|
179
|
+
"insertText": "Asset",
|
|
180
|
+
},
|
|
181
|
+
],
|
|
182
|
+
"objects": {
|
|
183
|
+
"ctx": {"type": "Context", "members": _members(Context)},
|
|
184
|
+
},
|
|
185
|
+
"classes": {
|
|
186
|
+
"Asset": {
|
|
187
|
+
"documentation": _summary(Asset),
|
|
188
|
+
"fields": _fields(Asset),
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
"contract": {
|
|
192
|
+
"required": list(REQUIRED_FUNCTIONS),
|
|
193
|
+
"optional": list(OPTIONAL_FUNCTIONS),
|
|
194
|
+
},
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def main() -> int:
|
|
199
|
+
payload = build()
|
|
200
|
+
OUTPUT_PATH.write_text(json.dumps(payload, indent=2) + "\n", encoding="utf-8")
|
|
201
|
+
print(f"Wrote {OUTPUT_PATH.relative_to(CLI_ROOT.parents[1])}")
|
|
202
|
+
return 0
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
if __name__ == "__main__":
|
|
206
|
+
raise SystemExit(main())
|
|
@@ -743,14 +743,24 @@ def main() -> None:
|
|
|
743
743
|
parser = argparse.ArgumentParser(description="Classifyre Metadata Extraction CLI")
|
|
744
744
|
parser.add_argument(
|
|
745
745
|
"command",
|
|
746
|
-
choices=[
|
|
746
|
+
choices=[
|
|
747
|
+
"test",
|
|
748
|
+
"extract",
|
|
749
|
+
"discover",
|
|
750
|
+
"notebook",
|
|
751
|
+
"evaluate-file",
|
|
752
|
+
"train",
|
|
753
|
+
"dropbox-auth",
|
|
754
|
+
],
|
|
747
755
|
help="Command to run",
|
|
748
756
|
)
|
|
749
757
|
parser.add_argument(
|
|
750
758
|
"recipe",
|
|
751
759
|
nargs="?",
|
|
752
760
|
default=None,
|
|
753
|
-
help=
|
|
761
|
+
help=(
|
|
762
|
+
"Path to recipe JSON (a file path for evaluate-file, an execution request for notebook)"
|
|
763
|
+
),
|
|
754
764
|
)
|
|
755
765
|
parser.add_argument("--debug", action="store_true", help="Enable debug logging")
|
|
756
766
|
parser.add_argument(
|
|
@@ -856,6 +866,11 @@ def main() -> None:
|
|
|
856
866
|
if args.command == "dropbox-auth":
|
|
857
867
|
sys.exit(run_dropbox_auth_command(args))
|
|
858
868
|
|
|
869
|
+
if args.command == "notebook":
|
|
870
|
+
from .notebook.cli import run_notebook_command
|
|
871
|
+
|
|
872
|
+
sys.exit(run_notebook_command(args))
|
|
873
|
+
|
|
859
874
|
if args.command == "evaluate-file":
|
|
860
875
|
run_evaluate_file_command(args)
|
|
861
876
|
return
|
|
@@ -14,6 +14,7 @@ from pydantic import (
|
|
|
14
14
|
EmailStr,
|
|
15
15
|
Field,
|
|
16
16
|
RootModel,
|
|
17
|
+
constr,
|
|
17
18
|
)
|
|
18
19
|
|
|
19
20
|
|
|
@@ -59,6 +60,7 @@ class AssetType(StrEnum):
|
|
|
59
60
|
HUGGING_FACE = 'HUGGING_FACE'
|
|
60
61
|
SANDBOX = 'SANDBOX'
|
|
61
62
|
GIT = 'GIT'
|
|
63
|
+
CUSTOM = 'CUSTOM'
|
|
62
64
|
|
|
63
65
|
|
|
64
66
|
class DetectorType(StrEnum):
|
|
@@ -391,6 +393,7 @@ class Type(StrEnum):
|
|
|
391
393
|
HUGGING_FACE = 'HUGGING_FACE'
|
|
392
394
|
SANDBOX = 'SANDBOX'
|
|
393
395
|
GIT = 'GIT'
|
|
396
|
+
CUSTOM = 'CUSTOM'
|
|
394
397
|
|
|
395
398
|
|
|
396
399
|
class YouTubeRequired(BaseModel):
|
|
@@ -3473,6 +3476,7 @@ class Type22(StrEnum):
|
|
|
3473
3476
|
HUGGING_FACE = 'HUGGING_FACE'
|
|
3474
3477
|
SANDBOX = 'SANDBOX'
|
|
3475
3478
|
GIT = 'GIT'
|
|
3479
|
+
CUSTOM = 'CUSTOM'
|
|
3476
3480
|
|
|
3477
3481
|
|
|
3478
3482
|
class ConfluenceInput(CoreInput):
|
|
@@ -5278,6 +5282,151 @@ class GitInput(CoreInput):
|
|
|
5278
5282
|
)
|
|
5279
5283
|
|
|
5280
5284
|
|
|
5285
|
+
class NotebookCodeCell(BaseModel):
|
|
5286
|
+
"""
|
|
5287
|
+
A Python cell. Must remain valid standard Python -- IPython magics (%time, !pip) are rejected.
|
|
5288
|
+
"""
|
|
5289
|
+
|
|
5290
|
+
model_config = ConfigDict(
|
|
5291
|
+
extra='forbid',
|
|
5292
|
+
)
|
|
5293
|
+
id: str = Field(
|
|
5294
|
+
...,
|
|
5295
|
+
description='Stable cell identifier, unique within the notebook',
|
|
5296
|
+
pattern='^[A-Za-z0-9_-]{1,64}$',
|
|
5297
|
+
)
|
|
5298
|
+
type: Literal['code']
|
|
5299
|
+
source: str = Field(
|
|
5300
|
+
..., description='Python source of this cell', max_length=100000
|
|
5301
|
+
)
|
|
5302
|
+
|
|
5303
|
+
|
|
5304
|
+
class NotebookMarkdownCell(BaseModel):
|
|
5305
|
+
"""
|
|
5306
|
+
Prose. Never executed; serialized as comments when the notebook is exported to Python.
|
|
5307
|
+
"""
|
|
5308
|
+
|
|
5309
|
+
model_config = ConfigDict(
|
|
5310
|
+
extra='forbid',
|
|
5311
|
+
)
|
|
5312
|
+
id: str = Field(
|
|
5313
|
+
...,
|
|
5314
|
+
description='Stable cell identifier, unique within the notebook',
|
|
5315
|
+
pattern='^[A-Za-z0-9_-]{1,64}$',
|
|
5316
|
+
)
|
|
5317
|
+
type: Literal['markdown']
|
|
5318
|
+
source: str = Field(
|
|
5319
|
+
..., description='Markdown source of this cell', max_length=100000
|
|
5320
|
+
)
|
|
5321
|
+
|
|
5322
|
+
|
|
5323
|
+
class CustomNotebook(BaseModel):
|
|
5324
|
+
"""
|
|
5325
|
+
Cells run in document order in one fresh process per execution. There is no persistent kernel: state is rebuilt from the current cell sources every time.
|
|
5326
|
+
"""
|
|
5327
|
+
|
|
5328
|
+
model_config = ConfigDict(
|
|
5329
|
+
extra='forbid',
|
|
5330
|
+
)
|
|
5331
|
+
revision: int | None = Field(
|
|
5332
|
+
1,
|
|
5333
|
+
description='Monotonic revision, bumped on every save. Used for optimistic locking so two editors cannot silently overwrite each other.',
|
|
5334
|
+
ge=1,
|
|
5335
|
+
)
|
|
5336
|
+
cells: list[NotebookCodeCell | NotebookMarkdownCell] = Field(
|
|
5337
|
+
...,
|
|
5338
|
+
description='Ordered notebook cells. The assembled code cells must define test_connection() and extract().',
|
|
5339
|
+
max_length=200,
|
|
5340
|
+
min_length=1,
|
|
5341
|
+
)
|
|
5342
|
+
|
|
5343
|
+
|
|
5344
|
+
class CustomRequired(BaseModel):
|
|
5345
|
+
"""
|
|
5346
|
+
The Python notebook that implements this connector.
|
|
5347
|
+
"""
|
|
5348
|
+
|
|
5349
|
+
model_config = ConfigDict(
|
|
5350
|
+
extra='forbid',
|
|
5351
|
+
)
|
|
5352
|
+
notebook: CustomNotebook
|
|
5353
|
+
|
|
5354
|
+
|
|
5355
|
+
class Secrets(RootModel[str]):
|
|
5356
|
+
root: str = Field(..., max_length=8192)
|
|
5357
|
+
|
|
5358
|
+
|
|
5359
|
+
class CustomMasked(BaseModel):
|
|
5360
|
+
"""
|
|
5361
|
+
Encrypted key/value pairs, stored the same way as any other source credential.
|
|
5362
|
+
"""
|
|
5363
|
+
|
|
5364
|
+
model_config = ConfigDict(
|
|
5365
|
+
extra='forbid',
|
|
5366
|
+
)
|
|
5367
|
+
secrets: dict[constr(pattern=r'^[A-Za-z_][A-Za-z0-9_]{0,62}$'), Secrets] | None = (
|
|
5368
|
+
Field(
|
|
5369
|
+
{},
|
|
5370
|
+
description='Secret values the notebook reads with ctx.secret("name"). Encrypted at rest and redacted from logs and cell output. Keys must be valid Python identifiers.',
|
|
5371
|
+
max_length=64,
|
|
5372
|
+
validate_default=True,
|
|
5373
|
+
)
|
|
5374
|
+
)
|
|
5375
|
+
|
|
5376
|
+
|
|
5377
|
+
class CustomOptionalLimits(BaseModel):
|
|
5378
|
+
"""
|
|
5379
|
+
Bounds applied to every notebook execution and scan.
|
|
5380
|
+
"""
|
|
5381
|
+
|
|
5382
|
+
model_config = ConfigDict(
|
|
5383
|
+
extra='forbid',
|
|
5384
|
+
)
|
|
5385
|
+
max_assets: int | None = Field(
|
|
5386
|
+
None,
|
|
5387
|
+
description='Stop a scan after this many assets. Unset means no cap.',
|
|
5388
|
+
ge=1,
|
|
5389
|
+
le=1000000,
|
|
5390
|
+
)
|
|
5391
|
+
timeout_seconds: int | None = Field(
|
|
5392
|
+
900,
|
|
5393
|
+
description='Kill an execution that runs longer than this. Cells cannot be interrupted from inside Python, so this is the real stop button.',
|
|
5394
|
+
ge=10,
|
|
5395
|
+
le=86400,
|
|
5396
|
+
)
|
|
5397
|
+
max_output_bytes: int | None = Field(
|
|
5398
|
+
2097152,
|
|
5399
|
+
description='Total serialized cell output kept per execution. Larger outputs are truncated rather than stored.',
|
|
5400
|
+
ge=1024,
|
|
5401
|
+
le=52428800,
|
|
5402
|
+
)
|
|
5403
|
+
|
|
5404
|
+
|
|
5405
|
+
class Variables(RootModel[str]):
|
|
5406
|
+
root: str = Field(..., max_length=8192)
|
|
5407
|
+
|
|
5408
|
+
|
|
5409
|
+
class NotebookPackage(BaseModel):
|
|
5410
|
+
"""
|
|
5411
|
+
A Python distribution installed before the notebook runs.
|
|
5412
|
+
"""
|
|
5413
|
+
|
|
5414
|
+
model_config = ConfigDict(
|
|
5415
|
+
extra='forbid',
|
|
5416
|
+
)
|
|
5417
|
+
name: str = Field(
|
|
5418
|
+
...,
|
|
5419
|
+
description="Distribution name as published on the index (for example 'pandas').",
|
|
5420
|
+
pattern='^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$',
|
|
5421
|
+
)
|
|
5422
|
+
version: str | None = Field(
|
|
5423
|
+
None,
|
|
5424
|
+
description="Optional version or specifier: '2.2.0', '>=2.0', '~=1.4'. Empty means latest.",
|
|
5425
|
+
max_length=64,
|
|
5426
|
+
pattern='^$|^(==|>=|<=|~=|!=|>|<).+$|^[0-9][A-Za-z0-9._*+!-]*$',
|
|
5427
|
+
)
|
|
5428
|
+
|
|
5429
|
+
|
|
5281
5430
|
class YouTubeInput(CoreInput):
|
|
5282
5431
|
type: Literal['YOUTUBE'] = Field(..., description='Type of the asset or source')
|
|
5283
5432
|
required: YouTubeRequired
|
|
@@ -5413,6 +5562,48 @@ class IcebergInput(CoreInput):
|
|
|
5413
5562
|
)
|
|
5414
5563
|
|
|
5415
5564
|
|
|
5565
|
+
class CustomOptional(BaseModel):
|
|
5566
|
+
model_config = ConfigDict(
|
|
5567
|
+
extra='forbid',
|
|
5568
|
+
)
|
|
5569
|
+
variables: (
|
|
5570
|
+
dict[constr(pattern=r'^[A-Za-z_][A-Za-z0-9_]{0,62}$'), Variables] | None
|
|
5571
|
+
) = Field(
|
|
5572
|
+
{},
|
|
5573
|
+
description='Non-secret values the notebook reads with ctx.var("name"), such as a base URL or an account id. Stored in clear text. Keys must be valid Python identifiers.',
|
|
5574
|
+
max_length=64,
|
|
5575
|
+
validate_default=True,
|
|
5576
|
+
)
|
|
5577
|
+
limits: CustomOptionalLimits | None = None
|
|
5578
|
+
packages: list[NotebookPackage] | None = Field(
|
|
5579
|
+
[],
|
|
5580
|
+
description="Python packages installed into the run environment before any cell executes. Installed with uv; the base image's own dependencies are always present and do not need listing.",
|
|
5581
|
+
max_length=50,
|
|
5582
|
+
validate_default=True,
|
|
5583
|
+
)
|
|
5584
|
+
|
|
5585
|
+
|
|
5586
|
+
class CustomInput(CoreInput):
|
|
5587
|
+
type: Literal['CUSTOM'] = Field(..., description='Type of the asset or source')
|
|
5588
|
+
required: CustomRequired
|
|
5589
|
+
masked: CustomMasked | None = None
|
|
5590
|
+
optional: CustomOptional | None = None
|
|
5591
|
+
detectors: list[Detector] | None = Field(
|
|
5592
|
+
None, description='Detectors to run on ingested content'
|
|
5593
|
+
)
|
|
5594
|
+
custom_detectors: list[CustomDetectorSelection] | None = Field(
|
|
5595
|
+
None,
|
|
5596
|
+
description='Reusable custom detector IDs selected from the custom detector catalog.',
|
|
5597
|
+
)
|
|
5598
|
+
sampling: SamplingConfig
|
|
5599
|
+
scan_cache: ScanCacheConfig | None = None
|
|
5600
|
+
resources: ResourceOverrides | None = None
|
|
5601
|
+
cleanup_removed_detector_findings: bool | None = Field(
|
|
5602
|
+
True,
|
|
5603
|
+
description='When enabled (default), findings produced by detectors that are no longer configured on this source (removed or disabled) are automatically resolved at the start of the next run, keeping the findings list in step with the current detector set.',
|
|
5604
|
+
)
|
|
5605
|
+
|
|
5606
|
+
|
|
5416
5607
|
class SourceInput(
|
|
5417
5608
|
RootModel[
|
|
5418
5609
|
SandboxInput
|
|
@@ -5452,6 +5643,7 @@ class SourceInput(
|
|
|
5452
5643
|
| DropboxInput
|
|
5453
5644
|
| HuggingFaceInput
|
|
5454
5645
|
| GitInput
|
|
5646
|
+
| CustomInput
|
|
5455
5647
|
]
|
|
5456
5648
|
):
|
|
5457
5649
|
root: (
|
|
@@ -5492,6 +5684,7 @@ class SourceInput(
|
|
|
5492
5684
|
| DropboxInput
|
|
5493
5685
|
| HuggingFaceInput
|
|
5494
5686
|
| GitInput
|
|
5687
|
+
| CustomInput
|
|
5495
5688
|
) = Field(
|
|
5496
5689
|
...,
|
|
5497
5690
|
description='Merged configuration schema with all source types and common definitions',
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Notebook runtime for the CUSTOM source.
|
|
2
|
+
|
|
3
|
+
A notebook is a list of cells, not a running kernel. Every execution assembles
|
|
4
|
+
the current cell sources into one ordinary Python module, runs it in a fresh
|
|
5
|
+
process, serializes what the target cell produced, and exits. Nothing survives
|
|
6
|
+
between executions except the cell sources themselves -- which is what keeps
|
|
7
|
+
"what you see" and "what runs" the same thing.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from .contract import ContractReport, ContractViolation, validate_notebook
|
|
11
|
+
from .protocol import ExecutionMode, ExecutionRequest, ExecutionResponse
|
|
12
|
+
from .redact import Redactor
|
|
13
|
+
from .scaffold import cell_for_function, scaffold_cells
|
|
14
|
+
from .serialize import CellSpan, ModuleSource, to_module_source
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"CellSpan",
|
|
18
|
+
"ContractReport",
|
|
19
|
+
"ContractViolation",
|
|
20
|
+
"ExecutionMode",
|
|
21
|
+
"ExecutionRequest",
|
|
22
|
+
"ExecutionResponse",
|
|
23
|
+
"ModuleSource",
|
|
24
|
+
"Redactor",
|
|
25
|
+
"cell_for_function",
|
|
26
|
+
"scaffold_cells",
|
|
27
|
+
"to_module_source",
|
|
28
|
+
"validate_notebook",
|
|
29
|
+
]
|