29 from logilab.common.modutils import cleanup_sys_modules |
33 from logilab.common.modutils import cleanup_sys_modules |
30 from logilab.common.changelog import Version |
34 from logilab.common.changelog import Version |
31 |
35 |
32 from cubicweb.devtools import ApptestConfiguration |
36 from cubicweb.devtools import ApptestConfiguration |
33 from cubicweb.devtools.testlib import BaseTestCase, TemporaryDirectory |
37 from cubicweb.devtools.testlib import BaseTestCase, TemporaryDirectory |
34 from cubicweb.cwconfig import _find_prefix |
38 from cubicweb.cwconfig import ( |
|
39 CubicWebConfiguration, _find_prefix, _expand_modname) |
35 |
40 |
36 |
41 |
37 def unabsolutize(path): |
42 def unabsolutize(path): |
38 parts = path.split(os.sep) |
43 parts = path.split(os.sep) |
39 for i, part in reversed(tuple(enumerate(parts))): |
44 for i, part in reversed(tuple(enumerate(parts))): |
40 if part.startswith('cubicweb_'): |
45 if part.startswith('cubicweb_'): |
41 return os.sep.join([part[len('cubicweb_'):]] + parts[i+1:]) |
46 return os.sep.join([part[len('cubicweb_'):]] + parts[i+1:]) |
42 if part.startswith('cubicweb') or part == 'legacy_cubes': |
47 if part.startswith('cubicweb') or part == 'legacy_cubes': |
43 return os.sep.join(parts[i+1:]) |
48 return os.sep.join(parts[i+1:]) |
44 raise Exception('duh? %s' % path) |
49 raise Exception('duh? %s' % path) |
|
50 |
|
51 |
|
52 def templibdir(func): |
|
53 """create a temporary directory and insert it in sys.path""" |
|
54 @functools.wraps(func) |
|
55 def wrapper(*args, **kwargs): |
|
56 with TemporaryDirectory() as libdir: |
|
57 sys.path.insert(0, libdir) |
|
58 try: |
|
59 args = args + (libdir,) |
|
60 return func(*args, **kwargs) |
|
61 finally: |
|
62 sys.path.remove(libdir) |
|
63 return wrapper |
|
64 |
|
65 |
|
66 def create_filepath(filepath): |
|
67 filedir = dirname(filepath) |
|
68 if not os.path.exists(filedir): |
|
69 os.makedirs(filedir) |
|
70 with open(filepath, 'a'): |
|
71 pass |
|
72 |
|
73 |
|
74 @contextlib.contextmanager |
|
75 def temp_config(appid, instance_dir, cubes_dir, cubes): |
|
76 """context manager that create a config object with specified appid, |
|
77 instance_dir, cubes_dir and cubes""" |
|
78 cls = CubicWebConfiguration |
|
79 old = (cls._INSTANCES_DIR, cls.CUBES_DIR, cls.CUBES_PATH, |
|
80 sys.path[:], sys.meta_path[:]) |
|
81 old_modules = set(sys.modules) |
|
82 try: |
|
83 cls._INSTANCES_DIR, cls.CUBES_DIR, cls.CUBES_PATH = ( |
|
84 instance_dir, cubes_dir, []) |
|
85 config = cls(appid) |
|
86 config._cubes = cubes |
|
87 config.adjust_sys_path() |
|
88 yield config |
|
89 finally: |
|
90 (cls._INSTANCES_DIR, cls.CUBES_DIR, cls.CUBES_PATH, |
|
91 sys.path[:], sys.meta_path[:]) = old |
|
92 for module in set(sys.modules) - old_modules: |
|
93 del sys.modules[module] |
45 |
94 |
46 |
95 |
47 class CubicWebConfigurationTC(BaseTestCase): |
96 class CubicWebConfigurationTC(BaseTestCase): |
48 |
97 |
49 @classmethod |
98 @classmethod |
311 finally: |
360 finally: |
312 if venv: |
361 if venv: |
313 os.environ['VIRTUAL_ENV'] = venv |
362 os.environ['VIRTUAL_ENV'] = venv |
314 |
363 |
315 |
364 |
|
365 class ModnamesTC(unittest.TestCase): |
|
366 |
|
367 @templibdir |
|
368 def test_expand_modnames(self, libdir): |
|
369 tempdir = join(libdir, 'lib') |
|
370 filepaths = [ |
|
371 join(tempdir, '__init__.py'), |
|
372 join(tempdir, 'a.py'), |
|
373 join(tempdir, 'b.py'), |
|
374 join(tempdir, 'c.py'), |
|
375 join(tempdir, 'b', '__init__.py'), |
|
376 join(tempdir, 'b', 'a.py'), |
|
377 join(tempdir, 'b', 'c.py'), |
|
378 join(tempdir, 'b', 'd', '__init__.py'), |
|
379 join(tempdir, 'e', 'e.py'), |
|
380 ] |
|
381 for filepath in filepaths: |
|
382 create_filepath(filepath) |
|
383 # not importable |
|
384 self.assertEqual(list(_expand_modname('isnotimportable')), []) |
|
385 # not a python package |
|
386 self.assertEqual(list(_expand_modname('lib.e')), []) |
|
387 self.assertEqual(list(_expand_modname('lib.a')), [ |
|
388 ('lib.a', join(tempdir, 'a.py')), |
|
389 ]) |
|
390 # lib.b.d (subpackage) not to be imported |
|
391 self.assertEqual(list(_expand_modname('lib.b')), [ |
|
392 ('lib.b', join(tempdir, 'b', '__init__.py')), |
|
393 ('lib.b.a', join(tempdir, 'b', 'a.py')), |
|
394 ('lib.b.c', join(tempdir, 'b', 'c.py')), |
|
395 ]) |
|
396 self.assertEqual(list(_expand_modname('lib')), [ |
|
397 ('lib', join(tempdir, '__init__.py')), |
|
398 ('lib.a', join(tempdir, 'a.py')), |
|
399 ('lib.c', join(tempdir, 'c.py')), |
|
400 ]) |
|
401 for source in ( |
|
402 join(tempdir, 'c.py'), |
|
403 join(tempdir, 'b', 'c.py'), |
|
404 ): |
|
405 if not PY3: |
|
406 # ensure pyc file exists. |
|
407 # Doesn't required for PY3 since it create __pycache__ |
|
408 # directory and will not import if source file doesn't |
|
409 # exists. |
|
410 compileall.compile_file(source, force=True) |
|
411 self.assertTrue(os.path.exists(source + 'c')) |
|
412 # remove source file |
|
413 os.remove(source) |
|
414 self.assertEqual(list(_expand_modname('lib.c')), []) |
|
415 self.assertEqual(list(_expand_modname('lib.b')), [ |
|
416 ('lib.b', join(tempdir, 'b', '__init__.py')), |
|
417 ('lib.b.a', join(tempdir, 'b', 'a.py')), |
|
418 ]) |
|
419 self.assertEqual(list(_expand_modname('lib')), [ |
|
420 ('lib', join(tempdir, '__init__.py')), |
|
421 ('lib.a', join(tempdir, 'a.py')), |
|
422 ]) |
|
423 |
|
424 @templibdir |
|
425 def test_schema_modnames(self, libdir): |
|
426 for filepath in ( |
|
427 join(libdir, 'schema.py'), |
|
428 join(libdir, 'cubicweb_foo', '__init__.py'), |
|
429 join(libdir, 'cubicweb_foo', 'schema', '__init__.py'), |
|
430 join(libdir, 'cubicweb_foo', 'schema', 'a.py'), |
|
431 join(libdir, 'cubicweb_foo', 'schema', 'b.py'), |
|
432 join(libdir, 'cubes', '__init__.py'), |
|
433 join(libdir, 'cubes', 'bar', '__init__.py'), |
|
434 join(libdir, 'cubes', 'bar', 'schema.py'), |
|
435 join(libdir, '_instance_dir', 'data1', 'schema.py'), |
|
436 join(libdir, '_instance_dir', 'data2', 'noschema.py'), |
|
437 ): |
|
438 create_filepath(filepath) |
|
439 expected = [ |
|
440 ('cubicweb', 'cubicweb.schemas.bootstrap'), |
|
441 ('cubicweb', 'cubicweb.schemas.base'), |
|
442 ('cubicweb', 'cubicweb.schemas.workflow'), |
|
443 ('cubicweb', 'cubicweb.schemas.Bookmark'), |
|
444 ('bar', 'cubes.bar.schema'), |
|
445 ('foo', 'cubes.foo.schema'), |
|
446 ('foo', 'cubes.foo.schema.a'), |
|
447 ('foo', 'cubes.foo.schema.b'), |
|
448 ] |
|
449 # app has schema file |
|
450 instance_dir, cubes_dir = ( |
|
451 join(libdir, '_instance_dir'), join(libdir, 'cubes')) |
|
452 with temp_config('data1', instance_dir, cubes_dir, |
|
453 ('foo', 'bar')) as config: |
|
454 self.assertEqual(pkgutil.find_loader('schema').get_filename(), |
|
455 join(libdir, '_instance_dir', |
|
456 'data1', 'schema.py')) |
|
457 self.assertEqual(config.schema_modnames(), |
|
458 expected + [('data', 'schema')]) |
|
459 # app doesn't have schema file |
|
460 with temp_config('data2', instance_dir, cubes_dir, |
|
461 ('foo', 'bar')) as config: |
|
462 self.assertEqual(pkgutil.find_loader('schema').get_filename(), |
|
463 join(libdir, 'schema.py')) |
|
464 self.assertEqual(config.schema_modnames(), expected) |
|
465 |
|
466 |
|
467 |
|
468 |
316 if __name__ == '__main__': |
469 if __name__ == '__main__': |
317 unittest.main() |
470 unittest.main() |