Implement construct_from_string on PandasArrayExtensionDtype - #8468
Open
shashvat-singham wants to merge 1 commit into
Open
Conversation
Pandas compares dtypes against plain strings throughout its internals, and
`ExtensionDtype.__eq__` routes those through `construct_from_string`. The
base implementation starts with
assert isinstance(cls.name, str), (cls, type(cls.name))
`name` is a property here because it depends on `value_type`, so the
assertion fires and every such comparison raised
AssertionError: (PandasArrayExtensionDtype, <class 'property'>)
That took out `df.astype(object)`, `is_string_dtype(dtype)` and any bare
`dtype == "some string"`.
Parse "array[<dtype>]" back into the dtype, and raise TypeError for
anything else, which is how pandas spells "not my dtype".
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #8467.
The bug
PandasArrayExtensionDtypenever implementsconstruct_from_string, so it inherits the baseExtensionDtypeversion:nameis an instance@propertyhere, because it depends onvalue_type(array[float64]). On the class it is apropertyobject, so the assertion fires:ExtensionDtype.__eq__routes everydtype == "some string"throughconstruct_from_string, and pandas compares dtypes against strings throughout its internals. Onmain:df.astype(object)gets there viaastype_is_view→is_string_dtype→dtype == "string".The fix
Implement
construct_from_string: parsearray[<dtype>]back into aPandasArrayExtensionDtype, and raiseTypeErrorfor anything else — which is how pandas spells "not my dtype", and what__eq__catches to returnFalse.Tests
In
tests/features/test_array_xd.py:test_pandas_array_extension_dtype_construct_from_string—array[int32]/array[bool]/array[float64]round-trip to the rightvalue_type.test_pandas_array_extension_dtype_construct_from_string_rejects—TypeErrorforstring,int64,array[],array[not_a_dtype],not_an_array[int32].test_table_to_pandas_dtype_compares_to_string— the user-facing symptom:dtype == "string"isFalse,is_string_dtypeisFalse,df.astype(object)works.11 of these fail on
mainand pass here; fulltests/features/test_array_xd.pyis green (114 passed).ruff check/ruff format --checkclean.Interaction with #8464
Independent fixes, but they compound, so flagging it rather than letting CI surprise you. With only this change, pandas gets further and then trips the
_metadatabug from #8375:With both this and #8464 applied, all of those pass. This PR is based on
mainand does not include the_metadatachange, so the two can be reviewed and merged in either order — the tests here are written to not depend on #8464.The one thing still failing with both applied is
df.replace(1.0, 2.0), which hits the deliberateNotImplementedError("Invalid type to compare to: <class 'float'>")inPandasArrayExtensionArray.__eq__. That looks intentional, so I left it alone.Tested on Windows 11 / Python 3.11.9 / pandas 3.0.5 / pyarrow 25.0.1 / numpy 2.4.6.