1.1 --- a/deducer.py Mon May 01 23:35:01 2017 +0200
1.2 +++ b/deducer.py Fri Jun 16 00:37:50 2017 +0200
1.3 @@ -562,21 +562,36 @@
1.4
1.5 if not constrained and self.access_index_rev.get(location):
1.6
1.7 - # Record specific type guard details.
1.8 -
1.9 - if len(all_types) == 1:
1.10 - self.accessor_guard_tests[location] = ("specific", test_label_for_type(first(all_types)))
1.11 - elif is_single_class_type(all_types):
1.12 - self.accessor_guard_tests[location] = ("specific", "object")
1.13 -
1.14 - # Record common type guard details.
1.15 -
1.16 - elif len(all_general_types) == 1:
1.17 - self.accessor_guard_tests[location] = ("common", test_label_for_type(first(all_types)))
1.18 - elif is_single_class_type(all_general_types):
1.19 - self.accessor_guard_tests[location] = ("common", "object")
1.20 -
1.21 - # Otherwise, no convenient guard can be defined.
1.22 + # Test for self parameters in methods that could not be
1.23 + # constrained, potentially due to usage unsupported by the class
1.24 + # defining the method (such as in mix-in classes).
1.25 +
1.26 + if location.name != "self" or self.in_method(location.path):
1.27 + self.record_guard(location, all_types, all_general_types)
1.28 +
1.29 + def record_guard(self, location, all_types, all_general_types):
1.30 +
1.31 + """
1.32 + For the accessor 'location', record a guard if 'all_types' or
1.33 + 'all_general_types' are appropriate. Where no guard is recorded, access
1.34 + tests will need to be applied.
1.35 + """
1.36 +
1.37 + # Record specific type guard details.
1.38 +
1.39 + if len(all_types) == 1:
1.40 + self.accessor_guard_tests[location] = ("specific", test_label_for_type(first(all_types)))
1.41 + elif is_single_class_type(all_types):
1.42 + self.accessor_guard_tests[location] = ("specific", "object")
1.43 +
1.44 + # Record common type guard details.
1.45 +
1.46 + elif len(all_general_types) == 1:
1.47 + self.accessor_guard_tests[location] = ("common", test_label_for_type(first(all_types)))
1.48 + elif is_single_class_type(all_general_types):
1.49 + self.accessor_guard_tests[location] = ("common", "object")
1.50 +
1.51 + # Otherwise, no convenient guard can be defined.
1.52
1.53 def classify_accesses(self):
1.54
1.55 @@ -1462,24 +1477,29 @@
1.56
1.57 # Constrain "self" references.
1.58
1.59 - if location.name == "self":
1.60 -
1.61 - # Test for the class of the method in the deduced types.
1.62 -
1.63 - class_name = self.in_method(location.path)
1.64 -
1.65 - if class_name and class_name not in class_types and class_name not in only_instance_types:
1.66 + class_name = self.in_method(location.path)
1.67 + constrained = False
1.68 +
1.69 + if class_name and location.name == "self":
1.70 +
1.71 + # Constrain the types to the class's hierarchy.
1.72 +
1.73 + class_types, only_instance_types, module_types, constrained = \
1.74 + self.constrain_to_class(class_name, class_types, only_instance_types)
1.75 +
1.76 + # Without any deduced types, produce an error.
1.77 +
1.78 + if not class_types and not only_instance_types:
1.79 raise DeduceError("In %s, usage {%s} is not directly supported by class %s or its instances." %
1.80 (location.path, encode_usage(usage), class_name))
1.81
1.82 - # Constrain the types to the class's hierarchy.
1.83 -
1.84 - t = self.constrain_self_reference(location.path, class_types, only_instance_types)
1.85 - if t:
1.86 - class_types, only_instance_types, module_types, constrained = t
1.87 - return class_types, only_instance_types, module_types, constrained, have_assignments
1.88 -
1.89 - return class_types, only_instance_types, module_types, False, have_assignments
1.90 + # If the class defining the method does not appear amongst the
1.91 + # types supporting the usage, remove the constrained status of the
1.92 + # name.
1.93 +
1.94 + constrained = constrained and (class_name in class_types or class_name in only_instance_types)
1.95 +
1.96 + return class_types, only_instance_types, module_types, constrained, have_assignments
1.97
1.98 def constrain_self_reference(self, unit_path, class_types, only_instance_types):
1.99
1.100 @@ -1496,6 +1516,18 @@
1.101 if not class_name:
1.102 return None
1.103
1.104 + return self.constrain_to_class(class_name, class_types, only_instance_types)
1.105 +
1.106 + def constrain_to_class(self, class_name, class_types, only_instance_types):
1.107 +
1.108 + """
1.109 + Constrain to 'class_name' and its descendants, the given 'class_types'
1.110 + and 'only_instance_types'.
1.111 +
1.112 + Return the class, instance, module types plus whether the types are
1.113 + constrained.
1.114 + """
1.115 +
1.116 classes = set([class_name])
1.117 classes.update(self.get_descendants_for_class(class_name))
1.118
1.119 @@ -1512,7 +1544,11 @@
1.120
1.121 "Return whether 'path' refers to a method."
1.122
1.123 - class_name, method_name = path.rsplit(".", 1)
1.124 + t = path.rsplit(".", 1)
1.125 + if len(t) == 1:
1.126 + return False
1.127 +
1.128 + class_name, method_name = t
1.129 return class_name != "__builtins__.core.type" and self.importer.classes.has_key(class_name) and class_name
1.130
1.131 def init_reference_details(self, location):
2.1 --- a/lib/__builtins__/mapping.py Mon May 01 23:35:01 2017 +0200
2.2 +++ b/lib/__builtins__/mapping.py Fri Jun 16 00:37:50 2017 +0200
2.3 @@ -71,17 +71,6 @@
2.4
2.5 return index % len(self.buckets)
2.6
2.7 - def _find_entry(self, buckets, key, index):
2.8 -
2.9 - """
2.10 - Search in 'buckets' for 'key', using an 'index' identifying the bucket
2.11 - involved.
2.12 -
2.13 - Method to be overridden by subclasses.
2.14 - """
2.15 -
2.16 - pass
2.17 -
2.18 def _items(self):
2.19
2.20 "Return the values stored in all buckets."
2.21 @@ -103,14 +92,10 @@
2.22 del self.buckets[index][i]
2.23 self.size -= 1
2.24
2.25 - def _resize(self, capacity):
2.26 + # Methods implemented by subclasses:
2.27
2.28 - """
2.29 - Resize the hashtable to have the given 'capacity'.
2.30 - Method to be overridden by subclasses.
2.31 - """
2.32 -
2.33 - pass
2.34 + # _find_entry(self, buckets, key, index)
2.35 + # _resize(self, capacity)
2.36
2.37 # Public special methods.
2.38
3.1 --- a/lib/__builtins__/sequence.py Mon May 01 23:35:01 2017 +0200
3.2 +++ b/lib/__builtins__/sequence.py Fri Jun 16 00:37:50 2017 +0200
3.3 @@ -115,26 +115,6 @@
3.4
3.5 return self.__get_multiple_items__(start, end, step)
3.6
3.7 - # Methods implemented by subclasses.
3.8 -
3.9 - def __setslice__(self, start, end, value):
3.10 -
3.11 - "Method to be overridden by subclasses."
3.12 -
3.13 - pass
3.14 -
3.15 - def __get_single_item__(self, index):
3.16 -
3.17 - "Method to be overridden by subclasses."
3.18 -
3.19 - return None
3.20 -
3.21 - def __set_single_item__(self, index, value):
3.22 -
3.23 - "Method to be overridden by subclasses."
3.24 -
3.25 - pass
3.26 -
3.27 def __get_multiple_items__(self, start, end, step):
3.28
3.29 """
3.30 @@ -150,11 +130,12 @@
3.31
3.32 return result
3.33
3.34 - def __len__(self):
3.35 + # Methods implemented by subclasses:
3.36
3.37 - "Method to be overridden by subclasses."
3.38 -
3.39 - return 0
3.40 + # __setslice__(self, start, end, value)
3.41 + # __get_single_item__(self, index)
3.42 + # __set_single_item__(self, index, value)
3.43 + # __len__(self)
3.44
3.45 class hashable(itemaccess):
3.46
3.47 @@ -270,11 +251,9 @@
3.48
3.49 return not self.__eq__(other)
3.50
3.51 - def __iter__(self):
3.52 + # Methods implemented by subclasses:
3.53
3.54 - "Method to be overridden by subclasses."
3.55 -
3.56 - raise StopIteration()
3.57 + # __iter__(self)
3.58
3.59 def _get_absolute_index(index, length):
3.60