Skip to content

TYP: setter for index/columns property-like (AxisProperty) #46565

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 10, 2022

Conversation

simonjayhawkins
Copy link
Member

No description provided.

@simonjayhawkins simonjayhawkins added the Typing type annotations, mypy/pyright type checking label Mar 29, 2022
Comment on lines +8 to +10
DataFrame,
Index,
Series,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an issue with mypy that can't resolve the types for the decorated methods that IIRC @jbrockmendel encountered before when adding the stubs for the Cython code initially. It seems to be related to the imports and putting them here seems prevent the problem resurfacing.

@overload
def __get__(self, obj: None, type) -> AxisProperty: ...
def __set__(
self, obj: DataFrame | Series, value: AnyArrayLike | Sequence
Copy link
Member Author

@simonjayhawkins simonjayhawkins Mar 29, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

type annotation for value chosen just to match _set_axis which is added to Series to match the existing ensure_index annotation and changed on NDFrame for consistency.

Copy link
Member

@twoertwein twoertwein Mar 30, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just an idea, might be not worth it to enforce that obj is compatible with value.

IndexCompatibleT = TypeVar("IndexCompatibleT", AnyArrayLike, Sequence)

class Has_set_axis(Protocol[IndexCompatibleT]):
    def _set_axis(self: NDFrame, axis: int, value: IndexCompatibleT) -> object:
        ...


def __set__(self, obj: Has_set_axis[IndexCompatibleT], value: IndexCompatibleT) -> None:
    ...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

from the other response, I think that only NDFrame objects use AxisProperty and we tend to avoid NDFrame in annotations that would be part of the public API since NDFrame is not public, but obviously need to use it in some circumstances.

Until the other issue is resolved, I'm not sure I can comment on whether we would be better off using a protocol here instead.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to be fair, obj would probably not surface in the public api, only value would.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the index/column properties are only actually added to DataFrame/Series in the codebase.

In theory they could be added to any NDFrame object and I suppose we could refactor the code to add the AxisProperty dynamically in the base class based on the other NDFrame attributes, i.e. we know the axis numbers and names.

Having said that, i'm -1 on doing this dynamically and therefore happy with the DataFrame|Series to match the actual code.

if not isinstance(result, (ABCSeries, ABCDataFrame)) or not result.index.equals(
obj.index
obj.index # type:ignore[arg-type]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not investigated this one yet. maybe fix later.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is AxisProperty used by all NDFrame? That might cover most/all objects in this union.

A slightly (too) complex approach would be to use a Protocol for __get__: only objects that have _mgr and only _mgr that have _mgr.axes where axes is Sequence[Index].

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that all those objects are valid e.g. AttributeError: 'DataFrameGroupBy' object has no attribute 'index'

I assume that the condition should be narrowing to DataFrame/Series from the error message.

# "Optional[List[str]]", variable has type "Index")
ret.columns = columns # type: ignore[assignment]
# columns is not narrowed by mypy from relabeling flag
assert columns is not None # for mypy
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not yet ran the tests locally to check we don't get failures but it appears relabeling and columns are not independent variables, which mypy cannot understand and we should try to avoid. Not planning to refactor at this time.

@github-actions
Copy link
Contributor

This pull request is stale because it has been open for thirty days with no activity. Please update and respond to this comment if you're still interested in working on this.

@github-actions github-actions bot added the Stale label Apr 30, 2022
Copy link
Member

@twoertwein twoertwein left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I wasn't sure whether you still wanted to investigate some mypy errors. Happy to merge it after you rebase it.

@twoertwein twoertwein removed the Stale label May 11, 2022
@mroeschke mroeschke added this to the 1.5 milestone Jun 10, 2022
@jreback jreback merged commit 7440fe2 into pandas-dev:main Jun 10, 2022
@simonjayhawkins simonjayhawkins deleted the AxisProperty branch June 11, 2022 09:36
yehoshuadimarsky pushed a commit to yehoshuadimarsky/pandas that referenced this pull request Jul 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Typing type annotations, mypy/pyright type checking
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants