-
Notifications
You must be signed in to change notification settings - Fork 167
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
Add annotation stubs for PyGraph
and PyDiGraph
#401
Conversation
Pull Request Test Coverage Report for Build 2778787088
💛 - Coveralls |
@@ -1066,7 +1066,7 @@ impl PyDiGraph { | |||
/// ``(source, target, weight)`` where source and target are integer | |||
/// node indices. If the node index is not present in the graph | |||
/// nodes will be added (with a node weight of ``None``) to that index. | |||
#[pyo3(text_signature = "(self, edge_lsit, /)")] | |||
#[pyo3(text_signature = "(self, edge_list, /)")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW, this typo has been on our code base for 2 years. mypy caught it
tox.ini
Outdated
basepython = python3 | ||
envdir = .tox/stubs | ||
deps = | ||
mypy @ git+https://github.com/python/mypy.git |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to keep using the latest version until python/mypy#14041 is out
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this was released as of Mypy 1.0 a couple of weeks ago.
Alright, this is ready for review after so long. Some things might be missing (e.g. all functions from |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to merge to me! Fantastic work, Ivan - I know I'm not one of the actual retworkx devs so it's a bit weird coming from me, but still!
I left a question or two inline (mostly for future reference), and maybe one place where's the possibility for marginally better typing, but nothing that actually needs action on this PR. I'd recommend to merge it now before it gets out-of-date again - it's been a great effort since the correct typing here is quite complex with the extra constraints on the Self
type, and some of the additional co-/contra-/in- variant typing.
def add_edges_from( | ||
self, | ||
obj_list: Sequence[Tuple[int, int, T]], | ||
/, | ||
) -> List[int]: ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was a little surprised to learn that PyO3 won't convert Iterable
as a valid conversion type for Vec<_>
, but you're definitely correct with the hint here. I guess maybe PyO3 didn't want to do conversions that require multiple reallocations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PyO3 has some weird quirks with iterations (e.g. #614 that broke us) so sometimes I just accept the Vec<_>
conversion and if it is not in our tests it is not "canonical"
def from_adjacency_matrix( | ||
matrix: np.ndarray, /, null_value: float = ... | ||
) -> PyDiGraph[int, float]: ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Numpy technically provide stronger type hints now, and Unpack
+TypeVarTuple
give some sort of way of specifying ndarray shapes / dtypes. Unless you particularly want to look into that right now, though, I'd not worry about it in favour of just landing this PR.
def to_dot( | ||
self, | ||
/, | ||
node_attr: Optional[Callable[[S], Dict[str, str]]] = ..., | ||
edge_attr: Optional[Callable[[T], Dict[str, str]]] = ..., | ||
graph_attr: Optional[Dict[str, str]] = ..., | ||
filename: Optional[str] = ..., | ||
) -> Optional[str]: ... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, this could be done later if you'd rather just land the PR:
I think there's a way to teach type checkers that the return type is dependent on the types of one of the arguments. It's made more complex because of the default value of the argument, so I don't precisely know the correct syntax, but it's something like
@typing.overload
def to_dot(self, /, ..., filename: None = ...) -> str: ...
@typing.overload
def to_dot(self, /, ..., filename: str = ...) -> None: ...
def to_dot(self, /, ..., filename = None): ...
I don't remember exactly how you sort out the syntax in a typing stub to combine the overload with the default value, but it's something along those lines.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this, I will try implementing it
tox.ini
Outdated
basepython = python3 | ||
envdir = .tox/stubs | ||
deps = | ||
mypy @ git+https://github.com/python/mypy.git |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this was released as of Mypy 1.0 a couple of weeks ago.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This LGTM, thanks for adding this and sticking with it so long! It will be great to finally merge this as the longest open PR we've ever had in rustworkx :)
Related to #352
This PR adds type annotation stubs, it contains
.pyi
files with type annotations. I started by annotating thePyGraph
andPyDiGraph
files, as well as the custom types.I tried to follow the PEP 561 convetion: we include
.pyi
files in the same directory as our Python code. Note that this is a first step in annotations: they are partial, we can add more as we goWe also test the annotations using mypy.stubtest. This was the most reliable approach. For now, we ignore missing stubs and focus only on the functions imported from Rust code
Some items we need to handle because the PR has been open for long: