From 23fe5549122edae2101f41c14cedc432f1563cf7 Mon Sep 17 00:00:00 2001 From: Colin Carroll Date: Sun, 20 May 2018 16:21:04 -0400 Subject: [PATCH] Add optional dependency class --- .pylintrc | 3 ++- arviz/compat/__init__.py | 4 ++++ arviz/compat/optional_dep.py | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 arviz/compat/__init__.py create mode 100644 arviz/compat/optional_dep.py diff --git a/.pylintrc b/.pylintrc index bfcaede8af..5c7899fbbe 100644 --- a/.pylintrc +++ b/.pylintrc @@ -61,7 +61,8 @@ disable=missing-docstring, too-many-locals, too-many-branches, too-many-statements, - no-self-use + no-self-use, + too-few-public-methods # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option diff --git a/arviz/compat/__init__.py b/arviz/compat/__init__.py new file mode 100644 index 0000000000..061b0d2511 --- /dev/null +++ b/arviz/compat/__init__.py @@ -0,0 +1,4 @@ +#pylint: disable=invalid-name +from .optional_dep import OptionalDep +pymc3 = OptionalDep('pymc3') +altair = OptionalDep('altair') diff --git a/arviz/compat/optional_dep.py b/arviz/compat/optional_dep.py new file mode 100644 index 0000000000..1524a3576c --- /dev/null +++ b/arviz/compat/optional_dep.py @@ -0,0 +1,32 @@ +import importlib +import sys + + +class OptionalDep(object): + """Wrapper for optional library dependencies. + + Note that since only __getattr__ is implemented, if this object implements + methods, those will be used *before* the true library is called. + + For example + + class PyMC3(OptionalDep): + def trace_to_dataframe(*args, **kwargs): + ... + + pm = PyMC3() + pm.trace_to_dataframe(trace) # calls the OptionalDep method + pm.Normal('x', 0, 1) # calls pymc3.Normal + """ + def __init__(self, name): + self.__name = name + self.__module = None + + def __getattr__(self, name): + if self.__module is None: + try: + self.__module = importlib.import_module(self.__name) + except ModuleNotFoundError: + raise ModuleNotFoundError( + 'Failed to import optional module {}'.format(self.__name), sys.exc_info()[0]) + return getattr(self.__module, name)