pyomo.common.dependencies
Mock object that raises
DeferredImportError
upon attribute accessThis object is returned by
attempt_import()
in lieu of the module in the case that the module import fails. Any attempts to access attributes on this object will raise aDeferredImportError
exception.- Parameters:
name (str) – The module name that was being imported
message (str) – The string message to return in the raised exception
version_error (str) – A string to add to the message if the module failed to import because it did not match the required version
import_error (str) – A string to add to the message documenting the Exception raised when the module failed to import.
package (str) – The module name that originally attempted the import
Return a type’s method resolution order.
Log the import error message to the specified logger
This will log the the import error message to the specified logger. If
msg=
is specified, it will override the default message passed to this instance ofModuleUnavailable
.
DEPRECATED.
Deprecated since version 6.0: use
log_import_warning()
- class pyomo.common.dependencies.DeferredImportModule(indicator, deferred_submodules, submodule_name)[source]
Mock module object to support the deferred import of a module.
This object is returned by
attempt_import()
in lieu of the module whenattempt_import()
is called withdefer_import=True
. Any attempts to access attributes on this object will trigger the actual module import and return either the appropriate module attribute or else if the module import fails, raise aDeferredImportError
exception.
Function to generate an “unavailable” base class
This function returns a custom class that wraps the
ModuleUnavailable
instance returned byattempt_import()
when the target module is not available. Any attempt to instantiate this class (or a class derived from it) or access a class attribute will raise theDeferredImportError
from the wrappedModuleUnavailable
object.- Parameters:
unavailable_module (ModuleUnavailable) – The
ModuleUnavailable
instance (fromattempt_import()
) to use to generate theDeferredImportError
.
Example
Declaring a class that inherits from an optional dependency:
>>> from pyomo.common.dependencies import attempt_import, UnavailableClass >>> bogus, bogus_available = attempt_import('bogus_unavailable_class') >>> class MyPlugin(bogus.plugin if bogus_available else UnavailableClass(bogus)): ... pass
Attempting to instantiate the derived class generates an exception when the module is unavailable:
>>> MyPlugin() Traceback (most recent call last): ... pyomo.common.dependencies.DeferredImportError: The class 'MyPlugin' cannot be created because a needed optional dependency was not found (import raised ModuleNotFoundError: No module named 'bogus_unavailable_class')
As does attempting to access class attributes on the derived class:
>>> MyPlugin.create_instance() Traceback (most recent call last): ... pyomo.common.dependencies.DeferredImportError: The class attribute 'MyPlugin.create_instance' is not available because a needed optional dependency was not found (import raised ModuleNotFoundError: No module named 'bogus_unavailable_class')
- class pyomo.common.dependencies.DeferredImportIndicator(name, error_message, catch_exceptions, minimum_version, original_globals, callback, importer, deferred_submodules)[source]
Placeholder indicating if an import was successful.
This object serves as a placeholder for the Boolean indicator if a deferred module import was successful. Casting this instance to bool will cause the import to be attempted. The actual import logic is here and not in the
DeferredImportModule
to reduce the number of attributes on theDeferredImportModule
.DeferredImportIndicator
supports limited logical expressions using the&
(and) and|
(or) binary operators. Creating these expressions does not trigger the import of the correspondingDeferredImportModule
instances, although casting the resulting expression tobool()
will trigger any relevant imports.
- class pyomo.common.dependencies.DeferredImportCallbackLoader(loader, deferred_indicators: List[DeferredImportIndicator])[source]
Custom Loader to resolve registered
DeferredImportIndicator
objectsThis
importlib.abc.Loader
loader wraps a regular loader and automatically resolves the registeredDeferredImportIndicator
objects after the module is loaded.
- class pyomo.common.dependencies.DeferredImportCallbackFinder[source]
Custom Finder that will wrap the normal loader to trigger callbacks
This
importlib.abc.MetaPathFinder
finder will wrap the normal loader returned byPathFinder
with a loader that will trigger custom callbacks after the module is loaded. We use this to trigger the post import callbacks registered throughattempt_import()
even when a user imports the target library directly (and not through attribute access on theDeferredImportModule
.
- pyomo.common.dependencies.attempt_import(name, error_message=None, only_catch_importerror=None, minimum_version=None, alt_names=None, callback=None, importer=None, defer_check=None, defer_import=None, deferred_submodules=None, catch_exceptions=None)[source]
Attempt to import the specified module.
This will attempt to import the specified module, returning a
(module, available)
tuple. If the import was successful,module
will be the imported module andavailable
will be True. If the import results in an exception, thenmodule
will be an instance ofModuleUnavailable
andavailable
will be FalseThe following
>>> from pyomo.common.dependencies import attempt_import >>> numpy, numpy_available = attempt_import('numpy')
Is roughly equivalent to
>>> from pyomo.common.dependencies import ModuleUnavailable >>> try: ... import numpy ... numpy_available = True ... except ImportError as e: ... numpy = ModuleUnavailable('numpy', 'Numpy is not available', ... '', str(e), globals()['__name__']) ... numpy_available = False
The import can be “deferred” until the first time the code either attempts to access the module or checks the Boolean value of the available flag. This allows optional dependencies to be declared at the module scope but not imported until they are actually used by the module (thereby speeding up the initial package import). Deferred imports are handled by two helper classes (
DeferredImportModule
andDeferredImportIndicator
). Upon actual import,DeferredImportIndicator.resolve()
attempts to replace those objects (in both the local and original global namespaces) with the imported module and Boolean flag so that subsequent uses of the module do not incur any overhead due to the delayed import.- Parameters:
name (str) – The name of the module to import
error_message (str, optional) – The message for the exception raised by
ModuleUnavailable
only_catch_importerror (bool, optional) –
DEPRECATED: use
catch_exceptions
instead ofonly_catch_importerror
.If True (the default), exceptions other than
ImportError
raised during module import will be reraised. If False, any exception will result in returning aModuleUnavailable
object. (deprecated in version 5.7.3)minimum_version (str, optional) – The minimum acceptable module version (retrieved from
module.__version__
)alt_names (list, optional) –
DEPRECATED:
alt_names
no longer needs to be specified and is ignored.A list of common alternate names by which to look for this module in the
globals()
namespaces. For example, the alt_names for NumPy would be['np']
. (deprecated in version 6.0)callback (Callable[[ModuleType, bool], None], optional) – A function with the signature
fcn(module, available)
that will be called after the import is first attempted.importer (function, optional) – A function that will perform the import and return the imported module (or raise an
ImportError
). This is useful for cases where there are several equivalent modules and you want to import/return the first one that is available.defer_check (bool, optional) – DEPRECATED: renamed to
defer_import
(deprecated in version 6.7.2.dev0)defer_import (bool, optional) – If True, then the attempted import is deferred until the first use of either the module or the availability flag. The method will return instances of
DeferredImportModule
andDeferredImportIndicator
. If False, the import will be attempted immediately. If not set, then the import will be deferred unless thename
is already present insys.modules
.deferred_submodules (Iterable[str], optional) – If provided, an iterable of submodule names within this module that can be accessed without triggering a deferred import of this module. For example, this module uses
deferred_submodules=['pyplot', 'pylab']
formatplotlib
.catch_exceptions (Iterable[Exception], optional) – If provided, this is the list of exceptions that will be caught when importing the target module, resulting in
attempt_import
returning aModuleUnavailable
instance. The default is to only catchImportError
. This is useful when a module can regularly return additional exceptions during import.
- Returns:
module – the imported module, or an instance of
ModuleUnavailable
, or an instance ofDeferredImportModule
bool – Boolean indicating if the module import succeeded or an instance of
DeferredImportIndicator
- pyomo.common.dependencies.declare_deferred_modules_as_importable(globals_dict)[source]
DEPRECATED.
Make all
DeferredImportModules
inglobals_dict
importableThis function will go throughout the specified
globals_dict
dictionary and add any instances ofDeferredImportModule
that it finds (and any of their deferred submodules) tosys.modules
so that the modules can be imported through theglobals_dict
namespace.For example,
pyomo/common/dependencies.py
declares:>>> scipy, scipy_available = attempt_import( ... 'scipy', callback=_finalize_scipy, ... deferred_submodules=['stats', 'sparse', 'spatial', 'integrate']) >>> declare_deferred_modules_as_importable(globals()) WARNING: DEPRECATED: ...
Which enables users to use:
>>> import pyomo.common.dependencies.scipy.sparse as spa
If the deferred import has not yet been triggered, then the
DeferredImportModule
is returned and namedspa
. However, if the import has already been triggered, thenspa
will either be thescipy.sparse
module, or aModuleUnavailable
instance.Deprecated since version 6.7.2.dev0:
declare_deferred_modules_as_importable()
is deprecated. Use thedeclare_modules_as_importable
context manager.
- class pyomo.common.dependencies.declare_modules_as_importable(globals_dict)[source]
Make all
ModuleType
andDeferredImportModules
importable through theglobals_dict
context.This context manager will detect all modules imported into the specified
globals_dict
environment (either directly or throughattempt_import()
) and will make those modules importable from the specifiedglobals_dict
context. It works by detecting changes in the specifiedglobals_dict
dictionary and adding any new modules or instances ofDeferredImportModule
that it finds (and any of their deferred submodules) tosys.modules
so that the modules can be imported through theglobals_dict
namespace.For example,
pyomo/common/dependencies.py
declares:>>> with declare_modules_as_importable(globals()): ... scipy, scipy_available = attempt_import( ... 'scipy', callback=_finalize_scipy, ... deferred_submodules=['stats', 'sparse', 'spatial', 'integrate'])
Which enables users to use:
>>> import pyomo.common.dependencies.scipy.sparse as spa
If the deferred import has not yet been triggered, then the
DeferredImportModule
is returned and namedspa
. However, if the import has already been triggered, thenspa
will either be thescipy.sparse
module, or aModuleUnavailable
instance.