metaobjects 0.24.4__tar.gz → 0.25.0__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.
- {metaobjects-0.24.4 → metaobjects-0.25.0}/PKG-INFO +1 -1
- {metaobjects-0.24.4 → metaobjects-0.25.0}/pyproject.toml +1 -1
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/__init__.py +2 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/agent_context/scaffold.py +62 -3
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/apidocs/builder.py +10 -4
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/cli.py +260 -32
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/KNOWN_GAPS.md +25 -0
- metaobjects-0.25.0/src/metaobjects/codegen/config.py +74 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/generator_registry.py +8 -1
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/generators/entity_model.py +23 -10
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/generators/filter_allowlist_generator.py +2 -15
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/generators/m2m_codegen.py +58 -33
- metaobjects-0.25.0/src/metaobjects/codegen/generators/names_generator.py +547 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/generators/router_generator.py +28 -21
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/instance_artifacts.py +5 -2
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/metaobjects-config.schema.json +5 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/project_config.py +32 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/errors.py +7 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/meta_data.py +33 -6
- metaobjects-0.25.0/src/metaobjects/naming.py +136 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/parser.py +101 -2
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/registry.py +8 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/registry_manifest.py +1 -1
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/runtime/object_manager.py +68 -41
- metaobjects-0.25.0/src/metaobjects/source_resolution.py +105 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/spec_metamodel/attr.json +1 -1
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/spec_metamodel/field.json +1 -1
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/spec_metamodel/layout.json +1 -1
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/spec_metamodel/object.json +1 -1
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/spec_metamodel/origin.json +1 -1
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/spec_metamodel/relationship.json +1 -1
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/spec_metamodel/source.json +1 -1
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/spec_metamodel/template.json +1 -1
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/spec_metamodel/validator.json +1 -1
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/spec_metamodel/view.json +1 -1
- metaobjects-0.25.0/tests/codegen/test_cli.py +346 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_cli_config_verify.py +106 -3
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_cli_registry.py +2 -2
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_entity_model.py +27 -14
- metaobjects-0.25.0/tests/codegen/test_m2m_codegen.py +383 -0
- metaobjects-0.25.0/tests/codegen/test_names_extends_chain.py +481 -0
- metaobjects-0.25.0/tests/codegen/test_names_generator.py +523 -0
- metaobjects-0.25.0/tests/codegen/test_no_magic_physical_names.py +922 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_project_config.py +74 -0
- metaobjects-0.25.0/tests/codegen/test_source_resolution.py +312 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_sourceless_projection.py +5 -7
- metaobjects-0.25.0/tests/loader/test_abstract_subtype_authored.py +159 -0
- metaobjects-0.25.0/tests/runtime/test_object_manager_table_name.py +87 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_agent_context_staleness.py +38 -0
- metaobjects-0.25.0/tests/unit/test_column_naming_strategy.py +105 -0
- metaobjects-0.25.0/tests/unit/test_effective_children_sibling_shadowing.py +176 -0
- metaobjects-0.25.0/tests/unit/test_no_dead_config_fields.py +100 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/uv.lock +1 -1
- metaobjects-0.24.4/src/metaobjects/codegen/config.py +0 -27
- metaobjects-0.24.4/tests/codegen/test_cli.py +0 -163
- metaobjects-0.24.4/tests/codegen/test_m2m_codegen.py +0 -157
- {metaobjects-0.24.4 → metaobjects-0.25.0}/.gitignore +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/LICENSE +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/README.md +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/hatch_build.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/scripts/generate_embedded_library.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/agent_context/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/apidocs/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/apidocs/api_model.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/apidocs/naming.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/apidocs/paths.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/apidocs/renderer.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/attr_class_map.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/collision_names.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/constants.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/extract_delegate_emitter.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/extract_schema_emitter.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/format.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/fr010_field_mapping.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/generator.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/generators/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/generators/extractor_generator.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/generators/find_inbound.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/generators/fr019_shared_enum.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/generators/output_parser_generator.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/generators/output_prompt_generator.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/generators/payload_vo_generator.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/generators/render_helper_generator.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/generators/template_generator.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/generators/tph_plan.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/generators/trace_helper_generator.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/output_format_spec_emitter.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/overwrite_policy.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/runner.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/runtime/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/runtime/filter_parser.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/template_codegen/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/template_codegen/output_pattern.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/template_codegen/template_data.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/template_codegen/template_spec.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/codegen/type_map.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/config/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/config/neutral_config.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/config/source_resolver.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/core_types.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/datatype.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/documentation/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/documentation/doc_constants.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/documentation/doc_provider.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/documentation/doc_schema.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/library/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/library/embedded_library.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/library/library_sources.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/loader/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/loader/merge.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/loader/meta_data_loader.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/loader/registered_validation.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/loader/sources/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/loader/sources/directory_source.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/loader/sources/file_source.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/loader/sources/meta_data_source.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/loader/sources/uri_source.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/loader/validate_discriminator.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/loader/validate_enum_normalize_ambiguity.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/loader/validate_field_mutability.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/loader/validate_source_escapes.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/loader/validate_source_parameter_ref.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/loader/validate_source_physical_names.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/loader/validation_passes.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/attr/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/attr/attr_constants.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/attr/meta_attr.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/field/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/field/field_constants.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/field/meta_field.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/identity/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/identity/identity_constants.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/identity/meta_identity.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/index/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/index/index_constants.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/index/meta_index.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/object/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/object/meta_object.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/object/meta_object_aware.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/object/object_class_registry.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/object/object_constants.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/object/object_extract.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/object/value_object.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/relationship/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/relationship/derive_m2m_fields.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/relationship/meta_relationship.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/relationship/relationship_constants.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/requirement/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/requirement/meta_requirement.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/requirement/requirement_constants.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/validator/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/core/validator/validator_constants.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/meta_root.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/persistence/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/persistence/db/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/persistence/db/db_constants.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/persistence/db/db_provider.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/persistence/origin/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/persistence/origin/meta_origin.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/persistence/origin/origin_constants.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/persistence/source/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/persistence/source/meta_source.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/persistence/source/source_constants.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/presentation/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/presentation/layout/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/presentation/layout/layout_constants.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/presentation/layout/meta_layout.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/presentation/ui/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/presentation/ui/ui_provider.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/presentation/view/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/presentation/view/meta_view.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/presentation/view/view_constants.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/provider_extends.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/template/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/template/meta_template.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/template/prompt_provider.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/meta/template/template_constants.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/naming_refs.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/parser_yaml.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/provider.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/py.typed +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/render/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/render/email_document.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/render/escapers.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/render/extract/KNOWN_GAPS.md +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/render/extract/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/render/extract/coerce.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/render/extract/extract.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/render/extract/extract_map.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/render/extract/json_forgiving_reader.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/render/extract/locate.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/render/extract/normalize.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/render/extract/strip.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/render/extract/types.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/render/extract/xml_forgiving_reader.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/render/filesystem_provider.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/render/payload_accessors.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/render/prompt/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/render/prompt/output_format_renderer.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/render/prompt/output_format_spec.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/render/prompt/prompt_field.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/render/prompt/prompt_overrides.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/render/prompt/prompt_style.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/render/renderer.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/render/verify.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/runtime/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/runtime/llm_recorder.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/runtime/n2m_resolver.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/runtime/tph.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/serializer_json.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/shared/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/shared/base_types.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/shared/separators.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/shared/structural.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/source/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/source/error_source.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/source/json_path.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/source/semantic_diff.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/source/yaml_positions.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/spec_metamodel/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/spec_metamodel/db.json +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/spec_metamodel/documentation.json +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/spec_metamodel/identity.json +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/spec_metamodel/index.json +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/spec_metamodel/prompt.json +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/spec_metamodel/requirement.json +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/spec_metamodel/ui-web.json +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/spec_metamodel/ui.json +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/super_resolve.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/validation_types.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/src/metaobjects/yaml_desugar.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/golden/extends/expected/BaseEntity.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/golden/extends/expected/Program.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/golden/extends/meta.json +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/golden/nested-array/expected/AuthorBrief.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/golden/nested-array/expected/PostBrief.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/golden/nested-array/meta.json +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/golden/scalars/expected/Metric.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/golden/scalars/expected/Report.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/golden/scalars/meta.json +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/golden/vanilla/expected/Subscriber.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/golden/vanilla/meta.json +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_abstract_conformance.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_api_docs_builder.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_api_docs_paths.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_cli_config_gen.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_cli_providers.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_cli_staleness_nudge.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_cli_verify_strict.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_cli_verify_subverbs.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_constants_config.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_enum_conformance.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_extends_abstract_field_inheritance.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_extract_tier_collision.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_extractor_generator.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_filter_allowlist_generator.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_format.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_fr010_nested_object_prompt.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_fr010_output_codegen.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_fr019_shared_provided_conformance.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_generator.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_generator_extension_seams.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_golden.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_inherit_without_restate_gate.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_inheritance_conformance.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_instance_artifacts.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_origin_nullability.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_output_parser_generator.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_overwrite_policy.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_overwrite_policy_hash.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_payload_vo_generator.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_projection_compile.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_render_helper_conformance.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_render_helper_generator.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_reverse_finders.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_router_autoset.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_router_generator.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_runner.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_template_data.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_template_generator.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_template_output_pattern.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_template_scope_helpers.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_template_scope_walk.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_template_spec.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_tph_codegen.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_trace_helper_generator.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_type_map.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_validation_conformance.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/codegen/test_write_through.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/config/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/config/test_neutral_config.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/config/test_source_resolver.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/conformance/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/conformance/capabilities.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/conformance/conformance-expected-failures.json +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/conformance/conformance_adapter.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/conformance/corpus.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/conformance/expected_failures.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/conformance/fixture_discovery.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/conformance/navigator.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/conformance/test_api_docs_cross_port_conformance.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/conformance/test_conformance.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/conformance/test_extract_conformance.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/conformance/test_extract_object_verdict.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/conformance/test_fr010_loader_attrs.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/conformance/test_fr011_attrs.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/conformance/test_generator_registry_conformance.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/conformance/test_object_model_conformance.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/conformance/test_provider_composition_conformance.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/conformance/test_registry_conformance.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/conformance/test_runner_hardfail.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/conformance/test_source_resolution_conformance.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/conformance/test_spec_metamodel_embed.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/conformance/test_strict_attr_load.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/conformance/test_template_codegen_conformance.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/conformance/test_template_generator_conformance.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/conformance/test_yaml_conformance.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/conformance/yaml-conformance-expected-failures.json +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/integration/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/integration/api_contract_assertions.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/integration/api_contract_jsonb_server.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/integration/api_contract_m2m_server.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/integration/api_contract_server.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/integration/generated_jsonb_app.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/integration/generated_m2m_app.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/integration/generated_router_app.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/integration/generated_tph_app.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/integration/meta_ai_trace.yaml +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/integration/normalization.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/integration/postgres_container.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/integration/query_runner.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/integration/scenarios.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/integration/test_api_contract.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/integration/test_api_contract_generated.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/integration/test_api_contract_jsonb.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/integration/test_api_contract_m2m.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/integration/test_api_contract_m2m_generated.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/integration/test_api_contract_tph_generated.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/integration/test_generated_router_uuid_pk.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/integration/test_llm_call_trace.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/integration/test_normalization.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/integration/test_query_scenarios.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/integration/test_runtime_return_types.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/loader/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/loader/test_enum_extends_values_conflict.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/loader/test_field_mutability_order.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/loader/test_shipped_library_ai.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/loader/test_template_payload_target_210.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/open_closed_proof_test.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/render/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/render/extract/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/render/extract/test_coerce.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/render/extract/test_extract.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/render/extract/test_extract_map.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/render/extract/test_json_forgiving_reader.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/render/extract/test_locate.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/render/extract/test_model.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/render/extract/test_normalize.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/render/extract/test_strip.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/render/extract/test_xml_forgiving_reader.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/render/prompt/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/render/prompt/test_output_format_renderer.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/render/test_email_document.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/render/test_filesystem_provider.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/render/test_output_format_renderer_nested.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/render/test_output_prompt_conformance.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/render/test_render_conformance.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/render/test_render_max_chars.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/render/test_verify.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/render/test_verify_conformance.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/runtime/test_object_manager_enum_intvaluemap.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/source/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/source/test_fr5c_merge_attribution.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/source/test_fr5d_reference_resolution.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/source/test_fr5e_database_source_shape.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/source/test_json_path.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/source/test_semantic_diff.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/source/test_source_on_node.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/source/test_yaml_positions.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/test_api_docs_accuracy.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/__init__.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_capabilities.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_common_attrs.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_core_types.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_effective_package.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_errors.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_field_enum.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_field_enum_intvaluemap.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_field_map_validation.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_field_uuid_dbcolumntype.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_fr016_source_name_and_kind_aliases.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_index_lookup.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_llm_recorder.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_loader.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_loader_bom.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_loader_class.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_merge.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_meta_attr.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_meta_data.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_meta_source.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_module_shortcuts.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_n2m_resolver.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_n2m_resolver_inherited.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_object_manager_autoset_stamping.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_object_manager_uuid_coercion.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_object_manager_write_through.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_one_primary_source.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_parser.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_parser_yaml.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_provider.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_provider_extension.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_registry.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_registry_completeness.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_registry_extend.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_registry_sealed.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_relationship_referential_actions.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_resolution_key.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_runtime_resolution_key_binding.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_serializer.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_shared_constants.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_smoke.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_source_escapes.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_sources.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_strict_child_placement.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_super_resolve.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_template_toolcall.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_template_wrong_subtype_attrs.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_validation_attr_schema.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_validation_filter_values.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_validation_origin_195.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_validation_origin_paths.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_validation_sort_field.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_validation_warnings.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_write_coercion_arrays.py +0 -0
- {metaobjects-0.24.4 → metaobjects-0.25.0}/tests/unit/test_yaml_desugar.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: metaobjects
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.25.0
|
|
4
4
|
Summary: Cross-language metadata standard: declare typed entities once, generate idiomatic drift-checked code across languages — Python port.
|
|
5
5
|
Project-URL: Homepage, https://metaobjects.dev
|
|
6
6
|
Project-URL: Repository, https://github.com/metaobjectsdev/metaobjects
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "metaobjects"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.25.0"
|
|
4
4
|
description = "Cross-language metadata standard: declare typed entities once, generate idiomatic drift-checked code across languages — Python port."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
|
@@ -35,6 +35,7 @@ from .meta.core.object.object_extract import (
|
|
|
35
35
|
extract_schema_for,
|
|
36
36
|
)
|
|
37
37
|
from .meta.core.object.value_object import ValueObject
|
|
38
|
+
from .naming import resolve_column_name
|
|
38
39
|
|
|
39
40
|
# Module-level shortcuts: the 99% case for callers who don't need a
|
|
40
41
|
# long-lived loader. Signatures + docstrings come straight from the
|
|
@@ -58,6 +59,7 @@ __all__ = [
|
|
|
58
59
|
"load_directory",
|
|
59
60
|
"load_uris",
|
|
60
61
|
"load_string",
|
|
62
|
+
"resolve_column_name",
|
|
61
63
|
# Runtime object model (Phase A)
|
|
62
64
|
"ValueObject",
|
|
63
65
|
"MetaObjectAware",
|
|
@@ -10,6 +10,7 @@ installed MetaObjects version.
|
|
|
10
10
|
|
|
11
11
|
from __future__ import annotations
|
|
12
12
|
|
|
13
|
+
import re
|
|
13
14
|
from dataclasses import dataclass
|
|
14
15
|
from importlib.metadata import PackageNotFoundError, version as _pkg_version
|
|
15
16
|
|
|
@@ -76,6 +77,61 @@ class Manifest:
|
|
|
76
77
|
)
|
|
77
78
|
|
|
78
79
|
|
|
80
|
+
# The sentinel a port stamps when it cannot resolve its own installed version.
|
|
81
|
+
_UNRESOLVED_VERSION = "0.0.0"
|
|
82
|
+
|
|
83
|
+
_RELEASE_RE = re.compile(r"^(\d+)\.(\d+)\.(\d+)$")
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _release_series(version: object) -> tuple[int, int] | None:
|
|
87
|
+
"""Ordered release coordinate ``(minor, patch)``, or ``None`` when not orderable.
|
|
88
|
+
|
|
89
|
+
The MAJOR is deliberately dropped. It is a per-registry constant, not information:
|
|
90
|
+
npm/PyPI/NuGet ship ``0.<m>.<p>`` and Maven Central the same ``<m>.<p>`` on its
|
|
91
|
+
historical major ``7``, so minor.patch IS the shared release coordinate across all
|
|
92
|
+
four ports.
|
|
93
|
+
|
|
94
|
+
``None`` means "not orderable, so nudge", and deliberately covers prereleases
|
|
95
|
+
(``0.24.5-rc.1``), build metadata (``0.24.5+abc``) and the ``0.0.0`` sentinel. Each
|
|
96
|
+
must keep nudging: an RC-scaffolded context against a final release is still worth
|
|
97
|
+
refreshing, and an unknown install must never assert "in sync".
|
|
98
|
+
"""
|
|
99
|
+
if not isinstance(version, str):
|
|
100
|
+
return None
|
|
101
|
+
v = version.strip()
|
|
102
|
+
if v == _UNRESOLVED_VERSION:
|
|
103
|
+
return None
|
|
104
|
+
m = _RELEASE_RE.match(v)
|
|
105
|
+
if m is None:
|
|
106
|
+
return None
|
|
107
|
+
return int(m.group(2)), int(m.group(3))
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _context_is_ahead_of_install(generated_by: object, current_version: str) -> bool:
|
|
111
|
+
"""True when the manifest was stamped by a release STRICTLY NEWER than the install.
|
|
112
|
+
|
|
113
|
+
The one exemption from "any drift nudges", and it exists because of the
|
|
114
|
+
publish-what-changed rule (docs/RELEASING.md): a registry publishes only when it has
|
|
115
|
+
a changed product file, so a port legitimately sits behind npm — while
|
|
116
|
+
``meta agent-docs``, the canonical scaffolder for EVERY port, stamps the npm version
|
|
117
|
+
it was run from. A Python install at ``0.24.4`` whose context was scaffolded by npm
|
|
118
|
+
``0.24.7`` is correct, and nudging it is issue #347 exactly: the remedy re-runs the
|
|
119
|
+
scaffolder, which re-stamps ``0.24.7``, so the advisory can never be satisfied and
|
|
120
|
+
fires on every build forever.
|
|
121
|
+
|
|
122
|
+
KNOWN BOUND, stated rather than hidden: ordering on minor.patch assumes both versions
|
|
123
|
+
sit in the same release SERIES. That holds for every release to date and after the
|
|
124
|
+
1.0/8.0 cut, but not ACROSS it — there a ``0.24.x`` context against a ``1.0.0``
|
|
125
|
+
install reads as "ahead" and the nudge is suppressed once. A missed advisory, never a
|
|
126
|
+
wrong action.
|
|
127
|
+
"""
|
|
128
|
+
stamped = _release_series(generated_by)
|
|
129
|
+
installed = _release_series(current_version)
|
|
130
|
+
if stamped is None or installed is None:
|
|
131
|
+
return False # not orderable → nudge
|
|
132
|
+
return stamped > installed
|
|
133
|
+
|
|
134
|
+
|
|
79
135
|
def agent_context_staleness(
|
|
80
136
|
manifest: dict[str, object] | None, current_version: str
|
|
81
137
|
) -> str | None:
|
|
@@ -85,15 +141,18 @@ def agent_context_staleness(
|
|
|
85
141
|
is in sync — and a one-line advisory message otherwise. Pure + advisory:
|
|
86
142
|
never raises, never blocks, never writes.
|
|
87
143
|
|
|
88
|
-
The comparison is **exact equality**
|
|
89
|
-
|
|
90
|
-
|
|
144
|
+
The comparison is **exact equality** first: ANY drift nudges (a re-scaffold is
|
|
145
|
+
cheap + idempotent), so this is not a semver compare — a prerelease or
|
|
146
|
+
build-metadata difference is still a reason to refresh. See
|
|
147
|
+
``_context_is_ahead_of_install`` for the ONE case that is exempt.
|
|
91
148
|
"""
|
|
92
149
|
if manifest is None:
|
|
93
150
|
return None # no agent context here → nothing to nudge
|
|
94
151
|
generated_by = manifest.get("generatedBy")
|
|
95
152
|
if generated_by == current_version:
|
|
96
153
|
return None # in sync
|
|
154
|
+
if _context_is_ahead_of_install(generated_by, current_version):
|
|
155
|
+
return None # scaffolded by a NEWER release than this install — see below
|
|
97
156
|
frm = generated_by if generated_by else "an older MetaObjects"
|
|
98
157
|
return (
|
|
99
158
|
f"MetaObjects agent context was generated by {frm}; "
|
|
@@ -4,7 +4,7 @@ This is the ACCURATE-BY-CONSTRUCTION half of the api-docs pipeline: every
|
|
|
4
4
|
documented symbol name comes from the :mod:`metaobjects.apidocs.naming` seam (never
|
|
5
5
|
re-concatenated here — the SAME seam the real generators delegate to), and every
|
|
6
6
|
inclusion decision comes from an applies-predicate that REUSES the corresponding
|
|
7
|
-
generator's own gate helpers (``emits_instance_artifacts`` / ``
|
|
7
|
+
generator's own gate helpers (``emits_instance_artifacts`` / ``primary_rdb_source``
|
|
8
8
|
+ source kind / ``resolve_payload_vo`` / format check / ``is_tph_subtype``) rather
|
|
9
9
|
than re-implementing the gate. The result is that what this builder documents ==
|
|
10
10
|
what the generators emit, by SHARING the single source of truth.
|
|
@@ -47,9 +47,9 @@ from metaobjects.codegen.generators.payload_vo_generator import (
|
|
|
47
47
|
is_field_required,
|
|
48
48
|
resolve_payload_vo,
|
|
49
49
|
)
|
|
50
|
-
from metaobjects.codegen.generators.router_generator import _primary_source_rdb
|
|
51
50
|
from metaobjects.codegen.generators.tph_plan import is_tph_subtype
|
|
52
51
|
from metaobjects.codegen.instance_artifacts import emits_instance_artifacts, is_abstract
|
|
52
|
+
from metaobjects.source_resolution import primary_rdb_source
|
|
53
53
|
from metaobjects.meta.core.field import field_constants as fc
|
|
54
54
|
from metaobjects.meta.core.field.meta_field import MetaField
|
|
55
55
|
from metaobjects.meta.core.object.meta_object import MetaObject
|
|
@@ -91,7 +91,7 @@ def _is_writable_table_entity(obj: MetaObject, object_index: dict[str, MetaObjec
|
|
|
91
91
|
return False
|
|
92
92
|
if is_tph_subtype(obj):
|
|
93
93
|
return False
|
|
94
|
-
src =
|
|
94
|
+
src = primary_rdb_source(obj)
|
|
95
95
|
if src is None:
|
|
96
96
|
return False
|
|
97
97
|
return src.effective_kind() == SOURCE_KIND_TABLE
|
|
@@ -261,7 +261,13 @@ class PythonApiModelBuilder:
|
|
|
261
261
|
add("PUT " + item, "update (PUT alias)")
|
|
262
262
|
add("DELETE " + item, "delete")
|
|
263
263
|
|
|
264
|
-
# M:N traversal — GET /<source-plural>/{id}/<relation>.
|
|
264
|
+
# M:N traversal — GET /<source-plural>/{id}/<relation>. `docs` has no
|
|
265
|
+
# `GenConfig`/`--column-naming` of its own (see `cli.py`'s docs handler) and
|
|
266
|
+
# this loop reads only `.target_entity` / `.relation_name` off the
|
|
267
|
+
# descriptor — never a physical column/table name — so resolving it under
|
|
268
|
+
# the port default here changes nothing observable; threading a naming
|
|
269
|
+
# strategy through would mean inventing a config seam this command doesn't
|
|
270
|
+
# have, for a value nothing here would read.
|
|
265
271
|
for d in resolve_m2m_descriptors(entity, object_index):
|
|
266
272
|
target = object_index.get(d.target_entity)
|
|
267
273
|
target_name = target.name if target is not None else d.target_entity
|
|
@@ -17,6 +17,9 @@ Two subcommands:
|
|
|
17
17
|
|
|
18
18
|
--codegen regenerate into a temp dir + diff against the committed
|
|
19
19
|
``--out`` tree (Python's historical default behavior).
|
|
20
|
+
``--column-naming`` must match the strategy ``gen`` was
|
|
21
|
+
run with (R31) or the ``names`` generator's constants
|
|
22
|
+
report spurious drift.
|
|
20
23
|
--templates template/prompt ``{{field}}`` ↔ payload-VO drift — the
|
|
21
24
|
render ``verify()`` gate — resolving each ``template.*``
|
|
22
25
|
node's refs via a filesystem provider rooted at
|
|
@@ -55,6 +58,7 @@ from metaobjects.agent_context import (
|
|
|
55
58
|
)
|
|
56
59
|
from metaobjects.meta.meta_data import MetaData
|
|
57
60
|
from metaobjects.codegen.config import GenConfig
|
|
61
|
+
from metaobjects.codegen.overwrite_policy import has_hash_manifest, read_generated_hash
|
|
58
62
|
from metaobjects.codegen.project_config import (
|
|
59
63
|
CONFIG_FILENAME,
|
|
60
64
|
ConfigError,
|
|
@@ -68,6 +72,7 @@ from metaobjects.codegen.generators.extractor_generator import extractor_generat
|
|
|
68
72
|
from metaobjects.codegen.generators.filter_allowlist_generator import (
|
|
69
73
|
filter_allowlist_generator,
|
|
70
74
|
)
|
|
75
|
+
from metaobjects.codegen.generators.names_generator import names_generator
|
|
71
76
|
from metaobjects.codegen.generators.output_parser_generator import (
|
|
72
77
|
output_parser_generator,
|
|
73
78
|
)
|
|
@@ -87,6 +92,7 @@ from metaobjects.codegen.generators.render_helper_generator import (
|
|
|
87
92
|
_resolve_payload_vo,
|
|
88
93
|
)
|
|
89
94
|
from metaobjects.meta.template import template_constants as tc
|
|
95
|
+
from metaobjects.naming import COLUMN_NAMING_STRATEGIES, DEFAULT_COLUMN_NAMING
|
|
90
96
|
from metaobjects.render.filesystem_provider import FilesystemProvider
|
|
91
97
|
from metaobjects.render.verify import (
|
|
92
98
|
ERR_REQUIRED_SLOT_UNUSED,
|
|
@@ -117,6 +123,7 @@ def _default_generators() -> list[Generator]:
|
|
|
117
123
|
entity_model(),
|
|
118
124
|
router_generator(),
|
|
119
125
|
filter_allowlist_generator(),
|
|
126
|
+
names_generator(),
|
|
120
127
|
payload_vo_generator(),
|
|
121
128
|
output_parser_generator(),
|
|
122
129
|
output_prompt_generator(),
|
|
@@ -368,6 +375,7 @@ def _run_suite(
|
|
|
368
375
|
entity_filter: list[str] | None = None,
|
|
369
376
|
emit_package_init: bool = True,
|
|
370
377
|
gen_state_dir: str | None = None,
|
|
378
|
+
column_naming: str = DEFAULT_COLUMN_NAMING,
|
|
371
379
|
) -> list[str]:
|
|
372
380
|
"""Run a generator suite against an ALREADY-LOADED ``root`` into ``out_dir``.
|
|
373
381
|
|
|
@@ -396,6 +404,7 @@ def _run_suite(
|
|
|
396
404
|
out_dir=out_dir,
|
|
397
405
|
emit_package_init=emit_package_init,
|
|
398
406
|
gen_state_dir=gen_state_dir,
|
|
407
|
+
column_naming=column_naming,
|
|
399
408
|
)
|
|
400
409
|
suite = generators if generators is not None else _default_generators()
|
|
401
410
|
result = run_gen(config, root, generators=suite, entity_filter=entity_filter)
|
|
@@ -412,6 +421,7 @@ def _generate(
|
|
|
412
421
|
emit_package_init: bool = True,
|
|
413
422
|
strict: bool = False,
|
|
414
423
|
providers: list[object] | None = None,
|
|
424
|
+
column_naming: str = DEFAULT_COLUMN_NAMING,
|
|
415
425
|
) -> tuple[list[str], list[str]]:
|
|
416
426
|
"""Run the generator suite into ``out_dir``.
|
|
417
427
|
|
|
@@ -426,6 +436,10 @@ def _generate(
|
|
|
426
436
|
``(written_paths, errors)``. On a load error, ``errors`` is non-empty and no
|
|
427
437
|
files are written. ``strict`` (ADR-0023, #96) is threaded to the load — the
|
|
428
438
|
``verify --codegen`` caller passes True; ``gen`` keeps the default False.
|
|
439
|
+
``column_naming`` (R31) must match the strategy the committed output was
|
|
440
|
+
produced with, or the ``names`` generator's constants regenerate under the
|
|
441
|
+
wrong strategy and every ``<ENTITY>_<FIELD>_COLUMN`` reports spurious drift —
|
|
442
|
+
the caller reads it from the SAME ``--column-naming`` flag `gen` accepts.
|
|
429
443
|
"""
|
|
430
444
|
root, errors = _load_root(metadata_dir, strict=strict, providers=providers)
|
|
431
445
|
if root is None:
|
|
@@ -438,7 +452,10 @@ def _generate(
|
|
|
438
452
|
# directory deleted seconds later. The real gen paths anchor their own manifest via
|
|
439
453
|
# gen_state_dir_for().
|
|
440
454
|
return (
|
|
441
|
-
_run_suite(
|
|
455
|
+
_run_suite(
|
|
456
|
+
root, out_dir, generators, entity_filter, emit_package_init, None,
|
|
457
|
+
column_naming=column_naming,
|
|
458
|
+
),
|
|
442
459
|
[],
|
|
443
460
|
)
|
|
444
461
|
|
|
@@ -454,6 +471,65 @@ def gen_state_dir_for(metadata_dir: str) -> str:
|
|
|
454
471
|
return str(Path(metadata_dir).resolve().parent / ".metaobjects" / ".gen-state")
|
|
455
472
|
|
|
456
473
|
|
|
474
|
+
#: The conventional declarative-template-spec file (SP-1 §4), discovered when
|
|
475
|
+
#: ``--template-spec`` is not passed. VISIBLE and at the project root on purpose:
|
|
476
|
+
#: this repo splits author input (visible — ``metaobjects/``, ``templates/``) from
|
|
477
|
+
#: tool state (hidden — ``.metaobjects/``), and a spec is authored, not generated.
|
|
478
|
+
#: It also sits beside the ``templates/`` dir its refs resolve under.
|
|
479
|
+
TEMPLATE_SPEC_FILENAME = "template-spec.json"
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
def project_root_for(metadata_dir: str) -> Path:
|
|
483
|
+
"""The project a metadata directory belongs to: its PARENT — the directory
|
|
484
|
+
holding ``metaobjects/``. Same rule as :func:`gen_state_dir_for` (which is
|
|
485
|
+
anchored here) and the C# port's ``GenCommand.ProjectRootFor``."""
|
|
486
|
+
return Path(metadata_dir).resolve().parent
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
def template_spec_path_for(metadata_dir: str, explicit: str | None) -> str | None:
|
|
490
|
+
"""Resolve the template-spec to use, or ``None`` for "no template generators".
|
|
491
|
+
|
|
492
|
+
An explicit ``--template-spec`` always wins and is used verbatim (a flag naming
|
|
493
|
+
a missing file stays a hard error at read time — silently ignoring a path the
|
|
494
|
+
user typed would be worse). Otherwise the conventional
|
|
495
|
+
``<projectRoot>/template-spec.json`` is used IF it exists.
|
|
496
|
+
|
|
497
|
+
**Every code path that builds a generator list must call this.** The defect this
|
|
498
|
+
exists to prevent is `gen` and `verify --codegen` resolving the spec differently:
|
|
499
|
+
`gen` honoured the flag while `verify` built its own list and never looked, so
|
|
500
|
+
`verify` regenerated WITHOUT the template generators and reported their committed
|
|
501
|
+
output as stale — with a remedy that loops (regenerating cannot produce files the
|
|
502
|
+
regen does not know about).
|
|
503
|
+
"""
|
|
504
|
+
if explicit:
|
|
505
|
+
return explicit
|
|
506
|
+
candidate = project_root_for(metadata_dir) / TEMPLATE_SPEC_FILENAME
|
|
507
|
+
return str(candidate) if candidate.is_file() else None
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
def template_spec_generators(
|
|
511
|
+
metadata_dir: str, explicit: str | None, templates_dir: str,
|
|
512
|
+
) -> tuple[list[Generator], str | None]:
|
|
513
|
+
"""The declarative Mustache generators for this project, or an error message.
|
|
514
|
+
|
|
515
|
+
Returns ``(generators, None)`` on success — an EMPTY list when there is no spec
|
|
516
|
+
at all — and ``([], message)`` when a spec was found but could not be used.
|
|
517
|
+
"""
|
|
518
|
+
spec_path = template_spec_path_for(metadata_dir, explicit)
|
|
519
|
+
if spec_path is None:
|
|
520
|
+
return [], None
|
|
521
|
+
from metaobjects.codegen.template_codegen.template_spec import (
|
|
522
|
+
parse_template_spec,
|
|
523
|
+
template_spec_to_generators,
|
|
524
|
+
)
|
|
525
|
+
|
|
526
|
+
try:
|
|
527
|
+
spec = parse_template_spec(json.loads(Path(spec_path).read_text(encoding="utf-8")))
|
|
528
|
+
except (OSError, ValueError) as exc:
|
|
529
|
+
return [], f"error: invalid template-spec {spec_path!r}: {exc}"
|
|
530
|
+
return template_spec_to_generators(spec, FilesystemProvider(templates_dir)), None
|
|
531
|
+
|
|
532
|
+
|
|
457
533
|
def resolve_metadata_location(
|
|
458
534
|
config: ProjectConfig | None,
|
|
459
535
|
root: Path,
|
|
@@ -696,20 +772,12 @@ def _cmd_gen(args: argparse.Namespace) -> int:
|
|
|
696
772
|
# SEPARATE pass with emit_package_init=False — no Python __init__.py is injected
|
|
697
773
|
# into their (possibly non-Python) output tree. Templates resolve under
|
|
698
774
|
# --templates via a FilesystemProvider.
|
|
699
|
-
spec_gens
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
try:
|
|
707
|
-
spec = parse_template_spec(json.loads(Path(args.template_spec).read_text(encoding="utf-8")))
|
|
708
|
-
except (OSError, ValueError) as exc:
|
|
709
|
-
print(f"error: invalid --template-spec: {exc}", file=sys.stderr)
|
|
710
|
-
return 1
|
|
711
|
-
provider = FilesystemProvider(args.templates)
|
|
712
|
-
spec_gens = template_spec_to_generators(spec, provider)
|
|
775
|
+
spec_gens, spec_err = template_spec_generators(
|
|
776
|
+
args.metadata_dir, getattr(args, "template_spec", None), args.templates,
|
|
777
|
+
)
|
|
778
|
+
if spec_err is not None:
|
|
779
|
+
print(spec_err, file=sys.stderr)
|
|
780
|
+
return 1
|
|
713
781
|
|
|
714
782
|
entities = _parse_entities(getattr(args, "entities", None))
|
|
715
783
|
providers, providers_ok = _providers_from_args(args)
|
|
@@ -724,7 +792,11 @@ def _cmd_gen(args: argparse.Namespace) -> int:
|
|
|
724
792
|
print(f" {msg}", file=sys.stderr)
|
|
725
793
|
return 1
|
|
726
794
|
gen_state = gen_state_dir_for(args.metadata_dir)
|
|
727
|
-
|
|
795
|
+
column_naming = getattr(args, "column_naming", None) or DEFAULT_COLUMN_NAMING
|
|
796
|
+
written = _run_suite(
|
|
797
|
+
root, args.out, generators, entities,
|
|
798
|
+
gen_state_dir=gen_state, column_naming=column_naming,
|
|
799
|
+
)
|
|
728
800
|
if spec_gens:
|
|
729
801
|
# The template-spec pass renders user-supplied templates: a bad ref or a
|
|
730
802
|
# wrong --templates dir raises RenderError (not OSError/ValueError, so it
|
|
@@ -734,7 +806,7 @@ def _cmd_gen(args: argparse.Namespace) -> int:
|
|
|
734
806
|
try:
|
|
735
807
|
spec_written = _run_suite(
|
|
736
808
|
root, args.out, spec_gens, entities, emit_package_init=False,
|
|
737
|
-
gen_state_dir=gen_state,
|
|
809
|
+
gen_state_dir=gen_state, column_naming=column_naming,
|
|
738
810
|
)
|
|
739
811
|
except RenderError as exc:
|
|
740
812
|
print(
|
|
@@ -845,7 +917,11 @@ def _cmd_gen_neutral_fallback(args: argparse.Namespace) -> int:
|
|
|
845
917
|
return 1
|
|
846
918
|
|
|
847
919
|
gen_state = str(root_dir.resolve() / ".metaobjects" / ".gen-state")
|
|
848
|
-
|
|
920
|
+
column_naming = getattr(args, "column_naming", None) or DEFAULT_COLUMN_NAMING
|
|
921
|
+
written = _run_suite(
|
|
922
|
+
root, args.out, generators, entities,
|
|
923
|
+
gen_state_dir=gen_state, column_naming=column_naming,
|
|
924
|
+
)
|
|
849
925
|
for path in written:
|
|
850
926
|
print(path)
|
|
851
927
|
print(f"metaobjects gen: wrote {len(written)} file(s) to {args.out}")
|
|
@@ -864,6 +940,23 @@ def _cmd_gen_config(args: argparse.Namespace) -> int:
|
|
|
864
940
|
config_path = _find_config(args)
|
|
865
941
|
if config_path is None:
|
|
866
942
|
return _cmd_gen_neutral_fallback(args)
|
|
943
|
+
# An EXPLICIT --template-spec here was silently ignored: config mode goes straight
|
|
944
|
+
# to _run_gen_targets, which has no spec pass. Refuse instead of accepting a flag
|
|
945
|
+
# that does nothing. It cannot simply be honoured, because a spec has no `target`
|
|
946
|
+
# (the CLI ports reject that field outright) while config mode is target-shaped, so
|
|
947
|
+
# there is no non-arbitrary outDir to write into. A DISCOVERED spec is ignored here
|
|
948
|
+
# rather than refused — discovery must not hard-fail a command that never asked for
|
|
949
|
+
# it, and gen/verify agree in config mode either way, so no drift can result.
|
|
950
|
+
if getattr(args, "template_spec", None):
|
|
951
|
+
print(
|
|
952
|
+
"error: --template-spec is not supported in declarative-config mode "
|
|
953
|
+
f"({config_path}): a template-spec entry names no target, and config mode "
|
|
954
|
+
"writes per target, so there is no outDir to render into. Run the explicit "
|
|
955
|
+
"form instead: metaobjects gen <metadata_dir> --out <dir> --template-spec "
|
|
956
|
+
"<json> --templates <dir>.",
|
|
957
|
+
file=sys.stderr,
|
|
958
|
+
)
|
|
959
|
+
return 2
|
|
867
960
|
try:
|
|
868
961
|
config = load_project_config(config_path)
|
|
869
962
|
except ConfigError as exc:
|
|
@@ -903,33 +996,83 @@ def _cmd_gen_config(args: argparse.Namespace) -> int:
|
|
|
903
996
|
return 0
|
|
904
997
|
|
|
905
998
|
|
|
999
|
+
#: Never compared: interpreter droppings, not generated artifacts. A committed
|
|
1000
|
+
#: ``__pycache__`` would otherwise read as drift on every run.
|
|
1001
|
+
_UNCOMPARED_DIRS = {"__pycache__", ".gen-state", ".metaobjects"}
|
|
1002
|
+
_UNCOMPARED_SUFFIXES = {".pyc", ".pyo"}
|
|
1003
|
+
|
|
1004
|
+
|
|
906
1005
|
def _relative_set(root: Path) -> dict[str, str]:
|
|
907
|
-
"""Map every
|
|
1006
|
+
"""Map every generated-artifact file under ``root`` to its content, keyed by rel path.
|
|
908
1007
|
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
1008
|
+
Deliberately NOT scoped to ``*.py``. It was, with a note saying to broaden it "if a
|
|
1009
|
+
generator ever emits a non-``.py`` artifact" — and one does: the declarative
|
|
1010
|
+
``--template-spec`` generators emit text/markdown/csv/json/xml/html by design. The
|
|
1011
|
+
consequence was a gate that answered ``in sync`` with a template-emitted file
|
|
1012
|
+
DELETED and another CORRUPTED, because neither was a ``.py`` and neither was
|
|
1013
|
+
compared. A gate silent about its own output is worse than one that is wrong.
|
|
1014
|
+
|
|
1015
|
+
Binary files are skipped rather than decoded: every generator this project ships
|
|
1016
|
+
emits text, so an undecodable file is by definition not ours.
|
|
912
1017
|
"""
|
|
913
1018
|
files: dict[str, str] = {}
|
|
914
|
-
if root.exists():
|
|
915
|
-
|
|
916
|
-
|
|
1019
|
+
if not root.exists():
|
|
1020
|
+
return files
|
|
1021
|
+
for p in sorted(root.rglob("*")):
|
|
1022
|
+
if not p.is_file():
|
|
1023
|
+
continue
|
|
1024
|
+
rel = p.relative_to(root)
|
|
1025
|
+
if any(part in _UNCOMPARED_DIRS for part in rel.parts):
|
|
1026
|
+
continue
|
|
1027
|
+
if p.suffix in _UNCOMPARED_SUFFIXES:
|
|
1028
|
+
continue
|
|
1029
|
+
try:
|
|
1030
|
+
files[str(rel)] = p.read_text(encoding="utf-8")
|
|
1031
|
+
except (UnicodeDecodeError, OSError):
|
|
1032
|
+
continue
|
|
917
1033
|
return files
|
|
918
1034
|
|
|
919
1035
|
|
|
920
|
-
def
|
|
1036
|
+
def _is_ours_for(gen_state_dir: str | None):
|
|
1037
|
+
"""Jurisdiction predicate for the ``extra`` verdict: did WE write this path?
|
|
1038
|
+
|
|
1039
|
+
``out_dir`` is a DIRECTORY, not a namespace this tool owns — the same ruling the
|
|
1040
|
+
TypeScript gate reached (0.24.3), for the same reason. Broadening the comparison
|
|
1041
|
+
beyond ``*.py`` means the gate now sees every stranger's file too, and convicting
|
|
1042
|
+
those turns a project with zero drift into a red build.
|
|
1043
|
+
|
|
1044
|
+
The manifest already records what we WROTE, keyed relative to ``out_dir`` — the
|
|
1045
|
+
same key space this diff uses — so it answers the ownership question exactly.
|
|
1046
|
+
FAILS CLOSED, matching :func:`is_pristine_generated`: with no manifest at all
|
|
1047
|
+
nothing is proven, so every file stays in scope and the old verdict stands.
|
|
1048
|
+
"""
|
|
1049
|
+
if gen_state_dir is None or not has_hash_manifest(gen_state_dir):
|
|
1050
|
+
return lambda _rel: True
|
|
1051
|
+
return lambda rel: read_generated_hash(gen_state_dir, rel) is not None
|
|
1052
|
+
|
|
1053
|
+
|
|
1054
|
+
def _diff_report(
|
|
1055
|
+
expected: dict[str, str],
|
|
1056
|
+
committed: dict[str, str],
|
|
1057
|
+
gen_state_dir: str | None = None,
|
|
1058
|
+
) -> int:
|
|
921
1059
|
"""Compare a regenerated file map against the committed one; print the
|
|
922
1060
|
standard ``verify --codegen`` drift report. Returns 0 (in sync) or 1.
|
|
923
1061
|
|
|
924
1062
|
Extracted so the explicit-``<metadata_dir>`` flag mode
|
|
925
1063
|
(:func:`_verify_codegen`) and the ``.metaobjects/config.json`` fallback
|
|
926
1064
|
rung (:func:`_verify_codegen_neutral_fallback`) report drift identically.
|
|
1065
|
+
|
|
1066
|
+
``gen_state_dir`` scopes the ``extra`` verdict to files we have a record of
|
|
1067
|
+
writing — see :func:`_is_ours_for`. Omit it to keep the unscoped verdict.
|
|
927
1068
|
"""
|
|
1069
|
+
is_ours = _is_ours_for(gen_state_dir)
|
|
928
1070
|
changed = sorted(
|
|
929
1071
|
k for k in expected if k in committed and expected[k] != committed[k]
|
|
930
1072
|
)
|
|
931
1073
|
missing = sorted(k for k in expected if k not in committed) # not yet committed
|
|
932
|
-
|
|
1074
|
+
# A committed file a fresh regen would not emit is STALE only if it is ours.
|
|
1075
|
+
extra = sorted(k for k in committed if k not in expected and is_ours(k))
|
|
933
1076
|
|
|
934
1077
|
if not changed and not missing and not extra:
|
|
935
1078
|
print(f"metaobjects verify: in sync ({len(expected)} file(s)).")
|
|
@@ -973,13 +1116,37 @@ def _verify_codegen(args: argparse.Namespace) -> int:
|
|
|
973
1116
|
# ADR-0023 strict-by-default (#96): verify loads strict unless --lax is given,
|
|
974
1117
|
# so an undeclared/typo'd own @attr fails verify (matching Java's Maven goal).
|
|
975
1118
|
strict = not getattr(args, "lax", False)
|
|
1119
|
+
# R31: the `names` generator's constants are strategy-dependent (#248-adjacent —
|
|
1120
|
+
# the same generator Task 9 turned on). A regen that defaults to `literal` while
|
|
1121
|
+
# the committed output was produced with `gen --column-naming snake_case` (or any
|
|
1122
|
+
# other non-default strategy) convicts every <ENTITY>_<FIELD>_COLUMN constant as
|
|
1123
|
+
# drift — a gate failing work the product itself sanctions. Must match the `gen`
|
|
1124
|
+
# invocation that produced --out, exactly like --entities above.
|
|
1125
|
+
column_naming = getattr(args, "column_naming", None) or DEFAULT_COLUMN_NAMING
|
|
976
1126
|
providers, providers_ok = _providers_from_args(args)
|
|
977
1127
|
if not providers_ok:
|
|
978
1128
|
return 1
|
|
1129
|
+
# The declarative template generators, resolved by the SAME rule `gen` uses —
|
|
1130
|
+
# explicit flag, else the conventional <projectRoot>/template-spec.json. Without
|
|
1131
|
+
# this, verify regenerated only the default suite and then reported every
|
|
1132
|
+
# spec-emitted file as `extra:` ("stale committed file"), exiting 1 with a remedy
|
|
1133
|
+
# that loops: `gen` reproduces those files but the next verify fails identically.
|
|
1134
|
+
# `verify` spells the templates dir --templates-root (its --templates is the
|
|
1135
|
+
# subverb selector), so the flag is read per-verb and threaded to one resolver.
|
|
1136
|
+
spec_gens, spec_err = template_spec_generators(
|
|
1137
|
+
args.metadata_dir,
|
|
1138
|
+
getattr(args, "template_spec", None),
|
|
1139
|
+
getattr(args, "templates_root", None) or "templates",
|
|
1140
|
+
)
|
|
1141
|
+
if spec_err is not None:
|
|
1142
|
+
print(spec_err, file=sys.stderr)
|
|
1143
|
+
return 1
|
|
1144
|
+
|
|
979
1145
|
with tempfile.TemporaryDirectory() as tmp:
|
|
980
1146
|
entities = _parse_entities(getattr(args, "entities", None))
|
|
981
1147
|
written, errors = _generate(
|
|
982
|
-
args.metadata_dir, tmp, None, entities, strict=strict, providers=providers
|
|
1148
|
+
args.metadata_dir, tmp, None, entities, strict=strict, providers=providers,
|
|
1149
|
+
column_naming=column_naming,
|
|
983
1150
|
)
|
|
984
1151
|
if errors:
|
|
985
1152
|
print("error: failed to load metadata:", file=sys.stderr)
|
|
@@ -989,10 +1156,30 @@ def _verify_codegen(args: argparse.Namespace) -> int:
|
|
|
989
1156
|
print(_strict_load_hint(), file=sys.stderr)
|
|
990
1157
|
return 1
|
|
991
1158
|
|
|
1159
|
+
if spec_gens:
|
|
1160
|
+
# Mirror `gen`'s SECOND pass exactly, emit_package_init=False included —
|
|
1161
|
+
# a diff against output produced by a two-pass gen has to be produced the
|
|
1162
|
+
# same way, or the __init__.py placement alone reads as drift.
|
|
1163
|
+
from metaobjects.render.renderer import RenderError
|
|
1164
|
+
|
|
1165
|
+
try:
|
|
1166
|
+
_generate(
|
|
1167
|
+
args.metadata_dir, tmp, spec_gens, entities,
|
|
1168
|
+
emit_package_init=False, strict=strict, providers=providers,
|
|
1169
|
+
column_naming=column_naming,
|
|
1170
|
+
)
|
|
1171
|
+
except RenderError as exc:
|
|
1172
|
+
print(
|
|
1173
|
+
f"error: template-spec render failed (check the template refs and "
|
|
1174
|
+
f"the templates dir): {exc}",
|
|
1175
|
+
file=sys.stderr,
|
|
1176
|
+
)
|
|
1177
|
+
return 1
|
|
1178
|
+
|
|
992
1179
|
expected = _relative_set(Path(tmp))
|
|
993
1180
|
committed = _relative_set(Path(args.out))
|
|
994
1181
|
|
|
995
|
-
return _diff_report(expected, committed)
|
|
1182
|
+
return _diff_report(expected, committed, gen_state_dir_for(args.metadata_dir))
|
|
996
1183
|
|
|
997
1184
|
|
|
998
1185
|
def _verify_codegen_neutral_fallback(args: argparse.Namespace) -> int:
|
|
@@ -1018,6 +1205,10 @@ def _verify_codegen_neutral_fallback(args: argparse.Namespace) -> int:
|
|
|
1018
1205
|
return 1
|
|
1019
1206
|
|
|
1020
1207
|
strict = not getattr(args, "lax", False)
|
|
1208
|
+
# R31 — see _verify_codegen: must match the strategy `gen` (this same rung)
|
|
1209
|
+
# produced --out with, or the `names` generator's constants regenerate under
|
|
1210
|
+
# the wrong strategy and report spurious drift.
|
|
1211
|
+
column_naming = getattr(args, "column_naming", None) or DEFAULT_COLUMN_NAMING
|
|
1021
1212
|
providers, providers_ok = _providers_from_args(args)
|
|
1022
1213
|
if not providers_ok:
|
|
1023
1214
|
return 1
|
|
@@ -1033,11 +1224,18 @@ def _verify_codegen_neutral_fallback(args: argparse.Namespace) -> int:
|
|
|
1033
1224
|
print(_strict_load_hint(), file=sys.stderr)
|
|
1034
1225
|
return 1
|
|
1035
1226
|
|
|
1036
|
-
_run_suite(
|
|
1227
|
+
_run_suite(
|
|
1228
|
+
root, tmp, None, entities, gen_state_dir=None, column_naming=column_naming
|
|
1229
|
+
)
|
|
1037
1230
|
expected = _relative_set(Path(tmp))
|
|
1038
1231
|
committed = _relative_set(Path(args.out))
|
|
1039
1232
|
|
|
1040
|
-
|
|
1233
|
+
# This rung has NO positional metadata dir — cwd is the project (same anchor
|
|
1234
|
+
# `_cmd_gen_neutral_fallback` writes its manifest to), so the jurisdiction lookup
|
|
1235
|
+
# must be built from that, not from args.metadata_dir (None here by definition).
|
|
1236
|
+
return _diff_report(
|
|
1237
|
+
expected, committed, str(root_dir.resolve() / ".metaobjects" / ".gen-state")
|
|
1238
|
+
)
|
|
1041
1239
|
|
|
1042
1240
|
|
|
1043
1241
|
def _temp_slot_for(temp_root: Path, real_outdir: str, config_dir: Path) -> str:
|
|
@@ -1150,7 +1348,11 @@ def _verify_codegen_config(args: argparse.Namespace) -> int:
|
|
|
1150
1348
|
k for k in expected if k in committed and expected[k] != committed[k]
|
|
1151
1349
|
)
|
|
1152
1350
|
missing = sorted(k for k in expected if k not in committed)
|
|
1153
|
-
|
|
1351
|
+
# Same jurisdiction rule as _diff_report — this rung inlines its diff to
|
|
1352
|
+
# report per-target, so the guard has to be inlined with it. Without it,
|
|
1353
|
+
# broadening the comparison past *.py convicts every stranger's file.
|
|
1354
|
+
is_ours = _is_ours_for(gen_state_dir_for(config.metadata_dir()))
|
|
1355
|
+
extra = sorted(k for k in committed if k not in expected and is_ours(k))
|
|
1154
1356
|
|
|
1155
1357
|
names = "+".join(
|
|
1156
1358
|
t.name for t in closure if config.out_dir_for(t) == real_outdir
|
|
@@ -1411,6 +1613,19 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
1411
1613
|
help="directory of metadata JSON/YAML files",
|
|
1412
1614
|
)
|
|
1413
1615
|
gen.add_argument("--out", default=None, help="output directory for generated code")
|
|
1616
|
+
gen.add_argument(
|
|
1617
|
+
"--column-naming",
|
|
1618
|
+
dest="column_naming",
|
|
1619
|
+
choices=COLUMN_NAMING_STRATEGIES,
|
|
1620
|
+
default=DEFAULT_COLUMN_NAMING,
|
|
1621
|
+
help=(
|
|
1622
|
+
"column-naming strategy for a field with no explicit @column "
|
|
1623
|
+
f"(default: {DEFAULT_COLUMN_NAMING!r}, matching this port's "
|
|
1624
|
+
"ObjectManager default — NOT `meta migrate`'s snake_case). Read by "
|
|
1625
|
+
"the `names` generator; pass the same strategy the schema was "
|
|
1626
|
+
"created with."
|
|
1627
|
+
),
|
|
1628
|
+
)
|
|
1414
1629
|
gen.add_argument(
|
|
1415
1630
|
"--generators",
|
|
1416
1631
|
default=None,
|
|
@@ -1550,6 +1765,19 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
1550
1765
|
action="store_true",
|
|
1551
1766
|
help="codegen drift: regenerate to a temp dir + diff vs --out (default)",
|
|
1552
1767
|
)
|
|
1768
|
+
verify.add_argument(
|
|
1769
|
+
"--column-naming",
|
|
1770
|
+
dest="column_naming",
|
|
1771
|
+
choices=COLUMN_NAMING_STRATEGIES,
|
|
1772
|
+
default=DEFAULT_COLUMN_NAMING,
|
|
1773
|
+
help=(
|
|
1774
|
+
"column-naming strategy the committed --out was generated with (default: "
|
|
1775
|
+
f"{DEFAULT_COLUMN_NAMING!r}, matching `gen`'s default). The `names` "
|
|
1776
|
+
"generator's constants are strategy-dependent, so a --codegen regen must "
|
|
1777
|
+
"use the SAME strategy `gen` was run with or every <ENTITY>_<FIELD>_COLUMN "
|
|
1778
|
+
"constant reports spurious drift."
|
|
1779
|
+
),
|
|
1780
|
+
)
|
|
1553
1781
|
verify.add_argument(
|
|
1554
1782
|
"--templates",
|
|
1555
1783
|
action="store_true",
|