Skip to content

Commit

Permalink
Remove SequenceIncompleteValue (#519)
Browse files Browse the repository at this point in the history
  • Loading branch information
JelleZijlstra authored Apr 13, 2022
1 parent 40065df commit ed28da3
Show file tree
Hide file tree
Showing 2 changed files with 1 addition and 128 deletions.
1 change: 1 addition & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Unreleased

- Remove `SequenceIncompleteValue` (#519)
- Add implementation function for `dict.pop` (#517)
- Remove `WeakExtension` (#517)
- Fix propagation of no-return-unless constraints from calls
Expand Down
128 changes: 0 additions & 128 deletions pyanalyze/value.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ def function(x: int, y: list[int], z: Any):
import pyanalyze
from pyanalyze.extensions import CustomCheck

from .find_unused import used
from .safe import all_of_type, safe_equals, safe_issubclass, safe_isinstance

T = TypeVar("T")
Expand Down Expand Up @@ -1023,133 +1022,6 @@ def simplify(self) -> GenericValue:
return GenericValue(self.typ, [arg])


# TODO(jelle): Replace with SequenceValue
@used # for compatibility for now
@dataclass(unsafe_hash=True, init=False)
class SequenceIncompleteValue(GenericValue):
"""A :class:`TypedValue` subclass representing a sequence of known type and length.
For example, the expression ``[int(self.foo)]`` may be typed as
``SequenceIncompleteValue(list, [TypedValue(int)])``.
This is only used for ``set``, ``list``, and ``tuple``.
This type is being phased out in favor of :class:`SequenceValue`.
"""

members: Tuple[Value, ...]
"""The elements of the sequence."""

def __init__(self, typ: Union[type, str], members: Sequence[Value]) -> None:
if members:
args = (unite_values(*members),)
else:
args = (AnyValue(AnySource.unreachable),)
super().__init__(typ, args)
self.members = tuple(members)

@classmethod
def make_or_known(
cls, typ: type, members: Sequence[Value]
) -> Union[KnownValue, "SequenceIncompleteValue"]:
if all_of_type(members, KnownValue):
return KnownValue(typ(member.val for member in members))
else:
return SequenceIncompleteValue(typ, members)

def can_assign(self, other: Value, ctx: CanAssignContext) -> CanAssign:
if isinstance(other, SequenceIncompleteValue):
can_assign = self.get_type_object(ctx).can_assign(self, other, ctx)
if isinstance(can_assign, CanAssignError):
return CanAssignError(
f"Cannot assign {stringify_object(other.typ)} to"
f" {stringify_object(self.typ)}"
)
my_len = len(self.members)
their_len = len(other.members)
if my_len != their_len:
type_str = stringify_object(self.typ)
return CanAssignError(
f"Cannot assign {type_str} of length {their_len} to {type_str} of"
f" length {my_len}"
)
if my_len == 0:
return {} # they're both empty
bounds_maps = [can_assign]
for i, (my_member, their_member) in enumerate(
zip(self.members, other.members)
):
can_assign = my_member.can_assign(their_member, ctx)
if isinstance(can_assign, CanAssignError):
return CanAssignError(
f"Types for member {i} are incompatible", [can_assign]
)
bounds_maps.append(can_assign)
return unify_bounds_maps(bounds_maps)
elif isinstance(other, SequenceValue):
can_assign = self.get_type_object(ctx).can_assign(self, other, ctx)
if isinstance(can_assign, CanAssignError):
return CanAssignError(
f"Cannot assign {stringify_object(other.typ)} to"
f" {stringify_object(self.typ)}"
)
my_len = len(self.members)
their_len = len(other.members)
if my_len != their_len:
type_str = stringify_object(self.typ)
return CanAssignError(
f"Cannot assign {type_str} of length {their_len} to {type_str} of"
f" length {my_len}"
)
if my_len == 0:
return {} # they're both empty
bounds_maps = [can_assign]
for i, (my_member, (is_many, their_member)) in enumerate(
zip(self.members, other.members)
):
if is_many:
return CanAssignError(
f"Member {i} is a single element, but an unpacked type is"
" provided"
)
can_assign = my_member.can_assign(their_member, ctx)
if isinstance(can_assign, CanAssignError):
return CanAssignError(
f"Types for member {i} are incompatible", [can_assign]
)
bounds_maps.append(can_assign)
return unify_bounds_maps(bounds_maps)
return super().can_assign(other, ctx)

def substitute_typevars(self, typevars: TypeVarMap) -> Value:
return SequenceIncompleteValue(
self.typ, [member.substitute_typevars(typevars) for member in self.members]
)

def __str__(self) -> str:
members = ", ".join(str(m) for m in self.members)
if self.typ is tuple:
return f"tuple[{members}]"
return f"<{stringify_object(self.typ)} containing [{members}]>"

def walk_values(self) -> Iterable[Value]:
yield self
for member in self.members:
yield from member.walk_values()

def simplify(self) -> GenericValue:
if self.typ is tuple:
return SequenceIncompleteValue(
tuple, [member.simplify() for member in self.members]
)
members = [member.simplify() for member in self.members]
arg = unite_values(*members)
if arg is NO_RETURN_VALUE:
arg = AnyValue(AnySource.unreachable)
return GenericValue(self.typ, [arg])


@dataclass(frozen=True)
class KVPair:
"""Represents a single entry in a :class:`DictIncompleteValue`."""
Expand Down

0 comments on commit ed28da3

Please sign in to comment.