1.1 --- a/inspector.py Mon Oct 17 15:39:07 2016 +0200
1.2 +++ b/inspector.py Mon Oct 17 18:56:34 2016 +0200
1.3 @@ -41,6 +41,7 @@
1.4
1.5 BasicModule.__init__(self, name, importer)
1.6
1.7 + self.in_assignment = False
1.8 self.in_class = False
1.9 self.in_conditional = False
1.10 self.in_invocation = False
1.11 @@ -342,7 +343,11 @@
1.12
1.13 elif isinstance(n, compiler.ast.AssAttr):
1.14 if expr: self.process_structure_node(expr)
1.15 +
1.16 + in_assignment = self.in_assignment
1.17 + self.in_assignment = True
1.18 self.process_attribute_access(n)
1.19 + self.in_assignment = in_assignment
1.20
1.21 # Lists and tuples are matched against the expression and their
1.22 # items assigned to expression items.
1.23 @@ -362,12 +367,19 @@
1.24
1.25 "Process the given attribute access node 'n'."
1.26
1.27 - # Obtain any completed chain and return the reference to it.
1.28 + # Parts of the attribute chain are neither invoked nor assigned.
1.29
1.30 in_invocation = self.in_invocation
1.31 self.in_invocation = False
1.32 + in_assignment = self.in_assignment
1.33 + self.in_assignment = False
1.34 +
1.35 + # Obtain any completed chain and return the reference to it.
1.36 +
1.37 name_ref = self.process_attribute_chain(n)
1.38 +
1.39 self.in_invocation = in_invocation
1.40 + self.in_assignment = in_assignment
1.41
1.42 if self.have_access_expression(n):
1.43 return name_ref
1.44 @@ -423,8 +435,6 @@
1.45 immediate_access = len(self.attrs) == 1
1.46 assignment = immediate_access and isinstance(n, compiler.ast.AssAttr)
1.47
1.48 - del self.attrs[0]
1.49 -
1.50 # Record global-based chains for subsequent resolution.
1.51
1.52 is_global = self.in_function and not self.function_locals[path].has_key(name) or \
1.53 @@ -445,7 +455,8 @@
1.54 # Record attribute usage in the tracker, and record the branch
1.55 # information for the access.
1.56
1.57 - branches = tracker.use_attribute(name, attrname, self.in_invocation)
1.58 + branches = tracker.use_attribute(name, attrname, self.in_invocation,
1.59 + self.in_assignment and immediate_access)
1.60
1.61 if not branches:
1.62 raise InspectError("Name %s is accessed using %s before an assignment." % (
1.63 @@ -453,6 +464,8 @@
1.64
1.65 self.record_branches_for_access(branches, name, attrnames)
1.66 access_number = self.record_access_details(name, attrnames, assignment)
1.67 +
1.68 + del self.attrs[0]
1.69 return AccessRef(name, attrnames, access_number)
1.70
1.71 def process_class_node(self, n):
1.72 @@ -486,10 +499,13 @@
1.73 bases.append(base_class)
1.74
1.75 # Record bases for the class and retain the class name.
1.76 + # Note that the function class does not inherit from the object class.
1.77
1.78 class_name = self.get_object_path(n.name)
1.79
1.80 - if not bases and class_name != "__builtins__.core.object":
1.81 + if not bases and class_name != "__builtins__.core.object" and \
1.82 + class_name != "__builtins__.core.function":
1.83 +
1.84 ref = self.get_object("__builtins__.object")
1.85 bases.append(ref)
1.86
1.87 @@ -509,8 +525,14 @@
1.88 self.in_class = class_name
1.89 self.set_instance_attr("__class__", Reference("<class>", class_name))
1.90 self.enter_namespace(n.name)
1.91 - self.set_name("__fn__") # special instantiator attribute
1.92 - self.set_name("__args__") # special instantiator attribute
1.93 +
1.94 + # Do not provide the special instantiator attributes on the function
1.95 + # class. Function instances provide these attributes.
1.96 +
1.97 + if class_name != "__builtins__.core.function":
1.98 + self.set_name("__fn__") # special instantiator attribute
1.99 + self.set_name("__args__") # special instantiator attribute
1.100 +
1.101 self.assign_general_local("__name__", self.get_constant("str", class_name))
1.102 self.process_structure_node(n.code)
1.103 self.exit_namespace()
1.104 @@ -710,10 +732,14 @@
1.105 self.allocate_arguments(path, n.args)
1.106
1.107 try:
1.108 - # Process the expression, obtaining any identified reference.
1.109 + # Communicate to the invocation target expression that it forms the
1.110 + # target of an invocation, potentially affecting attribute accesses.
1.111
1.112 in_invocation = self.in_invocation
1.113 self.in_invocation = True
1.114 +
1.115 + # Process the expression, obtaining any identified reference.
1.116 +
1.117 name_ref = self.process_structure_node(n.node)
1.118 self.in_invocation = in_invocation
1.119