1.1 --- a/importer.py Thu Dec 15 23:50:05 2016 +0100
1.2 +++ b/importer.py Thu Dec 15 23:52:11 2016 +0100
1.3 @@ -445,18 +445,19 @@
1.4 if module.name not in self.required:
1.5 init_item(self.waiting, module.name, set)
1.6 self.waiting[module.name].add(provider)
1.7 + if self.verbose:
1.8 + print >>sys.stderr, "Noting", provider, "for", ref, "from", module.name
1.9
1.10 # Make this module required in the accessing module.
1.11
1.12 elif provider not in self.required:
1.13 self.required.add(provider)
1.14 if self.verbose:
1.15 - print >>sys.stderr, "Requiring", provider, "for", ref
1.16 + print >>sys.stderr, "Requiring", provider, "for", ref, "from", module.name
1.17
1.18 # Record a module ordering dependency.
1.19
1.20 - if not found.static() or self.uses_dynamic_callable(found):
1.21 - self.add_provider(module.name, provider)
1.22 + self.test_dependency(found, module.name, provider)
1.23
1.24 module.deferred = original_deferred
1.25
1.26 @@ -466,6 +467,16 @@
1.27 for module_name in self.waiting.keys():
1.28 self.require_providers(module_name)
1.29
1.30 + def test_dependency(self, ref, module_name, provider):
1.31 +
1.32 + """
1.33 + Test 'ref' for establishing a dependency from 'module_name' to
1.34 + 'provider'.
1.35 + """
1.36 +
1.37 + if not ref.static() or self.uses_dynamic_callable(ref):
1.38 + self.add_provider(module_name, provider)
1.39 +
1.40 def add_provider(self, module_name, provider):
1.41
1.42 "Add a dependency for 'module_name' of 'provider'."
1.43 @@ -488,6 +499,19 @@
1.44 print >>sys.stderr, "Requiring", provider
1.45 self.require_providers(provider)
1.46
1.47 + def uses_callable(self, ref):
1.48 +
1.49 + "Return whether 'ref' refers to a callable."
1.50 +
1.51 + # Find the function or method associated with the reference.
1.52 +
1.53 + if ref.has_kind("<function>"):
1.54 + return ref.get_origin()
1.55 + elif ref.has_kind("<class>"):
1.56 + return "%s.__init__" % ref.get_origin()
1.57 + else:
1.58 + return False
1.59 +
1.60 def uses_dynamic_callable(self, ref):
1.61
1.62 """
1.63 @@ -495,14 +519,12 @@
1.64 need initialising before the callable can be used.
1.65 """
1.66
1.67 - # Find the function or method associated with the reference.
1.68 + origin = self.uses_callable(ref)
1.69 + if not origin:
1.70 + return False
1.71
1.72 - if ref.has_kind("<function>"):
1.73 - origin = ref.get_origin()
1.74 - elif ref.has_kind("<class>"):
1.75 - origin = "%s.__init__" % ref.get_origin()
1.76 - else:
1.77 - return False
1.78 + if ref.has_kind("<class>"):
1.79 + return True
1.80
1.81 # Find any defaults for the function or method.
1.82
1.83 @@ -566,10 +588,35 @@
1.84
1.85 "Check the ordering dependencies."
1.86
1.87 + mutual = set()
1.88 +
1.89 + # Get dependency relationships for each module.
1.90 +
1.91 for module_name, modules in self.depends.items():
1.92 +
1.93 + # Find the reverse relationship.
1.94 +
1.95 for provider in modules:
1.96 if self.depends.has_key(provider) and module_name in self.depends[provider]:
1.97 - raise ProgramError, "Modules %s and %s may not depend on each other for non-static objects." % (module_name, provider)
1.98 +
1.99 + # Record the module names in order.
1.100 +
1.101 + mutual.add((module_name < provider and module_name or provider,
1.102 + module_name > provider and module_name or provider))
1.103 +
1.104 + if not mutual:
1.105 + return
1.106 +
1.107 + # Format the dependencies.
1.108 +
1.109 + mutual = list(mutual)
1.110 + mutual.sort()
1.111 + l = []
1.112 +
1.113 + for module_name, provider in mutual:
1.114 + l.append("(%s <-> %s)" % (module_name, provider))
1.115 +
1.116 + raise ProgramError, "Modules may not depend on each other for non-static objects:\n%s" % "\n".join(l)
1.117
1.118 def find_dependency(self, ref):
1.119