1.1 --- a/importer.py Sat Dec 17 00:33:59 2016 +0100
1.2 +++ b/importer.py Sat Dec 17 01:51:10 2016 +0100
1.3 @@ -66,6 +66,7 @@
1.4 # Object relationships and dependencies.
1.5
1.6 self.depends = {}
1.7 + self.module_depends = {}
1.8
1.9 # Basic program information.
1.10
1.11 @@ -462,7 +463,7 @@
1.12 # Record a module ordering dependency.
1.13
1.14 if not found.static():
1.15 - self.add_dependency(module.name, provider)
1.16 + self.add_module_dependency(module.name, provider)
1.17
1.18 # Restore the original references so that they may be read back in
1.19 # and produce the same results.
1.20 @@ -476,6 +477,7 @@
1.21 self.require_providers(module_name)
1.22
1.23 self.add_special_dependencies()
1.24 + self.add_module_dependencies()
1.25
1.26 def require_providers(self, module_name):
1.27
1.28 @@ -531,14 +533,63 @@
1.29 ref = Reference("<function>", name)
1.30 self.add_dependency(name, ref.parent())
1.31
1.32 + def add_module_dependencies(self):
1.33 +
1.34 + "Record module-based dependencies."
1.35 +
1.36 + for module_name, providers in self.module_depends.items():
1.37 + if self.modules.has_key(module_name):
1.38 + for provider in providers:
1.39 + if self.modules.has_key(provider):
1.40 + self.add_dependency(module_name, provider)
1.41 +
1.42 def add_dependency(self, path, origin):
1.43
1.44 "Add dependency details for 'path' involving 'origin'."
1.45
1.46 - if origin:
1.47 + if origin and not origin.startswith("%s." % path):
1.48 init_item(self.depends, path, set)
1.49 self.depends[path].add(origin)
1.50
1.51 + def add_module_dependency(self, module_name, provider):
1.52 +
1.53 + "Add dependency details for 'module_name' involving 'provider'."
1.54 +
1.55 + if provider:
1.56 + init_item(self.module_depends, module_name, set)
1.57 + self.module_depends[module_name].add(provider)
1.58 +
1.59 + def condense_dependencies(self):
1.60 +
1.61 + """
1.62 + Condense the dependencies by removing all functions that do not need
1.63 + initialisation.
1.64 + """
1.65 +
1.66 + d = {}
1.67 + for path, depends in self.depends.items():
1.68 + d[path] = {}
1.69 + d[path] = self.condense_dependency_entry(depends, d)
1.70 +
1.71 + self.depends = {}
1.72 +
1.73 + for path, depends in d.items():
1.74 + if depends:
1.75 + self.depends[path] = depends
1.76 +
1.77 + def condense_dependency_entry(self, depends, d):
1.78 + l = set()
1.79 + for depend in depends:
1.80 + if self.modules.has_key(depend) or self.classes.has_key(depend) or \
1.81 + self.is_dynamic_callable(depend):
1.82 +
1.83 + l.add(depend)
1.84 + else:
1.85 + deps = d.get(depend)
1.86 + if deps:
1.87 + l.update(self.condense_dependency_entry(deps, d))
1.88 + return l
1.89 +
1.90 # NOTE: Consolidate this information in a common location.
1.91
1.92 special_attributes = ("__args__", "__file__", "__fn__", "__fname__", "__mname__", "__name__")
1.93 @@ -579,7 +630,7 @@
1.94 # Identify non-constant defaults.
1.95
1.96 for name, ref in defaults:
1.97 - if not ref.is_constant_alias():
1.98 + if not ref.static() and not ref.is_constant_alias():
1.99 return True
1.100
1.101 return False
1.102 @@ -588,17 +639,21 @@
1.103
1.104 "Produce an object initialisation ordering."
1.105
1.106 + self.condense_dependencies()
1.107 +
1.108 # Record the number of modules using or depending on each module.
1.109
1.110 usage = {}
1.111
1.112 + # Record path-based dependencies.
1.113 +
1.114 for path in self.depends.keys():
1.115 - usage[path] = 0
1.116 + usage[path] = set()
1.117
1.118 for path, depends in self.depends.items():
1.119 for origin in depends:
1.120 - init_item(usage, origin, lambda: 0)
1.121 - usage[origin] += 1
1.122 + init_item(usage, origin, set)
1.123 + usage[origin].add(path)
1.124
1.125 # Produce an ordering by obtaining exposed modules (required by modules
1.126 # already processed) and putting them at the start of the list.
1.127 @@ -609,7 +664,7 @@
1.128 have_next = False
1.129
1.130 for path, n in usage.items():
1.131 - if n == 0:
1.132 + if not n:
1.133 ordered.insert(0, path)
1.134 depends = self.depends.get(path)
1.135
1.136 @@ -617,7 +672,7 @@
1.137
1.138 if depends:
1.139 for origin in depends:
1.140 - usage[origin] -= 1
1.141 + usage[origin].remove(path)
1.142
1.143 del usage[path]
1.144 have_next = True