def test_getqualifiedname_cycles(self): foo = object() # We create a graph of modules that contains circular references. The # search process should avoid them. The searched object is hidden at the # bottom of a path of length roughly 10. ns = {} mods = [] for i in range(10): mod = imp.new_module('mod_{}'.format(i)) if i == 9: mod.foo = foo # Module i refers to module i+1 if mods: mods[-1].__dict__[mod.__name__] = mod else: ns[mod.__name__] = mod # Module i refers to all modules j < i. for prev in mods: mod.__dict__[prev.__name__] = prev mods.append(mod) self.assertIsNone(inspect_utils.getqualifiedname(ns, inspect_utils)) self.assertIsNotNone( inspect_utils.getqualifiedname(ns, foo, max_depth=10000000000))
def test_getqualifiedname_efficiency(self): foo = object() # We create a densely connected graph consisting of a relatively small # number of modules and hide our symbol in one of them. The path to the # symbol is at least 10, and each node has about 10 neighbors. However, # by skipping visited modules, the search should take much less. ns = {} prev_level = [] for i in range(10): current_level = [] for j in range(10): mod_name = 'mod_{}_{}'.format(i, j) mod = imp.new_module(mod_name) current_level.append(mod) if i == 9 and j == 9: mod.foo = foo if prev_level: # All modules at level i refer to all modules at level i+1 for prev in prev_level: for mod in current_level: prev.__dict__[mod.__name__] = mod else: for mod in current_level: ns[mod.__name__] = mod prev_level = current_level self.assertIsNone(inspect_utils.getqualifiedname(ns, inspect_utils)) self.assertIsNotNone( inspect_utils.getqualifiedname(ns, foo, max_depth=10000000000))
def test_getqualifiedname_finds_via_parent_module(self): # TODO(mdan): This test is vulnerable to change in the lib module. # A better way to forge modules should be found. self.assertEqual( inspect_utils.getqualifiedname( lib.__dict__, lib.io.file_io.FileIO, max_depth=1), 'io.file_io.FileIO')
def test_getqualifiedname(self): foo = object() qux = imp.new_module('quxmodule') bar = imp.new_module('barmodule') baz = object() bar.baz = baz ns = { 'foo': foo, 'bar': bar, 'qux': qux, } self.assertIsNone(inspect_utils.getqualifiedname(ns, inspect_utils)) self.assertEqual(inspect_utils.getqualifiedname(ns, foo), 'foo') self.assertEqual(inspect_utils.getqualifiedname(ns, bar), 'bar') self.assertEqual(inspect_utils.getqualifiedname(ns, baz), 'bar.baz')
def as_qualified_name(o): name = inspect_utils.getqualifiedname(ctx.info.namespace, o, max_depth=1) if not name: # TODO(mdan): This needs to account for the symbols defined locally. name = ctx.namer.new_symbol(o.__name__, ()) ctx.program.add_symbol(name, weakref.ref(o)) return name
def as_qualified_name(o): name = inspect_utils.getqualifiedname(ctx.info.namespace, o, max_depth=1) if not name: if isinstance(o, weakref.ref): # `o` might already be a weak reference, if this object was # constructed from code generated by `to_ast` itself. # If so, unpack it. o = o() # TODO(mdan): This needs to account for the symbols defined locally. name = ctx.namer.new_symbol(o.__name__, ()) ctx.program.add_symbol(name, weakref.ref(o)) return name
def as_qualified_name(o): name = inspect_utils.getqualifiedname(namespace, o) if not name: raise ValueError('Could not locate entity {} in {}'.format( o, namespace)) return name