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

Google sync #1529

Merged
merged 4 commits into from
Nov 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 14 additions & 10 deletions pytype/abstract/_interpreter_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,17 +115,18 @@ def make(cls, name, *, def_opcode, code, f_locals, f_globals, defaults,
"""
annotations = annotations or {}
overloads = ctx.vm.frame.overloads[name]
if f_locals == ctx.convert.unsolvable:
local_members = {}
else:
local_members = f_locals.members
key = (name, code,
_hash_all_dicts(
(f_globals.members, set(code.names)),
(f_locals.members,
set(f_locals.members) - set(code.varnames)), ({
key: ctx.program.NewVariable([value], [], ctx.root_node)
for key, value in annotations.items()
}, None), (dict(
enumerate(
ctx.program.NewVariable([f], [], ctx.root_node)
for f in overloads)), None),
(local_members, set(local_members) - set(code.varnames)),
({key: ctx.program.NewVariable([value], [], ctx.root_node)
for key, value in annotations.items()}, None),
(dict(enumerate(ctx.program.NewVariable([f], [], ctx.root_node)
for f in overloads)), None),
(dict(enumerate(defaults)), None),
(dict(enumerate(closure or ())), None)))
if key not in cls._function_cache:
Expand Down Expand Up @@ -382,11 +383,14 @@ def _hash_call(self, callargs, frame):
if (self.ctx.options.skip_repeat_calls and
("self" not in callargs or not self.ctx.callself_stack or
callargs["self"].data != self.ctx.callself_stack[-1].data)):
if frame.f_locals == self.ctx.convert.unsolvable:
local_members = {}
else:
local_members = frame.f_locals.members
callkey = _hash_all_dicts(
(callargs, None),
(frame.f_globals.members, set(self.code.names)),
(frame.f_locals.members,
set(frame.f_locals.members) - set(self.code.varnames)))
(local_members, set(local_members) - set(self.code.varnames)))
else:
# Make the callkey the number of times this function has been called so
# that no call has the same key as a previous one.
Expand Down
6 changes: 5 additions & 1 deletion pytype/block_environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ def add_block(self, frame, block):
if b in self.block_locals and b != block and b not in self._dead_ends]
n_inc = len(incoming)
if n_inc == 0:
frame_locals = {k: [v] for k, v in frame.f_locals.pyval.items()}
try:
f_locals = frame.f_locals.pyval.items()
except AttributeError:
f_locals = ()
frame_locals = {k: [v] for k, v in f_locals}
local.update(frame_locals)
elif n_inc == 1:
inc, = incoming
Expand Down
2 changes: 1 addition & 1 deletion pytype/compare.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def _is_primitive(ctx, value):
if _is_primitive_constant(ctx, value):
return True
elif isinstance(value, abstract.Instance):
return value.full_name in ctx.convert.primitive_class_names
return value.full_name in ctx.convert.primitive_classes_by_name
return False


Expand Down
8 changes: 6 additions & 2 deletions pytype/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ def __init__(self, ctx):
self.primitive_classes = {
v: self.constant_to_value(v) for v in primitive_classes
}
self.primitive_class_names = [
".".join(self._type_to_name(x)) for x in self.primitive_classes]
self.primitive_classes_by_name = {
".".join(self._type_to_name(x)): x for x in self.primitive_classes}
self.none = abstract.ConcreteValue(None, self.primitive_classes[NoneType],
self.ctx)
self.true = abstract.ConcreteValue(True, self.primitive_classes[bool],
Expand Down Expand Up @@ -930,6 +930,10 @@ def _constant_to_value(self, pyval, subst, get_node):
mycls = self.constant_to_value(cls, subst, self.ctx.root_node)
if isinstance(mycls, typed_dict.TypedDictClass):
instance = mycls.instantiate_value(self.ctx.root_node, None)
elif (isinstance(mycls, abstract.PyTDClass) and
mycls.pytd_cls.name in self.primitive_classes_by_name):
instance = self.primitive_class_instances[
self.primitive_classes_by_name[mycls.pytd_cls.name]]
else:
instance = abstract.Instance(mycls, self.ctx)
log.info("New pytd instance for %s: %r", cls.name, instance)
Expand Down
10 changes: 8 additions & 2 deletions pytype/pyi/parser_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2017,13 +2017,19 @@ def test_property_decorator_bad_syntax(self):
class A:
@property
def name(self, bad_arg): ...
""", 1, "@property needs 1 param(s), got 2")
""", 1, "@property must have 1 param(s), but actually has 2")

self.check_error("""
class A:
@name.setter
def name(self): ...
""", 1, "@name.setter needs 2 param(s), got 1")
""", 1, "@name.setter must have 2 param(s), but actually has 1")

self.check("""
class A:
@property
def name(self, optional_arg: str = ...): ...
""", expected=parser_test_base.IGNORE)

self.check_error("""
class A:
Expand Down
9 changes: 6 additions & 3 deletions pytype/pytd/codegen/function.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,12 +232,15 @@ def __post_init__(self):

def add_property(self, decorator, sig):
prop = self.prop_names[decorator]
if prop.arity == len(sig.params):
if prop.arity == len([s for s in sig.params if not s.optional]):
assert self.properties is not None
self.properties.set(prop.type, sig, self.name)
else:
raise TypeError("Property decorator @%s needs %d param(s), got %d" %
(decorator, prop.arity, len(sig.params)))
raise TypeError(
f"Function '{self.name}' decorated by property decorator"
f" @{decorator} must have {prop.arity} param(s), but actually has"
f" {len(sig.params)}"
)

def add_overload(self, fn: NameAndSig):
"""Add an overloaded signature to a function."""
Expand Down
10 changes: 10 additions & 0 deletions pytype/tests/test_splits2.py
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,16 @@ def Build(self) -> List[str]:
return a.Get()
""")

def test_frametype(self):
self.Check("""
import inspect
current = inspect.currentframe()
assert current is not None
caller = current.f_back
assert caller is not None
code = caller.f_code
""")


if __name__ == "__main__":
test_base.main()
14 changes: 9 additions & 5 deletions pytype/vm.py
Original file line number Diff line number Diff line change
Expand Up @@ -770,11 +770,15 @@ def load_from(
name: str, discard_concrete_values: bool = False
) -> Tuple[frame_state.FrameState, cfg.Variable]:
"""Load an item out of locals, globals, or builtins."""
store.load_lazy_attribute(name)
try:
member = store.members[name]
except KeyError:
return state, self._load_annotation(state.node, name, store)
if isinstance(store, mixin.LazyMembers):
store.load_lazy_attribute(name)
try:
member = store.members[name]
except KeyError:
return state, self._load_annotation(state.node, name, store)
else:
assert store == self.ctx.convert.unsolvable
return state, self.ctx.new_unsolvable(state.node)
bindings = member.Bindings(state.node)
if (not bindings and self._late_annotations_stack and member.bindings and
all(isinstance(v, abstract.Module) for v in member.data)):
Expand Down