omnibase_infra 0.2.6__py3-none-any.whl
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.
- omnibase_infra/__init__.py +101 -0
- omnibase_infra/adapters/adapter_onex_tool_execution.py +451 -0
- omnibase_infra/capabilities/__init__.py +15 -0
- omnibase_infra/capabilities/capability_inference_rules.py +211 -0
- omnibase_infra/capabilities/contract_capability_extractor.py +221 -0
- omnibase_infra/capabilities/intent_type_extractor.py +160 -0
- omnibase_infra/cli/__init__.py +1 -0
- omnibase_infra/cli/commands.py +216 -0
- omnibase_infra/clients/__init__.py +0 -0
- omnibase_infra/configs/widget_mapping.yaml +176 -0
- omnibase_infra/constants_topic_patterns.py +26 -0
- omnibase_infra/contracts/handlers/filesystem/handler_contract.yaml +264 -0
- omnibase_infra/contracts/handlers/mcp/handler_contract.yaml +141 -0
- omnibase_infra/decorators/__init__.py +29 -0
- omnibase_infra/decorators/allow_any.py +109 -0
- omnibase_infra/dlq/__init__.py +90 -0
- omnibase_infra/dlq/constants_dlq.py +57 -0
- omnibase_infra/dlq/models/__init__.py +26 -0
- omnibase_infra/dlq/models/enum_replay_status.py +37 -0
- omnibase_infra/dlq/models/model_dlq_replay_record.py +135 -0
- omnibase_infra/dlq/models/model_dlq_tracking_config.py +184 -0
- omnibase_infra/dlq/service_dlq_tracking.py +611 -0
- omnibase_infra/enums/__init__.py +132 -0
- omnibase_infra/enums/enum_any_type_violation.py +104 -0
- omnibase_infra/enums/enum_backend_type.py +27 -0
- omnibase_infra/enums/enum_capture_outcome.py +42 -0
- omnibase_infra/enums/enum_capture_state.py +88 -0
- omnibase_infra/enums/enum_chain_violation_type.py +119 -0
- omnibase_infra/enums/enum_circuit_state.py +51 -0
- omnibase_infra/enums/enum_confirmation_event_type.py +27 -0
- omnibase_infra/enums/enum_consumer_group_purpose.py +92 -0
- omnibase_infra/enums/enum_contract_type.py +84 -0
- omnibase_infra/enums/enum_dedupe_strategy.py +46 -0
- omnibase_infra/enums/enum_dispatch_status.py +191 -0
- omnibase_infra/enums/enum_environment.py +46 -0
- omnibase_infra/enums/enum_execution_shape_violation.py +103 -0
- omnibase_infra/enums/enum_handler_error_type.py +111 -0
- omnibase_infra/enums/enum_handler_loader_error.py +178 -0
- omnibase_infra/enums/enum_handler_source_mode.py +86 -0
- omnibase_infra/enums/enum_handler_source_type.py +87 -0
- omnibase_infra/enums/enum_handler_type.py +77 -0
- omnibase_infra/enums/enum_handler_type_category.py +61 -0
- omnibase_infra/enums/enum_infra_transport_type.py +73 -0
- omnibase_infra/enums/enum_introspection_reason.py +154 -0
- omnibase_infra/enums/enum_kafka_acks.py +99 -0
- omnibase_infra/enums/enum_message_category.py +213 -0
- omnibase_infra/enums/enum_node_archetype.py +74 -0
- omnibase_infra/enums/enum_node_output_type.py +185 -0
- omnibase_infra/enums/enum_non_retryable_error_category.py +224 -0
- omnibase_infra/enums/enum_policy_type.py +32 -0
- omnibase_infra/enums/enum_registration_state.py +261 -0
- omnibase_infra/enums/enum_registration_status.py +33 -0
- omnibase_infra/enums/enum_registry_response_status.py +28 -0
- omnibase_infra/enums/enum_response_status.py +26 -0
- omnibase_infra/enums/enum_retry_error_category.py +98 -0
- omnibase_infra/enums/enum_security_rule_id.py +103 -0
- omnibase_infra/enums/enum_selection_strategy.py +91 -0
- omnibase_infra/enums/enum_topic_standard.py +42 -0
- omnibase_infra/enums/enum_validation_severity.py +78 -0
- omnibase_infra/errors/__init__.py +160 -0
- omnibase_infra/errors/error_architecture_violation.py +152 -0
- omnibase_infra/errors/error_binding_resolution.py +128 -0
- omnibase_infra/errors/error_chain_propagation.py +188 -0
- omnibase_infra/errors/error_compute_registry.py +95 -0
- omnibase_infra/errors/error_consul.py +132 -0
- omnibase_infra/errors/error_container_wiring.py +243 -0
- omnibase_infra/errors/error_event_bus_registry.py +105 -0
- omnibase_infra/errors/error_infra.py +610 -0
- omnibase_infra/errors/error_message_type_registry.py +101 -0
- omnibase_infra/errors/error_policy_registry.py +115 -0
- omnibase_infra/errors/error_vault.py +123 -0
- omnibase_infra/event_bus/__init__.py +72 -0
- omnibase_infra/event_bus/configs/kafka_event_bus_config.yaml +84 -0
- omnibase_infra/event_bus/event_bus_inmemory.py +797 -0
- omnibase_infra/event_bus/event_bus_kafka.py +1716 -0
- omnibase_infra/event_bus/mixin_kafka_broadcast.py +180 -0
- omnibase_infra/event_bus/mixin_kafka_dlq.py +771 -0
- omnibase_infra/event_bus/models/__init__.py +29 -0
- omnibase_infra/event_bus/models/config/__init__.py +20 -0
- omnibase_infra/event_bus/models/config/model_kafka_event_bus_config.py +693 -0
- omnibase_infra/event_bus/models/model_dlq_event.py +206 -0
- omnibase_infra/event_bus/models/model_dlq_metrics.py +304 -0
- omnibase_infra/event_bus/models/model_event_headers.py +115 -0
- omnibase_infra/event_bus/models/model_event_message.py +60 -0
- omnibase_infra/event_bus/testing/__init__.py +26 -0
- omnibase_infra/event_bus/testing/adapter_protocol_event_publisher_inmemory.py +418 -0
- omnibase_infra/event_bus/testing/model_publisher_metrics.py +64 -0
- omnibase_infra/event_bus/topic_constants.py +376 -0
- omnibase_infra/handlers/__init__.py +82 -0
- omnibase_infra/handlers/filesystem/__init__.py +48 -0
- omnibase_infra/handlers/filesystem/enum_file_system_operation.py +35 -0
- omnibase_infra/handlers/filesystem/model_file_system_request.py +298 -0
- omnibase_infra/handlers/filesystem/model_file_system_result.py +166 -0
- omnibase_infra/handlers/handler_consul.py +795 -0
- omnibase_infra/handlers/handler_db.py +1046 -0
- omnibase_infra/handlers/handler_filesystem.py +1478 -0
- omnibase_infra/handlers/handler_graph.py +2015 -0
- omnibase_infra/handlers/handler_http.py +926 -0
- omnibase_infra/handlers/handler_intent.py +387 -0
- omnibase_infra/handlers/handler_manifest_persistence.contract.yaml +184 -0
- omnibase_infra/handlers/handler_manifest_persistence.py +1539 -0
- omnibase_infra/handlers/handler_mcp.py +1430 -0
- omnibase_infra/handlers/handler_qdrant.py +1076 -0
- omnibase_infra/handlers/handler_vault.py +428 -0
- omnibase_infra/handlers/mcp/__init__.py +19 -0
- omnibase_infra/handlers/mcp/adapter_onex_to_mcp.py +446 -0
- omnibase_infra/handlers/mcp/protocols.py +178 -0
- omnibase_infra/handlers/mcp/transport_streamable_http.py +352 -0
- omnibase_infra/handlers/mixins/__init__.py +47 -0
- omnibase_infra/handlers/mixins/mixin_consul_initialization.py +349 -0
- omnibase_infra/handlers/mixins/mixin_consul_kv.py +338 -0
- omnibase_infra/handlers/mixins/mixin_consul_service.py +542 -0
- omnibase_infra/handlers/mixins/mixin_consul_topic_index.py +585 -0
- omnibase_infra/handlers/mixins/mixin_vault_initialization.py +338 -0
- omnibase_infra/handlers/mixins/mixin_vault_retry.py +412 -0
- omnibase_infra/handlers/mixins/mixin_vault_secrets.py +450 -0
- omnibase_infra/handlers/mixins/mixin_vault_token.py +365 -0
- omnibase_infra/handlers/models/__init__.py +286 -0
- omnibase_infra/handlers/models/consul/__init__.py +81 -0
- omnibase_infra/handlers/models/consul/enum_consul_operation_type.py +57 -0
- omnibase_infra/handlers/models/consul/model_consul_deregister_payload.py +51 -0
- omnibase_infra/handlers/models/consul/model_consul_handler_config.py +153 -0
- omnibase_infra/handlers/models/consul/model_consul_handler_payload.py +89 -0
- omnibase_infra/handlers/models/consul/model_consul_kv_get_found_payload.py +55 -0
- omnibase_infra/handlers/models/consul/model_consul_kv_get_not_found_payload.py +49 -0
- omnibase_infra/handlers/models/consul/model_consul_kv_get_recurse_payload.py +50 -0
- omnibase_infra/handlers/models/consul/model_consul_kv_item.py +33 -0
- omnibase_infra/handlers/models/consul/model_consul_kv_put_payload.py +41 -0
- omnibase_infra/handlers/models/consul/model_consul_register_payload.py +53 -0
- omnibase_infra/handlers/models/consul/model_consul_retry_config.py +66 -0
- omnibase_infra/handlers/models/consul/model_payload_consul.py +66 -0
- omnibase_infra/handlers/models/consul/registry_payload_consul.py +214 -0
- omnibase_infra/handlers/models/graph/__init__.py +35 -0
- omnibase_infra/handlers/models/graph/enum_graph_operation_type.py +20 -0
- omnibase_infra/handlers/models/graph/model_graph_execute_payload.py +38 -0
- omnibase_infra/handlers/models/graph/model_graph_handler_config.py +54 -0
- omnibase_infra/handlers/models/graph/model_graph_handler_payload.py +44 -0
- omnibase_infra/handlers/models/graph/model_graph_query_payload.py +40 -0
- omnibase_infra/handlers/models/graph/model_graph_record.py +22 -0
- omnibase_infra/handlers/models/http/__init__.py +50 -0
- omnibase_infra/handlers/models/http/enum_http_operation_type.py +29 -0
- omnibase_infra/handlers/models/http/model_http_body_content.py +45 -0
- omnibase_infra/handlers/models/http/model_http_get_payload.py +88 -0
- omnibase_infra/handlers/models/http/model_http_handler_payload.py +90 -0
- omnibase_infra/handlers/models/http/model_http_post_payload.py +88 -0
- omnibase_infra/handlers/models/http/model_payload_http.py +66 -0
- omnibase_infra/handlers/models/http/registry_payload_http.py +212 -0
- omnibase_infra/handlers/models/mcp/__init__.py +23 -0
- omnibase_infra/handlers/models/mcp/enum_mcp_operation_type.py +24 -0
- omnibase_infra/handlers/models/mcp/model_mcp_handler_config.py +40 -0
- omnibase_infra/handlers/models/mcp/model_mcp_tool_call.py +32 -0
- omnibase_infra/handlers/models/mcp/model_mcp_tool_result.py +45 -0
- omnibase_infra/handlers/models/model_consul_handler_response.py +96 -0
- omnibase_infra/handlers/models/model_db_describe_response.py +83 -0
- omnibase_infra/handlers/models/model_db_query_payload.py +95 -0
- omnibase_infra/handlers/models/model_db_query_response.py +60 -0
- omnibase_infra/handlers/models/model_filesystem_config.py +98 -0
- omnibase_infra/handlers/models/model_filesystem_delete_payload.py +54 -0
- omnibase_infra/handlers/models/model_filesystem_delete_result.py +77 -0
- omnibase_infra/handlers/models/model_filesystem_directory_entry.py +75 -0
- omnibase_infra/handlers/models/model_filesystem_ensure_directory_payload.py +54 -0
- omnibase_infra/handlers/models/model_filesystem_ensure_directory_result.py +60 -0
- omnibase_infra/handlers/models/model_filesystem_list_directory_payload.py +60 -0
- omnibase_infra/handlers/models/model_filesystem_list_directory_result.py +68 -0
- omnibase_infra/handlers/models/model_filesystem_read_payload.py +62 -0
- omnibase_infra/handlers/models/model_filesystem_read_result.py +61 -0
- omnibase_infra/handlers/models/model_filesystem_write_payload.py +70 -0
- omnibase_infra/handlers/models/model_filesystem_write_result.py +55 -0
- omnibase_infra/handlers/models/model_graph_handler_response.py +98 -0
- omnibase_infra/handlers/models/model_handler_response.py +103 -0
- omnibase_infra/handlers/models/model_http_handler_response.py +101 -0
- omnibase_infra/handlers/models/model_manifest_metadata.py +75 -0
- omnibase_infra/handlers/models/model_manifest_persistence_config.py +62 -0
- omnibase_infra/handlers/models/model_manifest_query_payload.py +90 -0
- omnibase_infra/handlers/models/model_manifest_query_result.py +97 -0
- omnibase_infra/handlers/models/model_manifest_retrieve_payload.py +44 -0
- omnibase_infra/handlers/models/model_manifest_retrieve_result.py +98 -0
- omnibase_infra/handlers/models/model_manifest_store_payload.py +47 -0
- omnibase_infra/handlers/models/model_manifest_store_result.py +67 -0
- omnibase_infra/handlers/models/model_operation_context.py +187 -0
- omnibase_infra/handlers/models/model_qdrant_handler_response.py +98 -0
- omnibase_infra/handlers/models/model_retry_state.py +162 -0
- omnibase_infra/handlers/models/model_vault_handler_response.py +98 -0
- omnibase_infra/handlers/models/qdrant/__init__.py +44 -0
- omnibase_infra/handlers/models/qdrant/enum_qdrant_operation_type.py +26 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_collection_payload.py +42 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_delete_payload.py +36 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_handler_config.py +42 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_handler_payload.py +54 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_search_payload.py +42 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_search_result.py +30 -0
- omnibase_infra/handlers/models/qdrant/model_qdrant_upsert_payload.py +36 -0
- omnibase_infra/handlers/models/vault/__init__.py +69 -0
- omnibase_infra/handlers/models/vault/enum_vault_operation_type.py +35 -0
- omnibase_infra/handlers/models/vault/model_payload_vault.py +66 -0
- omnibase_infra/handlers/models/vault/model_vault_delete_payload.py +57 -0
- omnibase_infra/handlers/models/vault/model_vault_handler_config.py +148 -0
- omnibase_infra/handlers/models/vault/model_vault_handler_payload.py +101 -0
- omnibase_infra/handlers/models/vault/model_vault_list_payload.py +58 -0
- omnibase_infra/handlers/models/vault/model_vault_renew_token_payload.py +67 -0
- omnibase_infra/handlers/models/vault/model_vault_retry_config.py +66 -0
- omnibase_infra/handlers/models/vault/model_vault_secret_payload.py +106 -0
- omnibase_infra/handlers/models/vault/model_vault_write_payload.py +66 -0
- omnibase_infra/handlers/models/vault/registry_payload_vault.py +213 -0
- omnibase_infra/handlers/registration_storage/__init__.py +43 -0
- omnibase_infra/handlers/registration_storage/handler_registration_storage_mock.py +392 -0
- omnibase_infra/handlers/registration_storage/handler_registration_storage_postgres.py +922 -0
- omnibase_infra/handlers/registration_storage/models/__init__.py +23 -0
- omnibase_infra/handlers/registration_storage/models/model_delete_registration_request.py +58 -0
- omnibase_infra/handlers/registration_storage/models/model_update_registration_request.py +73 -0
- omnibase_infra/handlers/registration_storage/protocol_registration_persistence.py +191 -0
- omnibase_infra/handlers/service_discovery/__init__.py +43 -0
- omnibase_infra/handlers/service_discovery/handler_service_discovery_consul.py +1051 -0
- omnibase_infra/handlers/service_discovery/handler_service_discovery_mock.py +258 -0
- omnibase_infra/handlers/service_discovery/models/__init__.py +22 -0
- omnibase_infra/handlers/service_discovery/models/model_discovery_result.py +64 -0
- omnibase_infra/handlers/service_discovery/models/model_registration_result.py +138 -0
- omnibase_infra/handlers/service_discovery/models/model_service_info.py +109 -0
- omnibase_infra/handlers/service_discovery/protocol_discovery_operations.py +170 -0
- omnibase_infra/idempotency/__init__.py +94 -0
- omnibase_infra/idempotency/models/__init__.py +43 -0
- omnibase_infra/idempotency/models/model_idempotency_check_result.py +85 -0
- omnibase_infra/idempotency/models/model_idempotency_guard_config.py +130 -0
- omnibase_infra/idempotency/models/model_idempotency_record.py +86 -0
- omnibase_infra/idempotency/models/model_idempotency_store_health_check_result.py +81 -0
- omnibase_infra/idempotency/models/model_idempotency_store_metrics.py +140 -0
- omnibase_infra/idempotency/models/model_postgres_idempotency_store_config.py +299 -0
- omnibase_infra/idempotency/protocol_idempotency_store.py +184 -0
- omnibase_infra/idempotency/store_inmemory.py +265 -0
- omnibase_infra/idempotency/store_postgres.py +923 -0
- omnibase_infra/infrastructure/__init__.py +0 -0
- omnibase_infra/migrations/001_create_event_ledger.sql +166 -0
- omnibase_infra/migrations/001_drop_event_ledger.sql +18 -0
- omnibase_infra/mixins/__init__.py +71 -0
- omnibase_infra/mixins/mixin_async_circuit_breaker.py +656 -0
- omnibase_infra/mixins/mixin_dict_like_accessors.py +146 -0
- omnibase_infra/mixins/mixin_envelope_extraction.py +119 -0
- omnibase_infra/mixins/mixin_node_introspection.py +2670 -0
- omnibase_infra/mixins/mixin_retry_execution.py +386 -0
- omnibase_infra/mixins/protocol_circuit_breaker_aware.py +133 -0
- omnibase_infra/models/__init__.py +144 -0
- omnibase_infra/models/bindings/__init__.py +59 -0
- omnibase_infra/models/bindings/constants.py +144 -0
- omnibase_infra/models/bindings/model_binding_resolution_result.py +103 -0
- omnibase_infra/models/bindings/model_operation_binding.py +44 -0
- omnibase_infra/models/bindings/model_operation_bindings_subcontract.py +152 -0
- omnibase_infra/models/bindings/model_parsed_binding.py +52 -0
- omnibase_infra/models/corpus/__init__.py +17 -0
- omnibase_infra/models/corpus/model_capture_config.py +133 -0
- omnibase_infra/models/corpus/model_capture_result.py +86 -0
- omnibase_infra/models/discovery/__init__.py +42 -0
- omnibase_infra/models/discovery/model_dependency_spec.py +319 -0
- omnibase_infra/models/discovery/model_discovered_capabilities.py +50 -0
- omnibase_infra/models/discovery/model_introspection_config.py +330 -0
- omnibase_infra/models/discovery/model_introspection_performance_metrics.py +169 -0
- omnibase_infra/models/discovery/model_introspection_task_config.py +116 -0
- omnibase_infra/models/dispatch/__init__.py +155 -0
- omnibase_infra/models/dispatch/model_debug_trace_snapshot.py +114 -0
- omnibase_infra/models/dispatch/model_dispatch_context.py +439 -0
- omnibase_infra/models/dispatch/model_dispatch_error.py +336 -0
- omnibase_infra/models/dispatch/model_dispatch_log_context.py +400 -0
- omnibase_infra/models/dispatch/model_dispatch_metadata.py +228 -0
- omnibase_infra/models/dispatch/model_dispatch_metrics.py +496 -0
- omnibase_infra/models/dispatch/model_dispatch_outcome.py +317 -0
- omnibase_infra/models/dispatch/model_dispatch_outputs.py +231 -0
- omnibase_infra/models/dispatch/model_dispatch_result.py +436 -0
- omnibase_infra/models/dispatch/model_dispatch_route.py +279 -0
- omnibase_infra/models/dispatch/model_dispatcher_metrics.py +275 -0
- omnibase_infra/models/dispatch/model_dispatcher_registration.py +352 -0
- omnibase_infra/models/dispatch/model_materialized_dispatch.py +141 -0
- omnibase_infra/models/dispatch/model_parsed_topic.py +135 -0
- omnibase_infra/models/dispatch/model_topic_parser.py +725 -0
- omnibase_infra/models/dispatch/model_tracing_context.py +285 -0
- omnibase_infra/models/errors/__init__.py +45 -0
- omnibase_infra/models/errors/model_handler_validation_error.py +594 -0
- omnibase_infra/models/errors/model_infra_error_context.py +99 -0
- omnibase_infra/models/errors/model_message_type_registry_error_context.py +71 -0
- omnibase_infra/models/errors/model_timeout_error_context.py +110 -0
- omnibase_infra/models/handlers/__init__.py +80 -0
- omnibase_infra/models/handlers/model_bootstrap_handler_descriptor.py +162 -0
- omnibase_infra/models/handlers/model_contract_discovery_result.py +82 -0
- omnibase_infra/models/handlers/model_handler_descriptor.py +200 -0
- omnibase_infra/models/handlers/model_handler_identifier.py +215 -0
- omnibase_infra/models/handlers/model_handler_source_config.py +220 -0
- omnibase_infra/models/health/__init__.py +9 -0
- omnibase_infra/models/health/model_health_check_result.py +40 -0
- omnibase_infra/models/lifecycle/__init__.py +39 -0
- omnibase_infra/models/logging/__init__.py +51 -0
- omnibase_infra/models/logging/model_log_context.py +756 -0
- omnibase_infra/models/mcp/__init__.py +15 -0
- omnibase_infra/models/mcp/model_mcp_contract_config.py +80 -0
- omnibase_infra/models/mcp/model_mcp_server_config.py +67 -0
- omnibase_infra/models/mcp/model_mcp_tool_definition.py +73 -0
- omnibase_infra/models/mcp/model_mcp_tool_parameter.py +35 -0
- omnibase_infra/models/model_node_identity.py +126 -0
- omnibase_infra/models/model_retry_error_classification.py +78 -0
- omnibase_infra/models/projection/__init__.py +43 -0
- omnibase_infra/models/projection/model_capability_fields.py +112 -0
- omnibase_infra/models/projection/model_registration_projection.py +434 -0
- omnibase_infra/models/projection/model_registration_snapshot.py +322 -0
- omnibase_infra/models/projection/model_sequence_info.py +182 -0
- omnibase_infra/models/projection/model_snapshot_topic_config.py +591 -0
- omnibase_infra/models/projectors/__init__.py +41 -0
- omnibase_infra/models/projectors/model_projector_column.py +289 -0
- omnibase_infra/models/projectors/model_projector_discovery_result.py +65 -0
- omnibase_infra/models/projectors/model_projector_index.py +270 -0
- omnibase_infra/models/projectors/model_projector_schema.py +415 -0
- omnibase_infra/models/projectors/model_projector_validation_error.py +63 -0
- omnibase_infra/models/projectors/util_sql_identifiers.py +115 -0
- omnibase_infra/models/registration/__init__.py +68 -0
- omnibase_infra/models/registration/commands/__init__.py +15 -0
- omnibase_infra/models/registration/commands/model_node_registration_acked.py +108 -0
- omnibase_infra/models/registration/events/__init__.py +56 -0
- omnibase_infra/models/registration/events/model_node_became_active.py +103 -0
- omnibase_infra/models/registration/events/model_node_liveness_expired.py +103 -0
- omnibase_infra/models/registration/events/model_node_registration_accepted.py +98 -0
- omnibase_infra/models/registration/events/model_node_registration_ack_received.py +98 -0
- omnibase_infra/models/registration/events/model_node_registration_ack_timed_out.py +112 -0
- omnibase_infra/models/registration/events/model_node_registration_initiated.py +107 -0
- omnibase_infra/models/registration/events/model_node_registration_rejected.py +104 -0
- omnibase_infra/models/registration/model_event_bus_topic_entry.py +59 -0
- omnibase_infra/models/registration/model_introspection_metrics.py +253 -0
- omnibase_infra/models/registration/model_node_capabilities.py +190 -0
- omnibase_infra/models/registration/model_node_event_bus_config.py +99 -0
- omnibase_infra/models/registration/model_node_heartbeat_event.py +126 -0
- omnibase_infra/models/registration/model_node_introspection_event.py +195 -0
- omnibase_infra/models/registration/model_node_metadata.py +79 -0
- omnibase_infra/models/registration/model_node_registration.py +162 -0
- omnibase_infra/models/registration/model_node_registration_record.py +162 -0
- omnibase_infra/models/registry/__init__.py +29 -0
- omnibase_infra/models/registry/model_domain_constraint.py +202 -0
- omnibase_infra/models/registry/model_message_type_entry.py +271 -0
- omnibase_infra/models/resilience/__init__.py +9 -0
- omnibase_infra/models/resilience/model_circuit_breaker_config.py +227 -0
- omnibase_infra/models/routing/__init__.py +25 -0
- omnibase_infra/models/routing/model_routing_entry.py +52 -0
- omnibase_infra/models/routing/model_routing_subcontract.py +70 -0
- omnibase_infra/models/runtime/__init__.py +49 -0
- omnibase_infra/models/runtime/model_contract_security_config.py +41 -0
- omnibase_infra/models/runtime/model_discovery_error.py +81 -0
- omnibase_infra/models/runtime/model_discovery_result.py +162 -0
- omnibase_infra/models/runtime/model_discovery_warning.py +74 -0
- omnibase_infra/models/runtime/model_failed_plugin_load.py +63 -0
- omnibase_infra/models/runtime/model_handler_contract.py +296 -0
- omnibase_infra/models/runtime/model_loaded_handler.py +129 -0
- omnibase_infra/models/runtime/model_plugin_load_context.py +93 -0
- omnibase_infra/models/runtime/model_plugin_load_summary.py +124 -0
- omnibase_infra/models/security/__init__.py +50 -0
- omnibase_infra/models/security/classification_levels.py +99 -0
- omnibase_infra/models/security/model_environment_policy.py +145 -0
- omnibase_infra/models/security/model_handler_security_policy.py +107 -0
- omnibase_infra/models/security/model_security_error.py +81 -0
- omnibase_infra/models/security/model_security_validation_result.py +328 -0
- omnibase_infra/models/security/model_security_warning.py +67 -0
- omnibase_infra/models/snapshot/__init__.py +27 -0
- omnibase_infra/models/snapshot/model_field_change.py +65 -0
- omnibase_infra/models/snapshot/model_snapshot.py +270 -0
- omnibase_infra/models/snapshot/model_snapshot_diff.py +203 -0
- omnibase_infra/models/snapshot/model_subject_ref.py +81 -0
- omnibase_infra/models/types/__init__.py +71 -0
- omnibase_infra/models/validation/__init__.py +89 -0
- omnibase_infra/models/validation/model_any_type_validation_result.py +118 -0
- omnibase_infra/models/validation/model_any_type_violation.py +141 -0
- omnibase_infra/models/validation/model_category_match_result.py +345 -0
- omnibase_infra/models/validation/model_chain_violation.py +166 -0
- omnibase_infra/models/validation/model_coverage_metrics.py +316 -0
- omnibase_infra/models/validation/model_execution_shape_rule.py +159 -0
- omnibase_infra/models/validation/model_execution_shape_validation.py +208 -0
- omnibase_infra/models/validation/model_execution_shape_validation_result.py +294 -0
- omnibase_infra/models/validation/model_execution_shape_violation.py +122 -0
- omnibase_infra/models/validation/model_localhandler_validation_result.py +139 -0
- omnibase_infra/models/validation/model_localhandler_violation.py +100 -0
- omnibase_infra/models/validation/model_output_validation_params.py +74 -0
- omnibase_infra/models/validation/model_validate_and_raise_params.py +84 -0
- omnibase_infra/models/validation/model_validation_error_params.py +84 -0
- omnibase_infra/models/validation/model_validation_outcome.py +287 -0
- omnibase_infra/nodes/__init__.py +57 -0
- omnibase_infra/nodes/architecture_validator/__init__.py +79 -0
- omnibase_infra/nodes/architecture_validator/contract.yaml +252 -0
- omnibase_infra/nodes/architecture_validator/contract_architecture_validator.yaml +203 -0
- omnibase_infra/nodes/architecture_validator/mixins/__init__.py +16 -0
- omnibase_infra/nodes/architecture_validator/mixins/mixin_file_path_rule.py +92 -0
- omnibase_infra/nodes/architecture_validator/models/__init__.py +36 -0
- omnibase_infra/nodes/architecture_validator/models/model_architecture_validation_request.py +56 -0
- omnibase_infra/nodes/architecture_validator/models/model_architecture_validation_result.py +311 -0
- omnibase_infra/nodes/architecture_validator/models/model_architecture_violation.py +163 -0
- omnibase_infra/nodes/architecture_validator/models/model_rule_check_result.py +265 -0
- omnibase_infra/nodes/architecture_validator/models/model_validation_request.py +105 -0
- omnibase_infra/nodes/architecture_validator/models/model_validation_result.py +314 -0
- omnibase_infra/nodes/architecture_validator/node.py +262 -0
- omnibase_infra/nodes/architecture_validator/node_architecture_validator.py +383 -0
- omnibase_infra/nodes/architecture_validator/protocols/__init__.py +9 -0
- omnibase_infra/nodes/architecture_validator/protocols/protocol_architecture_rule.py +225 -0
- omnibase_infra/nodes/architecture_validator/registry/__init__.py +28 -0
- omnibase_infra/nodes/architecture_validator/registry/registry_infra_architecture_validator.py +106 -0
- omnibase_infra/nodes/architecture_validator/validators/__init__.py +104 -0
- omnibase_infra/nodes/architecture_validator/validators/validator_no_direct_dispatch.py +422 -0
- omnibase_infra/nodes/architecture_validator/validators/validator_no_handler_publishing.py +481 -0
- omnibase_infra/nodes/architecture_validator/validators/validator_no_orchestrator_fsm.py +491 -0
- omnibase_infra/nodes/contract_registry_reducer/__init__.py +29 -0
- omnibase_infra/nodes/contract_registry_reducer/contract.yaml +255 -0
- omnibase_infra/nodes/contract_registry_reducer/models/__init__.py +38 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_contract_registry_state.py +266 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_cleanup_topic_references.py +55 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_deactivate_contract.py +58 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_mark_stale.py +49 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_update_heartbeat.py +71 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_update_topic.py +66 -0
- omnibase_infra/nodes/contract_registry_reducer/models/model_payload_upsert_contract.py +92 -0
- omnibase_infra/nodes/contract_registry_reducer/node.py +121 -0
- omnibase_infra/nodes/contract_registry_reducer/reducer.py +784 -0
- omnibase_infra/nodes/contract_registry_reducer/registry/__init__.py +9 -0
- omnibase_infra/nodes/contract_registry_reducer/registry/registry_infra_contract_registry_reducer.py +101 -0
- omnibase_infra/nodes/effects/README.md +358 -0
- omnibase_infra/nodes/effects/__init__.py +26 -0
- omnibase_infra/nodes/effects/contract.yaml +167 -0
- omnibase_infra/nodes/effects/models/__init__.py +32 -0
- omnibase_infra/nodes/effects/models/model_backend_result.py +190 -0
- omnibase_infra/nodes/effects/models/model_effect_idempotency_config.py +92 -0
- omnibase_infra/nodes/effects/models/model_registry_request.py +132 -0
- omnibase_infra/nodes/effects/models/model_registry_response.py +263 -0
- omnibase_infra/nodes/effects/protocol_consul_client.py +89 -0
- omnibase_infra/nodes/effects/protocol_effect_idempotency_store.py +143 -0
- omnibase_infra/nodes/effects/protocol_postgres_adapter.py +96 -0
- omnibase_infra/nodes/effects/registry_effect.py +525 -0
- omnibase_infra/nodes/effects/store_effect_idempotency_inmemory.py +425 -0
- omnibase_infra/nodes/handlers/consul/contract.yaml +85 -0
- omnibase_infra/nodes/handlers/db/contract.yaml +72 -0
- omnibase_infra/nodes/handlers/graph/contract.yaml +127 -0
- omnibase_infra/nodes/handlers/http/contract.yaml +74 -0
- omnibase_infra/nodes/handlers/intent/contract.yaml +66 -0
- omnibase_infra/nodes/handlers/mcp/contract.yaml +69 -0
- omnibase_infra/nodes/handlers/vault/contract.yaml +91 -0
- omnibase_infra/nodes/node_intent_storage_effect/__init__.py +50 -0
- omnibase_infra/nodes/node_intent_storage_effect/contract.yaml +194 -0
- omnibase_infra/nodes/node_intent_storage_effect/models/__init__.py +24 -0
- omnibase_infra/nodes/node_intent_storage_effect/models/model_intent_storage_input.py +141 -0
- omnibase_infra/nodes/node_intent_storage_effect/models/model_intent_storage_output.py +130 -0
- omnibase_infra/nodes/node_intent_storage_effect/node.py +94 -0
- omnibase_infra/nodes/node_intent_storage_effect/registry/__init__.py +35 -0
- omnibase_infra/nodes/node_intent_storage_effect/registry/registry_infra_intent_storage.py +294 -0
- omnibase_infra/nodes/node_ledger_projection_compute/__init__.py +50 -0
- omnibase_infra/nodes/node_ledger_projection_compute/contract.yaml +104 -0
- omnibase_infra/nodes/node_ledger_projection_compute/node.py +284 -0
- omnibase_infra/nodes/node_ledger_projection_compute/registry/__init__.py +29 -0
- omnibase_infra/nodes/node_ledger_projection_compute/registry/registry_infra_ledger_projection.py +118 -0
- omnibase_infra/nodes/node_ledger_write_effect/__init__.py +82 -0
- omnibase_infra/nodes/node_ledger_write_effect/contract.yaml +200 -0
- omnibase_infra/nodes/node_ledger_write_effect/handlers/__init__.py +22 -0
- omnibase_infra/nodes/node_ledger_write_effect/handlers/handler_ledger_append.py +372 -0
- omnibase_infra/nodes/node_ledger_write_effect/handlers/handler_ledger_query.py +597 -0
- omnibase_infra/nodes/node_ledger_write_effect/models/__init__.py +31 -0
- omnibase_infra/nodes/node_ledger_write_effect/models/model_ledger_append_result.py +54 -0
- omnibase_infra/nodes/node_ledger_write_effect/models/model_ledger_entry.py +92 -0
- omnibase_infra/nodes/node_ledger_write_effect/models/model_ledger_query.py +53 -0
- omnibase_infra/nodes/node_ledger_write_effect/models/model_ledger_query_result.py +41 -0
- omnibase_infra/nodes/node_ledger_write_effect/node.py +89 -0
- omnibase_infra/nodes/node_ledger_write_effect/protocols/__init__.py +13 -0
- omnibase_infra/nodes/node_ledger_write_effect/protocols/protocol_ledger_persistence.py +127 -0
- omnibase_infra/nodes/node_ledger_write_effect/registry/__init__.py +9 -0
- omnibase_infra/nodes/node_ledger_write_effect/registry/registry_infra_ledger_write.py +121 -0
- omnibase_infra/nodes/node_registration_orchestrator/README.md +542 -0
- omnibase_infra/nodes/node_registration_orchestrator/__init__.py +120 -0
- omnibase_infra/nodes/node_registration_orchestrator/contract.yaml +482 -0
- omnibase_infra/nodes/node_registration_orchestrator/dispatchers/__init__.py +53 -0
- omnibase_infra/nodes/node_registration_orchestrator/dispatchers/dispatcher_node_introspected.py +376 -0
- omnibase_infra/nodes/node_registration_orchestrator/dispatchers/dispatcher_node_registration_acked.py +376 -0
- omnibase_infra/nodes/node_registration_orchestrator/dispatchers/dispatcher_runtime_tick.py +373 -0
- omnibase_infra/nodes/node_registration_orchestrator/handlers/__init__.py +62 -0
- omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_heartbeat.py +376 -0
- omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_introspected.py +694 -0
- omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_node_registration_acked.py +458 -0
- omnibase_infra/nodes/node_registration_orchestrator/handlers/handler_runtime_tick.py +364 -0
- omnibase_infra/nodes/node_registration_orchestrator/introspection_event_router.py +544 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/__init__.py +75 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_consul_intent_payload.py +194 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_consul_registration_intent.py +67 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_intent_execution_result.py +50 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_node_liveness_expired.py +107 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_orchestrator_config.py +67 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_orchestrator_input.py +41 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_orchestrator_output.py +166 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_postgres_intent_payload.py +235 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_postgres_upsert_intent.py +68 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_reducer_execution_result.py +384 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_reducer_state.py +60 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_registration_intent.py +177 -0
- omnibase_infra/nodes/node_registration_orchestrator/models/model_registry_intent.py +247 -0
- omnibase_infra/nodes/node_registration_orchestrator/node.py +195 -0
- omnibase_infra/nodes/node_registration_orchestrator/plugin.py +909 -0
- omnibase_infra/nodes/node_registration_orchestrator/protocols.py +439 -0
- omnibase_infra/nodes/node_registration_orchestrator/registry/__init__.py +41 -0
- omnibase_infra/nodes/node_registration_orchestrator/registry/registry_infra_node_registration_orchestrator.py +528 -0
- omnibase_infra/nodes/node_registration_orchestrator/timeout_coordinator.py +393 -0
- omnibase_infra/nodes/node_registration_orchestrator/wiring.py +743 -0
- omnibase_infra/nodes/node_registration_reducer/__init__.py +15 -0
- omnibase_infra/nodes/node_registration_reducer/contract.yaml +301 -0
- omnibase_infra/nodes/node_registration_reducer/models/__init__.py +38 -0
- omnibase_infra/nodes/node_registration_reducer/models/model_validation_result.py +113 -0
- omnibase_infra/nodes/node_registration_reducer/node.py +139 -0
- omnibase_infra/nodes/node_registration_reducer/registry/__init__.py +9 -0
- omnibase_infra/nodes/node_registration_reducer/registry/registry_infra_node_registration_reducer.py +79 -0
- omnibase_infra/nodes/node_registration_storage_effect/__init__.py +41 -0
- omnibase_infra/nodes/node_registration_storage_effect/contract.yaml +220 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/__init__.py +44 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_delete_result.py +132 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_registration_record.py +199 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_registration_update.py +155 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_health_check_details.py +123 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_health_check_result.py +117 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_query.py +100 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_storage_result.py +136 -0
- omnibase_infra/nodes/node_registration_storage_effect/models/model_upsert_result.py +127 -0
- omnibase_infra/nodes/node_registration_storage_effect/node.py +112 -0
- omnibase_infra/nodes/node_registration_storage_effect/protocols/__init__.py +22 -0
- omnibase_infra/nodes/node_registration_storage_effect/protocols/protocol_registration_persistence.py +333 -0
- omnibase_infra/nodes/node_registration_storage_effect/registry/__init__.py +23 -0
- omnibase_infra/nodes/node_registration_storage_effect/registry/registry_infra_registration_storage.py +215 -0
- omnibase_infra/nodes/node_registry_effect/__init__.py +85 -0
- omnibase_infra/nodes/node_registry_effect/contract.yaml +677 -0
- omnibase_infra/nodes/node_registry_effect/handlers/__init__.py +70 -0
- omnibase_infra/nodes/node_registry_effect/handlers/handler_consul_deregister.py +211 -0
- omnibase_infra/nodes/node_registry_effect/handlers/handler_consul_register.py +212 -0
- omnibase_infra/nodes/node_registry_effect/handlers/handler_partial_retry.py +417 -0
- omnibase_infra/nodes/node_registry_effect/handlers/handler_postgres_deactivate.py +215 -0
- omnibase_infra/nodes/node_registry_effect/handlers/handler_postgres_upsert.py +208 -0
- omnibase_infra/nodes/node_registry_effect/models/__init__.py +43 -0
- omnibase_infra/nodes/node_registry_effect/models/model_partial_retry_request.py +92 -0
- omnibase_infra/nodes/node_registry_effect/node.py +165 -0
- omnibase_infra/nodes/node_registry_effect/registry/__init__.py +27 -0
- omnibase_infra/nodes/node_registry_effect/registry/registry_infra_registry_effect.py +196 -0
- omnibase_infra/nodes/node_service_discovery_effect/__init__.py +111 -0
- omnibase_infra/nodes/node_service_discovery_effect/contract.yaml +246 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/__init__.py +67 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/enum_health_status.py +72 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/enum_service_discovery_operation.py +58 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_discovery_query.py +99 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_discovery_result.py +98 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_health_check_config.py +121 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_query_metadata.py +63 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_registration_result.py +130 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_service_discovery_health_check_details.py +111 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_service_discovery_health_check_result.py +119 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_service_info.py +106 -0
- omnibase_infra/nodes/node_service_discovery_effect/models/model_service_registration.py +121 -0
- omnibase_infra/nodes/node_service_discovery_effect/node.py +111 -0
- omnibase_infra/nodes/node_service_discovery_effect/protocols/__init__.py +14 -0
- omnibase_infra/nodes/node_service_discovery_effect/protocols/protocol_discovery_operations.py +279 -0
- omnibase_infra/nodes/node_service_discovery_effect/registry/__init__.py +13 -0
- omnibase_infra/nodes/node_service_discovery_effect/registry/registry_infra_service_discovery.py +222 -0
- omnibase_infra/nodes/reducers/__init__.py +30 -0
- omnibase_infra/nodes/reducers/models/__init__.py +37 -0
- omnibase_infra/nodes/reducers/models/model_payload_consul_register.py +87 -0
- omnibase_infra/nodes/reducers/models/model_payload_ledger_append.py +133 -0
- omnibase_infra/nodes/reducers/models/model_payload_postgres_upsert_registration.py +60 -0
- omnibase_infra/nodes/reducers/models/model_registration_confirmation.py +166 -0
- omnibase_infra/nodes/reducers/models/model_registration_state.py +433 -0
- omnibase_infra/nodes/reducers/registration_reducer.py +1138 -0
- omnibase_infra/observability/__init__.py +143 -0
- omnibase_infra/observability/constants_metrics.py +91 -0
- omnibase_infra/observability/factory_observability_sink.py +525 -0
- omnibase_infra/observability/handlers/__init__.py +118 -0
- omnibase_infra/observability/handlers/handler_logging_structured.py +967 -0
- omnibase_infra/observability/handlers/handler_metrics_prometheus.py +1120 -0
- omnibase_infra/observability/handlers/model_logging_handler_config.py +71 -0
- omnibase_infra/observability/handlers/model_logging_handler_response.py +77 -0
- omnibase_infra/observability/handlers/model_metrics_handler_config.py +172 -0
- omnibase_infra/observability/handlers/model_metrics_handler_payload.py +135 -0
- omnibase_infra/observability/handlers/model_metrics_handler_response.py +101 -0
- omnibase_infra/observability/hooks/__init__.py +74 -0
- omnibase_infra/observability/hooks/hook_observability.py +1223 -0
- omnibase_infra/observability/models/__init__.py +30 -0
- omnibase_infra/observability/models/enum_required_log_context_key.py +77 -0
- omnibase_infra/observability/models/model_buffered_log_entry.py +117 -0
- omnibase_infra/observability/models/model_logging_sink_config.py +73 -0
- omnibase_infra/observability/models/model_metrics_sink_config.py +156 -0
- omnibase_infra/observability/sinks/__init__.py +69 -0
- omnibase_infra/observability/sinks/sink_logging_structured.py +809 -0
- omnibase_infra/observability/sinks/sink_metrics_prometheus.py +710 -0
- omnibase_infra/plugins/__init__.py +27 -0
- omnibase_infra/plugins/examples/__init__.py +28 -0
- omnibase_infra/plugins/examples/plugin_json_normalizer.py +271 -0
- omnibase_infra/plugins/examples/plugin_json_normalizer_error_handling.py +210 -0
- omnibase_infra/plugins/models/__init__.py +21 -0
- omnibase_infra/plugins/models/model_plugin_context.py +76 -0
- omnibase_infra/plugins/models/model_plugin_input_data.py +58 -0
- omnibase_infra/plugins/models/model_plugin_output_data.py +62 -0
- omnibase_infra/plugins/plugin_compute_base.py +449 -0
- omnibase_infra/projectors/__init__.py +30 -0
- omnibase_infra/projectors/contracts/__init__.py +63 -0
- omnibase_infra/projectors/contracts/registration_projector.yaml +370 -0
- omnibase_infra/projectors/projection_reader_registration.py +1559 -0
- omnibase_infra/projectors/snapshot_publisher_registration.py +1329 -0
- omnibase_infra/protocols/__init__.py +104 -0
- omnibase_infra/protocols/protocol_capability_projection.py +253 -0
- omnibase_infra/protocols/protocol_capability_query.py +251 -0
- omnibase_infra/protocols/protocol_container_aware.py +200 -0
- omnibase_infra/protocols/protocol_dispatch_engine.py +152 -0
- omnibase_infra/protocols/protocol_event_bus_like.py +127 -0
- omnibase_infra/protocols/protocol_event_projector.py +96 -0
- omnibase_infra/protocols/protocol_idempotency_store.py +142 -0
- omnibase_infra/protocols/protocol_message_dispatcher.py +247 -0
- omnibase_infra/protocols/protocol_message_type_registry.py +306 -0
- omnibase_infra/protocols/protocol_plugin_compute.py +368 -0
- omnibase_infra/protocols/protocol_projector_schema_validator.py +82 -0
- omnibase_infra/protocols/protocol_registry_metrics.py +215 -0
- omnibase_infra/protocols/protocol_snapshot_publisher.py +396 -0
- omnibase_infra/protocols/protocol_snapshot_store.py +567 -0
- omnibase_infra/runtime/__init__.py +445 -0
- omnibase_infra/runtime/binding_config_resolver.py +2771 -0
- omnibase_infra/runtime/binding_resolver.py +753 -0
- omnibase_infra/runtime/chain_aware_dispatch.py +467 -0
- omnibase_infra/runtime/constants_notification.py +75 -0
- omnibase_infra/runtime/constants_security.py +70 -0
- omnibase_infra/runtime/contract_handler_discovery.py +587 -0
- omnibase_infra/runtime/contract_loaders/__init__.py +51 -0
- omnibase_infra/runtime/contract_loaders/handler_routing_loader.py +464 -0
- omnibase_infra/runtime/contract_loaders/operation_bindings_loader.py +789 -0
- omnibase_infra/runtime/dispatch_context_enforcer.py +427 -0
- omnibase_infra/runtime/emit_daemon/__init__.py +97 -0
- omnibase_infra/runtime/emit_daemon/cli.py +844 -0
- omnibase_infra/runtime/emit_daemon/client.py +811 -0
- omnibase_infra/runtime/emit_daemon/config.py +535 -0
- omnibase_infra/runtime/emit_daemon/daemon.py +812 -0
- omnibase_infra/runtime/emit_daemon/event_registry.py +477 -0
- omnibase_infra/runtime/emit_daemon/model_daemon_request.py +139 -0
- omnibase_infra/runtime/emit_daemon/model_daemon_response.py +191 -0
- omnibase_infra/runtime/emit_daemon/queue.py +618 -0
- omnibase_infra/runtime/enums/__init__.py +18 -0
- omnibase_infra/runtime/enums/enum_config_ref_scheme.py +33 -0
- omnibase_infra/runtime/enums/enum_scheduler_status.py +170 -0
- omnibase_infra/runtime/envelope_validator.py +179 -0
- omnibase_infra/runtime/event_bus_subcontract_wiring.py +466 -0
- omnibase_infra/runtime/handler_bootstrap_source.py +507 -0
- omnibase_infra/runtime/handler_contract_config_loader.py +603 -0
- omnibase_infra/runtime/handler_contract_source.py +750 -0
- omnibase_infra/runtime/handler_identity.py +81 -0
- omnibase_infra/runtime/handler_plugin_loader.py +2046 -0
- omnibase_infra/runtime/handler_registry.py +329 -0
- omnibase_infra/runtime/handler_source_resolver.py +367 -0
- omnibase_infra/runtime/invocation_security_enforcer.py +427 -0
- omnibase_infra/runtime/kafka_contract_source.py +984 -0
- omnibase_infra/runtime/kernel.py +40 -0
- omnibase_infra/runtime/mixin_policy_validation.py +522 -0
- omnibase_infra/runtime/mixin_semver_cache.py +402 -0
- omnibase_infra/runtime/mixins/__init__.py +24 -0
- omnibase_infra/runtime/mixins/mixin_projector_notification_publishing.py +566 -0
- omnibase_infra/runtime/mixins/mixin_projector_sql_operations.py +778 -0
- omnibase_infra/runtime/models/__init__.py +229 -0
- omnibase_infra/runtime/models/model_batch_lifecycle_result.py +217 -0
- omnibase_infra/runtime/models/model_binding_config.py +168 -0
- omnibase_infra/runtime/models/model_binding_config_cache_stats.py +135 -0
- omnibase_infra/runtime/models/model_binding_config_resolver_config.py +329 -0
- omnibase_infra/runtime/models/model_cached_secret.py +138 -0
- omnibase_infra/runtime/models/model_compute_key.py +138 -0
- omnibase_infra/runtime/models/model_compute_registration.py +97 -0
- omnibase_infra/runtime/models/model_config_cache_entry.py +61 -0
- omnibase_infra/runtime/models/model_config_ref.py +331 -0
- omnibase_infra/runtime/models/model_config_ref_parse_result.py +125 -0
- omnibase_infra/runtime/models/model_contract_load_result.py +224 -0
- omnibase_infra/runtime/models/model_domain_plugin_config.py +92 -0
- omnibase_infra/runtime/models/model_domain_plugin_result.py +270 -0
- omnibase_infra/runtime/models/model_duplicate_response.py +54 -0
- omnibase_infra/runtime/models/model_enabled_protocols_config.py +61 -0
- omnibase_infra/runtime/models/model_event_bus_config.py +54 -0
- omnibase_infra/runtime/models/model_failed_component.py +55 -0
- omnibase_infra/runtime/models/model_health_check_response.py +168 -0
- omnibase_infra/runtime/models/model_health_check_result.py +229 -0
- omnibase_infra/runtime/models/model_lifecycle_result.py +245 -0
- omnibase_infra/runtime/models/model_logging_config.py +42 -0
- omnibase_infra/runtime/models/model_optional_correlation_id.py +167 -0
- omnibase_infra/runtime/models/model_optional_string.py +94 -0
- omnibase_infra/runtime/models/model_optional_uuid.py +110 -0
- omnibase_infra/runtime/models/model_policy_context.py +100 -0
- omnibase_infra/runtime/models/model_policy_key.py +138 -0
- omnibase_infra/runtime/models/model_policy_registration.py +139 -0
- omnibase_infra/runtime/models/model_policy_result.py +103 -0
- omnibase_infra/runtime/models/model_policy_type_filter.py +157 -0
- omnibase_infra/runtime/models/model_projector_notification_config.py +171 -0
- omnibase_infra/runtime/models/model_projector_plugin_loader_config.py +47 -0
- omnibase_infra/runtime/models/model_protocol_registration_config.py +65 -0
- omnibase_infra/runtime/models/model_retry_policy.py +105 -0
- omnibase_infra/runtime/models/model_runtime_config.py +150 -0
- omnibase_infra/runtime/models/model_runtime_contract_config.py +268 -0
- omnibase_infra/runtime/models/model_runtime_scheduler_config.py +625 -0
- omnibase_infra/runtime/models/model_runtime_scheduler_metrics.py +233 -0
- omnibase_infra/runtime/models/model_runtime_tick.py +193 -0
- omnibase_infra/runtime/models/model_secret_cache_stats.py +82 -0
- omnibase_infra/runtime/models/model_secret_mapping.py +63 -0
- omnibase_infra/runtime/models/model_secret_resolver_config.py +107 -0
- omnibase_infra/runtime/models/model_secret_resolver_metrics.py +111 -0
- omnibase_infra/runtime/models/model_secret_source_info.py +72 -0
- omnibase_infra/runtime/models/model_secret_source_spec.py +66 -0
- omnibase_infra/runtime/models/model_security_config.py +109 -0
- omnibase_infra/runtime/models/model_shutdown_batch_result.py +75 -0
- omnibase_infra/runtime/models/model_shutdown_config.py +94 -0
- omnibase_infra/runtime/models/model_transition_notification_outbox_config.py +112 -0
- omnibase_infra/runtime/models/model_transition_notification_outbox_metrics.py +140 -0
- omnibase_infra/runtime/models/model_transition_notification_publisher_metrics.py +357 -0
- omnibase_infra/runtime/projector_plugin_loader.py +1462 -0
- omnibase_infra/runtime/projector_schema_manager.py +565 -0
- omnibase_infra/runtime/projector_shell.py +1330 -0
- omnibase_infra/runtime/protocol_contract_descriptor.py +92 -0
- omnibase_infra/runtime/protocol_contract_source.py +92 -0
- omnibase_infra/runtime/protocol_domain_plugin.py +474 -0
- omnibase_infra/runtime/protocol_handler_discovery.py +221 -0
- omnibase_infra/runtime/protocol_handler_plugin_loader.py +327 -0
- omnibase_infra/runtime/protocol_lifecycle_executor.py +435 -0
- omnibase_infra/runtime/protocol_policy.py +366 -0
- omnibase_infra/runtime/protocols/__init__.py +37 -0
- omnibase_infra/runtime/protocols/protocol_runtime_scheduler.py +468 -0
- omnibase_infra/runtime/publisher_topic_scoped.py +294 -0
- omnibase_infra/runtime/registry/__init__.py +93 -0
- omnibase_infra/runtime/registry/mixin_message_type_query.py +326 -0
- omnibase_infra/runtime/registry/mixin_message_type_registration.py +354 -0
- omnibase_infra/runtime/registry/registry_event_bus_binding.py +268 -0
- omnibase_infra/runtime/registry/registry_message_type.py +542 -0
- omnibase_infra/runtime/registry/registry_protocol_binding.py +445 -0
- omnibase_infra/runtime/registry_compute.py +1143 -0
- omnibase_infra/runtime/registry_contract_source.py +693 -0
- omnibase_infra/runtime/registry_dispatcher.py +678 -0
- omnibase_infra/runtime/registry_policy.py +1185 -0
- omnibase_infra/runtime/runtime_contract_config_loader.py +406 -0
- omnibase_infra/runtime/runtime_scheduler.py +1070 -0
- omnibase_infra/runtime/secret_resolver.py +2112 -0
- omnibase_infra/runtime/security_metadata_validator.py +776 -0
- omnibase_infra/runtime/service_kernel.py +1651 -0
- omnibase_infra/runtime/service_message_dispatch_engine.py +2350 -0
- omnibase_infra/runtime/service_runtime_host_process.py +3493 -0
- omnibase_infra/runtime/transition_notification_outbox.py +1190 -0
- omnibase_infra/runtime/transition_notification_publisher.py +765 -0
- omnibase_infra/runtime/util_container_wiring.py +1124 -0
- omnibase_infra/runtime/util_validation.py +314 -0
- omnibase_infra/runtime/util_version.py +98 -0
- omnibase_infra/runtime/util_wiring.py +723 -0
- omnibase_infra/schemas/schema_registration_projection.sql +320 -0
- omnibase_infra/schemas/schema_transition_notification_outbox.sql +245 -0
- omnibase_infra/services/__init__.py +89 -0
- omnibase_infra/services/corpus_capture.py +684 -0
- omnibase_infra/services/mcp/__init__.py +31 -0
- omnibase_infra/services/mcp/mcp_server_lifecycle.py +449 -0
- omnibase_infra/services/mcp/service_mcp_tool_discovery.py +411 -0
- omnibase_infra/services/mcp/service_mcp_tool_registry.py +329 -0
- omnibase_infra/services/mcp/service_mcp_tool_sync.py +565 -0
- omnibase_infra/services/registry_api/__init__.py +40 -0
- omnibase_infra/services/registry_api/main.py +261 -0
- omnibase_infra/services/registry_api/models/__init__.py +66 -0
- omnibase_infra/services/registry_api/models/model_capability_widget_mapping.py +38 -0
- omnibase_infra/services/registry_api/models/model_pagination_info.py +48 -0
- omnibase_infra/services/registry_api/models/model_registry_discovery_response.py +73 -0
- omnibase_infra/services/registry_api/models/model_registry_health_response.py +49 -0
- omnibase_infra/services/registry_api/models/model_registry_instance_view.py +88 -0
- omnibase_infra/services/registry_api/models/model_registry_node_view.py +88 -0
- omnibase_infra/services/registry_api/models/model_registry_summary.py +60 -0
- omnibase_infra/services/registry_api/models/model_response_list_instances.py +43 -0
- omnibase_infra/services/registry_api/models/model_response_list_nodes.py +51 -0
- omnibase_infra/services/registry_api/models/model_warning.py +49 -0
- omnibase_infra/services/registry_api/models/model_widget_defaults.py +28 -0
- omnibase_infra/services/registry_api/models/model_widget_mapping.py +51 -0
- omnibase_infra/services/registry_api/routes.py +371 -0
- omnibase_infra/services/registry_api/service.py +837 -0
- omnibase_infra/services/service_capability_query.py +945 -0
- omnibase_infra/services/service_health.py +898 -0
- omnibase_infra/services/service_node_selector.py +530 -0
- omnibase_infra/services/service_timeout_emitter.py +699 -0
- omnibase_infra/services/service_timeout_scanner.py +394 -0
- omnibase_infra/services/session/__init__.py +56 -0
- omnibase_infra/services/session/config_consumer.py +137 -0
- omnibase_infra/services/session/config_store.py +139 -0
- omnibase_infra/services/session/consumer.py +1007 -0
- omnibase_infra/services/session/protocol_session_aggregator.py +117 -0
- omnibase_infra/services/session/store.py +997 -0
- omnibase_infra/services/snapshot/__init__.py +31 -0
- omnibase_infra/services/snapshot/service_snapshot.py +647 -0
- omnibase_infra/services/snapshot/store_inmemory.py +637 -0
- omnibase_infra/services/snapshot/store_postgres.py +1279 -0
- omnibase_infra/shared/__init__.py +8 -0
- omnibase_infra/testing/__init__.py +10 -0
- omnibase_infra/testing/utils.py +23 -0
- omnibase_infra/topics/__init__.py +45 -0
- omnibase_infra/topics/platform_topic_suffixes.py +140 -0
- omnibase_infra/topics/util_topic_composition.py +95 -0
- omnibase_infra/types/__init__.py +48 -0
- omnibase_infra/types/type_cache_info.py +49 -0
- omnibase_infra/types/type_dsn.py +173 -0
- omnibase_infra/types/type_infra_aliases.py +60 -0
- omnibase_infra/types/typed_dict/__init__.py +29 -0
- omnibase_infra/types/typed_dict/typed_dict_envelope_build_params.py +115 -0
- omnibase_infra/types/typed_dict/typed_dict_introspection_cache.py +128 -0
- omnibase_infra/types/typed_dict/typed_dict_performance_metrics_cache.py +140 -0
- omnibase_infra/types/typed_dict_capabilities.py +64 -0
- omnibase_infra/utils/__init__.py +117 -0
- omnibase_infra/utils/correlation.py +208 -0
- omnibase_infra/utils/util_atomic_file.py +261 -0
- omnibase_infra/utils/util_consumer_group.py +232 -0
- omnibase_infra/utils/util_datetime.py +372 -0
- omnibase_infra/utils/util_db_transaction.py +239 -0
- omnibase_infra/utils/util_dsn_validation.py +333 -0
- omnibase_infra/utils/util_env_parsing.py +264 -0
- omnibase_infra/utils/util_error_sanitization.py +457 -0
- omnibase_infra/utils/util_pydantic_validators.py +477 -0
- omnibase_infra/utils/util_retry_optimistic.py +281 -0
- omnibase_infra/utils/util_semver.py +233 -0
- omnibase_infra/validation/__init__.py +307 -0
- omnibase_infra/validation/contracts/security.validation.yaml +114 -0
- omnibase_infra/validation/enums/__init__.py +11 -0
- omnibase_infra/validation/enums/enum_contract_violation_severity.py +13 -0
- omnibase_infra/validation/infra_validators.py +1514 -0
- omnibase_infra/validation/linter_contract.py +907 -0
- omnibase_infra/validation/mixin_any_type_classification.py +120 -0
- omnibase_infra/validation/mixin_any_type_exemption.py +580 -0
- omnibase_infra/validation/mixin_any_type_reporting.py +106 -0
- omnibase_infra/validation/mixin_execution_shape_violation_checks.py +596 -0
- omnibase_infra/validation/mixin_node_archetype_detection.py +254 -0
- omnibase_infra/validation/models/__init__.py +15 -0
- omnibase_infra/validation/models/model_contract_lint_result.py +101 -0
- omnibase_infra/validation/models/model_contract_violation.py +41 -0
- omnibase_infra/validation/service_validation_aggregator.py +395 -0
- omnibase_infra/validation/validation_exemptions.yaml +2033 -0
- omnibase_infra/validation/validator_any_type.py +715 -0
- omnibase_infra/validation/validator_chain_propagation.py +839 -0
- omnibase_infra/validation/validator_execution_shape.py +465 -0
- omnibase_infra/validation/validator_localhandler.py +261 -0
- omnibase_infra/validation/validator_registration_security.py +410 -0
- omnibase_infra/validation/validator_routing_coverage.py +1020 -0
- omnibase_infra/validation/validator_runtime_shape.py +915 -0
- omnibase_infra/validation/validator_security.py +513 -0
- omnibase_infra/validation/validator_topic_category.py +1152 -0
- omnibase_infra-0.2.6.dist-info/METADATA +197 -0
- omnibase_infra-0.2.6.dist-info/RECORD +833 -0
- omnibase_infra-0.2.6.dist-info/WHEEL +4 -0
- omnibase_infra-0.2.6.dist-info/entry_points.txt +5 -0
- omnibase_infra-0.2.6.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2025 OmniNode Team
|
|
3
|
+
"""Classification mixin for Any type detection.
|
|
4
|
+
|
|
5
|
+
This mixin provides methods for classifying AST nodes as type aliases,
|
|
6
|
+
Field() calls, type expressions, etc.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import ast
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class MixinAnyTypeClassification:
|
|
15
|
+
"""Mixin providing type classification methods for Any type detection.
|
|
16
|
+
|
|
17
|
+
This mixin extracts classification logic from AnyTypeDetector to reduce
|
|
18
|
+
method count while maintaining functionality.
|
|
19
|
+
|
|
20
|
+
Methods:
|
|
21
|
+
_is_likely_type_alias_name: Check if name suggests a type alias.
|
|
22
|
+
_is_type_alias_annotation: Check if node is a type alias definition.
|
|
23
|
+
_is_type_expression: Check if expression is a type expression.
|
|
24
|
+
_is_field_call: Check if expression is a Pydantic Field() call.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def _is_likely_type_alias_name(self, name: str) -> bool:
|
|
28
|
+
"""Check if a name is likely a type alias based on naming conventions.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
name: The variable name to check.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
True if the name suggests a type alias.
|
|
35
|
+
"""
|
|
36
|
+
if not name:
|
|
37
|
+
return False
|
|
38
|
+
# Explicit type alias suffixes
|
|
39
|
+
if name.endswith(("Type", "Types")):
|
|
40
|
+
return True
|
|
41
|
+
# PascalCase without underscores (like type names)
|
|
42
|
+
if name[0].isupper() and "_" not in name and not name.isupper():
|
|
43
|
+
return True
|
|
44
|
+
return False
|
|
45
|
+
|
|
46
|
+
def _is_type_alias_annotation(self, node: ast.AnnAssign) -> bool:
|
|
47
|
+
"""Check if an annotated assignment is a type alias.
|
|
48
|
+
|
|
49
|
+
Type aliases are detected by:
|
|
50
|
+
- Annotation is TypeAlias
|
|
51
|
+
- Target name follows type alias conventions (PascalCase or ends with Type)
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
node: The annotated assignment node.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
True if this appears to be a type alias definition.
|
|
58
|
+
"""
|
|
59
|
+
# Check for TypeAlias annotation
|
|
60
|
+
if isinstance(node.annotation, ast.Name) and node.annotation.id == "TypeAlias":
|
|
61
|
+
return True
|
|
62
|
+
if (
|
|
63
|
+
isinstance(node.annotation, ast.Attribute)
|
|
64
|
+
and node.annotation.attr == "TypeAlias"
|
|
65
|
+
):
|
|
66
|
+
return True
|
|
67
|
+
|
|
68
|
+
# Check target name conventions
|
|
69
|
+
if isinstance(node.target, ast.Name):
|
|
70
|
+
name = node.target.id
|
|
71
|
+
# Type aliases typically use PascalCase or end with "Type"
|
|
72
|
+
# Exclude ALL_CAPS names (not name.isupper()) to match _is_likely_type_alias_name
|
|
73
|
+
if name.endswith("Type") or (
|
|
74
|
+
name[0].isupper() and "_" not in name and not name.isupper()
|
|
75
|
+
):
|
|
76
|
+
# Only consider it a type alias if value is a type expression
|
|
77
|
+
if node.value is not None:
|
|
78
|
+
return self._is_type_expression(node.value)
|
|
79
|
+
|
|
80
|
+
return False
|
|
81
|
+
|
|
82
|
+
def _is_type_expression(self, node: ast.expr) -> bool:
|
|
83
|
+
"""Check if an expression is likely a type expression.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
node: The AST expression.
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
True if the expression appears to be a type definition.
|
|
90
|
+
"""
|
|
91
|
+
if isinstance(node, ast.Name):
|
|
92
|
+
return True
|
|
93
|
+
if isinstance(node, ast.Subscript):
|
|
94
|
+
return True
|
|
95
|
+
if isinstance(node, ast.BinOp):
|
|
96
|
+
# Union syntax: X | Y
|
|
97
|
+
return True
|
|
98
|
+
if isinstance(node, ast.Attribute):
|
|
99
|
+
return True
|
|
100
|
+
return False
|
|
101
|
+
|
|
102
|
+
def _is_field_call(self, node: ast.expr) -> bool:
|
|
103
|
+
"""Check if an expression is a Pydantic Field() call.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
node: The AST expression.
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
True if this is a Field() call.
|
|
110
|
+
"""
|
|
111
|
+
if not isinstance(node, ast.Call):
|
|
112
|
+
return False
|
|
113
|
+
|
|
114
|
+
func = node.func
|
|
115
|
+
if isinstance(func, ast.Name) and func.id == "Field":
|
|
116
|
+
return True
|
|
117
|
+
if isinstance(func, ast.Attribute) and func.attr == "Field":
|
|
118
|
+
return True
|
|
119
|
+
|
|
120
|
+
return False
|
|
@@ -0,0 +1,580 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2025 OmniNode Team
|
|
3
|
+
"""Exemption mixin for Any type detection.
|
|
4
|
+
|
|
5
|
+
This mixin provides methods for managing exemptions via decorators,
|
|
6
|
+
comments, and file-level NOTE patterns.
|
|
7
|
+
|
|
8
|
+
Exemption Format Requirements:
|
|
9
|
+
All NOTE comments must include an OMN ticket reference:
|
|
10
|
+
# NOTE: OMN-1234 - Reason for Any usage
|
|
11
|
+
|
|
12
|
+
This applies to:
|
|
13
|
+
- File-level NOTE comments (within 2 lines of Any import)
|
|
14
|
+
- Field-level NOTE comments (above or inline with Field())
|
|
15
|
+
- Type-ignore directive justifications (NOTE must be on line above)
|
|
16
|
+
|
|
17
|
+
Invalid formats (will NOT be accepted):
|
|
18
|
+
- # NOTE: Required for... (missing OMN-XXXX ticket code)
|
|
19
|
+
- # reason (missing NOTE: prefix and ticket code)
|
|
20
|
+
- # NOTE: reason (missing OMN-XXXX ticket code)
|
|
21
|
+
|
|
22
|
+
Valid formats:
|
|
23
|
+
- # NOTE: OMN-1234 - Required for Pydantic discriminated union
|
|
24
|
+
- # NOTE: OMN-5678 - Dynamic JSON payload handling
|
|
25
|
+
- # NOTE: omn-9999 - Case-insensitive ticket codes accepted
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from __future__ import annotations
|
|
29
|
+
|
|
30
|
+
import ast
|
|
31
|
+
import re
|
|
32
|
+
|
|
33
|
+
# Decorator names that allow Any type usage
|
|
34
|
+
_ALLOW_DECORATORS: frozenset[str] = frozenset({"allow_any", "allow_any_type"})
|
|
35
|
+
|
|
36
|
+
# Regex pattern for OMN ticket codes
|
|
37
|
+
# Matches: OMN-1234, OMN-12345, etc.
|
|
38
|
+
_OMN_TICKET_PATTERN = re.compile(r"OMN-\d+", re.IGNORECASE)
|
|
39
|
+
|
|
40
|
+
# Type-ignore pattern for detecting type: ignore comments
|
|
41
|
+
_TYPE_IGNORE_PATTERN = re.compile(r"#\s*type:\s*ignore", re.IGNORECASE)
|
|
42
|
+
|
|
43
|
+
# Number of lines to look back for NOTE comments.
|
|
44
|
+
# 3 lines is sufficient because NOTE comments should appear:
|
|
45
|
+
# - Immediately above the field (1 line)
|
|
46
|
+
# - With a blank line gap (2 lines)
|
|
47
|
+
# - After a decorator (3 lines max)
|
|
48
|
+
# Larger values risk matching unrelated NOTE comments, so keep this tight.
|
|
49
|
+
_NOTE_LOOKBACK_LINES = 3
|
|
50
|
+
|
|
51
|
+
# Number of lines to look around file-level Any imports for NOTE comments.
|
|
52
|
+
# This is intentionally tight (2 lines before/after) to ensure NOTE comments
|
|
53
|
+
# are closely associated with the import they document.
|
|
54
|
+
_FILE_LEVEL_NOTE_WINDOW = 2
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _extract_comment_portion(line: str) -> str | None:
|
|
58
|
+
"""Extract the comment portion of a line, ignoring # in string literals.
|
|
59
|
+
|
|
60
|
+
This function finds the first # that is NOT inside a string literal
|
|
61
|
+
(single-quoted, double-quoted, or triple-quoted).
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
line: A single line of source code.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
The comment portion (including #) if found, None otherwise.
|
|
68
|
+
|
|
69
|
+
Examples:
|
|
70
|
+
>>> _extract_comment_portion("x = 1 # comment")
|
|
71
|
+
'# comment'
|
|
72
|
+
>>> _extract_comment_portion('x = "# not comment" # real comment')
|
|
73
|
+
'# real comment'
|
|
74
|
+
>>> _extract_comment_portion('x = "# not comment"')
|
|
75
|
+
None
|
|
76
|
+
"""
|
|
77
|
+
in_single_quote = False
|
|
78
|
+
in_double_quote = False
|
|
79
|
+
i = 0
|
|
80
|
+
n = len(line)
|
|
81
|
+
|
|
82
|
+
while i < n:
|
|
83
|
+
char = line[i]
|
|
84
|
+
|
|
85
|
+
# Check for triple quotes (must check before single quotes)
|
|
86
|
+
if i + 2 < n:
|
|
87
|
+
triple = line[i : i + 3]
|
|
88
|
+
if triple == '"""' and not in_single_quote:
|
|
89
|
+
# Triple double quote - skip to end or toggle
|
|
90
|
+
if in_double_quote:
|
|
91
|
+
in_double_quote = False
|
|
92
|
+
else:
|
|
93
|
+
in_double_quote = True
|
|
94
|
+
i += 3
|
|
95
|
+
continue
|
|
96
|
+
if triple == "'''" and not in_double_quote:
|
|
97
|
+
# Triple single quote - skip to end or toggle
|
|
98
|
+
if in_single_quote:
|
|
99
|
+
in_single_quote = False
|
|
100
|
+
else:
|
|
101
|
+
in_single_quote = True
|
|
102
|
+
i += 3
|
|
103
|
+
continue
|
|
104
|
+
|
|
105
|
+
# Check for escaped quotes
|
|
106
|
+
if char == "\\" and i + 1 < n:
|
|
107
|
+
# Skip escaped character
|
|
108
|
+
i += 2
|
|
109
|
+
continue
|
|
110
|
+
|
|
111
|
+
# Check for single quote
|
|
112
|
+
if char == "'" and not in_double_quote:
|
|
113
|
+
in_single_quote = not in_single_quote
|
|
114
|
+
i += 1
|
|
115
|
+
continue
|
|
116
|
+
|
|
117
|
+
# Check for double quote
|
|
118
|
+
if char == '"' and not in_single_quote:
|
|
119
|
+
in_double_quote = not in_double_quote
|
|
120
|
+
i += 1
|
|
121
|
+
continue
|
|
122
|
+
|
|
123
|
+
# Check for comment (only if not in string)
|
|
124
|
+
if char == "#" and not in_single_quote and not in_double_quote:
|
|
125
|
+
return line[i:]
|
|
126
|
+
|
|
127
|
+
i += 1
|
|
128
|
+
|
|
129
|
+
return None
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def _is_any_exemption_note(text: str) -> bool:
|
|
133
|
+
"""Check if text contains a valid Any exemption note.
|
|
134
|
+
|
|
135
|
+
A valid exemption note must have:
|
|
136
|
+
1. A comment marker (#)
|
|
137
|
+
2. "NOTE:" immediately after the comment marker (with optional whitespace)
|
|
138
|
+
3. An OMN ticket code (e.g., OMN-1234)
|
|
139
|
+
4. A reason/description after the ticket code
|
|
140
|
+
|
|
141
|
+
This prevents generic NOTE comments from accidentally matching and ensures
|
|
142
|
+
NOTE: is at the start of a comment, not buried in the middle.
|
|
143
|
+
|
|
144
|
+
Valid examples:
|
|
145
|
+
- "# NOTE: OMN-1234 - Required for Pydantic discriminated union"
|
|
146
|
+
- "code # NOTE: OMN-5678 - Dynamic JSON payload handling"
|
|
147
|
+
- "# NOTE: OMN-9999 - Workaround for typing limitations"
|
|
148
|
+
- "# NOTE: omn-1234 - Case-insensitive ticket codes accepted"
|
|
149
|
+
|
|
150
|
+
Invalid examples:
|
|
151
|
+
- "# Some text NOTE: OMN-1234 - reason" (NOTE not at comment start)
|
|
152
|
+
- "NOTE: OMN-1234 - reason" (no comment marker)
|
|
153
|
+
- "# NOTE: Required for..." (missing OMN-XXXX ticket code)
|
|
154
|
+
- "# NOTE: reason" (missing OMN-XXXX ticket code)
|
|
155
|
+
- "# reason" (missing NOTE: prefix and ticket code)
|
|
156
|
+
- "x = 'NOTE: OMN-1234'" (NOTE in string, not comment)
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
text: Text to check. Can be a single line of source code (with or without
|
|
160
|
+
code before the comment) or a pre-extracted comment portion starting
|
|
161
|
+
with '#'. The function uses _extract_comment_portion internally to
|
|
162
|
+
properly handle '#' characters inside string literals.
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
True if text contains a valid Any exemption note at comment start with
|
|
166
|
+
an OMN ticket reference.
|
|
167
|
+
"""
|
|
168
|
+
# Use _extract_comment_portion to properly handle # in string literals
|
|
169
|
+
# e.g., x = "# not a comment" # real comment
|
|
170
|
+
# This prevents false negatives where text.find("#") finds the wrong #
|
|
171
|
+
comment_portion = _extract_comment_portion(text)
|
|
172
|
+
if comment_portion is None:
|
|
173
|
+
return False
|
|
174
|
+
|
|
175
|
+
# Extract the text after # and strip leading whitespace
|
|
176
|
+
# comment_portion is guaranteed to start with #
|
|
177
|
+
comment = comment_portion[1:].lstrip()
|
|
178
|
+
comment_lower = comment.lower()
|
|
179
|
+
|
|
180
|
+
# NOTE: must be at the start of the comment (after # and whitespace)
|
|
181
|
+
if not comment_lower.startswith("note:"):
|
|
182
|
+
return False
|
|
183
|
+
|
|
184
|
+
# Extract text after "NOTE:" for OMN ticket validation
|
|
185
|
+
text_after_note = comment[5:] # Keep original case for regex matching
|
|
186
|
+
|
|
187
|
+
# Check for OMN ticket code (e.g., OMN-1234)
|
|
188
|
+
if _OMN_TICKET_PATTERN.search(text_after_note):
|
|
189
|
+
return True
|
|
190
|
+
|
|
191
|
+
return False
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def _has_type_ignore_with_valid_note(source_lines: list[str], line_num: int) -> bool:
|
|
195
|
+
"""Check if a type: ignore comment has a valid NOTE on the line above.
|
|
196
|
+
|
|
197
|
+
When using `# type: ignore` to suppress type checker warnings for Any usage,
|
|
198
|
+
the preceding line MUST have a NOTE comment with an OMN ticket reference.
|
|
199
|
+
|
|
200
|
+
Valid pattern:
|
|
201
|
+
# NOTE: OMN-1234 - Required for Pydantic discriminated union
|
|
202
|
+
field: Any = Field(...) # type: ignore[valid-type]
|
|
203
|
+
|
|
204
|
+
Invalid patterns:
|
|
205
|
+
field: Any = Field(...) # type: ignore[valid-type] (no NOTE above)
|
|
206
|
+
|
|
207
|
+
# NOTE: Required for discriminated union (no OMN ticket)
|
|
208
|
+
field: Any = Field(...) # type: ignore[valid-type]
|
|
209
|
+
|
|
210
|
+
Args:
|
|
211
|
+
source_lines: List of source code lines.
|
|
212
|
+
line_num: 1-based line number of the line with type: ignore.
|
|
213
|
+
|
|
214
|
+
Returns:
|
|
215
|
+
True if the type: ignore has a valid NOTE with OMN ticket on preceding line.
|
|
216
|
+
"""
|
|
217
|
+
# Check if current line has type: ignore
|
|
218
|
+
if line_num < 1 or line_num > len(source_lines):
|
|
219
|
+
return False
|
|
220
|
+
|
|
221
|
+
current_line = source_lines[line_num - 1]
|
|
222
|
+
# Extract only the comment portion to check for type: ignore
|
|
223
|
+
# This prevents false matches where "type: ignore" appears in string literals
|
|
224
|
+
comment_portion = _extract_comment_portion(current_line)
|
|
225
|
+
if comment_portion is None or not _TYPE_IGNORE_PATTERN.search(comment_portion):
|
|
226
|
+
return False
|
|
227
|
+
|
|
228
|
+
# Check the line above for a valid NOTE comment
|
|
229
|
+
if line_num < 2:
|
|
230
|
+
return False
|
|
231
|
+
|
|
232
|
+
preceding_line = source_lines[line_num - 2]
|
|
233
|
+
# Extract comment portion from preceding line before checking
|
|
234
|
+
# This ensures we only match NOTE in actual comments, not code/strings
|
|
235
|
+
preceding_comment = _extract_comment_portion(preceding_line)
|
|
236
|
+
if preceding_comment is None:
|
|
237
|
+
return False
|
|
238
|
+
return _is_any_exemption_note(preceding_comment)
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def _is_in_multiline_import(
|
|
242
|
+
source_lines: list[str], start_idx: int, max_lines: int
|
|
243
|
+
) -> tuple[bool, int, int]:
|
|
244
|
+
"""Check if we're at the start of a multi-line import block.
|
|
245
|
+
|
|
246
|
+
Handles both parenthesized imports and backslash-continuation imports:
|
|
247
|
+
from typing import (
|
|
248
|
+
Any,
|
|
249
|
+
Dict,
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
from typing import \\
|
|
253
|
+
Any, \\
|
|
254
|
+
Dict
|
|
255
|
+
|
|
256
|
+
Args:
|
|
257
|
+
source_lines: List of source code lines.
|
|
258
|
+
start_idx: Index to start checking from.
|
|
259
|
+
max_lines: Maximum number of lines to scan.
|
|
260
|
+
|
|
261
|
+
Returns:
|
|
262
|
+
Tuple of (is_multiline, start_line_idx, end_line_idx).
|
|
263
|
+
If not multiline, returns (False, -1, -1).
|
|
264
|
+
"""
|
|
265
|
+
if start_idx >= len(source_lines) or start_idx >= max_lines:
|
|
266
|
+
return (False, -1, -1)
|
|
267
|
+
|
|
268
|
+
line = source_lines[start_idx]
|
|
269
|
+
|
|
270
|
+
# Check for parenthesized import: "from typing import ("
|
|
271
|
+
if "from typing import" in line and "(" in line:
|
|
272
|
+
if ")" in line:
|
|
273
|
+
# Single line: from typing import (Any, Dict)
|
|
274
|
+
return (False, -1, -1)
|
|
275
|
+
# Find closing parenthesis
|
|
276
|
+
for end_idx in range(start_idx + 1, min(len(source_lines), max_lines)):
|
|
277
|
+
if ")" in source_lines[end_idx]:
|
|
278
|
+
return (True, start_idx, end_idx)
|
|
279
|
+
return (True, start_idx, min(len(source_lines), max_lines) - 1)
|
|
280
|
+
|
|
281
|
+
# Check for backslash continuation: "from typing import \"
|
|
282
|
+
if "from typing import" in line and line.rstrip().endswith("\\"):
|
|
283
|
+
end_idx = start_idx
|
|
284
|
+
for i in range(start_idx + 1, min(len(source_lines), max_lines)):
|
|
285
|
+
if not source_lines[i].rstrip().endswith("\\"):
|
|
286
|
+
end_idx = i
|
|
287
|
+
break
|
|
288
|
+
end_idx = i
|
|
289
|
+
return (True, start_idx, end_idx)
|
|
290
|
+
|
|
291
|
+
return (False, -1, -1)
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
class MixinAnyTypeExemption:
|
|
295
|
+
"""Mixin providing exemption management for Any type detection.
|
|
296
|
+
|
|
297
|
+
This mixin extracts exemption logic from AnyTypeDetector to reduce
|
|
298
|
+
method count while maintaining functionality.
|
|
299
|
+
|
|
300
|
+
Required attributes (from main class):
|
|
301
|
+
source_lines: list[str] - Source code lines for context checking.
|
|
302
|
+
allowed_lines: set[int] - Set of line numbers exempted.
|
|
303
|
+
has_file_level_note: bool - Whether file has NOTE near Any import.
|
|
304
|
+
|
|
305
|
+
Methods:
|
|
306
|
+
_check_file_level_note: Check for file-level NOTE comment.
|
|
307
|
+
_has_allow_decorator: Check for @allow_any decorator.
|
|
308
|
+
_allow_all_lines_in_node: Exempt all lines in an AST node.
|
|
309
|
+
_is_field_with_note: Check for Field() with NOTE comment.
|
|
310
|
+
"""
|
|
311
|
+
|
|
312
|
+
# These attributes are expected to exist on the main class
|
|
313
|
+
source_lines: list[str]
|
|
314
|
+
allowed_lines: set[int]
|
|
315
|
+
has_file_level_note: bool
|
|
316
|
+
|
|
317
|
+
def _check_file_level_note(self) -> bool:
|
|
318
|
+
"""Check if file has a NOTE comment near the Any import.
|
|
319
|
+
|
|
320
|
+
A file-level NOTE comment (within 2 lines of 'from typing import Any'
|
|
321
|
+
or 'import typing') exempts all Pydantic Field() usages with Any in
|
|
322
|
+
that file. This supports the common pattern of documenting the
|
|
323
|
+
workaround once at the import rather than at each field.
|
|
324
|
+
|
|
325
|
+
The NOTE comment must follow the specific format with OMN ticket:
|
|
326
|
+
# NOTE: OMN-1234 - Required for Pydantic discriminated union
|
|
327
|
+
# NOTE: OMN-5678 - Dynamic JSON payload handling
|
|
328
|
+
|
|
329
|
+
Generic NOTE comments without OMN ticket codes do NOT qualify:
|
|
330
|
+
# NOTE: Required for... (INVALID - missing ticket)
|
|
331
|
+
# NOTE: reason (INVALID - missing ticket)
|
|
332
|
+
|
|
333
|
+
Supports both single-line and multi-line import blocks:
|
|
334
|
+
from typing import Any # NOTE: OMN-1234 - JSON payload fields
|
|
335
|
+
|
|
336
|
+
from typing import (
|
|
337
|
+
Any, # NOTE: OMN-1234 - JSON payload fields
|
|
338
|
+
Dict,
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
from typing import \\
|
|
342
|
+
Any # NOTE: OMN-1234 - Backslash continuation import
|
|
343
|
+
|
|
344
|
+
Returns:
|
|
345
|
+
True if file has a valid file-level NOTE comment with OMN ticket.
|
|
346
|
+
|
|
347
|
+
Note:
|
|
348
|
+
Only scans first 100 lines for performance. Imports should
|
|
349
|
+
always appear near the top of Python files per PEP 8.
|
|
350
|
+
|
|
351
|
+
IMPORTANT: Each line is checked individually rather than joining
|
|
352
|
+
context into a single string. This prevents false positives where
|
|
353
|
+
"NOTE:" appears on one line and "OMN-1234" on a different,
|
|
354
|
+
unrelated line.
|
|
355
|
+
|
|
356
|
+
Uses _extract_comment_portion to avoid false positives from
|
|
357
|
+
# characters inside string literals.
|
|
358
|
+
|
|
359
|
+
The window is intentionally tight (2 lines before/after) to ensure
|
|
360
|
+
NOTE comments are closely associated with the import they document.
|
|
361
|
+
"""
|
|
362
|
+
# Only scan first 100 lines - imports must be at top per PEP 8
|
|
363
|
+
max_lines = min(100, len(self.source_lines))
|
|
364
|
+
|
|
365
|
+
# Track if we're inside a multi-line import block
|
|
366
|
+
in_multiline_import = False
|
|
367
|
+
multiline_import_start = -1
|
|
368
|
+
multiline_import_end = -1
|
|
369
|
+
|
|
370
|
+
i = 0
|
|
371
|
+
while i < max_lines:
|
|
372
|
+
line = self.source_lines[i]
|
|
373
|
+
|
|
374
|
+
# Skip if we're inside a known multi-line block
|
|
375
|
+
if in_multiline_import and i <= multiline_import_end:
|
|
376
|
+
# Check if this line contains Any (case-sensitive for import)
|
|
377
|
+
if "Any" in line:
|
|
378
|
+
# Check the entire multi-line block and surrounding lines for NOTE
|
|
379
|
+
# Use tight window for lines before/after the block
|
|
380
|
+
start = max(0, multiline_import_start - _FILE_LEVEL_NOTE_WINDOW)
|
|
381
|
+
end = min(
|
|
382
|
+
len(self.source_lines),
|
|
383
|
+
multiline_import_end + _FILE_LEVEL_NOTE_WINDOW + 1,
|
|
384
|
+
)
|
|
385
|
+
for check_line in self.source_lines[start:end]:
|
|
386
|
+
comment = _extract_comment_portion(check_line)
|
|
387
|
+
if comment and _is_any_exemption_note(comment):
|
|
388
|
+
return True
|
|
389
|
+
|
|
390
|
+
# Check if we've reached the end of the multi-line block
|
|
391
|
+
if i >= multiline_import_end:
|
|
392
|
+
in_multiline_import = False
|
|
393
|
+
multiline_import_start = -1
|
|
394
|
+
multiline_import_end = -1
|
|
395
|
+
i += 1
|
|
396
|
+
continue
|
|
397
|
+
|
|
398
|
+
# Check for multi-line import (parenthesized or backslash continuation)
|
|
399
|
+
is_multiline, start_idx, end_idx = _is_in_multiline_import(
|
|
400
|
+
self.source_lines, i, max_lines
|
|
401
|
+
)
|
|
402
|
+
if is_multiline:
|
|
403
|
+
in_multiline_import = True
|
|
404
|
+
multiline_import_start = start_idx
|
|
405
|
+
multiline_import_end = end_idx
|
|
406
|
+
# Check if Any is on the first line of the multi-line import
|
|
407
|
+
if "Any" in line:
|
|
408
|
+
start = max(0, start_idx - _FILE_LEVEL_NOTE_WINDOW)
|
|
409
|
+
end = min(
|
|
410
|
+
len(self.source_lines),
|
|
411
|
+
end_idx + _FILE_LEVEL_NOTE_WINDOW + 1,
|
|
412
|
+
)
|
|
413
|
+
for check_line in self.source_lines[start:end]:
|
|
414
|
+
comment = _extract_comment_portion(check_line)
|
|
415
|
+
if comment and _is_any_exemption_note(comment):
|
|
416
|
+
return True
|
|
417
|
+
i += 1
|
|
418
|
+
continue
|
|
419
|
+
|
|
420
|
+
# Single-line import: "from typing import Any"
|
|
421
|
+
if "from typing import" in line and "Any" in line:
|
|
422
|
+
# Check surrounding lines INDIVIDUALLY using tight window
|
|
423
|
+
# to prevent cross-line false positives
|
|
424
|
+
start = max(0, i - _FILE_LEVEL_NOTE_WINDOW)
|
|
425
|
+
end = min(len(self.source_lines), i + _FILE_LEVEL_NOTE_WINDOW + 1)
|
|
426
|
+
for check_line in self.source_lines[start:end]:
|
|
427
|
+
# Use _extract_comment_portion to avoid string literal false positives
|
|
428
|
+
comment = _extract_comment_portion(check_line)
|
|
429
|
+
if comment and _is_any_exemption_note(comment):
|
|
430
|
+
return True
|
|
431
|
+
|
|
432
|
+
# Also check for 'import typing' style
|
|
433
|
+
elif "import typing" in line:
|
|
434
|
+
start = max(0, i - _FILE_LEVEL_NOTE_WINDOW)
|
|
435
|
+
end = min(len(self.source_lines), i + _FILE_LEVEL_NOTE_WINDOW + 1)
|
|
436
|
+
for check_line in self.source_lines[start:end]:
|
|
437
|
+
comment = _extract_comment_portion(check_line)
|
|
438
|
+
if comment and _is_any_exemption_note(comment):
|
|
439
|
+
return True
|
|
440
|
+
|
|
441
|
+
i += 1
|
|
442
|
+
|
|
443
|
+
return False
|
|
444
|
+
|
|
445
|
+
def _has_allow_decorator(self, decorator_list: list[ast.expr]) -> bool:
|
|
446
|
+
"""Check if any decorator allows Any type usage.
|
|
447
|
+
|
|
448
|
+
Args:
|
|
449
|
+
decorator_list: List of decorator AST expressions.
|
|
450
|
+
|
|
451
|
+
Returns:
|
|
452
|
+
True if an allow decorator is present.
|
|
453
|
+
"""
|
|
454
|
+
for decorator in decorator_list:
|
|
455
|
+
# Direct decorator: @allow_any
|
|
456
|
+
if isinstance(decorator, ast.Name) and decorator.id in _ALLOW_DECORATORS:
|
|
457
|
+
return True
|
|
458
|
+
# Call decorator: @allow_any("reason")
|
|
459
|
+
if isinstance(decorator, ast.Call):
|
|
460
|
+
if (
|
|
461
|
+
isinstance(decorator.func, ast.Name)
|
|
462
|
+
and decorator.func.id in _ALLOW_DECORATORS
|
|
463
|
+
):
|
|
464
|
+
return True
|
|
465
|
+
return False
|
|
466
|
+
|
|
467
|
+
def _allow_all_lines_in_node(self, node: ast.AST) -> None:
|
|
468
|
+
"""Allow Any usage in all lines within a node.
|
|
469
|
+
|
|
470
|
+
Args:
|
|
471
|
+
node: The AST node whose lines should be exempted.
|
|
472
|
+
"""
|
|
473
|
+
for stmt in ast.walk(node):
|
|
474
|
+
if hasattr(stmt, "lineno"):
|
|
475
|
+
self.allowed_lines.add(stmt.lineno)
|
|
476
|
+
|
|
477
|
+
def _is_field_with_note(self, node: ast.AnnAssign) -> bool:
|
|
478
|
+
"""Check if an annotated assignment is a Field() with NOTE comment.
|
|
479
|
+
|
|
480
|
+
The NOTE comment must appear:
|
|
481
|
+
- At file level (near the Any import), OR
|
|
482
|
+
- On the same line as the field (inline comment), OR
|
|
483
|
+
- In the contiguous comment block immediately preceding the field, OR
|
|
484
|
+
- As a NOTE comment above a type: ignore directive
|
|
485
|
+
|
|
486
|
+
The NOTE comment must follow the specific format with OMN ticket:
|
|
487
|
+
# NOTE: OMN-1234 - Required for Pydantic discriminated union
|
|
488
|
+
# NOTE: OMN-5678 - Dynamic JSON payload handling
|
|
489
|
+
|
|
490
|
+
Generic NOTE comments without OMN ticket codes do NOT qualify:
|
|
491
|
+
# NOTE: Required for... (INVALID - missing ticket)
|
|
492
|
+
# NOTE: reason (INVALID - missing ticket)
|
|
493
|
+
# Any reason here (INVALID - wrong format, must start with NOTE:)
|
|
494
|
+
|
|
495
|
+
File-level NOTE comments (within 2 lines of Any import) exempt all
|
|
496
|
+
Field() usages in that file, supporting the common pattern of
|
|
497
|
+
documenting the workaround once at the import.
|
|
498
|
+
|
|
499
|
+
Type-ignore pattern (requires NOTE on preceding line):
|
|
500
|
+
# NOTE: OMN-1234 - Required for Pydantic discriminated union
|
|
501
|
+
field: Any = Field(...) # type: ignore[valid-type]
|
|
502
|
+
|
|
503
|
+
Args:
|
|
504
|
+
node: The annotated assignment node.
|
|
505
|
+
|
|
506
|
+
Returns:
|
|
507
|
+
True if this is a Field() call with a proper NOTE comment
|
|
508
|
+
containing an OMN ticket reference.
|
|
509
|
+
|
|
510
|
+
Note:
|
|
511
|
+
This method requires _is_field_call and _contains_any from
|
|
512
|
+
MixinAnyTypeClassification and the main class respectively.
|
|
513
|
+
|
|
514
|
+
For inline comments, ONLY the comment portion is inspected.
|
|
515
|
+
This prevents false matches where NOTE appears in code/strings.
|
|
516
|
+
"""
|
|
517
|
+
# Check if value is a Field() call
|
|
518
|
+
# NOTE: OMN-1305 - _is_field_call from MixinAnyTypeClassification (mixin composition)
|
|
519
|
+
if node.value is None or not self._is_field_call(node.value): # type: ignore[attr-defined]
|
|
520
|
+
return False
|
|
521
|
+
|
|
522
|
+
# Check if annotation contains Any
|
|
523
|
+
# NOTE: OMN-1305 - _contains_any from AnyTypeDetector (mixin composition)
|
|
524
|
+
if not self._contains_any(node.annotation): # type: ignore[attr-defined]
|
|
525
|
+
return False
|
|
526
|
+
|
|
527
|
+
# File-level NOTE comment exempts all Field() usages
|
|
528
|
+
if self.has_file_level_note:
|
|
529
|
+
return True
|
|
530
|
+
|
|
531
|
+
line_num = node.lineno
|
|
532
|
+
|
|
533
|
+
# First, check for inline NOTE comment on the same line
|
|
534
|
+
# CRITICAL: Extract ONLY the comment portion to avoid matching NOTE in code
|
|
535
|
+
# This handles cases like:
|
|
536
|
+
# field: Any = Field(NOTE="something") # NOTE: OMN-1234 - reason
|
|
537
|
+
# We only check "# NOTE: OMN-1234 - reason", not "NOTE=" in the code.
|
|
538
|
+
#
|
|
539
|
+
# _extract_comment_portion correctly handles:
|
|
540
|
+
# - Hash (#) characters inside string literals
|
|
541
|
+
# - Single, double, and triple quoted strings
|
|
542
|
+
# - Escaped quotes within strings
|
|
543
|
+
if 0 < line_num <= len(self.source_lines):
|
|
544
|
+
current_line = self.source_lines[line_num - 1]
|
|
545
|
+
# Extract only the actual comment, ignoring # in strings
|
|
546
|
+
comment_portion = _extract_comment_portion(current_line)
|
|
547
|
+
if comment_portion and _is_any_exemption_note(comment_portion):
|
|
548
|
+
return True
|
|
549
|
+
|
|
550
|
+
# Check for type: ignore with valid NOTE on preceding line
|
|
551
|
+
# This handles the pattern:
|
|
552
|
+
# # NOTE: OMN-1234 - Required for Pydantic discriminated union
|
|
553
|
+
# field: Any = Field(...) # type: ignore[valid-type]
|
|
554
|
+
if _has_type_ignore_with_valid_note(self.source_lines, line_num):
|
|
555
|
+
return True
|
|
556
|
+
|
|
557
|
+
# Look for NOTE comment in contiguous comment block immediately above
|
|
558
|
+
# Stop as soon as we hit a non-comment, non-blank line
|
|
559
|
+
for i in range(line_num - 2, max(-1, line_num - _NOTE_LOOKBACK_LINES - 2), -1):
|
|
560
|
+
if i < 0 or i >= len(self.source_lines):
|
|
561
|
+
break
|
|
562
|
+
|
|
563
|
+
line_content = self.source_lines[i].strip()
|
|
564
|
+
|
|
565
|
+
# Skip blank lines
|
|
566
|
+
if not line_content:
|
|
567
|
+
continue
|
|
568
|
+
|
|
569
|
+
# Check if this is a comment line
|
|
570
|
+
if line_content.startswith("#"):
|
|
571
|
+
# Use strict matching - must have NOTE: and OMN ticket code
|
|
572
|
+
if _is_any_exemption_note(line_content):
|
|
573
|
+
return True
|
|
574
|
+
# Continue looking in the comment block
|
|
575
|
+
continue
|
|
576
|
+
|
|
577
|
+
# Non-comment, non-blank line - stop looking
|
|
578
|
+
break
|
|
579
|
+
|
|
580
|
+
return False
|