Skip to content
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

Fix some type hinting to help with migrating Distribution #7484

Merged
merged 8 commits into from
Oct 9, 2024

Conversation

thomasaarholt
Copy link
Contributor

@thomasaarholt thomasaarholt commented Aug 29, 2024

Description

This is a small PR. I've added and fixed type hinting to a few lines of code. The idea is to make it easier to migrate the Distribution class to a function-based approach as discussed in the related issue.

Related Issue

Checklist

Type of change

  • New feature / enhancement
  • Bug fix
  • Documentation
  • Maintenance
  • Other (please specify):

📚 Documentation preview 📚: https://pymc--7484.org.readthedocs.build/en/7484/

Copy link

codecov bot commented Aug 29, 2024

Codecov Report

Attention: Patch coverage is 90.00000% with 1 line in your changes missing coverage. Please review.

Project coverage is 92.16%. Comparing base (d596afb) to head (157c29a).

Files with missing lines Patch % Lines
pymc/distributions/distribution.py 80.00% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #7484      +/-   ##
==========================================
- Coverage   92.16%   92.16%   -0.01%     
==========================================
  Files         103      103              
  Lines       17200    17203       +3     
==========================================
+ Hits        15853    15855       +2     
- Misses       1347     1348       +1     
Files with missing lines Coverage Δ
pymc/distributions/continuous.py 97.92% <100.00%> (+<0.01%) ⬆️
pymc/distributions/distribution.py 91.66% <80.00%> (-0.23%) ⬇️

@ricardoV94 ricardoV94 added maintenance no releasenotes Skipped in automatic release notes generation labels Aug 31, 2024
@ricardoV94
Copy link
Member

@thomasaarholt
Copy link
Contributor Author

Trying a solution, see below.

Yes. That's this commit, where I fixed the incorrect type hint syntax.

All three reported errors are the same:

Incompatible types in assignment 
(expression has type "Callable[[Any, VarArg(Any), DefaultNamedArg(Any, 'size')], Any]", 
base class "Distribution" defined the type as "RandomVariable | SymbolicRandomVariable")

and are due to Mixture, Censored and Discrete distributions having rv_op = <a method>, while e.g. Normal has rv_op = <a class>.

class Censored(Distribution):
    rv_type = CensoredRV
    rv_op = CensoredRV.rv_op # <-- a method

class Normal(Distribution):
    rv_op = NormalRV() # <-- an instance of NormalRV, which is a subclass of RandomVariable

Solution
Typing the above, I realize that since we are really wanting to type this by behaviour rather than state. So I've tried typing it as Callable[..., TensorVariable] instead, which is how it always behaves (I think).

@ricardoV94
Copy link
Member

sounds correct

@thomasaarholt
Copy link
Contributor Author

I am not going to worry about the error in func_utils.py. It's in find_constrained_prior, which is a) deprecated and b) not typed correctly (first argument should be type[Distribution]).

I am currently testing if I can forego the = None on the rv_op and rv_type completely. I don't think these are necessary.

@thomasaarholt
Copy link
Contributor Author

The failing test is unrelated I guess? @ricardoV94

I think I'm finished with this one 😊

@ricardoV94
Copy link
Member

I am not going to worry about the error in func_utils.py. It's in find_constrained_prior, which is a) deprecated and b) not typed correctly (first argument should be type[Distribution]).

I am currently testing if I can forego the = None on the rv_op and rv_type completely. I don't think these are necessary.

Then can you remove the type hints, we can't merge with a known failing CI or it will be a source of confusion for everyone else

@thomasaarholt
Copy link
Contributor Author

I can remove the type hint for class attribute rv_op, but then I either need to leave it = None (which the passing tests just established is unnecessary), replace it (with Any, probably, and a comment explaining what I've learnt about it), or remove the entire attribute, since the following is not legal Python:

class Foo:
    bar

Use of bound_arg_indices shows that this should be a (start, end) tuple, not a list.
I don't want to touch the `= None` part. I could add ` | None`
to the type hint but I suspect the `= None` is unnecessary.
This is a bit like using a Protocol class, we say that whatever
is passed to rv_op, it should return a TensorVariable.
I don't think these are necessary at all. The tests will tell us so.
@thomasaarholt
Copy link
Contributor Author

@ricardoV94 mind taking a look?

Comment on lines 125 to 126
if class_change_dist_size is not None:
raise ValueError("HAHAHA")
Copy link
Member

Choose a reason for hiding this comment

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

Fun debug statement left :)

Suggested change
if class_change_dist_size is not None:
raise ValueError("HAHAHA")

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hehe! That's what I get for not adding my changes line by line for this particular commit!

@@ -152,7 +152,7 @@ class BoundedContinuous(Continuous):
"""Base class for bounded continuous distributions"""

# Indices of the arguments that define the lower and upper bounds of the distribution
bound_args_indices: list[int] | None = None
bound_args_indices: tuple[int, int] | None = None
Copy link
Member

@ricardoV94 ricardoV94 Oct 7, 2024

Choose a reason for hiding this comment

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

Aren't there distributions with only one of the bounds (lower, upper)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're right, there are! I was wondering why mypy didn't flag it, but of course it was originally an error as list[int] doesn't allow (3, None)! Fixing this

@thomasaarholt
Copy link
Contributor Author

The failing tests stem from this commit, not this PR.

@ricardoV94
Copy link
Member

@thomasaarholt should be fixed by #7529

@ricardoV94 ricardoV94 merged commit 938aff4 into pymc-devs:main Oct 9, 2024
17 of 20 checks passed
@ricardoV94
Copy link
Member

Thanks @thomasaarholt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
maintenance no releasenotes Skipped in automatic release notes generation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants