metaobjects 1.0.11__tar.gz → 1.0.13__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-1.0.11 → metaobjects-1.0.13}/PKG-INFO +1 -1
- {metaobjects-1.0.11 → metaobjects-1.0.13}/pyproject.toml +1 -1
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/apidocs/naming.py +56 -7
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/cli.py +151 -0
- metaobjects-1.0.13/src/metaobjects/codegen/collection_name_collision.py +58 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/runner.py +5 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/errors.py +6 -0
- metaobjects-1.0.13/src/metaobjects/fmt.py +214 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/persistence/source/meta_source.py +13 -2
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/render/extract/__init__.py +2 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/render/extract/extract.py +34 -2
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/render/extract/types.py +28 -1
- metaobjects-1.0.13/tests/codegen/test_cli_fmt.py +137 -0
- metaobjects-1.0.13/tests/codegen/test_collection_name_collision.py +109 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_extractor_generator.py +41 -0
- metaobjects-1.0.13/tests/codegen/test_fmt_format_file.py +45 -0
- metaobjects-1.0.13/tests/codegen/test_route_path_naming.py +149 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_runner.py +21 -0
- metaobjects-1.0.13/tests/conformance/test_fmt_conformance.py +54 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/render/extract/test_extract.py +100 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_fr016_source_name_and_kind_aliases.py +33 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/uv.lock +1 -1
- metaobjects-1.0.11/tests/codegen/test_route_path_naming.py +0 -67
- {metaobjects-1.0.11 → metaobjects-1.0.13}/.gitignore +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/LICENSE +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/README.md +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/hatch_build.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/scripts/generate_embedded_library.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/agent_context/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/agent_context/scaffold.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/apidocs/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/apidocs/api_model.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/apidocs/builder.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/apidocs/paths.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/apidocs/renderer.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/attr_class_map.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/KNOWN_GAPS.md +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/collision_names.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/config.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/constants.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/eject.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/extract_delegate_emitter.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/extract_schema_emitter.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/format.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/fr010_field_mapping.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/generator.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/generator_registry.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/generators/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/generators/entity_model.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/generators/extractor_generator.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/generators/filter_allowlist_generator.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/generators/find_inbound.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/generators/fr019_shared_enum.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/generators/m2m_codegen.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/generators/names_generator.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/generators/output_parser_generator.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/generators/output_prompt_generator.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/generators/render_helper_generator.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/generators/router_generator.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/generators/template_generator.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/generators/tph_plan.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/generators/trace_helper_generator.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/instance_artifacts.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/metaobjects-config.schema.json +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/model_walk.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/output_format_spec_emitter.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/overwrite_policy.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/project_config.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/runtime/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/runtime/constraint_errors.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/runtime/filter_parser.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/template_codegen/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/template_codegen/output_pattern.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/template_codegen/template_data.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/template_codegen/template_spec.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/type_map.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/codegen/value_objects.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/config/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/config/dependencies.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/config/neutral_config.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/config/source_resolver.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/core_types.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/datatype.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/documentation/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/documentation/doc_constants.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/documentation/doc_provider.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/documentation/doc_schema.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/library/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/library/embedded_library.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/library/library_sources.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/loader/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/loader/merge.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/loader/meta_data_loader.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/loader/registered_validation.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/loader/sources/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/loader/sources/directory_source.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/loader/sources/file_source.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/loader/sources/meta_data_source.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/loader/sources/uri_source.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/loader/validate_discriminator.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/loader/validate_enum_normalize_ambiguity.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/loader/validate_field_mutability.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/loader/validate_source_escapes.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/loader/validate_source_parameter_ref.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/loader/validate_source_physical_names.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/loader/validation_passes.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/attr/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/attr/attr_constants.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/attr/meta_attr.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/field/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/field/field_constants.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/field/meta_field.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/identity/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/identity/identity_constants.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/identity/meta_identity.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/index/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/index/index_constants.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/index/meta_index.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/object/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/object/meta_object.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/object/meta_object_aware.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/object/object_class_registry.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/object/object_constants.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/object/object_extract.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/object/value_object.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/relationship/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/relationship/derive_m2m_fields.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/relationship/meta_relationship.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/relationship/relationship_constants.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/relationship/relationship_references.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/requirement/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/requirement/meta_requirement.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/requirement/requirement_constants.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/validator/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/core/validator/validator_constants.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/meta_data.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/meta_root.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/persistence/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/persistence/db/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/persistence/db/db_constants.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/persistence/db/db_provider.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/persistence/origin/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/persistence/origin/meta_origin.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/persistence/origin/origin_constants.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/persistence/source/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/persistence/source/source_constants.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/presentation/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/presentation/layout/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/presentation/layout/layout_constants.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/presentation/layout/meta_layout.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/presentation/ui/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/presentation/ui/ui_provider.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/presentation/view/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/presentation/view/meta_view.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/presentation/view/view_constants.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/provider_extends.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/template/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/template/meta_template.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/template/prompt_provider.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/template/template_constants.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta_endpoint.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/naming.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/naming_refs.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/parser.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/parser_yaml.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/provider.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/py.typed +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/registry.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/registry_manifest.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/render/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/render/email_document.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/render/escapers.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/render/extract/KNOWN_GAPS.md +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/render/extract/coerce.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/render/extract/extract_map.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/render/extract/json_forgiving_reader.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/render/extract/locate.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/render/extract/normalize.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/render/extract/strip.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/render/extract/xml_forgiving_reader.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/render/filesystem_provider.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/render/payload_accessors.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/render/prompt/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/render/prompt/output_format_renderer.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/render/prompt/output_format_spec.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/render/prompt/prompt_field.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/render/prompt/prompt_overrides.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/render/prompt/prompt_style.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/render/renderer.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/render/verify.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/runtime/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/runtime/llm_recorder.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/runtime/n2m_resolver.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/runtime/object_manager.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/runtime/tph.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/scope.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/serializer_json.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/shared/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/shared/base_types.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/shared/separators.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/shared/structural.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/source/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/source/error_source.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/source/json_path.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/source/semantic_diff.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/source/yaml_positions.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/source_resolution.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/spec_metamodel/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/spec_metamodel/attr.json +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/spec_metamodel/db.json +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/spec_metamodel/documentation.json +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/spec_metamodel/field.json +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/spec_metamodel/identity.json +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/spec_metamodel/index.json +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/spec_metamodel/layout.json +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/spec_metamodel/object.json +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/spec_metamodel/origin.json +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/spec_metamodel/prompt.json +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/spec_metamodel/relationship.json +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/spec_metamodel/requirement.json +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/spec_metamodel/source.json +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/spec_metamodel/template.json +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/spec_metamodel/ui-web.json +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/spec_metamodel/ui.json +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/spec_metamodel/validator.json +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/spec_metamodel/view.json +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/super_resolve.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/validation_types.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/yaml_desugar.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/gen_suite.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/golden/extends/expected/BaseEntity.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/golden/extends/expected/Program.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/golden/extends/meta.json +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/golden/nested-array/expected/AuthorBrief.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/golden/nested-array/expected/PostBrief.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/golden/nested-array/meta.json +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/golden/scalars/expected/Metric.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/golden/scalars/expected/Report.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/golden/scalars/meta.json +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/golden/vanilla/expected/Subscriber.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/golden/vanilla/meta.json +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_abstract_conformance.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_api_docs_builder.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_api_docs_paths.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_cli.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_cli_config_gen.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_cli_config_verify.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_cli_dependencies.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_cli_gen_unknown_attr.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_cli_providers.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_cli_registry.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_cli_render_helper_template_root.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_cli_staleness_nudge.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_cli_verify_strict.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_cli_verify_subverbs.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_codegen_compile_conformance.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_constants_config.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_eject.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_eject_runtime.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_entity_model.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_enum_conformance.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_extends_abstract_field_inheritance.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_extract_tier_collision.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_filter_allowlist_generator.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_format.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_fr010_nested_object_prompt.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_fr010_output_codegen.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_fr019_shared_provided_conformance.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_gen_state_keying.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_generator.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_generator_extension_seams.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_golden.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_inherit_without_restate_gate.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_inheritance_conformance.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_instance_artifacts.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_m2m_codegen.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_names_extends_chain.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_names_generator.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_no_magic_physical_names.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_origin_nullability.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_output_parser_generator.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_overwrite_policy.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_overwrite_policy_hash.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_project_config.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_projection_compile.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_recipe_generators.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_render_helper_conformance.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_render_helper_generator.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_reverse_finders.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_router_autoset.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_router_generator.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_router_generator_m2m_target_tph.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_router_generator_tph_m2m.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_router_generator_tph_m2m_shadowed.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_source_resolution.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_sourceless_entity_surface.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_sourceless_projection.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_template_data.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_template_generator.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_template_output_pattern.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_template_scope_helpers.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_template_scope_walk.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_template_spec.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_tph_codegen.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_trace_helper_generator.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_type_map.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_validation_conformance.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_value_objects.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/codegen/test_write_through.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/config/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/config/test_dependencies.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/config/test_library_package_guard.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/config/test_neutral_config.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/config/test_source_resolver.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/capabilities.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/conformance-expected-failures.json +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/conformance_adapter.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/corpus.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/expected_failures.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/fixture_discovery.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/navigator.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/test_api_docs_cross_port_conformance.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/test_conformance.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/test_dependency_conformance.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/test_extract_conformance.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/test_extract_object_array_bounds.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/test_extract_object_verdict.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/test_fr010_loader_attrs.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/test_fr011_attrs.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/test_generator_registry_conformance.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/test_object_model_conformance.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/test_provider_composition_conformance.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/test_registry_conformance.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/test_runner_hardfail.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/test_scope_conformance.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/test_source_resolution_conformance.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/test_spec_metamodel_embed.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/test_strict_attr_load.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/test_template_codegen_conformance.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/test_template_generator_conformance.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/test_yaml_conformance.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/conformance/yaml-conformance-expected-failures.json +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/api_contract_assertions.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/api_contract_jsonb_server.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/api_contract_m2m_server.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/api_contract_server.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/generated_jsonb_app.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/generated_m2m_app.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/generated_projection_app.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/generated_router_app.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/generated_tph_app.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/meta_ai_trace.yaml +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/normalization.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/postgres_container.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/query_runner.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/scenarios.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/test_api_contract.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/test_api_contract_generated.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/test_api_contract_jsonb.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/test_api_contract_m2m.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/test_api_contract_m2m_generated.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/test_api_contract_projection.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/test_api_contract_tph_generated.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/test_generated_router_uuid_pk.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/test_llm_call_trace.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/test_m2m_target_tph_generated.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/test_normalization.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/test_query_scenarios.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/test_runtime_return_types.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/test_tph_m2m_generated.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/integration/test_tph_m2m_shadowed_generated.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/loader/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/loader/test_abstract_subtype_authored.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/loader/test_child_wrapper_body_shape.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/loader/test_enum_extends_values_conflict.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/loader/test_field_mutability_order.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/loader/test_shipped_library_ai.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/loader/test_template_payload_target_210.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/open_closed_proof_test.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/render/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/render/extract/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/render/extract/test_coerce.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/render/extract/test_extract_map.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/render/extract/test_json_forgiving_reader.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/render/extract/test_locate.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/render/extract/test_model.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/render/extract/test_normalize.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/render/extract/test_strip.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/render/extract/test_xml_forgiving_reader.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/render/prompt/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/render/prompt/test_output_format_renderer.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/render/test_email_document.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/render/test_filesystem_provider.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/render/test_output_format_renderer_nested.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/render/test_output_prompt_conformance.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/render/test_render_conformance.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/render/test_render_max_chars.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/render/test_render_model_payload.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/render/test_verify.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/render/test_verify_conformance.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/runtime/test_constraint_errors.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/runtime/test_object_manager_currency_read.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/runtime/test_object_manager_enum_intvaluemap.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/runtime/test_object_manager_table_name.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/source/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/source/test_fr5c_merge_attribution.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/source/test_fr5d_reference_resolution.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/source/test_fr5e_database_source_shape.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/source/test_json_path.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/source/test_semantic_diff.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/source/test_source_on_node.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/source/test_yaml_positions.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/test_api_docs_accuracy.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/test_meta_endpoint.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/__init__.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_agent_context_staleness.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_capabilities.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_column_naming_strategy.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_common_attrs.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_core_types.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_derive_m2m_declaring_entity.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_effective_children_sibling_shadowing.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_effective_package.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_errors.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_field_enum.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_field_enum_intvaluemap.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_field_map_validation.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_field_uuid_dbcolumntype.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_file_source_id.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_index_lookup.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_llm_recorder.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_loader.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_loader_bom.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_loader_class.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_merge.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_meta_attr.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_meta_data.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_meta_source.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_module_shortcuts.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_n2m_resolver.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_n2m_resolver_inherited.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_no_dead_config_fields.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_object_manager_autoset_stamping.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_object_manager_uuid_coercion.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_object_manager_write_through.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_one_primary_source.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_parser.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_parser_yaml.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_provider.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_provider_extension.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_registry.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_registry_completeness.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_registry_extend.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_registry_sealed.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_relationship_m2m_validation.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_relationship_references.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_relationship_referential_actions.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_resolution_key.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_runtime_resolution_key_binding.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_serializer.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_serializer_shared_document.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_shared_constants.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_smoke.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_source_escapes.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_sources.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_strict_child_placement.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_super_resolve.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_template_toolcall.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_template_wrong_subtype_attrs.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_validation_attr_schema.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_validation_filter_values.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_validation_origin_195.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_validation_origin_paths.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_validation_sort_field.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_validation_warnings.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_write_coercion_arrays.py +0 -0
- {metaobjects-1.0.11 → metaobjects-1.0.13}/tests/unit/test_yaml_desugar.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: metaobjects
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.13
|
|
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 = "1.0.
|
|
3
|
+
version = "1.0.13"
|
|
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"
|
|
@@ -74,6 +74,52 @@ def _route_snake_case(name: str) -> str:
|
|
|
74
74
|
return to_snake_case(name)
|
|
75
75
|
|
|
76
76
|
|
|
77
|
+
_ALREADY_PLURAL_EXCLUDED_PRECEDING_CHARS = "suia"
|
|
78
|
+
"""The four letters that precede a genuinely SINGULAR "...s" ending in the common
|
|
79
|
+
patterns this codebase's entity names hit — status, address, bonus, alias, gas,
|
|
80
|
+
analysis. Anything else before a final "s" reads as already-plural."""
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _is_already_plural(word: str) -> bool:
|
|
84
|
+
"""True when ``word`` already reads as a plural noun, so running it through
|
|
85
|
+
the ordinary suffix rule would double it — the real defect this exists to
|
|
86
|
+
fix: ``program_purchase_stats`` -> ``program_purchase_statses`` shipped as a
|
|
87
|
+
REST collection path in an adopter's app.
|
|
88
|
+
|
|
89
|
+
Heuristic, not a dictionary: a word ending in ``s`` is already-plural UNLESS
|
|
90
|
+
the character immediately before that final ``s`` is one of s/u/i/a
|
|
91
|
+
(case-insensitive). Covers stats, settings, details, news, analytics,
|
|
92
|
+
series, photos; leaves status, address, bonus, alias, gas, analysis on the
|
|
93
|
+
ordinary suffix path (unchanged).
|
|
94
|
+
|
|
95
|
+
Known miss, deliberately not fixed here: a genuinely singular word ending in
|
|
96
|
+
"...s" with none of those four letters before it reads as already-plural too
|
|
97
|
+
— ``lens`` -> ``lens`` (correct plural ``lenses``). Fixing that needs a real
|
|
98
|
+
dictionary, which this is not; the heuristic optimizes for the shape the
|
|
99
|
+
doubling defect actually hits (entity names that are already a plural
|
|
100
|
+
concept)."""
|
|
101
|
+
if len(word) < 2:
|
|
102
|
+
return False
|
|
103
|
+
lowered = word.lower()
|
|
104
|
+
if lowered[-1] != "s":
|
|
105
|
+
return False
|
|
106
|
+
return lowered[-2] not in _ALREADY_PLURAL_EXCLUDED_PRECEDING_CHARS
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def _pluralize_legacy_suffix_only(name: str) -> str:
|
|
110
|
+
"""FROZEN — byte-for-byte the pre-fix suffix-only pluralization rule, with no
|
|
111
|
+
already-plural detection. Exposed only so :func:`pluralize` can fall back to
|
|
112
|
+
it. The DEFAULT PHYSICAL name fallback lives in a completely separate,
|
|
113
|
+
independently-frozen implementation (``meta_source._pluralize``) — this is
|
|
114
|
+
NOT that one, and the two must never be merged into a single call site."""
|
|
115
|
+
lowered = name.lower()
|
|
116
|
+
if lowered.endswith(("s", "x", "z", "ch", "sh")):
|
|
117
|
+
return name + "es"
|
|
118
|
+
if len(name) >= 2 and lowered[-1] == "y" and lowered[-2] not in "aeiou":
|
|
119
|
+
return name[:-1] + "ies"
|
|
120
|
+
return name + "s"
|
|
121
|
+
|
|
122
|
+
|
|
77
123
|
def pluralize(name: str) -> str:
|
|
78
124
|
"""``post_category`` → ``post_categories``; ``address`` → ``addresses``.
|
|
79
125
|
|
|
@@ -82,13 +128,16 @@ def pluralize(name: str) -> str:
|
|
|
82
128
|
``y`` becomes ``ies``; anything else takes ``s``. The cross-port
|
|
83
129
|
byte-identity covers the already-lowercased word :func:`route_path` feeds
|
|
84
130
|
in — suffix tests here run on a lowercased copy, unlike the JVM port's
|
|
85
|
-
case-sensitive ones, so mixed-case input may diverge.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
131
|
+
case-sensitive ones, so mixed-case input may diverge.
|
|
132
|
+
|
|
133
|
+
Adds already-plural detection (:func:`_is_already_plural`) on top of that
|
|
134
|
+
historical suffix rule (:func:`_pluralize_legacy_suffix_only`) — API/code-
|
|
135
|
+
surface pluralization only; the DEFAULT PHYSICAL table name fallback is
|
|
136
|
+
frozen separately (``meta_source._pluralize``), so an existing adopter
|
|
137
|
+
database never sees a proposed rename."""
|
|
138
|
+
if _is_already_plural(name):
|
|
139
|
+
return name
|
|
140
|
+
return _pluralize_legacy_suffix_only(name)
|
|
92
141
|
|
|
93
142
|
|
|
94
143
|
def model_class_name(obj: MetaData) -> str:
|
|
@@ -1069,6 +1069,132 @@ def _cmd_list(_args: argparse.Namespace) -> int:
|
|
|
1069
1069
|
return 0
|
|
1070
1070
|
|
|
1071
1071
|
|
|
1072
|
+
def _describe_fmt_report(report: "object", cwd: Path) -> str:
|
|
1073
|
+
from metaobjects import fmt
|
|
1074
|
+
|
|
1075
|
+
try:
|
|
1076
|
+
rel = report.path.relative_to(cwd)
|
|
1077
|
+
except ValueError:
|
|
1078
|
+
rel = report.path
|
|
1079
|
+
if report.status == fmt.STATUS_FORMATTED:
|
|
1080
|
+
return f" reformatted {rel}"
|
|
1081
|
+
if report.status == fmt.STATUS_WOULD_FORMAT:
|
|
1082
|
+
return f" not canonical {rel}"
|
|
1083
|
+
if report.status == fmt.STATUS_UNCHANGED:
|
|
1084
|
+
return f" ok {rel}"
|
|
1085
|
+
if report.status == fmt.STATUS_SKIPPED_YAML:
|
|
1086
|
+
return f" skipped (yaml) {rel} — {report.detail}"
|
|
1087
|
+
if report.status == fmt.STATUS_SKIPPED_OVERLAY:
|
|
1088
|
+
return (
|
|
1089
|
+
f" skipped (overlay) {rel} — this file declares an overlay fmt "
|
|
1090
|
+
"cannot resolve standalone"
|
|
1091
|
+
)
|
|
1092
|
+
if report.status == fmt.STATUS_ERROR:
|
|
1093
|
+
return f" error {rel} — {report.detail}"
|
|
1094
|
+
return f" {report.status} {rel}" # pragma: no cover — exhaustive in practice
|
|
1095
|
+
|
|
1096
|
+
|
|
1097
|
+
def _cmd_fmt(args: argparse.Namespace) -> int:
|
|
1098
|
+
"""``fmt`` (#304) — rewrite metadata files into canonical form; ``--check``
|
|
1099
|
+
lists non-canonical files and exits non-zero without changing anything.
|
|
1100
|
+
|
|
1101
|
+
Mirrors the TS reference surface exactly: no ``metadata_dir`` positional —
|
|
1102
|
+
files come from the neutral ``.metaobjects/config.json`` ladder
|
|
1103
|
+
(:func:`resolve_metadata_location`, rungs 3-4; this command does not read
|
|
1104
|
+
this port's own ``metaobjects.config.yaml`` rung 2, matching the scope the
|
|
1105
|
+
C# and Java ports also keep for `fmt`), optionally narrowed by explicit
|
|
1106
|
+
file arguments.
|
|
1107
|
+
"""
|
|
1108
|
+
from metaobjects import fmt
|
|
1109
|
+
from metaobjects.core_types import core_providers
|
|
1110
|
+
from metaobjects.library import library_sources
|
|
1111
|
+
from metaobjects.provider import compose_registry
|
|
1112
|
+
|
|
1113
|
+
providers_extra, providers_ok = _providers_from_args(args)
|
|
1114
|
+
if not providers_ok:
|
|
1115
|
+
return 1
|
|
1116
|
+
providers = [*core_providers, *providers_extra]
|
|
1117
|
+
registry = compose_registry(providers)
|
|
1118
|
+
|
|
1119
|
+
cwd = Path.cwd()
|
|
1120
|
+
collection = _resolve_metadata_location_or_print_error(None, cwd)
|
|
1121
|
+
if collection is None:
|
|
1122
|
+
return 1
|
|
1123
|
+
|
|
1124
|
+
all_files = list(collection.files)
|
|
1125
|
+
own_files = list(collection.own_files)
|
|
1126
|
+
|
|
1127
|
+
if args.files:
|
|
1128
|
+
wanted = [Path(f).resolve() for f in args.files]
|
|
1129
|
+
owned_set = {p.resolve() for p in own_files}
|
|
1130
|
+
missing = [str(p) for p in wanted if p not in owned_set]
|
|
1131
|
+
if missing:
|
|
1132
|
+
print(
|
|
1133
|
+
"error: not among this project's resolved metadata sources: "
|
|
1134
|
+
+ ", ".join(missing),
|
|
1135
|
+
file=sys.stderr,
|
|
1136
|
+
)
|
|
1137
|
+
print(
|
|
1138
|
+
"metaobjects fmt only formats files the metadata-location ladder "
|
|
1139
|
+
"already resolves — pass no arguments to format every one of them.",
|
|
1140
|
+
file=sys.stderr,
|
|
1141
|
+
)
|
|
1142
|
+
return 1
|
|
1143
|
+
wanted_set = {p for p in wanted}
|
|
1144
|
+
targets = [p for p in own_files if p.resolve() in wanted_set]
|
|
1145
|
+
else:
|
|
1146
|
+
targets = own_files
|
|
1147
|
+
|
|
1148
|
+
lib_sources = library_sources(list(collection.libraries)) if collection.libraries else []
|
|
1149
|
+
|
|
1150
|
+
result = fmt.run(
|
|
1151
|
+
all_files=all_files,
|
|
1152
|
+
target_files=targets,
|
|
1153
|
+
file_ids=dict(collection.file_ids),
|
|
1154
|
+
registry=registry,
|
|
1155
|
+
lib_sources=lib_sources,
|
|
1156
|
+
check=bool(args.check),
|
|
1157
|
+
providers=providers,
|
|
1158
|
+
)
|
|
1159
|
+
|
|
1160
|
+
if result.fatal is not None:
|
|
1161
|
+
print(f"error: {result.fatal}", file=sys.stderr)
|
|
1162
|
+
return 1
|
|
1163
|
+
|
|
1164
|
+
if not result.files:
|
|
1165
|
+
print("metaobjects fmt — no metadata files to format.")
|
|
1166
|
+
return 0
|
|
1167
|
+
|
|
1168
|
+
for report in result.files:
|
|
1169
|
+
print(_describe_fmt_report(report, cwd))
|
|
1170
|
+
|
|
1171
|
+
errored = sum(1 for r in result.files if r.status == fmt.STATUS_ERROR)
|
|
1172
|
+
needs_format = sum(1 for r in result.files if r.status == fmt.STATUS_WOULD_FORMAT)
|
|
1173
|
+
reformatted = sum(1 for r in result.files if r.status == fmt.STATUS_FORMATTED)
|
|
1174
|
+
|
|
1175
|
+
if args.check:
|
|
1176
|
+
if needs_format or errored:
|
|
1177
|
+
suffix = f", {errored} error(s)" if errored else ""
|
|
1178
|
+
print(
|
|
1179
|
+
f"metaobjects fmt --check — {needs_format} file(s) not canonical{suffix}. "
|
|
1180
|
+
"Run `metaobjects fmt` to fix.",
|
|
1181
|
+
file=sys.stderr,
|
|
1182
|
+
)
|
|
1183
|
+
return 1
|
|
1184
|
+
print("metaobjects fmt --check — every file is already canonical.")
|
|
1185
|
+
return 0
|
|
1186
|
+
|
|
1187
|
+
if errored:
|
|
1188
|
+
print(
|
|
1189
|
+
f"metaobjects fmt — {errored} file(s) could not be formatted safely (left unchanged).",
|
|
1190
|
+
file=sys.stderr,
|
|
1191
|
+
)
|
|
1192
|
+
return 1
|
|
1193
|
+
|
|
1194
|
+
print(f"metaobjects fmt — {reformatted} file(s) reformatted.")
|
|
1195
|
+
return 0
|
|
1196
|
+
|
|
1197
|
+
|
|
1072
1198
|
def _cmd_eject(args: argparse.Namespace) -> int:
|
|
1073
1199
|
"""Copy reference generators into ``codegen/generators/`` to own (ADR-0034 Am. 3)."""
|
|
1074
1200
|
root = Path(args.root) if args.root else Path.cwd()
|
|
@@ -2493,6 +2619,31 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
2493
2619
|
)
|
|
2494
2620
|
verify.set_defaults(func=_cmd_verify)
|
|
2495
2621
|
|
|
2622
|
+
fmt_p = sub.add_parser(
|
|
2623
|
+
"fmt",
|
|
2624
|
+
help="rewrite metadata files into canonical form (#304)",
|
|
2625
|
+
)
|
|
2626
|
+
fmt_p.add_argument(
|
|
2627
|
+
"files",
|
|
2628
|
+
nargs="*",
|
|
2629
|
+
metavar="FILE",
|
|
2630
|
+
help="optional explicit file(s) to format — must be members of this "
|
|
2631
|
+
"project's resolved metadata sources; omit to format every one of them",
|
|
2632
|
+
)
|
|
2633
|
+
fmt_p.add_argument(
|
|
2634
|
+
"--check",
|
|
2635
|
+
action="store_true",
|
|
2636
|
+
help="list files that are not canonical and exit non-zero; changes nothing",
|
|
2637
|
+
)
|
|
2638
|
+
fmt_p.add_argument(
|
|
2639
|
+
"--provider",
|
|
2640
|
+
action="append",
|
|
2641
|
+
default=None,
|
|
2642
|
+
metavar="MODULE:SYMBOL",
|
|
2643
|
+
help="consumer-registered Provider(s), repeatable (module:symbol)",
|
|
2644
|
+
)
|
|
2645
|
+
fmt_p.set_defaults(func=_cmd_fmt)
|
|
2646
|
+
|
|
2496
2647
|
eject_p = sub.add_parser(
|
|
2497
2648
|
"eject",
|
|
2498
2649
|
help="copy reference generators into codegen/generators/ to own and edit",
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""Collection-name collision refusal — the single choke point every route/router/
|
|
2
|
+
finder generator path goes through (called once, in ``run_gen``, over the full
|
|
3
|
+
entity set BEFORE any generator runs).
|
|
4
|
+
|
|
5
|
+
Two DISTINCT entities/projections pluralizing to the SAME API-surface collection
|
|
6
|
+
name (REST path, generated router module/finder names) is reachable from stock
|
|
7
|
+
metadata now that :func:`metaobjects.apidocs.naming.pluralize` no longer doubles an
|
|
8
|
+
already-plural word: ``Address`` (not already-plural: legacy-pluralizes to
|
|
9
|
+
``Addresses``) and ``Addresses`` (already-plural: left unchanged, ALSO
|
|
10
|
+
``Addresses``) collide, where before the fix they did not (``Addresses`` legacy-
|
|
11
|
+
pluralized to ``Addresseses``). Silently letting two entities share one collection
|
|
12
|
+
name would mean whichever generator runs second silently wins, or a straight
|
|
13
|
+
duplicate-module/route registration two files downstream of the real cause. This
|
|
14
|
+
refuses at the one place that can see the WHOLE set, with a message naming both
|
|
15
|
+
entities and the colliding name.
|
|
16
|
+
"""
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
from metaobjects.apidocs.naming import pluralize
|
|
20
|
+
from metaobjects.errors import ErrorCode
|
|
21
|
+
from metaobjects.meta.core.object.meta_object import MetaObject
|
|
22
|
+
from metaobjects.meta.core.object.object_constants import OBJECT_SUBTYPE_VALUE
|
|
23
|
+
|
|
24
|
+
ERR_COLLECTION_NAME_COLLISION = ErrorCode.ERR_COLLECTION_NAME_COLLISION.value
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def assert_no_collection_name_collisions(entities: list[MetaObject]) -> None:
|
|
28
|
+
"""Refuse a generation run in which two DISTINCT entities/projections pluralize
|
|
29
|
+
to the same API-surface collection name.
|
|
30
|
+
|
|
31
|
+
Scope: every object EXCEPT ``object.value`` (a value object never gets a route,
|
|
32
|
+
router module, or finder name — it is pure shape, so it cannot collide on any of
|
|
33
|
+
those). A TPH subtype IS included: it gets its own generated names against the
|
|
34
|
+
shared base table, so two subtypes (or a subtype and an unrelated top-level
|
|
35
|
+
entity) sharing a pluralized name collide on those generated symbols exactly as
|
|
36
|
+
two top-level entities would.
|
|
37
|
+
|
|
38
|
+
A PURE function of the entity set — never of traversal order: the reported pair
|
|
39
|
+
is deterministic (first-seen-by-input-order "owner" of a plural; raised as soon
|
|
40
|
+
as a second, different entity claims the same plural).
|
|
41
|
+
"""
|
|
42
|
+
owner_of_plural: dict[str, MetaObject] = {}
|
|
43
|
+
for obj in entities:
|
|
44
|
+
if obj.sub_type == OBJECT_SUBTYPE_VALUE:
|
|
45
|
+
continue
|
|
46
|
+
plural = pluralize(obj.name)
|
|
47
|
+
existing = owner_of_plural.get(plural)
|
|
48
|
+
if existing is not None:
|
|
49
|
+
if existing.resolution_key() != obj.resolution_key():
|
|
50
|
+
raise ValueError(
|
|
51
|
+
f"{ERR_COLLECTION_NAME_COLLISION}: \"{existing.name}\" and \"{obj.name}\" both "
|
|
52
|
+
f'pluralize to the API-surface collection name "{plural}" (REST path, generated '
|
|
53
|
+
"router module/finder names) — rename one entity so its pluralized name is "
|
|
54
|
+
"distinct. Default PHYSICAL table names are unaffected by this rule and are not "
|
|
55
|
+
"involved in the collision."
|
|
56
|
+
)
|
|
57
|
+
else:
|
|
58
|
+
owner_of_plural[plural] = obj
|
|
@@ -10,6 +10,7 @@ from metaobjects.meta.meta_root import MetaRoot
|
|
|
10
10
|
from metaobjects.meta.meta_data import MetaData
|
|
11
11
|
from metaobjects.meta.core.object.meta_object import MetaObject
|
|
12
12
|
from metaobjects.shared.base_types import TYPE_OBJECT
|
|
13
|
+
from .collection_name_collision import assert_no_collection_name_collisions
|
|
13
14
|
from .config import GenConfig
|
|
14
15
|
from .constants import generated_package_init
|
|
15
16
|
from .generator import GenContext, Generator
|
|
@@ -107,6 +108,10 @@ def run_gen(
|
|
|
107
108
|
if not safe:
|
|
108
109
|
return result
|
|
109
110
|
|
|
111
|
+
# Refuse before any generator runs — the one choke point that sees the WHOLE
|
|
112
|
+
# entity set every route/router-emitting generator below reads from.
|
|
113
|
+
assert_no_collection_name_collisions(safe)
|
|
114
|
+
|
|
110
115
|
emitted: dict[str, tuple[str, str]] = {} # full_path -> (content, generated_by)
|
|
111
116
|
for gen in generators:
|
|
112
117
|
ctx = GenContext(
|
|
@@ -200,6 +200,12 @@ class ErrorCode(str, Enum):
|
|
|
200
200
|
# Codegen (ADR-0044): two value-object FQNs in one payload artifact derive the same
|
|
201
201
|
# emitted record name even after package-qualification. Peer of ERR_VAR_NOT_ON_PAYLOAD.
|
|
202
202
|
ERR_PAYLOAD_NAME_COLLISION = "ERR_PAYLOAD_NAME_COLLISION"
|
|
203
|
+
# Codegen: two DISTINCT entities/projections in one generation run pluralize to the
|
|
204
|
+
# SAME API-surface collection name (route path, generated router/finder names) —
|
|
205
|
+
# e.g. "Address" and "Addresses" both resolving to "Addresses". A codegen-time (not
|
|
206
|
+
# loader) error, peer of ERR_PAYLOAD_NAME_COLLISION: refused rather than silently
|
|
207
|
+
# letting one entity's route win.
|
|
208
|
+
ERR_COLLECTION_NAME_COLLISION = "ERR_COLLECTION_NAME_COLLISION"
|
|
203
209
|
ERR_OUTPUT_TAG_MISSING = "ERR_OUTPUT_TAG_MISSING"
|
|
204
210
|
# SP-H Unit9 — @filterable: true on a field subtype with no filter-operator
|
|
205
211
|
# band (e.g. field.object). Would silently generate an empty-ops filter.
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
"""``metaobjects fmt`` (#304) — rewrite metadata files into the canonical form
|
|
2
|
+
the cross-port canonical serializer already produces. ``--check`` lists files
|
|
3
|
+
that are not canonical and exits non-zero without changing anything.
|
|
4
|
+
|
|
5
|
+
Mirrors the TS reference (``packages/metadata/src/fmt.ts`` +
|
|
6
|
+
``packages/cli/src/lib/fmt-engine.ts``) and the C#/Java ports exactly:
|
|
7
|
+
|
|
8
|
+
- Each file is formatted STANDALONE — own-mode, declared-here layer only
|
|
9
|
+
(ADR-0039). ``parse_document`` already builds a fresh, unmerged tree per
|
|
10
|
+
document (this port's loader does parse -> merge -> super-resolve as three
|
|
11
|
+
separate steps, unlike TS/C#'s accumulating-root parser) — calling it
|
|
12
|
+
directly and never running ``merge_roots``/``resolve_supers`` is what makes
|
|
13
|
+
a cross-file ``extends`` round-trip untouched (the raw ``super_ref`` string
|
|
14
|
+
is read directly by ``canonical_serialize``, never its resolution) and an
|
|
15
|
+
``overlay: true`` node never even attempt a merge.
|
|
16
|
+
- An ``overlay: true`` node is tagged (``is_overlay``) by the parser but never
|
|
17
|
+
resolved here — Python's overlay MERGE only happens in ``loader/merge.py``,
|
|
18
|
+
which this module never calls. A file containing one anywhere in its tree
|
|
19
|
+
(detected by :func:`_contains_overlay`) is reported as a skip rather than
|
|
20
|
+
guessed at — the concrete shape of "overlay files stay overlays".
|
|
21
|
+
- YAML is always skipped: no canonical YAML emitter exists (ADR-0006).
|
|
22
|
+
- Before writing, the whole project is reloaded with the candidate
|
|
23
|
+
substituted in via an in-memory source (never touching disk until proven
|
|
24
|
+
safe) and the write is refused unless that reload has no errors AND its
|
|
25
|
+
canonical form is byte-identical to the untouched baseline.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
from __future__ import annotations
|
|
29
|
+
|
|
30
|
+
import json
|
|
31
|
+
from dataclasses import dataclass, field
|
|
32
|
+
from pathlib import Path
|
|
33
|
+
from typing import Callable
|
|
34
|
+
|
|
35
|
+
from metaobjects.errors import MetaError
|
|
36
|
+
from metaobjects.loader.meta_data_loader import MetaDataLoader
|
|
37
|
+
from metaobjects.loader.sources.file_source import FileSource
|
|
38
|
+
from metaobjects.loader.sources.meta_data_source import InMemoryStringSource, MetaDataSource
|
|
39
|
+
from metaobjects.meta.meta_data import MetaData
|
|
40
|
+
from metaobjects.parser import parse_document
|
|
41
|
+
from metaobjects.registry import TypeRegistry
|
|
42
|
+
from metaobjects.serializer_json import canonical_serialize
|
|
43
|
+
|
|
44
|
+
#: Statuses a single file's run can report.
|
|
45
|
+
STATUS_FORMATTED = "formatted"
|
|
46
|
+
STATUS_WOULD_FORMAT = "would-format"
|
|
47
|
+
STATUS_UNCHANGED = "unchanged"
|
|
48
|
+
STATUS_SKIPPED_YAML = "skipped-yaml"
|
|
49
|
+
STATUS_SKIPPED_OVERLAY = "skipped-overlay"
|
|
50
|
+
STATUS_ERROR = "error"
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@dataclass
|
|
54
|
+
class FormatFileResult:
|
|
55
|
+
ok: bool
|
|
56
|
+
overlay: bool = False
|
|
57
|
+
text: str | None = None
|
|
58
|
+
message: str | None = None
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _contains_overlay(node: MetaData) -> bool:
|
|
62
|
+
"""Whether *node* or any descendant (own children only — this tree was
|
|
63
|
+
never merged, so every child already is its own) carries ``overlay: true``.
|
|
64
|
+
"""
|
|
65
|
+
if getattr(node, "is_overlay", False):
|
|
66
|
+
return True
|
|
67
|
+
return any(_contains_overlay(child) for child in node.own_children())
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def format_file(content: str, registry: TypeRegistry, source_id: str) -> FormatFileResult:
|
|
71
|
+
"""Format one file's own content. Parses *content* standalone via
|
|
72
|
+
:func:`parse_document` — never merged with any other file, super
|
|
73
|
+
resolution never run — and, on a clean parse with no overlay anywhere in
|
|
74
|
+
the tree, returns the canonical serialization of the resulting file root.
|
|
75
|
+
Never raises for a malformed file; that comes back as ``ok=False``.
|
|
76
|
+
"""
|
|
77
|
+
# Strip a UTF-8 BOM before parsing — json.loads rejects one outright
|
|
78
|
+
# ("Unexpected UTF-8 BOM (decode using utf-8-sig)"), and Java-authored
|
|
79
|
+
# files often carry one.
|
|
80
|
+
normalized = content[1:] if content.startswith("") else content
|
|
81
|
+
try:
|
|
82
|
+
doc = json.loads(normalized)
|
|
83
|
+
except json.JSONDecodeError as exc:
|
|
84
|
+
return FormatFileResult(ok=False, message=f"invalid JSON: {exc}")
|
|
85
|
+
|
|
86
|
+
try:
|
|
87
|
+
result = parse_document(doc, registry, source_id)
|
|
88
|
+
except Exception as exc: # a few structural failures raise rather than record
|
|
89
|
+
return FormatFileResult(ok=False, message=str(exc))
|
|
90
|
+
|
|
91
|
+
if result.errors:
|
|
92
|
+
message = "; ".join(e.message for e in result.errors)
|
|
93
|
+
return FormatFileResult(ok=False, message=message)
|
|
94
|
+
|
|
95
|
+
if _contains_overlay(result.root):
|
|
96
|
+
return FormatFileResult(
|
|
97
|
+
ok=False,
|
|
98
|
+
overlay=True,
|
|
99
|
+
message="this file declares an overlay fmt cannot resolve standalone",
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
return FormatFileResult(ok=True, text=canonical_serialize(result.root))
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
@dataclass
|
|
106
|
+
class FileReport:
|
|
107
|
+
path: Path
|
|
108
|
+
status: str
|
|
109
|
+
detail: str | None = None
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
@dataclass
|
|
113
|
+
class RunResult:
|
|
114
|
+
files: list[FileReport] = field(default_factory=list)
|
|
115
|
+
fatal: str | None = None
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def run(
|
|
119
|
+
all_files: list[Path],
|
|
120
|
+
target_files: list[Path],
|
|
121
|
+
file_ids: dict[Path, str],
|
|
122
|
+
registry: TypeRegistry,
|
|
123
|
+
lib_sources: list[MetaDataSource],
|
|
124
|
+
check: bool,
|
|
125
|
+
providers: list[object] | None = None,
|
|
126
|
+
) -> RunResult:
|
|
127
|
+
"""Run fmt over *target_files* (a subset of *all_files* — the project's
|
|
128
|
+
FULL resolved file set, needed for the whole-project safety-check reload
|
|
129
|
+
regardless of which files are in scope to format).
|
|
130
|
+
|
|
131
|
+
*providers* must be the SAME provider list *registry* (used for every
|
|
132
|
+
standalone per-file parse) was composed from — the whole-project baseline
|
|
133
|
+
and safety-check reloads build their own `MetaDataLoader`, which recomposes
|
|
134
|
+
a registry from *providers* itself rather than taking `registry` directly,
|
|
135
|
+
so passing a different set here would silently check two vocabularies
|
|
136
|
+
against each other.
|
|
137
|
+
"""
|
|
138
|
+
|
|
139
|
+
def source_id(path: Path) -> str:
|
|
140
|
+
return file_ids.get(path) or path.name
|
|
141
|
+
|
|
142
|
+
def build_sources(
|
|
143
|
+
override_path: Path | None = None, override_text: str | None = None
|
|
144
|
+
) -> list[MetaDataSource]:
|
|
145
|
+
sources: list[MetaDataSource] = list(lib_sources)
|
|
146
|
+
for p in all_files:
|
|
147
|
+
if override_path is not None and p == override_path:
|
|
148
|
+
sources.append(InMemoryStringSource(override_text or "", id=source_id(p)))
|
|
149
|
+
else:
|
|
150
|
+
sources.append(FileSource(p, id=source_id(p)))
|
|
151
|
+
return sources
|
|
152
|
+
|
|
153
|
+
baseline = MetaDataLoader(providers=providers, strict=False).load(build_sources())
|
|
154
|
+
if baseline.errors:
|
|
155
|
+
detail = "\n".join(f" {e.code}: {e.message}" for e in baseline.errors)
|
|
156
|
+
return RunResult(
|
|
157
|
+
fatal=(
|
|
158
|
+
"this project's metadata does not currently load cleanly — fix the "
|
|
159
|
+
f"error(s) below, then re-run fmt:\n{detail}"
|
|
160
|
+
)
|
|
161
|
+
)
|
|
162
|
+
baseline_canonical = canonical_serialize(baseline.root)
|
|
163
|
+
|
|
164
|
+
reports: list[FileReport] = []
|
|
165
|
+
for path in target_files:
|
|
166
|
+
ext = path.suffix.lower()
|
|
167
|
+
if ext in (".yaml", ".yml"):
|
|
168
|
+
reports.append(
|
|
169
|
+
FileReport(
|
|
170
|
+
path,
|
|
171
|
+
STATUS_SKIPPED_YAML,
|
|
172
|
+
"no canonical YAML emitter exists (ADR-0006: JSON is the canonical "
|
|
173
|
+
"interchange form) — left untouched",
|
|
174
|
+
)
|
|
175
|
+
)
|
|
176
|
+
continue
|
|
177
|
+
|
|
178
|
+
content = path.read_text(encoding="utf-8")
|
|
179
|
+
formatted = format_file(content, registry, source_id(path))
|
|
180
|
+
if not formatted.ok:
|
|
181
|
+
reports.append(
|
|
182
|
+
FileReport(
|
|
183
|
+
path,
|
|
184
|
+
STATUS_SKIPPED_OVERLAY if formatted.overlay else STATUS_ERROR,
|
|
185
|
+
formatted.message,
|
|
186
|
+
)
|
|
187
|
+
)
|
|
188
|
+
continue
|
|
189
|
+
|
|
190
|
+
if formatted.text == content:
|
|
191
|
+
reports.append(FileReport(path, STATUS_UNCHANGED))
|
|
192
|
+
continue
|
|
193
|
+
|
|
194
|
+
test_load = MetaDataLoader(providers=providers, strict=False).load(
|
|
195
|
+
build_sources(path, formatted.text)
|
|
196
|
+
)
|
|
197
|
+
safe = not test_load.errors and canonical_serialize(test_load.root) == baseline_canonical
|
|
198
|
+
if not safe:
|
|
199
|
+
reports.append(
|
|
200
|
+
FileReport(
|
|
201
|
+
path,
|
|
202
|
+
STATUS_ERROR,
|
|
203
|
+
"formatting this file would change the loaded model's meaning — left unchanged",
|
|
204
|
+
)
|
|
205
|
+
)
|
|
206
|
+
continue
|
|
207
|
+
|
|
208
|
+
if check:
|
|
209
|
+
reports.append(FileReport(path, STATUS_WOULD_FORMAT))
|
|
210
|
+
else:
|
|
211
|
+
path.write_text(formatted.text, encoding="utf-8")
|
|
212
|
+
reports.append(FileReport(path, STATUS_FORMATTED))
|
|
213
|
+
|
|
214
|
+
return RunResult(files=reports)
|
{metaobjects-1.0.11 → metaobjects-1.0.13}/src/metaobjects/meta/persistence/source/meta_source.py
RENAMED
|
@@ -47,7 +47,17 @@ def _to_snake_case(s: str) -> str:
|
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
def _pluralize(s: str) -> str:
|
|
50
|
-
"""
|
|
50
|
+
"""FROZEN — the DEFAULT PHYSICAL name derivation only (step 4 below, reached
|
|
51
|
+
only when metadata declares no explicit physical name). Matches the TS
|
|
52
|
+
reference ``pluralizeTableNameLegacy`` (metadata/src/naming.ts) — NOT the TS
|
|
53
|
+
``pluralize``, which now differs for an already-plural word, deliberately
|
|
54
|
+
with NO already-plural detection. An adopter's live database was created
|
|
55
|
+
with this rule; adding the already-plural check here would make a schema
|
|
56
|
+
migration propose a rename for every already-plural entity name on the next
|
|
57
|
+
run. The API-surface analog (``metaobjects.apidocs.naming.pluralize``) has
|
|
58
|
+
that fix — this one must not, and the two are intentionally separate,
|
|
59
|
+
independently-maintained implementations (never merge them into one call
|
|
60
|
+
site)."""
|
|
51
61
|
if not s:
|
|
52
62
|
return s
|
|
53
63
|
lower = s.lower()
|
|
@@ -128,7 +138,8 @@ class MetaSource(MetaData):
|
|
|
128
138
|
2. Legacy ``@table`` for non-table kind (pre-1.0 fallback).
|
|
129
139
|
3. Source's bare structural ``name`` via snake_case
|
|
130
140
|
(no pluralize — the source's name IS the logical name).
|
|
131
|
-
4. Owning entity's name via ``pluralize(snake_case())
|
|
141
|
+
4. Owning entity's name via the frozen legacy ``pluralize(snake_case())``
|
|
142
|
+
— see module-level ``_pluralize``'s docstring for why it is frozen.
|
|
132
143
|
|
|
133
144
|
Callers needing the legacy raw ``@table`` slot only should use
|
|
134
145
|
:meth:`table_name`; codegen / runtime should use ``physical_name``.
|
|
@@ -25,6 +25,7 @@ from metaobjects.render.extract.types import (
|
|
|
25
25
|
Format,
|
|
26
26
|
Normalizer,
|
|
27
27
|
OnField,
|
|
28
|
+
OnLocate,
|
|
28
29
|
ExtractOptions,
|
|
29
30
|
ExtractionOutcome,
|
|
30
31
|
ExtractSchema,
|
|
@@ -45,6 +46,7 @@ __all__ = [
|
|
|
45
46
|
"JsonForgivingReader",
|
|
46
47
|
"Normalizer",
|
|
47
48
|
"OnField",
|
|
49
|
+
"OnLocate",
|
|
48
50
|
"ExtractOptions",
|
|
49
51
|
"ExtractionOutcome",
|
|
50
52
|
"ExtractSchema",
|
|
@@ -38,23 +38,55 @@ def extract(
|
|
|
38
38
|
stripped = _strip.strip(text)
|
|
39
39
|
ci = o.tolerance != Tolerance.STRICT
|
|
40
40
|
|
|
41
|
+
# FR-364: the document-level on_locate hook runs BEFORE the default locator. A non-None
|
|
42
|
+
# return is the payload span, fed into the same format-specific forgiving reader a
|
|
43
|
+
# default-located span would be — tolerance/coercion/normalizers/on_field downstream are
|
|
44
|
+
# unaffected. A None return (or no hook) falls through to the default locate strategy
|
|
45
|
+
# unchanged. A raised exception propagates (not swallowed), matching on_field.
|
|
46
|
+
located: str | None = None if o.on_locate is None else o.on_locate(text if text is not None else "", schema.format)
|
|
47
|
+
|
|
41
48
|
# XML rootless (opts.rootless): the payload's fields ARE the top-level elements — there
|
|
42
49
|
# is no enclosing root to locate — so parse the whole stripped text's top-level elements
|
|
43
50
|
# directly. Otherwise locate the <rootName> span as before. JSON is unaffected. Mirrors
|
|
44
51
|
# Java Extract.extract.
|
|
45
52
|
span: str | None
|
|
46
53
|
raw: dict[str, object]
|
|
47
|
-
|
|
54
|
+
# Whether the SELECTED region (not the original reply) was itself empty/blank — the signal
|
|
55
|
+
# mark_empty() keys on below. For the default path this is the pre-existing "nothing to
|
|
56
|
+
# parse" test (stripped == "" or span is None); for on_locate it must be judged against the
|
|
57
|
+
# hook's OWN return, not the original text — otherwise an empty located span (e.g. the hook
|
|
58
|
+
# deliberately returning "") reports "not empty" while every field is LOST, because the
|
|
59
|
+
# original reply was non-blank even though the thing on_locate chose to parse was.
|
|
60
|
+
region_blank: bool
|
|
61
|
+
if located is not None:
|
|
62
|
+
span = located
|
|
63
|
+
if schema.format == Format.JSON:
|
|
64
|
+
raw = JsonForgivingReader().read(located)
|
|
65
|
+
elif o.rootless:
|
|
66
|
+
raw = XmlForgivingReader().read_rootless(located, ci)
|
|
67
|
+
else:
|
|
68
|
+
raw = XmlForgivingReader().read(located, ci)
|
|
69
|
+
# `from_` is deliberately left empty rather than the original text: a document-level
|
|
70
|
+
# audit entry that copied the whole raw reply (which can be arbitrarily large) into the
|
|
71
|
+
# report on every call would make the report itself heavy for no benefit `to`'s length
|
|
72
|
+
# doesn't already give. `to` is the located span's LENGTH, not the span text, for the
|
|
73
|
+
# same reason.
|
|
74
|
+
report.add_coercion(Coercion("", "", str(len(located)), "onLocate"))
|
|
75
|
+
region_blank = located.strip() == ""
|
|
76
|
+
elif schema.format == Format.JSON:
|
|
48
77
|
span = _select_json(text, stripped, schema.fields, ci)
|
|
49
78
|
raw = {} if span is None else JsonForgivingReader().read(span)
|
|
79
|
+
region_blank = stripped == "" or span is None
|
|
50
80
|
elif o.rootless:
|
|
51
81
|
span = None if stripped == "" else stripped
|
|
52
82
|
raw = {} if span is None else XmlForgivingReader().read_rootless(stripped, ci)
|
|
83
|
+
region_blank = stripped == "" or span is None
|
|
53
84
|
else:
|
|
54
85
|
span = _locate.xml(stripped, schema.root_name, ci)
|
|
55
86
|
raw = {} if span is None else XmlForgivingReader().read(span, ci)
|
|
87
|
+
region_blank = stripped == "" or span is None
|
|
56
88
|
|
|
57
|
-
if not raw and
|
|
89
|
+
if not raw and region_blank:
|
|
58
90
|
report.mark_empty()
|
|
59
91
|
|
|
60
92
|
_extract(schema.fields, raw, "", data, report, o, ci)
|