diff --git a/graphene/__init__.py b/graphene/__init__.py index 7a680edc..cf1a3079 100644 --- a/graphene/__init__.py +++ b/graphene/__init__.py @@ -43,6 +43,7 @@ if not __SETUP__: PageInfo ) from .utils.resolve_only_args import resolve_only_args + from .utils.module_loading import lazy_import __all__ = [ 'AbstractType', @@ -72,4 +73,6 @@ if not __SETUP__: 'ClientIDMutation', 'Connection', 'ConnectionField', - 'PageInfo'] + 'PageInfo', + 'lazy_import', + ] diff --git a/graphene/utils/module_loading.py b/graphene/utils/module_loading.py new file mode 100644 index 00000000..8312cfb0 --- /dev/null +++ b/graphene/utils/module_loading.py @@ -0,0 +1,26 @@ +from functools import partial +from importlib import import_module + + +def import_string(dotted_path): + """ + Import a dotted module path and return the attribute/class designated by the + last name in the path. Raise ImportError if the import failed. + """ + try: + module_path, class_name = dotted_path.rsplit('.', 1) + except ValueError as err: + raise ImportError("%s doesn't look like a module path" % dotted_path) + + module = import_module(module_path) + + try: + return getattr(module, class_name) + except AttributeError as err: + raise ImportError('Module "%s" does not define a "%s" attribute/class' % ( + module_path, class_name) + ) + + +def lazy_import(dotted_path): + return partial(import_string, dotted_path) diff --git a/graphene/utils/tests/test_module_loading.py b/graphene/utils/tests/test_module_loading.py new file mode 100644 index 00000000..a0975f74 --- /dev/null +++ b/graphene/utils/tests/test_module_loading.py @@ -0,0 +1,29 @@ +from pytest import raises + +from graphene import String +from ..module_loading import lazy_import, import_string + + +def test_import_string(): + MyString = import_string('graphene.String') + assert MyString == String + + +def test_import_string_module(): + with raises(Exception) as exc_info: + import_string('graphenea') + + assert str(exc_info.value) == 'graphenea doesn\'t look like a module path' + + +def test_import_string_class(): + with raises(Exception) as exc_info: + import_string('graphene.Stringa') + + assert str(exc_info.value) == 'Module "graphene" does not define a "Stringa" attribute/class' + + +def test_lazy_import(): + f = lazy_import('graphene.String') + MyString = f() + assert MyString == String