-
-
Notifications
You must be signed in to change notification settings - Fork 310
Support "is None" constraints from if statements during inference #1189
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
Changes from 19 commits
159af87
1c5b4b3
4dffa4d
4828797
c39baff
b54d841
de4c318
3da1c83
7fe82e6
fc4156e
55bb33f
8a3b443
5b86d5a
e032c0b
c1268a2
7d0b6b2
f963723
21e4cf9
65c3c55
f6e001b
5da24fe
b46f001
409543b
316ba46
dabf0e9
f70fbad
46c056f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,135 @@ | ||||||||||||||||||
| # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html | ||||||||||||||||||
cdce8p marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||
| # For details: https://github.com/PyCQA/astroid/blob/main/LICENSE | ||||||||||||||||||
| # Copyright (c) https://github.com/PyCQA/astroid/blob/main/CONTRIBUTORS.txt | ||||||||||||||||||
|
|
||||||||||||||||||
| """Classes representing different types of constraints on inference values.""" | ||||||||||||||||||
| from __future__ import annotations | ||||||||||||||||||
|
|
||||||||||||||||||
| from abc import ABC, abstractmethod | ||||||||||||||||||
| from typing import TypeVar, Union | ||||||||||||||||||
|
|
||||||||||||||||||
| from astroid import nodes, util | ||||||||||||||||||
|
|
||||||||||||||||||
| _NameNodes = Union[nodes.AssignAttr, nodes.Attribute, nodes.AssignName, nodes.Name] | ||||||||||||||||||
| _ConstraintT = TypeVar("_ConstraintT", bound="Constraint") | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
||||||||||||||||||
| class Constraint(ABC): | ||||||||||||||||||
| """Represents a single constraint on a variable.""" | ||||||||||||||||||
|
|
||||||||||||||||||
| def __init__(self, node: nodes.NodeNG, negate: bool) -> None: | ||||||||||||||||||
| self.node = node | ||||||||||||||||||
| """The node that this constraint applies to.""" | ||||||||||||||||||
| self.negate = negate | ||||||||||||||||||
| """True if this constraint is negated. E.g., "is not" instead of "is".""" | ||||||||||||||||||
|
|
||||||||||||||||||
| @classmethod | ||||||||||||||||||
| @abstractmethod | ||||||||||||||||||
| def match( | ||||||||||||||||||
| cls: _ConstraintT, node: _NameNodes, expr: nodes.NodeNG, negate: bool = False | ||||||||||||||||||
|
||||||||||||||||||
| @classmethod | |
| @abstractmethod | |
| def match( | |
| cls: _ConstraintT, node: _NameNodes, expr: nodes.NodeNG, negate: bool = False | |
| @classmethod | |
| @abstractmethod | |
| def match( | |
| cls: type[_ConstraintT], node: _NameNodes, expr: nodes.NodeNG, negate: bool = False |
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.
Changed this to be Self which I think makes more sense here, let me know if I need to revert
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.
Self would be awesome. Unfortunately it isn't supported by mypy yet.
The PR has already been merged, but we need to wait for the next release (1.0.0).
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.
Yeah, because it was already merged I thought it would be okay to use. pyright understands it and I don't think we will turn on mypy in astroid before 1.0.0 gets released so this doesn't give us any additional work (instead it prevents some 😄 )
Pierre-Sassoulas marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Outdated
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.
| @classmethod | |
| def match( | |
| cls: _ConstraintT, node: _NameNodes, expr: nodes.NodeNG, negate: bool = False | |
| @classmethod | |
| def match( | |
| cls: type[_ConstraintT], node: _NameNodes, expr: nodes.NodeNG, negate: bool = False |
Same here
Outdated
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.
cls.CONST_NONE is a type error. See: #1189 (comment)
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 might be fixed with using Self?
Pierre-Sassoulas marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Pierre-Sassoulas marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Pierre-Sassoulas marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Pierre-Sassoulas marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
Outdated
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.
Is there a case in which multiple constraint classes could match (in the future)? Does it make sense to change it to an Iterator then, i.e. yield constraint instead of return?
Uh oh!
There was an error while loading. Please reload this page.