Repository navigation
Fix GeometryField value conversion crashing on non-None values - #2238
binggao1230 wants to merge 5 commits into
Conversation
GeometryField subclasses Field directly (single base), so the _FieldMeta metaclass — which only auto-assigns field_type when there are multiple bases — leaves field_type as None. The base to_python_value/to_db_value converters then call isinstance(value, self.field_type), raising TypeError: isinstance() arg 2 must be a type ... on any non-None value. Declare field_type = str and parametrize as Field[str], mirroring the fix applied to TSVectorField in tortoise#2237.
The `instance` parameter is typed `type[Model] | Model`; passing `None` in these unit tests is fine at runtime (GeometryField's converter does not use it) but trips mypy, so annotate the two calls as the codebase does elsewhere.
|
The fix is correct and consistent with #2237. A few things worth addressing while it's open: 1. Are there other single-base
2. Something like: This documents the MySQL-only constraint and explains why 3. The The 4. Optional: a meta-level regression test. A lightweight test that walks the built-in field classes and asserts each has a non- Nothing here blocks the fix itself. |
|
Thanks — I checked the current I added the suggested docstring in Validation: the focused tests pass (3/3), ruff and mypy pass on the touched files, and the full SQLite-backed suite passes (1,913 passed, 148 skipped, 2 xfailed). |
Description
GeometryField(MySQL) subclassesFielddirectly with a single base:The
_FieldMetametaclass only auto-assignsfield_typewhen a field hasmultiple bases (
len(bases) > 1 and bases[0] is Field). A single-basesubclass therefore keeps the class default
field_type = None.The base value converters use it directly:
So any non-
Nonevalue round-tripping throughGeometryFieldraises:This trips both
to_python_value(reading a geometry back from the DB) andto_db_value(writing one).Fix
Declare a concrete
field_typeand parametrize the generic, exactly as#2237 did for
TSVectorField:Tests
Added
tests/contrib/mysql/test_geometry_field.py(DB-free) assertingfield_type is strand thatto_python_value/to_db_valuehandle bothNoneand a concrete"POINT(1 1)"value without raising. Reproduces as aTypeErrorbefore the fix; passes after.tests/fields/,tests/schema/test_generate_schema.pyand the new test allpass (474 passed, 66 skipped);
ruff format --checkandruff checkclean.Maintainer follow-up
The direct-
Fieldcensus on currentdevelopfound six classes.TSVectorField,CharField,BooleanField, andTimeDeltaFieldalready declare concretefield_typevalues;GeometryFieldwas the only concrete omission.RelationalFieldis the intentional non-column base (has_db_field = False), and its concrete relation instances receive their type during app initialization. I therefore kept this PR scoped toGeometryFieldrather than add the optional broad meta-test.The
instance=Nonecalls in the unit test deliberately use targeted# type: ignore[arg-type]comments becauseGeometryField.to_db_valuedoes not inspectinstance. Widening the base method signature would be a separate API/type change. The field now also documents that MySQLGEOMETRYis exposed as its WKT string representation.