diff --git a/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/test_data/base_row.py b/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/test_data/base_row.py index 70a20e0ee..2578eed40 100644 --- a/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/test_data/base_row.py +++ b/packages/overture-schema-codegen/src/overture/schema/codegen/pyspark/test_data/base_row.py @@ -683,10 +683,16 @@ def _value_from_check_enum( def _value_from_check_string_min_length( - _desc: ExpressionDescriptor, _scalar: Primitive, _cs: ConstraintSource + desc: ExpressionDescriptor, _scalar: Primitive, _cs: ConstraintSource ) -> str: - """Return any single character; satisfies `min_length>=1` for every schema today.""" - return "a" + """Return a filler string of exactly `min_length` characters. + + The descriptor's sole arg is the `min_length` bound. A shorter string + (a single character against `min_length > 1`) would violate the + constraint, making the generated conformance ::valid row invalid. + """ + min_length: int = desc.args[0] # type: ignore[assignment] + return "a" * min_length def _value_from_check_pattern( diff --git a/packages/overture-schema-codegen/tests/test_pyspark_base_row.py b/packages/overture-schema-codegen/tests/test_pyspark_base_row.py index a1e9ffb94..538491878 100644 --- a/packages/overture-schema-codegen/tests/test_pyspark_base_row.py +++ b/packages/overture-schema-codegen/tests/test_pyspark_base_row.py @@ -21,6 +21,7 @@ Primitive, ) from overture.schema.codegen.extraction.field_walk import terminal_of +from overture.schema.codegen.extraction.length_constraints import ScalarMinLen from overture.schema.codegen.extraction.model_extraction import extract_model from overture.schema.codegen.extraction.specs import ( FieldSpec, @@ -363,6 +364,37 @@ def test_uncurated_pattern_field_raises_during_generation(self) -> None: value_for_field(field, "Foo") +class TestStringMinLengthBaseRow: + """A string field with `min_length > 1` gets a value long enough to pass. + + The synthesizer must emit a string of at least `min_length` characters: + a single character satisfies `min_length == 1` but violates any larger + bound, which would make the generated conformance ::valid row invalid. + """ + + def test_scalar_constraints_honor_min_length(self) -> None: + scalar = Primitive( + base_type="str", + constraints=( + ConstraintSource( + source_ref=None, + source_name=None, + constraint=ScalarMinLen(min_length=3), + ), + ), + ) + val = _value_from_scalar_constraints(scalar) + assert isinstance(val, str) + assert len(val) >= 3 + + def test_base_row_string_min_length_passes_pydantic(self) -> None: + class StringMinLengthModel(BaseModel): + code: str = Field(min_length=3) + + row = generate_base_row(spec_for_model(StringMinLengthModel)) + StringMinLengthModel(**row) + + class TestValueForShapeScalarVariants: """_value_for_shape handles the Scalar variants it can reach."""