1.1 --- a/importer.py Sun Sep 04 00:08:11 2016 +0200
1.2 +++ b/importer.py Sun Sep 04 17:44:39 2016 +0200
1.3 @@ -51,6 +51,7 @@
1.4 self.verbose = verbose
1.5
1.6 self.to_import = set()
1.7 + self.required = set(["__main__"])
1.8
1.9 self.modules = {}
1.10 self.accessing_modules = {}
1.11 @@ -230,18 +231,22 @@
1.12
1.13 # Module management.
1.14
1.15 - def queue_module(self, name, module):
1.16 + def queue_module(self, name, accessor, required=False):
1.17
1.18 """
1.19 Queue the module with the given 'name' for import from the given
1.20 - 'module'.
1.21 + 'accessor' module. If 'required' is true (it is false by default), the
1.22 + module will be required in the final program.
1.23 """
1.24
1.25 if not self.modules.has_key(name):
1.26 self.to_import.add(name)
1.27
1.28 + if required:
1.29 + self.required.add(name)
1.30 +
1.31 init_item(self.accessing_modules, name, set)
1.32 - self.accessing_modules[name].add(module.name)
1.33 + self.accessing_modules[name].add(accessor.name)
1.34
1.35 def get_modules(self):
1.36
1.37 @@ -285,11 +290,24 @@
1.38
1.39 self.resolve()
1.40
1.41 + # Record the type of all classes.
1.42 +
1.43 + self.type_ref = self.get_object("__builtins__.type")
1.44 +
1.45 # Resolve dependencies within the program.
1.46
1.47 for module in self.modules.values():
1.48 module.complete()
1.49
1.50 + # Remove unneeded modules.
1.51 +
1.52 + all_modules = self.modules.items()
1.53 +
1.54 + for name, module in all_modules:
1.55 + if name not in self.required:
1.56 + module.unpropagate()
1.57 + del self.modules[name]
1.58 +
1.59 return m
1.60
1.61 def finalise(self):
1.62 @@ -318,9 +336,15 @@
1.63 else:
1.64 print >>sys.stderr, "Name %s references an unknown object: %s" % (name, ref.get_origin())
1.65
1.66 + # Record the resolved names and identify required modules.
1.67 +
1.68 for name, ref in resolved.items():
1.69 self.objects[name] = ref
1.70
1.71 + module_name = self.get_module_provider(ref)
1.72 + if module_name:
1.73 + self.required.add(module_name)
1.74 +
1.75 def find_dependency(self, ref):
1.76
1.77 "Find the ultimate dependency for 'ref'."
1.78 @@ -331,6 +355,15 @@
1.79 ref = self.objects.get(ref.get_origin())
1.80 return ref
1.81
1.82 + def get_module_provider(self, ref):
1.83 +
1.84 + "Identify the provider of the given 'ref'."
1.85 +
1.86 + for ancestor in ref.ancestors():
1.87 + if self.modules.has_key(ancestor):
1.88 + return ancestor
1.89 + return None
1.90 +
1.91 def finalise_classes(self):
1.92
1.93 "Finalise the class relationships and attributes."
1.94 @@ -425,9 +458,8 @@
1.95
1.96 "Set the type of each class."
1.97
1.98 - ref = self.get_object("__builtins__.type")
1.99 for attrs in self.all_class_attrs.values():
1.100 - attrs["__class__"] = ref.get_origin()
1.101 + attrs["__class__"] = self.type_ref.get_origin()
1.102
1.103 def define_instantiators(self):
1.104
2.1 --- a/inspector.py Sun Sep 04 00:08:11 2016 +0200
2.2 +++ b/inspector.py Sun Sep 04 17:44:39 2016 +0200
2.3 @@ -645,7 +645,7 @@
2.4 raise InspectError("Imported modules must be aliased unless a simple module is imported.", path, n)
2.5
2.6 self.set_module(alias or name.split(".")[-1], name)
2.7 - self.importer.queue_module(name, self)
2.8 + self.importer.queue_module(name, self, True)
2.9
2.10 def process_invocation_node(self, n):
2.11
3.1 --- a/modules.py Sun Sep 04 00:08:11 2016 +0200
3.2 +++ b/modules.py Sun Sep 04 17:44:39 2016 +0200
3.3 @@ -20,7 +20,7 @@
3.4 this program. If not, see <http://www.gnu.org/licenses/>.
3.5 """
3.6
3.7 -from common import init_item, CommonModule
3.8 +from common import init_item, remove_items, CommonModule
3.9 from encoders import decode_modifier_term, encode_modifiers, encode_usage
3.10 from referencing import decode_reference, Reference
3.11 from results import ResolvedNameRef
3.12 @@ -119,7 +119,6 @@
3.13 for name in self.classes.keys():
3.14 del self.importer.all_class_attrs[name]
3.15 del self.importer.all_instance_attrs[name]
3.16 - del self.importer.all_combined_attrs[name]
3.17 del self.importer.all_instance_attr_constants[name]
3.18
3.19 for name, bases in self.classes.items():
3.20 @@ -147,9 +146,7 @@
3.21 # automatically propagated when defined.
3.22
3.23 for name, ref in self.objects.items():
3.24 - if ref.provided_by_module(self.name) or name in self.importer.hidden:
3.25 - if ref.get_kind() != "<module>":
3.26 - del self.importer.objects[name]
3.27 + del self.importer.objects[name]
3.28
3.29 def propagate_attrs(self):
3.30
4.1 --- a/referencing.py Sun Sep 04 00:08:11 2016 +0200
4.2 +++ b/referencing.py Sun Sep 04 17:44:39 2016 +0200
4.3 @@ -131,19 +131,30 @@
4.4
4.5 return Reference("<var>", None, self.name)
4.6
4.7 - def provided_by_module(self, module_name):
4.8 -
4.9 - "Return whether the reference is provided by 'module_name'."
4.10 -
4.11 - path = self.origin
4.12 - return not path or path.rsplit(".", 1)[0] == module_name
4.13 -
4.14 def alias(self, name):
4.15
4.16 "Alias this reference employing 'name'."
4.17
4.18 return Reference(self.get_kind(), self.get_origin(), name)
4.19
4.20 + def ancestors(self):
4.21 +
4.22 + """
4.23 + Return ancestors of this reference's origin in order of decreasing
4.24 + depth.
4.25 + """
4.26 +
4.27 + if not self.origin:
4.28 + return None
4.29 +
4.30 + parts = self.get_origin().split(".")
4.31 + ancestors = []
4.32 +
4.33 + for i in range(len(parts) - 1, 0, -1):
4.34 + ancestors.append(".".join(parts[:i]))
4.35 +
4.36 + return ancestors
4.37 +
4.38 def decode_reference(s, name=None):
4.39
4.40 "Decode 's', making a reference."