Skip to content
Snippets Groups Projects
Commit ae64aee1 authored by Piotr Maślanka's avatar Piotr Maślanka
Browse files

v2.2.11

parent 87f77ea0
No related branches found
No related tags found
No related merge requests found
# v2.2.11
* _TBA_
* bugfix and extra features added to *import_from*
# v2.2.10
......
# coding=UTF-8
__version__ = '2.2.11a1'
__version__ = '2.2.11'
import typing as tp
import importlib
import pkgutil
import logging
import os
import pkgutil
import typing as tp
__all__ = ['import_from']
logger = logging.getLogger(__name__)
def import_from(path: tp.List[str], package_prefix: str, all_: tp.List[str], locals: tp.Dict[str, tp.Any], recursive: bool = True,
fail_on_attributerror: bool = True, add_all: bool = True) -> None:
def import_from(path: tp.List[str], package_prefix: str, all_: tp.List[str],
locals: tp.Dict[str, tp.Any], recursive: bool = True,
fail_on_attributerror: bool = True, create_all: bool = True,
skip_single_underscores: bool = True,
skip_not_having_all: bool = False) -> None:
"""
Import everything from a given module. Append these module's all to.
......@@ -26,37 +29,50 @@ def import_from(path: tp.List[str], package_prefix: str, all_: tp.List[str], loc
:param fail_on_attributerror: whether to fail if a module reports something in their __all__ that
is physically not there (ie. getattr() raised AttributeError
:param locals: module's locals, obtain them by calling locals() in importing module's context
:param add_all: whether to create artificial __all__'s for modules that don't have them
:param create_all: whether to create artificial __all__'s for modules that don't have them
:param skip_single_underscores: whether to refrain from importing things that are preceded with a single underscore.
Pertains to modules, as well as items
:param skip_not_having_all: skip module's not having an __all__ entry
:raise AttributeError: module's __all__ contained entry that was not in this module
"""
logger.warning('Invoking with path=%s', path)
for importer, modname, ispkg in pkgutil.walk_packages(path, onerror=lambda x: None):
if recursive and ispkg:
module = importlib.import_module(package_prefix+'.'+modname)
if modname.startswith('_') and skip_single_underscores:
continue
module = importlib.import_module(package_prefix + '.' + modname)
logger.warning(repr(package_prefix))
logger.warning(repr(modname))
try:
mod_all = module.__all__
except AttributeError:
if skip_not_having_all:
continue
mod_all = []
if add_all:
if create_all:
module.__all__ = mod_all
import_from([os.path.join(path[0], modname)], package_prefix+'.'+modname, mod_all, module.__dict__, recursive=recursive, fail_on_attributerror=fail_on_attributerror),
import_from([os.path.join(path[0], modname)], package_prefix + '.' + modname, mod_all,
module.__dict__, recursive=recursive,
fail_on_attributerror=fail_on_attributerror),
locals[modname] = module
__all__.append(modname)
if modname not in all_:
all_.append(modname)
elif not ispkg:
module = importlib.import_module(package_prefix+'.'+modname)
module = importlib.import_module(package_prefix + '.' + modname)
try:
package_ref = module.__all__
except AttributeError:
logger.warning('Module %s does not contain __all__, enumerating it instead', package_prefix+'.'+modname)
logger.warning('Module %s does not contain __all__, enumerating it instead',
package_prefix + '.' + modname)
package_ref = dir(module)
for item in package_ref:
if item.startswith('_') and skip_single_underscores:
continue
try:
locals[item] = getattr(module, item)
except AttributeError:
if fail_on_attributerror:
raise
else:
all_.append(item)
if item not in all_:
all_.append(item)
import logging
import typing as tp
logger = logging.getLogger(__name__)
import logging
import typing as tp
logger = logging.getLogger(__name__)
......@@ -11,4 +10,5 @@ __all__ = []
def do_import():
logger.warning(repr(__path__))
logger.warning(repr(__name__))
import_from(__path__, __name__, __all__, locals(), recursive=True, fail_on_attributerror=False, add_all=True)
import_from(__path__, __name__, __all__, locals(), recursive=True, fail_on_attributerror=False,
create_all=True)
import logging
import typing as tp
logger = logging.getLogger(__name__)
import logging
import typing as tp
logger = logging.getLogger(__name__)
def sub(a: float, b: float) -> float:
return a-b
\ No newline at end of file
return a - b
def _mul(a: float, b: float) -> float:
return a * b
import logging
import typing as tp
logger = logging.getLogger(__name__)
__all__ = ['add', 'would_have_failed']
def add(a: float, b: float) -> float:
return a+b
def add(a: float, b: float) -> float:
return a + b
......@@ -9,7 +9,10 @@ class TestImports(unittest.TestCase):
import tests.test_imports.importa
tests.test_imports.importa.do_import()
tests.test_imports.importa.importb.__all__
# this as well checks for the namespace's pollution
self.assertEqual(set(tests.test_imports.importa.importb.__all__),
{'logger', 'sub', 'logging', 'tp', 'add'})
self.assertEqual(tests.test_imports.importa.importb.add(4, 5), 9)
self.assertEqual(tests.test_imports.importa.importb.sub(4, 5), -1)
self.assertRaises(AttributeError, lambda: tests.test_imports.importa.importb.mul(1, 2))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment