2 from modulegraph
import modulegraph
9 from altgraph
import Graph
11 import xml
.etree
.ElementTree
as ET
20 from StringIO
import StringIO
22 from io
import StringIO
24 TESTDATA
= os
.path
.join(
25 os
.path
.dirname(os
.path
.abspath(__file__
)),
29 expectedFailure
= unittest
.expectedFailure
30 except AttributeError:
32 def expectedFailure(function
):
33 @functools.wraps(function
)
34 def wrapper(*args
, **kwds
):
36 function(*args
, **kwds
)
37 except AssertionError:
41 self
.fail("unexpected pass")
43 class TestDependencyInfo (unittest
.TestCase
):
44 def test_pickling(self
):
45 info
= modulegraph
.DependencyInfo(function
=True, conditional
=False, tryexcept
=True, fromlist
=False)
46 for proto
in range(pickle
.HIGHEST_PROTOCOL
+ 1):
47 b
= pickle
.dumps(info
, proto
)
48 self
.assertTrue(isinstance(b
, bytes
))
51 self
.assertEqual(o
, info
)
53 def test_merging(self
):
54 info1
= modulegraph
.DependencyInfo(function
=True, conditional
=False, tryexcept
=True, fromlist
=False)
55 info2
= modulegraph
.DependencyInfo(function
=False, conditional
=True, tryexcept
=True, fromlist
=False)
57 info1
._merged(info2
), modulegraph
.DependencyInfo(function
=True, conditional
=True, tryexcept
=True, fromlist
=False))
59 info2
= modulegraph
.DependencyInfo(function
=False, conditional
=True, tryexcept
=False, fromlist
=False)
61 info1
._merged(info2
), modulegraph
.DependencyInfo(function
=True, conditional
=True, tryexcept
=True, fromlist
=False))
63 info2
= modulegraph
.DependencyInfo(function
=False, conditional
=False, tryexcept
=False, fromlist
=False)
65 info1
._merged(info2
), modulegraph
.DependencyInfo(function
=False, conditional
=False, tryexcept
=False, fromlist
=False))
67 info1
= modulegraph
.DependencyInfo(function
=True, conditional
=False, tryexcept
=True, fromlist
=True)
69 info1
._merged(info2
), modulegraph
.DependencyInfo(function
=False, conditional
=False, tryexcept
=False, fromlist
=False))
71 info2
= modulegraph
.DependencyInfo(function
=False, conditional
=False, tryexcept
=False, fromlist
=True)
73 info1
._merged(info2
), modulegraph
.DependencyInfo(function
=False, conditional
=False, tryexcept
=False, fromlist
=True))
76 class TestFunctions (unittest
.TestCase
):
77 if not hasattr(unittest
.TestCase
, 'assertIsInstance'):
78 def assertIsInstance(self
, obj
, types
):
79 self
.assertTrue(isinstance(obj
, types
), '%r is not instance of %r'%(obj
, types
))
81 def test_eval_str_tuple(self
):
88 "('hello', \"world\")",
91 self
.assertEqual(modulegraph
._eval
_str
_tuple
(v
), eval(v
))
93 self
.assertRaises(ValueError, modulegraph
._eval
_str
_tuple
, "")
94 self
.assertRaises(ValueError, modulegraph
._eval
_str
_tuple
, "'a'")
95 self
.assertRaises(ValueError, modulegraph
._eval
_str
_tuple
, "'a', 'b'")
96 self
.assertRaises(ValueError, modulegraph
._eval
_str
_tuple
, "('a', ('b', 'c'))")
97 self
.assertRaises(ValueError, modulegraph
._eval
_str
_tuple
, "('a', ('b\", 'c'))")
99 def test_namespace_package_path(self
):
101 def __init__(self
, path
, namespace_packages
=None):
103 self
._namespace
_packages
= namespace_packages
105 def has_metadata(self
, key
):
106 if key
== 'namespace_packages.txt':
107 return self
._namespace
_packages
is not None
109 raise ValueError("invalid lookup key")
111 def get_metadata(self
, key
):
112 if key
== 'namespace_packages.txt':
113 if self
._namespace
_packages
is None:
114 raise ValueError("no file")
116 return self
._namespace
_packages
118 raise ValueError("invalid lookup key")
121 def __init__(self
, path
=None):
125 yield DS("/pkg/pkg1")
126 yield DS("/pkg/pkg2", "foo\n")
127 yield DS("/pkg/pkg3", "bar.baz\n")
128 yield DS("/pkg/pkg4", "foobar\nfoo\n")
130 saved_ws
= pkg_resources
.WorkingSet
132 pkg_resources
.WorkingSet
= WS
134 self
.assertEqual(modulegraph
._namespace
_package
_path
("sys", ["appdir/pkg"]), ["appdir/pkg"])
135 self
.assertEqual(modulegraph
._namespace
_package
_path
("foo", ["appdir/pkg"]), ["appdir/pkg", "/pkg/pkg2/foo", "/pkg/pkg4/foo"])
136 self
.assertEqual(modulegraph
._namespace
_package
_path
("bar.baz", ["appdir/pkg"]), ["appdir/pkg", "/pkg/pkg3/bar/baz"])
139 pkg_resources
.WorkingSet
= saved_ws
141 def test_os_listdir(self
):
143 os
.path
.dirname(os
.path
.abspath(__file__
)), 'testdata')
145 self
.assertEqual(modulegraph
.os_listdir('/etc/'), os
.listdir('/etc'))
146 self
.assertRaises(IOError, modulegraph
.os_listdir
, '/etc/hosts/foobar')
147 self
.assertRaises(IOError, modulegraph
.os_listdir
, os
.path
.join(root
, 'test.egg', 'bar'))
149 self
.assertEqual(list(sorted(modulegraph
.os_listdir(os
.path
.join(root
, 'test.egg', 'foo')))),
150 [ 'bar', 'bar.txt', 'baz.txt' ])
152 def test_code_to_file(self
):
154 code
= modulegraph
._code
_to
_file
.__code
__
155 except AttributeError:
156 code
= modulegraph
._code
_to
_file
.func_code
158 data
= modulegraph
._code
_to
_file
(code
)
159 self
.assertTrue(hasattr(data
, 'read'))
161 content
= data
.read()
162 self
.assertIsInstance(content
, bytes
)
165 def test_find_module(self
):
166 for path
in ('syspath', 'syspath.zip', 'syspath.egg'):
167 path
= os
.path
.join(os
.path
.dirname(TESTDATA
), path
)
168 if os
.path
.exists(os
.path
.join(path
, 'mymodule.pyc')):
169 os
.unlink(os
.path
.join(path
, 'mymodule.pyc'))
172 info
= modulegraph
.find_module('mymodule', path
=[path
] + sys
.path
)
176 description
= info
[2]
178 self
.assertTrue(hasattr(fp
, 'read'))
180 if path
.endswith('.zip') or path
.endswith('.egg'):
181 # Zip importers may precompile
182 if filename
.endswith('.py'):
183 self
.assertEqual(filename
, os
.path
.join(path
, 'mymodule.py'))
184 self
.assertEqual(description
, ('.py', 'rU', imp
.PY_SOURCE
))
187 self
.assertEqual(filename
, os
.path
.join(path
, 'mymodule.pyc'))
188 self
.assertEqual(description
, ('.pyc', 'rb', imp
.PY_COMPILED
))
191 self
.assertEqual(filename
, os
.path
.join(path
, 'mymodule.py'))
192 self
.assertEqual(description
, ('.py', 'rU', imp
.PY_SOURCE
))
194 # Compiled plain module, no source
195 if path
.endswith('.zip') or path
.endswith('.egg'):
196 self
.assertRaises(ImportError, modulegraph
.find_module
, 'mymodule2', path
=[path
] + sys
.path
)
199 info
= modulegraph
.find_module('mymodule2', path
=[path
] + sys
.path
)
203 description
= info
[2]
205 self
.assertTrue(hasattr(fp
, 'read'))
206 self
.assertEqual(filename
, os
.path
.join(path
, 'mymodule2.pyc'))
207 self
.assertEqual(description
, ('.pyc', 'rb', imp
.PY_COMPILED
))
211 # Compiled plain module, with source
212 # info = modulegraph.find_module('mymodule3', path=[path] + sys.path)
216 # description = info[2]
218 # self.assertTrue(hasattr(fp, 'read'))
220 # if sys.version_info[:2] >= (3,2):
221 # self.assertEqual(filename, os.path.join(path, '__pycache__', 'mymodule3.cpython-32.pyc'))
223 # self.assertEqual(filename, os.path.join(path, 'mymodule3.pyc'))
224 # self.assertEqual(description, ('.pyc', 'rb', imp.PY_COMPILED))
228 info
= modulegraph
.find_module('mypkg', path
=[path
] + sys
.path
)
231 description
= info
[2]
233 self
.assertEqual(fp
, None)
234 self
.assertEqual(filename
, os
.path
.join(path
, 'mypkg'))
235 self
.assertEqual(description
, ('', '', imp
.PKG_DIRECTORY
))
238 if path
.endswith('.zip'):
239 self
.assertRaises(ImportError, modulegraph
.find_module
, 'myext', path
=[path
] + sys
.path
)
242 info
= modulegraph
.find_module('myext', path
=[path
] + sys
.path
)
245 description
= info
[2]
247 if sys
.platform
== 'win32':
250 # This is a ly, but is good enough for now
253 self
.assertEqual(filename
, os
.path
.join(path
, 'myext' + ext
))
254 self
.assertEqual(description
, (ext
, 'rb', imp
.C_EXTENSION
))
255 self
.assertEqual(fp
, None)
257 def test_moduleInfoForPath(self
):
258 self
.assertEqual(modulegraph
.moduleInfoForPath("/somewhere/else/file.txt"), None)
260 info
= modulegraph
.moduleInfoForPath("/somewhere/else/file.py")
261 self
.assertEqual(info
[0], "file")
262 if sys
.version_info
[:2] >= (3,4):
263 self
.assertEqual(info
[1], "r")
265 self
.assertEqual(info
[1], "U")
266 self
.assertEqual(info
[2], imp
.PY_SOURCE
)
268 info
= modulegraph
.moduleInfoForPath("/somewhere/else/file.pyc")
269 self
.assertEqual(info
[0], "file")
270 self
.assertEqual(info
[1], "rb")
271 self
.assertEqual(info
[2], imp
.PY_COMPILED
)
273 if sys
.platform
in ('darwin', 'linux2'):
274 info
= modulegraph
.moduleInfoForPath("/somewhere/else/file.so")
275 self
.assertEqual(info
[0], "file")
276 self
.assertEqual(info
[1], "rb")
277 self
.assertEqual(info
[2], imp
.C_EXTENSION
)
279 elif sys
.platform
in ('win32',):
280 info
= modulegraph
.moduleInfoForPath("/somewhere/else/file.pyd")
281 self
.assertEqual(info
[0], "file")
282 self
.assertEqual(info
[1], "rb")
283 self
.assertEqual(info
[2], imp
.C_EXTENSION
)
285 if sys
.version_info
[:2] > (2,5):
286 exec(textwrap
.dedent('''\
287 def test_deprecated(self):
288 saved_add = modulegraph.addPackagePath
289 saved_replace = modulegraph.replacePackage
293 def log_add(*args, **kwds):
294 called.append(('add', args, kwds))
295 def log_replace(*args, **kwds):
296 called.append(('replace', args, kwds))
298 modulegraph.addPackagePath = log_add
299 modulegraph.replacePackage = log_replace
301 with warnings.catch_warnings(record=True) as w:
302 warnings.simplefilter("always")
303 modulegraph.ReplacePackage('a', 'b')
304 modulegraph.AddPackagePath('c', 'd')
306 self.assertEqual(len(w), 2)
307 self.assertTrue(w[-1].category is DeprecationWarning)
308 self.assertTrue(w[-2].category is DeprecationWarning)
310 self.assertEqual(called, [
311 ('replace', ('a', 'b'), {}),
312 ('add', ('c', 'd'), {}),
316 modulegraph.addPackagePath = saved_add
317 modulegraph.replacePackage = saved_replace
318 '''), locals(), globals())
320 def test_addPackage(self
):
321 saved
= modulegraph
._packagePathMap
322 self
.assertIsInstance(saved
, dict)
324 modulegraph
._packagePathMap
= {}
326 modulegraph
.addPackagePath('foo', 'a')
327 self
.assertEqual(modulegraph
._packagePathMap
, { 'foo': ['a'] })
329 modulegraph
.addPackagePath('foo', 'b')
330 self
.assertEqual(modulegraph
._packagePathMap
, { 'foo': ['a', 'b'] })
332 modulegraph
.addPackagePath('bar', 'b')
333 self
.assertEqual(modulegraph
._packagePathMap
, { 'foo': ['a', 'b'], 'bar': ['b'] })
336 modulegraph
._packagePathMap
= saved
339 def test_replacePackage(self
):
340 saved
= modulegraph
._replacePackageMap
341 self
.assertIsInstance(saved
, dict)
343 modulegraph
._replacePackageMap
= {}
345 modulegraph
.replacePackage("a", "b")
346 self
.assertEqual(modulegraph
._replacePackageMap
, {"a": "b"})
347 modulegraph
.replacePackage("a", "c")
348 self
.assertEqual(modulegraph
._replacePackageMap
, {"a": "c"})
349 modulegraph
.replacePackage("b", "c")
350 self
.assertEqual(modulegraph
._replacePackageMap
, {"a": "c", 'b': 'c'})
353 modulegraph
._replacePackageMap
= saved
355 class TestNode (unittest
.TestCase
):
356 if not hasattr(unittest
.TestCase
, 'assertIsInstance'):
357 def assertIsInstance(self
, obj
, types
):
358 self
.assertTrue(isinstance(obj
, types
), '%r is not instance of %r'%(obj
, types
))
359 def testBasicAttributes(self
):
360 n
= modulegraph
.Node("foobar.xyz")
361 self
.assertIsInstance(n
.debug
, int)
362 self
.assertEqual(n
.identifier
, n
.graphident
)
363 self
.assertEqual(n
.identifier
, 'foobar.xyz')
364 self
.assertEqual(n
.filename
, None)
365 self
.assertEqual(n
.packagepath
, None)
366 self
.assertEqual(n
.code
, None)
367 self
.assertEqual(n
.globalnames
, set())
368 self
.assertEqual(n
.starimports
, set())
370 def testMapping(self
):
371 n
= modulegraph
.Node("foobar.xyz")
372 self
.assertEqual(n
._namespace
, {})
374 self
.assertFalse('foo' in n
)
375 self
.assertRaises(KeyError, n
.__getitem
__, 'foo')
376 self
.assertEqual(n
.get('foo'), None)
377 self
.assertEqual(n
.get('foo', 'a'), 'a')
379 self
.assertEqual(n
['foo'], 42)
380 self
.assertTrue('foo' in n
)
381 self
.assertEqual(n
._namespace
, {'foo':42})
384 n1
= modulegraph
.Node("n1")
385 n2
= modulegraph
.Node("n2")
387 self
.assertTrue(n1
< n2
)
388 self
.assertFalse(n2
< n1
)
389 self
.assertTrue(n1
<= n1
)
390 self
.assertFalse(n1
== n2
)
391 self
.assertTrue(n1
== n1
)
392 self
.assertTrue(n1
!= n2
)
393 self
.assertFalse(n1
!= n1
)
394 self
.assertTrue(n2
> n1
)
395 self
.assertFalse(n1
> n2
)
396 self
.assertTrue(n1
>= n1
)
397 self
.assertTrue(n2
>= n1
)
399 def testHashing(self
):
400 n1a
= modulegraph
.Node('n1')
401 n1b
= modulegraph
.Node('n1')
402 n2
= modulegraph
.Node('n2')
407 self
.assertEqual(d
[n1b
], 'n1')
408 self
.assertEqual(d
[n2
], 'n2')
410 def test_infoTuple(self
):
411 n
= modulegraph
.Node('n1')
412 self
.assertEqual(n
.infoTuple(), ('n1',))
414 def assertNoMethods(self
, klass
):
415 d
= dict(klass
.__dict
__)
418 if '__qualname__' in d
:
420 del d
['__qualname__']
424 self
.assertEqual(d
, {})
426 def assertHasExactMethods(self
, klass
, *methods
):
427 d
= dict(klass
.__dict
__)
430 if '__qualname__' in d
:
432 del d
['__qualname__']
438 self
.assertTrue(nm
in d
, "%s doesn't have attribute %r"%(klass
, nm
))
441 self
.assertEqual(d
, {})
444 if not hasattr(unittest
.TestCase
, 'assertIsSubclass'):
445 def assertIsSubclass(self
, cls1
, cls2
, message
=None):
446 self
.assertTrue(issubclass(cls1
, cls2
),
447 message
or "%r is not a subclass of %r"%(cls1
, cls2
))
449 def test_subclasses(self
):
450 self
.assertIsSubclass(modulegraph
.AliasNode
, modulegraph
.Node
)
451 self
.assertIsSubclass(modulegraph
.Script
, modulegraph
.Node
)
452 self
.assertIsSubclass(modulegraph
.BadModule
, modulegraph
.Node
)
453 self
.assertIsSubclass(modulegraph
.ExcludedModule
, modulegraph
.BadModule
)
454 self
.assertIsSubclass(modulegraph
.MissingModule
, modulegraph
.BadModule
)
455 self
.assertIsSubclass(modulegraph
.BaseModule
, modulegraph
.Node
)
456 self
.assertIsSubclass(modulegraph
.BuiltinModule
, modulegraph
.BaseModule
)
457 self
.assertIsSubclass(modulegraph
.SourceModule
, modulegraph
.BaseModule
)
458 self
.assertIsSubclass(modulegraph
.CompiledModule
, modulegraph
.BaseModule
)
459 self
.assertIsSubclass(modulegraph
.Package
, modulegraph
.BaseModule
)
460 self
.assertIsSubclass(modulegraph
.Extension
, modulegraph
.BaseModule
)
462 # These classes have no new functionality, check that no code
464 self
.assertNoMethods(modulegraph
.BadModule
)
465 self
.assertNoMethods(modulegraph
.ExcludedModule
)
466 self
.assertNoMethods(modulegraph
.MissingModule
)
467 self
.assertNoMethods(modulegraph
.BuiltinModule
)
468 self
.assertNoMethods(modulegraph
.SourceModule
)
469 self
.assertNoMethods(modulegraph
.CompiledModule
)
470 self
.assertNoMethods(modulegraph
.Package
)
471 self
.assertNoMethods(modulegraph
.Extension
)
473 # AliasNode is basicly a clone of an existing node
474 self
.assertHasExactMethods(modulegraph
.Script
, '__init__', 'infoTuple')
475 n1
= modulegraph
.Node('n1')
476 n1
.packagepath
= ['a', 'b']
478 a1
= modulegraph
.AliasNode('a1', n1
)
479 self
.assertEqual(a1
.graphident
, 'a1')
480 self
.assertEqual(a1
.identifier
, 'n1')
481 self
.assertTrue(a1
.packagepath
is n1
.packagepath
)
482 self
.assertTrue(a1
._namespace
is n1
._namespace
)
483 self
.assertTrue(a1
.globalnames
is n1
.globalnames
)
484 self
.assertTrue(a1
.starimports
is n1
.starimports
)
487 self
.assertEqual(v
, ('a1', 'n1'))
489 # Scripts have a filename
490 self
.assertHasExactMethods(modulegraph
.Script
, '__init__', 'infoTuple')
491 s1
= modulegraph
.Script('do_import')
492 self
.assertEqual(s1
.graphident
, 'do_import')
493 self
.assertEqual(s1
.identifier
, 'do_import')
494 self
.assertEqual(s1
.filename
, 'do_import')
497 self
.assertEqual(v
, ('do_import',))
499 # BaseModule adds some attributes and a custom infotuple
500 self
.assertHasExactMethods(modulegraph
.BaseModule
, '__init__', 'infoTuple')
501 m1
= modulegraph
.BaseModule('foo')
502 self
.assertEqual(m1
.graphident
, 'foo')
503 self
.assertEqual(m1
.identifier
, 'foo')
504 self
.assertEqual(m1
.filename
, None)
505 self
.assertEqual(m1
.packagepath
, None)
507 m1
= modulegraph
.BaseModule('foo', 'bar', ['a'])
508 self
.assertEqual(m1
.graphident
, 'foo')
509 self
.assertEqual(m1
.identifier
, 'foo')
510 self
.assertEqual(m1
.filename
, 'bar')
511 self
.assertEqual(m1
.packagepath
, ['a'])
513 class TestModuleGraph (unittest
.TestCase
):
514 # Test for class modulegraph.modulegraph.ModuleGraph
515 if not hasattr(unittest
.TestCase
, 'assertIsInstance'):
516 def assertIsInstance(self
, obj
, types
):
517 self
.assertTrue(isinstance(obj
, types
), '%r is not instance of %r'%(obj
, types
))
519 def test_constructor(self
):
520 o
= modulegraph
.ModuleGraph()
521 self
.assertTrue(o
.path
is sys
.path
)
522 self
.assertEqual(o
.lazynodes
, {})
523 self
.assertEqual(o
.replace_paths
, ())
524 self
.assertEqual(o
.debug
, 0)
526 # Stricter tests would be nice, but that requires
527 # better control over what's on sys.path
528 self
.assertIsInstance(o
.nspackages
, dict)
531 o
= modulegraph
.ModuleGraph(['a', 'b', 'c'], ['modA'], [
532 ('fromA', 'toB'), ('fromC', 'toD')],
534 'modA': ['modB', 'modC'],
535 'modC': ['modE', 'modF'],
537 self
.assertEqual(o
.path
, ['a', 'b', 'c'])
538 self
.assertEqual(o
.lazynodes
, {
540 'modC': ['modE', 'modF'],
542 self
.assertEqual(o
.replace_paths
, [('fromA', 'toB'), ('fromC', 'toD')])
543 self
.assertEqual(o
.nspackages
, {})
544 self
.assertTrue(o
.graph
is g
)
545 self
.assertEqual(o
.debug
, 1)
547 def test_calc_setuptools_nspackages(self
):
548 stdlib
= [ fn
for fn
in sys
.path
if fn
.startswith(sys
.prefix
) and 'site-packages' not in fn
]
549 for subdir
in [ nm
for nm
in os
.listdir(TESTDATA
) if nm
!= 'src' ]:
550 graph
= modulegraph
.ModuleGraph(path
=[
551 os
.path
.join(TESTDATA
, subdir
, "parent"),
552 os
.path
.join(TESTDATA
, subdir
, "child"),
555 pkgs
= graph
.nspackages
556 self
.assertTrue('namedpkg' in pkgs
)
557 self
.assertEqual(set(pkgs
['namedpkg']),
559 os
.path
.join(TESTDATA
, subdir
, "parent", "namedpkg"),
560 os
.path
.join(TESTDATA
, subdir
, "child", "namedpkg"),
562 self
.assertFalse(os
.path
.exists(os
.path
.join(TESTDATA
, subdir
, "parent", "namedpkg", "__init__.py")))
563 self
.assertFalse(os
.path
.exists(os
.path
.join(TESTDATA
, subdir
, "child", "namedpkg", "__init__.py")))
565 def testImpliedReference(self
):
566 graph
= modulegraph
.ModuleGraph()
569 def import_hook(*args
):
570 record
.append(('import_hook',) + args
)
571 return [graph
.createNode(modulegraph
.Node
, args
[0])]
573 def _safe_import_hook(*args
):
574 record
.append(('_safe_import_hook',) + args
)
575 return [graph
.createNode(modulegraph
.Node
, args
[0])]
577 graph
.import_hook
= import_hook
578 graph
._safe
_import
_hook
= _safe_import_hook
580 n1
= graph
.createNode(modulegraph
.Node
, 'n1')
581 n2
= graph
.createNode(modulegraph
.Node
, 'n2')
583 graph
.implyNodeReference(n1
, n2
)
584 outs
, ins
= map(list, graph
.get_edges(n1
))
585 self
.assertEqual(outs
, [n2
])
586 self
.assertEqual(ins
, [])
588 self
.assertEqual(record
, [])
590 graph
.implyNodeReference(n2
, "n3")
591 n3
= graph
.findNode('n3')
592 outs
, ins
= map(list, graph
.get_edges(n2
))
593 self
.assertEqual(outs
, [n3
])
594 self
.assertEqual(ins
, [n1
])
595 self
.assertEqual(record
, [
596 ('_safe_import_hook', 'n3', n2
, None)
602 def test_findNode(self
):
603 self
.fail("findNode")
605 def test_run_script(self
):
606 script
= os
.path
.join(os
.path
.dirname(TESTDATA
), 'script')
608 graph
= modulegraph
.ModuleGraph()
609 master
= graph
.createNode(modulegraph
.Node
, 'root')
610 m
= graph
.run_script(script
, master
)
611 self
.assertEqual(list(graph
.get_edges(master
)[0])[0], m
)
612 self
.assertEqual(set(graph
.get_edges(m
)[0]), set([
613 graph
.findNode('sys'),
614 graph
.findNode('os'),
618 def test_import_hook(self
):
619 self
.fail("import_hook")
621 def test_determine_parent(self
):
622 graph
= modulegraph
.ModuleGraph()
623 graph
.import_hook('os.path', None)
624 graph
.import_hook('idlelib', None)
625 graph
.import_hook('xml.dom', None)
627 for node
in graph
.nodes():
628 if isinstance(node
, modulegraph
.Package
):
631 self
.fail("No package located, should have at least 'os'")
633 self
.assertIsInstance(node
, modulegraph
.Package
)
634 parent
= graph
._determine
_parent
(node
)
635 self
.assertEqual(parent
.identifier
, node
.identifier
)
636 self
.assertEqual(parent
, graph
.findNode(node
.identifier
))
637 self
.assertTrue(isinstance(parent
, modulegraph
.Package
))
639 # XXX: Might be a usecase for some odd code in determine_parent...
640 #node = modulegraph.Package('encodings')
641 #node.packagepath = parent.packagepath
642 #m = graph._determine_parent(node)
643 #self.assertTrue(m is parent)
645 m
= graph
.findNode('xml')
646 self
.assertEqual(graph
._determine
_parent
(m
), m
)
648 m
= graph
.findNode('xml.dom')
649 self
.assertEqual(graph
._determine
_parent
(m
), graph
.findNode('xml.dom'))
653 def test_find_head_package(self
):
654 self
.fail("find_head_package")
656 def test_load_tail(self
):
657 # XXX: This test is dodgy!
658 graph
= modulegraph
.ModuleGraph()
661 def _import_module(partname
, fqname
, parent
):
662 record
.append((partname
, fqname
, parent
))
663 if partname
== 'raises' or '.raises.' in fqname
:
665 return modulegraph
.Node(fqname
)
667 graph
._import
_module
= _import_module
670 root
= modulegraph
.Node('root')
671 m
= graph
._load
_tail
(root
, '')
672 self
.assertTrue(m
is root
)
673 self
.assertEqual(record
, [
677 root
= modulegraph
.Node('root')
678 m
= graph
._load
_tail
(root
, 'sub')
679 self
.assertFalse(m
is root
)
680 self
.assertEqual(record
, [
681 ('sub', 'root.sub', root
),
685 root
= modulegraph
.Node('root')
686 m
= graph
._load
_tail
(root
, 'sub.sub1')
687 self
.assertFalse(m
is root
)
688 node
= modulegraph
.Node('root.sub')
689 self
.assertEqual(record
, [
690 ('sub', 'root.sub', root
),
691 ('sub1', 'root.sub.sub1', node
),
695 root
= modulegraph
.Node('root')
696 m
= graph
._load
_tail
(root
, 'sub.sub1.sub2')
697 self
.assertFalse(m
is root
)
698 node
= modulegraph
.Node('root.sub')
699 node2
= modulegraph
.Node('root.sub.sub1')
700 self
.assertEqual(record
, [
701 ('sub', 'root.sub', root
),
702 ('sub1', 'root.sub.sub1', node
),
703 ('sub2', 'root.sub.sub1.sub2', node2
),
706 n
= graph
._load
_tail
(root
, 'raises')
707 self
.assertIsInstance(n
, modulegraph
.MissingModule
)
708 self
.assertEqual(n
.identifier
, 'root.raises')
710 n
= graph
._load
_tail
(root
, 'sub.raises')
711 self
.assertIsInstance(n
, modulegraph
.MissingModule
)
712 self
.assertEqual(n
.identifier
, 'root.sub.raises')
714 n
= graph
._load
_tail
(root
, 'sub.raises.sub')
715 self
.assertIsInstance(n
, modulegraph
.MissingModule
)
716 self
.assertEqual(n
.identifier
, 'root.sub.raises.sub')
721 def test_ensure_fromlist(self
):
722 # 1. basic 'from module import name, name'
723 # 2. 'from module import *'
724 # 3. from module import os
725 # (where 'os' is not a name in 'module',
726 # should create MissingModule node, and
727 # should *not* refer to the global os)
728 self
.fail("ensure_fromlist")
731 def test_find_all_submodules(self
):
733 # 2. no packagepath (basic module)
734 # 3. extensions, python modules
735 # 4. with/without zipfile
736 # 5. files that aren't python modules/extensions
737 self
.fail("find_all_submodules")
740 def test_import_module(self
):
741 self
.fail("import_module")
744 def test_load_module(self
):
745 self
.fail("load_module")
748 def test_safe_import_hook(self
):
749 self
.fail("safe_import_hook")
752 def test_scan_code(self
):
753 mod
= modulegraph
.Node('root')
755 graph
= modulegraph
.ModuleGraph()
756 code
= compile('', '<test>', 'exec', 0, False)
757 graph
.scan_code(code
, mod
)
758 self
.assertEqual(list(graph
.nodes()), [])
761 def _safe_import(name
, mod
, fromlist
, level
):
763 node
= node_map
[name
]
765 node
= modulegraph
.Node(name
)
766 node_map
[name
] = node
769 graph
= modulegraph
.ModuleGraph()
770 graph
._safe
_import
_hook
= _safe_import
772 code
= compile(textwrap
.dedent('''\
778 '''), '<test>', 'exec', 0, False)
779 graph
.scan_code(code
, mod
)
780 modules
= [node
.identifier
for node
in graph
.nodes()]
781 self
.assertEqual(set(node_map
), set(['sys', 'os.path', 'shutil']))
784 # from module import a, b, c
785 # from module import *
787 # -> with/without globals
788 # -> with/without modules in globals (e.g,
789 # from os import * adds dependency to os.path)
790 # from .module import a
791 # from ..module import a
795 # -> should add dependency to a
796 # try to build case where commented out
797 # code would behave different than current code
798 # (Carbon.SomeMod contains 'import Sibling' seems
799 # to cause difference in real code)
801 self
.fail("actual test needed")
806 def test_load_package(self
):
807 self
.fail("load_package")
809 def test_find_module(self
):
811 def mock_finder(name
, path
):
812 record
.append((name
, path
))
813 return saved_finder(name
, path
)
815 saved_finder
= modulegraph
.find_module
817 modulegraph
.find_module
= mock_finder
819 graph
= modulegraph
.ModuleGraph()
820 m
= graph
._find
_module
('sys', None)
821 self
.assertEqual(record
, [])
822 self
.assertEqual(m
, (None, None, ("", "", imp
.C_BUILTIN
)))
824 modulegraph
.find_module
= saved_finder
825 xml
= graph
.import_hook("xml")[0]
826 self
.assertEqual(xml
.identifier
, 'xml')
827 modulegraph
.find_module
= mock_finder
829 self
.assertRaises(ImportError, graph
._find
_module
, 'xml', None)
831 self
.assertEqual(record
, [])
832 m
= graph
._find
_module
('shutil', None)
833 self
.assertEqual(record
, [
834 ('shutil', graph
.path
),
836 self
.assertTrue(isinstance(m
, tuple))
837 self
.assertEqual(len(m
), 3)
838 self
.assertTrue(hasattr(m
[0], 'read'))
839 self
.assertIsInstance(m
[0].read(), str)
840 srcfn
= shutil
.__file
__
841 if srcfn
.endswith('.pyc'):
843 self
.assertEqual(m
[1], srcfn
)
844 self
.assertEqual(m
[2], ('.py', 'rU', imp
.PY_SOURCE
))
847 m2
= graph
._find
_module
('shutil', None)
848 self
.assertEqual(m
[1:], m2
[1:])
853 m
= graph
._find
_module
('sax', xml
.packagepath
, xml
)
855 (None, os
.path
.join(os
.path
.dirname(xml
.filename
), 'sax'),
856 ('', '', imp
.PKG_DIRECTORY
)))
857 self
.assertEqual(record
, [
858 ('sax', xml
.packagepath
),
860 if m
[0] is not None: m
[0].close()
863 modulegraph
.find_module
= saved_finder
866 def test_create_xref(self
):
867 self
.fail("create_xref")
870 def test_itergraphreport(self
):
871 self
.fail("itergraphreport")
873 def test_report(self
):
874 graph
= modulegraph
.ModuleGraph()
876 saved_stdout
= sys
.stdout
878 fp
= sys
.stdout
= StringIO()
880 lines
= fp
.getvalue().splitlines()
883 self
.assertEqual(len(lines
), 3)
884 self
.assertEqual(lines
[0], '')
885 self
.assertEqual(lines
[1], 'Class Name File')
886 self
.assertEqual(lines
[2], '----- ---- ----')
888 fp
= sys
.stdout
= StringIO()
889 graph
._safe
_import
_hook
('os', None, ())
890 graph
._safe
_import
_hook
('sys', None, ())
891 graph
._safe
_import
_hook
('nomod', None, ())
893 lines
= fp
.getvalue().splitlines()
896 self
.assertEqual(lines
[0], '')
897 self
.assertEqual(lines
[1], 'Class Name File')
898 self
.assertEqual(lines
[2], '----- ---- ----')
900 for n
in graph
.flatten():
902 expected
.append([type(n
).__name
__, n
.identifier
, n
.filename
])
904 expected
.append([type(n
).__name
__, n
.identifier
])
907 actual
= [item
.split() for item
in lines
[3:]]
909 self
.assertEqual(expected
, actual
)
913 sys
.stdout
= saved_stdout
915 def test_graphreport(self
):
917 def my_iter(flatpackages
="packages"):
919 yield str(flatpackages
) + "\n"
922 graph
= modulegraph
.ModuleGraph()
923 graph
.itergraphreport
= my_iter
926 graph
.graphreport(fp
)
927 self
.assertEqual(fp
.getvalue(), "line1\n()\nline2\n")
930 graph
.graphreport(fp
, "deps")
931 self
.assertEqual(fp
.getvalue(), "line1\ndeps\nline2\n")
933 saved_stdout
= sys
.stdout
935 sys
.stdout
= fp
= StringIO()
937 self
.assertEqual(fp
.getvalue(), "line1\n()\nline2\n")
940 sys
.stdout
= saved_stdout
943 def test_replace_paths_in_code(self
):
944 graph
= modulegraph
.ModuleGraph(replace_paths
=[
946 ('path3/path5', 'path4'),
949 co
= compile(textwrap
.dedent("""
950 [x for x in range(4)]
951 """), "path4/index.py", 'exec', 0, 1)
952 co
= graph
._replace
_paths
_in
_code
(co
)
953 self
.assertEqual(co
.co_filename
, 'path4/index.py')
955 co
= compile(textwrap
.dedent("""
956 [x for x in range(4)]
957 (x for x in range(4))
958 """), "path1/index.py", 'exec', 0, 1)
959 self
.assertEqual(co
.co_filename
, 'path1/index.py')
960 co
= graph
._replace
_paths
_in
_code
(co
)
961 self
.assertEqual(co
.co_filename
, 'path2/index.py')
962 for c
in co
.co_consts
:
963 if isinstance(c
, type(co
)):
964 self
.assertEqual(c
.co_filename
, 'path2/index.py')
966 co
= compile(textwrap
.dedent("""
967 [x for x in range(4)]
968 """), "path3/path4/index.py", 'exec', 0, 1)
969 co
= graph
._replace
_paths
_in
_code
(co
)
970 self
.assertEqual(co
.co_filename
, 'path3/path4/index.py')
972 co
= compile(textwrap
.dedent("""
973 [x for x in range(4)]
974 """), "path3/path5.py", 'exec', 0, 1)
975 co
= graph
._replace
_paths
_in
_code
(co
)
976 self
.assertEqual(co
.co_filename
, 'path3/path5.py')
978 co
= compile(textwrap
.dedent("""
979 [x for x in range(4)]
980 """), "path3/path5/index.py", 'exec', 0, 1)
981 co
= graph
._replace
_paths
_in
_code
(co
)
982 self
.assertEqual(co
.co_filename
, 'path4/index.py')
984 def test_createReference(self
):
985 graph
= modulegraph
.ModuleGraph()
986 n1
= modulegraph
.Node('n1')
987 n2
= modulegraph
.Node('n2')
991 graph
.createReference(n1
, n2
)
992 outs
, ins
= map(list, graph
.get_edges(n1
))
993 self
.assertEqual(outs
, [n2
])
994 self
.assertEqual(ins
, [])
995 outs
, ins
= map(list, graph
.get_edges(n2
))
996 self
.assertEqual(outs
, [])
997 self
.assertEqual(ins
, [n1
])
999 e
= graph
.graph
.edge_by_node('n1', 'n2')
1000 self
.assertIsInstance(e
, int)
1001 self
.assertEqual(graph
.graph
.edge_data(e
), 'direct')
1003 def test_create_xref(self
):
1004 # XXX: This test is far from optimal, it just ensures
1005 # that all code is exercised to catch small bugs and
1006 # py3k issues without verifying that the code actually
1008 graph
= modulegraph
.ModuleGraph()
1009 if __file__
.endswith('.py'):
1010 graph
.run_script(__file__
)
1012 graph
.run_script(__file__
[:-1])
1014 graph
.import_hook('os')
1015 graph
.import_hook('xml.etree')
1016 graph
.import_hook('unittest')
1019 graph
.create_xref(out
=fp
)
1021 data
= fp
.getvalue()
1022 r
= ET
.fromstring(data
)
1024 def test_itergraphreport(self
):
1025 # XXX: This test is far from optimal, it just ensures
1026 # that all code is exercised to catch small bugs and
1027 # py3k issues without verifying that the code actually
1029 graph
= modulegraph
.ModuleGraph()
1030 if __file__
.endswith('.py'):
1031 graph
.run_script(__file__
)
1033 graph
.run_script(__file__
[:-1])
1034 graph
.import_hook('os')
1035 graph
.import_hook('xml.etree')
1036 graph
.import_hook('unittest')
1037 graph
.import_hook('distutils.command.build')
1040 list(graph
.itergraphreport())
1042 # XXX: platpackages isn't implemented, and is undocumented hence
1043 # it is unclear what this is inteded to be...
1044 #list(graph.itergraphreport(flatpackages=...))
1049 class CompatTests (unittest
.TestCase
):
1050 def test_Bchr(self
):
1051 v
= modulegraph
._Bchr
(ord('A'))
1052 if sys
.version_info
[0] == 2:
1053 self
.assertTrue(isinstance(v
, bytes
))
1054 self
.assertEqual(v
, b
'A')
1056 self
.assertTrue(isinstance(v
, int))
1057 self
.assertEqual(v
, ord('A'))
1059 if __name__
== "__main__":