Skip to content

Fix and narrow repr.py typing #1616

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

Closed
wants to merge 1 commit into from

Conversation

GBeauregard
Copy link
Contributor

@GBeauregard GBeauregard commented Oct 19, 2021

Type of changes

  • Bug fix
  • New feature
  • Documentation / docstrings
  • Tests
  • Other

Checklist

  • I've run the latest black with default args on new code.
  • I've updated CHANGELOG.md and CONTRIBUTORS.md where appropriate.
  • I've added tests for new code.
  • I accept that @willmcgugan may be pedantic in the code review.

Description

Managed to squash a lot of # type: ignore in this one (8) and every case of Any. This was generally speaking just by fixing the typing.

First of many stabs at eliminating Any and # type: ignore from the codebase.

In order to correctly type the auto_repr function, I introduced a
SupportsRichRepr protocol; we could also have made this runtimecheckable
and replaced a hasattr check in the code with it, but it seemed
unnecessary so I opted not to.

There's a bit of a surprising cast in there. There's a bug/limitation in mypy that means it's internally incorrectly using Any for the tuple unpacking there so it doesn't reveal the need for the cast, but pyright does. The cast is needed at least until len() is recognized as a type narrowing pattern.

Apologies for all the separate pull requests; I kinda want to separate out the more complicated tasks.

There is one remaining #type: ignore in this file; it is because mypy doesn't allow inspecting __init__ under any circumstance, even though our use is not buggy: https://mypy-play.net/?mypy=latest&python=3.10&gist=c422a6478274d762a9bcc049051b8304. I'm unsure if I want to bring this up with mypy devs so I haven't for now (feel free to do so yourself and link me an issue if you like). It seems to me this lint is just intended to be something they always disallow.

@codecov
Copy link

codecov bot commented Oct 19, 2021

Codecov Report

Merging #1616 (e6fec11) into master (5dddadb) will increase coverage by 0.00%.
The diff coverage is 98.18%.

Impacted file tree graph

@@           Coverage Diff           @@
##           master    #1616   +/-   ##
=======================================
  Coverage   99.69%   99.69%           
=======================================
  Files          71       71           
  Lines        6860     6864    +4     
=======================================
+ Hits         6839     6843    +4     
  Misses         21       21           
Flag Coverage Δ
unittests 99.69% <98.18%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
rich/box.py 100.00% <ø> (ø)
rich/live.py 100.00% <ø> (ø)
rich/pager.py 90.00% <50.00%> (ø)
rich/columns.py 100.00% <100.00%> (ø)
rich/console.py 100.00% <100.00%> (ø)
rich/json.py 100.00% <100.00%> (ø)
rich/measure.py 100.00% <100.00%> (ø)
rich/panel.py 100.00% <100.00%> (ø)
rich/pretty.py 98.15% <100.00%> (ø)
rich/progress.py 97.87% <100.00%> (ø)
... and 12 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update eb673d1...e6fec11. Read the comment docs.

@GBeauregard GBeauregard force-pushed the repr-changes branch 7 times, most recently from 02b9857 to e2a4bbe Compare October 20, 2021 21:15
@GBeauregard
Copy link
Contributor Author

GBeauregard commented Oct 20, 2021

This one should be ready for review now; I'll try to slow down the pull requests to give you a chance to review them and I'll try to see what can be combined in the future.

First of many stabs at eliminating Any and # type: ignore from the
codebase. Here we eliminated several different type ignores; the
remaining # type: ignore is just a mypy limitation.

I also narrowed the typing of RichReprResult from Iterable[Any|...]] to
Iterable[object] since after inspection of the code this is what's
really required.

There's one particularly nasty cast that's needed. It's definitely a
mypy bug that it's not throwing an error for us here. See:
python/mypy#1178 and I've opened a similar
issue for pyright. There's an open PR for mypy that would resolve this,
but at least until this is fixed we need to be casting.

In order to correctly type the auto_repr function, I introduced a
SupportsRichRepr protocol; we could also have made this runtimecheckable
and replaced a hasattr check in the code with it, but it seemed
unnecessary so I opted not to.
@GBeauregard GBeauregard marked this pull request as draft October 22, 2021 18:31
@GBeauregard GBeauregard marked this pull request as ready for review October 22, 2021 18:33
@GBeauregard
Copy link
Contributor Author

GBeauregard commented Oct 22, 2021

Note the complicated cast I added to correctly type the case where type checkers can't handle len() narrowing. It reveals a probably unintended behavior of the code; It looks to assume the first tuple argument is Optional[str], but it can still be any object. Moreover, there was only an attempt to type it as str. It can be any object because the preceding isinstance(...,tuple) checked a union of types that includes object (or Any before I changed it); that object could f.ex. be a tuple such that narrowing to tuple doesn't get rid of that case.

I've chosen to avoid any functional changes in this PR so you can decide if you want to fix the unhandled edge cases later if you want. The current code doesn't fail anywhere; it just causes unexpected behavior.

An alternate approach to the typing problem that obviates the need for the complex cast is to change the typing of Result from the current union to simply Iterable[object] - this should be just as narrow typing-wise as before except for that we're no longer explicitly signalling to the type checker the possibility of a one item tuple so it won't throw an error anymore for the unpacking.

Yet another approach is if we want to change the behavior we can make a TypeGuard for the proper narrow case we want.

@GBeauregard GBeauregard closed this Feb 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant