summaryrefslogtreecommitdiffstats
path: root/contrib/python/ipython/py2/IPython/external
diff options
context:
space:
mode:
authormonster <[email protected]>2022-07-07 14:41:37 +0300
committermonster <[email protected]>2022-07-07 14:41:37 +0300
commit06e5c21a835c0e923506c4ff27929f34e00761c2 (patch)
tree75efcbc6854ef9bd476eb8bf00cc5c900da436a2 /contrib/python/ipython/py2/IPython/external
parent03f024c4412e3aa613bb543cf1660176320ba8f4 (diff)
fix ya.make
Diffstat (limited to 'contrib/python/ipython/py2/IPython/external')
-rw-r--r--contrib/python/ipython/py2/IPython/external/__init__.py5
-rw-r--r--contrib/python/ipython/py2/IPython/external/decorators/__init__.py9
-rw-r--r--contrib/python/ipython/py2/IPython/external/decorators/_decorators.py281
-rw-r--r--contrib/python/ipython/py2/IPython/external/decorators/_numpy_testing_noseclasses.py41
-rw-r--r--contrib/python/ipython/py2/IPython/external/decorators/_numpy_testing_utils.py112
-rw-r--r--contrib/python/ipython/py2/IPython/external/mathjax.py13
-rw-r--r--contrib/python/ipython/py2/IPython/external/qt_for_kernel.py95
-rw-r--r--contrib/python/ipython/py2/IPython/external/qt_loaders.py372
8 files changed, 0 insertions, 928 deletions
diff --git a/contrib/python/ipython/py2/IPython/external/__init__.py b/contrib/python/ipython/py2/IPython/external/__init__.py
deleted file mode 100644
index 3104c194622..00000000000
--- a/contrib/python/ipython/py2/IPython/external/__init__.py
+++ /dev/null
@@ -1,5 +0,0 @@
-"""
-This package contains all third-party modules bundled with IPython.
-"""
-
-__all__ = ["simplegeneric"]
diff --git a/contrib/python/ipython/py2/IPython/external/decorators/__init__.py b/contrib/python/ipython/py2/IPython/external/decorators/__init__.py
deleted file mode 100644
index dd8f52b711a..00000000000
--- a/contrib/python/ipython/py2/IPython/external/decorators/__init__.py
+++ /dev/null
@@ -1,9 +0,0 @@
-try:
- from numpy.testing.decorators import *
- from numpy.testing.noseclasses import KnownFailure
-except ImportError:
- from ._decorators import *
- try:
- from ._numpy_testing_noseclasses import KnownFailure
- except ImportError:
- pass
diff --git a/contrib/python/ipython/py2/IPython/external/decorators/_decorators.py b/contrib/python/ipython/py2/IPython/external/decorators/_decorators.py
deleted file mode 100644
index 19de5e5cded..00000000000
--- a/contrib/python/ipython/py2/IPython/external/decorators/_decorators.py
+++ /dev/null
@@ -1,281 +0,0 @@
-"""
-Decorators for labeling and modifying behavior of test objects.
-
-Decorators that merely return a modified version of the original
-function object are straightforward. Decorators that return a new
-function object need to use
-::
-
- nose.tools.make_decorator(original_function)(decorator)
-
-in returning the decorator, in order to preserve meta-data such as
-function name, setup and teardown functions and so on - see
-``nose.tools`` for more information.
-
-"""
-import warnings
-
-# IPython changes: make this work if numpy not available
-# Original code:
-#from numpy.testing.utils import \
-# WarningManager, WarningMessage
-# Our version:
-from ._numpy_testing_utils import WarningManager
-try:
- from ._numpy_testing_noseclasses import KnownFailureTest
-except:
- pass
-
-# End IPython changes
-
-def slow(t):
- """
- Label a test as 'slow'.
-
- The exact definition of a slow test is obviously both subjective and
- hardware-dependent, but in general any individual test that requires more
- than a second or two should be labeled as slow (the whole suite consists of
- thousands of tests, so even a second is significant).
-
- Parameters
- ----------
- t : callable
- The test to label as slow.
-
- Returns
- -------
- t : callable
- The decorated test `t`.
-
- Examples
- --------
- The `numpy.testing` module includes ``import decorators as dec``.
- A test can be decorated as slow like this::
-
- from numpy.testing import *
-
- @dec.slow
- def test_big(self):
- print 'Big, slow test'
-
- """
-
- t.slow = True
- return t
-
-def setastest(tf=True):
- """
- Signals to nose that this function is or is not a test.
-
- Parameters
- ----------
- tf : bool
- If True, specifies that the decorated callable is a test.
- If False, specifies that the decorated callable is not a test.
- Default is True.
-
- Notes
- -----
- This decorator can't use the nose namespace, because it can be
- called from a non-test module. See also ``istest`` and ``nottest`` in
- ``nose.tools``.
-
- Examples
- --------
- `setastest` can be used in the following way::
-
- from numpy.testing.decorators import setastest
-
- @setastest(False)
- def func_with_test_in_name(arg1, arg2):
- pass
-
- """
- def set_test(t):
- t.__test__ = tf
- return t
- return set_test
-
-def skipif(skip_condition, msg=None):
- """
- Make function raise SkipTest exception if a given condition is true.
-
- If the condition is a callable, it is used at runtime to dynamically
- make the decision. This is useful for tests that may require costly
- imports, to delay the cost until the test suite is actually executed.
-
- Parameters
- ----------
- skip_condition : bool or callable
- Flag to determine whether to skip the decorated test.
- msg : str, optional
- Message to give on raising a SkipTest exception. Default is None.
-
- Returns
- -------
- decorator : function
- Decorator which, when applied to a function, causes SkipTest
- to be raised when `skip_condition` is True, and the function
- to be called normally otherwise.
-
- Notes
- -----
- The decorator itself is decorated with the ``nose.tools.make_decorator``
- function in order to transmit function name, and various other metadata.
-
- """
-
- def skip_decorator(f):
- # Local import to avoid a hard nose dependency and only incur the
- # import time overhead at actual test-time.
- import nose
-
- # Allow for both boolean or callable skip conditions.
- if callable(skip_condition):
- skip_val = lambda : skip_condition()
- else:
- skip_val = lambda : skip_condition
-
- def get_msg(func,msg=None):
- """Skip message with information about function being skipped."""
- if msg is None:
- out = 'Test skipped due to test condition'
- else:
- out = '\n'+msg
-
- return "Skipping test: %s%s" % (func.__name__,out)
-
- # We need to define *two* skippers because Python doesn't allow both
- # return with value and yield inside the same function.
- def skipper_func(*args, **kwargs):
- """Skipper for normal test functions."""
- if skip_val():
- raise nose.SkipTest(get_msg(f,msg))
- else:
- return f(*args, **kwargs)
-
- def skipper_gen(*args, **kwargs):
- """Skipper for test generators."""
- if skip_val():
- raise nose.SkipTest(get_msg(f,msg))
- else:
- for x in f(*args, **kwargs):
- yield x
-
- # Choose the right skipper to use when building the actual decorator.
- if nose.util.isgenerator(f):
- skipper = skipper_gen
- else:
- skipper = skipper_func
-
- return nose.tools.make_decorator(f)(skipper)
-
- return skip_decorator
-
-def knownfailureif(fail_condition, msg=None):
- """
- Make function raise KnownFailureTest exception if given condition is true.
-
- If the condition is a callable, it is used at runtime to dynamically
- make the decision. This is useful for tests that may require costly
- imports, to delay the cost until the test suite is actually executed.
-
- Parameters
- ----------
- fail_condition : bool or callable
- Flag to determine whether to mark the decorated test as a known
- failure (if True) or not (if False).
- msg : str, optional
- Message to give on raising a KnownFailureTest exception.
- Default is None.
-
- Returns
- -------
- decorator : function
- Decorator, which, when applied to a function, causes SkipTest
- to be raised when `skip_condition` is True, and the function
- to be called normally otherwise.
-
- Notes
- -----
- The decorator itself is decorated with the ``nose.tools.make_decorator``
- function in order to transmit function name, and various other metadata.
-
- """
- if msg is None:
- msg = 'Test skipped due to known failure'
-
- # Allow for both boolean or callable known failure conditions.
- if callable(fail_condition):
- fail_val = lambda : fail_condition()
- else:
- fail_val = lambda : fail_condition
-
- def knownfail_decorator(f):
- # Local import to avoid a hard nose dependency and only incur the
- # import time overhead at actual test-time.
- import nose
- def knownfailer(*args, **kwargs):
- if fail_val():
- raise KnownFailureTest(msg)
- else:
- return f(*args, **kwargs)
- return nose.tools.make_decorator(f)(knownfailer)
-
- return knownfail_decorator
-
-def deprecated(conditional=True):
- """
- Filter deprecation warnings while running the test suite.
-
- This decorator can be used to filter DeprecationWarning's, to avoid
- printing them during the test suite run, while checking that the test
- actually raises a DeprecationWarning.
-
- Parameters
- ----------
- conditional : bool or callable, optional
- Flag to determine whether to mark test as deprecated or not. If the
- condition is a callable, it is used at runtime to dynamically make the
- decision. Default is True.
-
- Returns
- -------
- decorator : function
- The `deprecated` decorator itself.
-
- Notes
- -----
- .. versionadded:: 1.4.0
-
- """
- def deprecate_decorator(f):
- # Local import to avoid a hard nose dependency and only incur the
- # import time overhead at actual test-time.
- import nose
-
- def _deprecated_imp(*args, **kwargs):
- # Poor man's replacement for the with statement
- ctx = WarningManager(record=True)
- l = ctx.__enter__()
- warnings.simplefilter('always')
- try:
- f(*args, **kwargs)
- if not len(l) > 0:
- raise AssertionError("No warning raised when calling %s"
- % f.__name__)
- if not l[0].category is DeprecationWarning:
- raise AssertionError("First warning for %s is not a " \
- "DeprecationWarning( is %s)" % (f.__name__, l[0]))
- finally:
- ctx.__exit__()
-
- if callable(conditional):
- cond = conditional()
- else:
- cond = conditional
- if cond:
- return nose.tools.make_decorator(f)(_deprecated_imp)
- else:
- return f
- return deprecate_decorator
diff --git a/contrib/python/ipython/py2/IPython/external/decorators/_numpy_testing_noseclasses.py b/contrib/python/ipython/py2/IPython/external/decorators/_numpy_testing_noseclasses.py
deleted file mode 100644
index ca6ccd87bbc..00000000000
--- a/contrib/python/ipython/py2/IPython/external/decorators/_numpy_testing_noseclasses.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# IPython: modified copy of numpy.testing.noseclasses, so
-# IPython.external._decorators works without numpy being installed.
-
-# These classes implement a "known failure" error class.
-
-import os
-
-from nose.plugins.errorclass import ErrorClass, ErrorClassPlugin
-
-class KnownFailureTest(Exception):
- '''Raise this exception to mark a test as a known failing test.'''
- pass
-
-
-class KnownFailure(ErrorClassPlugin):
- '''Plugin that installs a KNOWNFAIL error class for the
- KnownFailureClass exception. When KnownFailureTest is raised,
- the exception will be logged in the knownfail attribute of the
- result, 'K' or 'KNOWNFAIL' (verbose) will be output, and the
- exception will not be counted as an error or failure.'''
- enabled = True
- knownfail = ErrorClass(KnownFailureTest,
- label='KNOWNFAIL',
- isfailure=False)
-
- def options(self, parser, env=os.environ):
- env_opt = 'NOSE_WITHOUT_KNOWNFAIL'
- parser.add_option('--no-knownfail', action='store_true',
- dest='noKnownFail', default=env.get(env_opt, False),
- help='Disable special handling of KnownFailureTest '
- 'exceptions')
-
- def configure(self, options, conf):
- if not self.can_configure:
- return
- self.conf = conf
- disable = getattr(options, 'noKnownFail', False)
- if disable:
- self.enabled = False
-
-
diff --git a/contrib/python/ipython/py2/IPython/external/decorators/_numpy_testing_utils.py b/contrib/python/ipython/py2/IPython/external/decorators/_numpy_testing_utils.py
deleted file mode 100644
index ad7bd0f9817..00000000000
--- a/contrib/python/ipython/py2/IPython/external/decorators/_numpy_testing_utils.py
+++ /dev/null
@@ -1,112 +0,0 @@
-# IPython: modified copy of numpy.testing.utils, so
-# IPython.external._decorators works without numpy being installed.
-"""
-Utility function to facilitate testing.
-"""
-
-import sys
-import warnings
-
-# The following two classes are copied from python 2.6 warnings module (context
-# manager)
-class WarningMessage(object):
-
- """
- Holds the result of a single showwarning() call.
-
- Notes
- -----
- `WarningMessage` is copied from the Python 2.6 warnings module,
- so it can be used in NumPy with older Python versions.
-
- """
-
- _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
- "line")
-
- def __init__(self, message, category, filename, lineno, file=None,
- line=None):
- local_values = locals()
- for attr in self._WARNING_DETAILS:
- setattr(self, attr, local_values[attr])
- if category:
- self._category_name = category.__name__
- else:
- self._category_name = None
-
- def __str__(self):
- return ("{message : %r, category : %r, filename : %r, lineno : %s, "
- "line : %r}" % (self.message, self._category_name,
- self.filename, self.lineno, self.line))
-
-class WarningManager:
- """
- A context manager that copies and restores the warnings filter upon
- exiting the context.
-
- The 'record' argument specifies whether warnings should be captured by a
- custom implementation of ``warnings.showwarning()`` and be appended to a
- list returned by the context manager. Otherwise None is returned by the
- context manager. The objects appended to the list are arguments whose
- attributes mirror the arguments to ``showwarning()``.
-
- The 'module' argument is to specify an alternative module to the module
- named 'warnings' and imported under that name. This argument is only useful
- when testing the warnings module itself.
-
- Notes
- -----
- `WarningManager` is a copy of the ``catch_warnings`` context manager
- from the Python 2.6 warnings module, with slight modifications.
- It is copied so it can be used in NumPy with older Python versions.
-
- """
- def __init__(self, record=False, module=None):
- self._record = record
- if module is None:
- self._module = sys.modules['warnings']
- else:
- self._module = module
- self._entered = False
-
- def __enter__(self):
- if self._entered:
- raise RuntimeError("Cannot enter %r twice" % self)
- self._entered = True
- self._filters = self._module.filters
- self._module.filters = self._filters[:]
- self._showwarning = self._module.showwarning
- if self._record:
- log = []
- def showwarning(*args, **kwargs):
- log.append(WarningMessage(*args, **kwargs))
- self._module.showwarning = showwarning
- return log
- else:
- return None
-
- def __exit__(self, type_, value, traceback):
- if not self._entered:
- raise RuntimeError("Cannot exit %r without entering first" % self)
- self._module.filters = self._filters
- self._module.showwarning = self._showwarning
-
-def assert_warns(warning_class, func, *args, **kw):
- """Fail unless a warning of class warning_class is thrown by callable when
- invoked with arguments args and keyword arguments kwargs.
-
- If a different type of warning is thrown, it will not be caught, and the
- test case will be deemed to have suffered an error.
- """
-
- # XXX: once we may depend on python >= 2.6, this can be replaced by the
- # warnings module context manager.
- with WarningManager(record=True) as l:
- warnings.simplefilter('always')
- func(*args, **kw)
- if not len(l) > 0:
- raise AssertionError("No warning raised when calling %s"
- % func.__name__)
- if not l[0].category is warning_class:
- raise AssertionError("First warning for %s is not a " \
- "%s( is %s)" % (func.__name__, warning_class, l[0]))
diff --git a/contrib/python/ipython/py2/IPython/external/mathjax.py b/contrib/python/ipython/py2/IPython/external/mathjax.py
deleted file mode 100644
index 1b9b80905ba..00000000000
--- a/contrib/python/ipython/py2/IPython/external/mathjax.py
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/usr/bin/python
-"""
-`IPython.external.mathjax` is deprecated with IPython 4.0+
-
-mathjax is now install by default with the notebook package
-
-"""
-
-import sys
-
-if __name__ == '__main__' :
- sys.exit("IPython.external.mathjax is deprecated, Mathjax is now installed by default with the notebook package")
-
diff --git a/contrib/python/ipython/py2/IPython/external/qt_for_kernel.py b/contrib/python/ipython/py2/IPython/external/qt_for_kernel.py
deleted file mode 100644
index 1a94e7e0a2e..00000000000
--- a/contrib/python/ipython/py2/IPython/external/qt_for_kernel.py
+++ /dev/null
@@ -1,95 +0,0 @@
-""" Import Qt in a manner suitable for an IPython kernel.
-
-This is the import used for the `gui=qt` or `matplotlib=qt` initialization.
-
-Import Priority:
-
-if Qt has been imported anywhere else:
- use that
-
-if matplotlib has been imported and doesn't support v2 (<= 1.0.1):
- use PyQt4 @v1
-
-Next, ask QT_API env variable
-
-if QT_API not set:
- ask matplotlib what it's using. If Qt4Agg or Qt5Agg, then use the
- version matplotlib is configured with
-
- else: (matplotlib said nothing)
- # this is the default path - nobody told us anything
- try in this order:
- PyQt default version, PySide, PyQt5
-else:
- use what QT_API says
-
-"""
-# NOTE: This is no longer an external, third-party module, and should be
-# considered part of IPython. For compatibility however, it is being kept in
-# IPython/external.
-
-import os
-import sys
-
-from IPython.utils.version import check_version
-from IPython.external.qt_loaders import (load_qt, loaded_api, QT_API_PYSIDE,
- QT_API_PYSIDE2, QT_API_PYQT, QT_API_PYQT5,
- QT_API_PYQTv1, QT_API_PYQT_DEFAULT)
-
-_qt_apis = (QT_API_PYSIDE, QT_API_PYSIDE2, QT_API_PYQT, QT_API_PYQT5, QT_API_PYQTv1,
- QT_API_PYQT_DEFAULT)
-
-#Constraints placed on an imported matplotlib
-def matplotlib_options(mpl):
- if mpl is None:
- return
- backend = mpl.rcParams.get('backend', None)
- if backend == 'Qt4Agg':
- mpqt = mpl.rcParams.get('backend.qt4', None)
- if mpqt is None:
- return None
- if mpqt.lower() == 'pyside':
- return [QT_API_PYSIDE]
- elif mpqt.lower() == 'pyqt4':
- return [QT_API_PYQT_DEFAULT]
- elif mpqt.lower() == 'pyqt4v2':
- return [QT_API_PYQT]
- raise ImportError("unhandled value for backend.qt4 from matplotlib: %r" %
- mpqt)
- elif backend == 'Qt5Agg':
- mpqt = mpl.rcParams.get('backend.qt5', None)
- if mpqt is None:
- return None
- if mpqt.lower() == 'pyqt5':
- return [QT_API_PYQT5]
- raise ImportError("unhandled value for backend.qt5 from matplotlib: %r" %
- mpqt)
-
-def get_options():
- """Return a list of acceptable QT APIs, in decreasing order of
- preference
- """
- #already imported Qt somewhere. Use that
- loaded = loaded_api()
- if loaded is not None:
- return [loaded]
-
- mpl = sys.modules.get('matplotlib', None)
-
- if mpl is not None and not check_version(mpl.__version__, '1.0.2'):
- #1.0.1 only supports PyQt4 v1
- return [QT_API_PYQT_DEFAULT]
-
- qt_api = os.environ.get('QT_API', None)
- if qt_api is None:
- #no ETS variable. Ask mpl, then use default fallback path
- return matplotlib_options(mpl) or [QT_API_PYQT_DEFAULT, QT_API_PYSIDE,
- QT_API_PYQT5, QT_API_PYSIDE2]
- elif qt_api not in _qt_apis:
- raise RuntimeError("Invalid Qt API %r, valid values are: %r" %
- (qt_api, ', '.join(_qt_apis)))
- else:
- return [qt_api]
-
-api_opts = get_options()
-QtCore, QtGui, QtSvg, QT_API = load_qt(api_opts)
diff --git a/contrib/python/ipython/py2/IPython/external/qt_loaders.py b/contrib/python/ipython/py2/IPython/external/qt_loaders.py
deleted file mode 100644
index 3b894fb2abd..00000000000
--- a/contrib/python/ipython/py2/IPython/external/qt_loaders.py
+++ /dev/null
@@ -1,372 +0,0 @@
-"""
-This module contains factory functions that attempt
-to return Qt submodules from the various python Qt bindings.
-
-It also protects against double-importing Qt with different
-bindings, which is unstable and likely to crash
-
-This is used primarily by qt and qt_for_kernel, and shouldn't
-be accessed directly from the outside
-"""
-import sys
-import types
-from functools import partial
-
-from IPython.utils.version import check_version
-
-# Available APIs.
-QT_API_PYQT = 'pyqt' # Force version 2
-QT_API_PYQT5 = 'pyqt5'
-QT_API_PYQTv1 = 'pyqtv1' # Force version 2
-QT_API_PYQT_DEFAULT = 'pyqtdefault' # use system default for version 1 vs. 2
-QT_API_PYSIDE = 'pyside'
-QT_API_PYSIDE2 = 'pyside2'
-
-api_to_module = {QT_API_PYSIDE2: 'PySide2',
- QT_API_PYSIDE: 'PySide',
- QT_API_PYQT: 'PyQt4',
- QT_API_PYQTv1: 'PyQt4',
- QT_API_PYQT5: 'PyQt5',
- QT_API_PYQT_DEFAULT: 'PyQt4',
- }
-
-
-class ImportDenier(object):
- """Import Hook that will guard against bad Qt imports
- once IPython commits to a specific binding
- """
-
- def __init__(self):
- self.__forbidden = set()
-
- def forbid(self, module_name):
- sys.modules.pop(module_name, None)
- self.__forbidden.add(module_name)
-
- def find_module(self, fullname, path=None):
- if path:
- return
- if fullname in self.__forbidden:
- return self
-
- def load_module(self, fullname):
- raise ImportError("""
- Importing %s disabled by IPython, which has
- already imported an Incompatible QT Binding: %s
- """ % (fullname, loaded_api()))
-
-ID = ImportDenier()
-sys.meta_path.insert(0, ID)
-
-
-def commit_api(api):
- """Commit to a particular API, and trigger ImportErrors on subsequent
- dangerous imports"""
-
- if api == QT_API_PYSIDE2:
- ID.forbid('PySide')
- ID.forbid('PyQt4')
- ID.forbid('PyQt5')
- if api == QT_API_PYSIDE:
- ID.forbid('PySide2')
- ID.forbid('PyQt4')
- ID.forbid('PyQt5')
- elif api == QT_API_PYQT5:
- ID.forbid('PySide2')
- ID.forbid('PySide')
- ID.forbid('PyQt4')
- else: # There are three other possibilities, all representing PyQt4
- ID.forbid('PyQt5')
- ID.forbid('PySide2')
- ID.forbid('PySide')
-
-
-def loaded_api():
- """Return which API is loaded, if any
-
- If this returns anything besides None,
- importing any other Qt binding is unsafe.
-
- Returns
- -------
- None, 'pyside2', 'pyside', 'pyqt', 'pyqt5', or 'pyqtv1'
- """
- if 'PyQt4.QtCore' in sys.modules:
- if qtapi_version() == 2:
- return QT_API_PYQT
- else:
- return QT_API_PYQTv1
- elif 'PySide.QtCore' in sys.modules:
- return QT_API_PYSIDE
- elif 'PySide2.QtCore' in sys.modules:
- return QT_API_PYSIDE2
- elif 'PyQt5.QtCore' in sys.modules:
- return QT_API_PYQT5
- return None
-
-
-def has_binding(api):
- """Safely check for PyQt4/5, PySide or PySide2, without importing submodules
-
- Supports Python <= 3.3
-
- Parameters
- ----------
- api : str [ 'pyqtv1' | 'pyqt' | 'pyqt5' | 'pyside' | 'pyside2' | 'pyqtdefault']
- Which module to check for
-
- Returns
- -------
- True if the relevant module appears to be importable
- """
- # we can't import an incomplete pyside and pyqt4
- # this will cause a crash in sip (#1431)
- # check for complete presence before importing
- module_name = api_to_module[api]
-
- import imp
- try:
- #importing top level PyQt4/PySide module is ok...
- mod = __import__(module_name)
- #...importing submodules is not
- imp.find_module('QtCore', mod.__path__)
- imp.find_module('QtGui', mod.__path__)
- imp.find_module('QtSvg', mod.__path__)
- if api in (QT_API_PYQT5, QT_API_PYSIDE2):
- # QT5 requires QtWidgets too
- imp.find_module('QtWidgets', mod.__path__)
-
- #we can also safely check PySide version
- if api == QT_API_PYSIDE:
- return check_version(mod.__version__, '1.0.3')
- else:
- return True
- except ImportError:
- return False
-
-def has_binding_new(api):
- """Safely check for PyQt4/5, PySide or PySide2, without importing submodules
-
- Supports Python >= 3.4
-
- Parameters
- ----------
- api : str [ 'pyqtv1' | 'pyqt' | 'pyqt5' | 'pyside' | 'pyside2' | 'pyqtdefault']
- Which module to check for
-
- Returns
- -------
- True if the relevant module appears to be importable
- """
- module_name = api_to_module[api]
- from importlib.util import find_spec
-
- required = ['QtCore', 'QtGui', 'QtSvg']
- if api in (QT_API_PYQT5, QT_API_PYSIDE2):
- # QT5 requires QtWidgets too
- required.append('QtWidgets')
-
- for submod in required:
- try:
- spec = find_spec('%s.%s' % (module_name, submod))
- except ImportError:
- # Package (e.g. PyQt5) not found
- return False
- else:
- if spec is None:
- # Submodule (e.g. PyQt5.QtCore) not found
- return False
-
- if api == QT_API_PYSIDE:
- # We can also safely check PySide version
- import PySide
- return check_version(PySide.__version__, '1.0.3')
-
- return True
-
-if sys.version_info >= (3, 4):
- has_binding = has_binding_new
-
-def qtapi_version():
- """Return which QString API has been set, if any
-
- Returns
- -------
- The QString API version (1 or 2), or None if not set
- """
- try:
- import sip
- except ImportError:
- return
- try:
- return sip.getapi('QString')
- except ValueError:
- return
-
-
-def can_import(api):
- """Safely query whether an API is importable, without importing it"""
- if not has_binding(api):
- return False
-
- current = loaded_api()
- if api == QT_API_PYQT_DEFAULT:
- return current in [QT_API_PYQT, QT_API_PYQTv1, None]
- else:
- return current in [api, None]
-
-
-def import_pyqt4(version=2):
- """
- Import PyQt4
-
- Parameters
- ----------
- version : 1, 2, or None
- Which QString/QVariant API to use. Set to None to use the system
- default
-
- ImportErrors rasied within this function are non-recoverable
- """
- # The new-style string API (version=2) automatically
- # converts QStrings to Unicode Python strings. Also, automatically unpacks
- # QVariants to their underlying objects.
- import sip
-
- if version is not None:
- sip.setapi('QString', version)
- sip.setapi('QVariant', version)
-
- from PyQt4 import QtGui, QtCore, QtSvg
-
- if not check_version(QtCore.PYQT_VERSION_STR, '4.7'):
- raise ImportError("IPython requires PyQt4 >= 4.7, found %s" %
- QtCore.PYQT_VERSION_STR)
-
- # Alias PyQt-specific functions for PySide compatibility.
- QtCore.Signal = QtCore.pyqtSignal
- QtCore.Slot = QtCore.pyqtSlot
-
- # query for the API version (in case version == None)
- version = sip.getapi('QString')
- api = QT_API_PYQTv1 if version == 1 else QT_API_PYQT
- return QtCore, QtGui, QtSvg, api
-
-
-def import_pyqt5():
- """
- Import PyQt5
-
- ImportErrors rasied within this function are non-recoverable
- """
- import sip
-
- from PyQt5 import QtCore, QtSvg, QtWidgets, QtGui
-
- # Alias PyQt-specific functions for PySide compatibility.
- QtCore.Signal = QtCore.pyqtSignal
- QtCore.Slot = QtCore.pyqtSlot
-
- # Join QtGui and QtWidgets for Qt4 compatibility.
- QtGuiCompat = types.ModuleType('QtGuiCompat')
- QtGuiCompat.__dict__.update(QtGui.__dict__)
- QtGuiCompat.__dict__.update(QtWidgets.__dict__)
-
- api = QT_API_PYQT5
- return QtCore, QtGuiCompat, QtSvg, api
-
-
-def import_pyside():
- """
- Import PySide
-
- ImportErrors raised within this function are non-recoverable
- """
- from PySide import QtGui, QtCore, QtSvg
- return QtCore, QtGui, QtSvg, QT_API_PYSIDE
-
-def import_pyside2():
- """
- Import PySide2
-
- ImportErrors raised within this function are non-recoverable
- """
- from PySide2 import QtGui, QtCore, QtSvg, QtWidgets, QtPrintSupport
-
- # Join QtGui and QtWidgets for Qt4 compatibility.
- QtGuiCompat = types.ModuleType('QtGuiCompat')
- QtGuiCompat.__dict__.update(QtGui.__dict__)
- QtGuiCompat.__dict__.update(QtWidgets.__dict__)
- QtGuiCompat.__dict__.update(QtPrintSupport.__dict__)
-
- return QtCore, QtGuiCompat, QtSvg, QT_API_PYSIDE2
-
-
-def load_qt(api_options):
- """
- Attempt to import Qt, given a preference list
- of permissible bindings
-
- It is safe to call this function multiple times.
-
- Parameters
- ----------
- api_options: List of strings
- The order of APIs to try. Valid items are 'pyside', 'pyside2',
- 'pyqt', 'pyqt5', 'pyqtv1' and 'pyqtdefault'
-
- Returns
- -------
-
- A tuple of QtCore, QtGui, QtSvg, QT_API
- The first three are the Qt modules. The last is the
- string indicating which module was loaded.
-
- Raises
- ------
- ImportError, if it isn't possible to import any requested
- bindings (either becaues they aren't installed, or because
- an incompatible library has already been installed)
- """
- loaders = {
- QT_API_PYSIDE2: import_pyside2,
- QT_API_PYSIDE: import_pyside,
- QT_API_PYQT: import_pyqt4,
- QT_API_PYQT5: import_pyqt5,
- QT_API_PYQTv1: partial(import_pyqt4, version=1),
- QT_API_PYQT_DEFAULT: partial(import_pyqt4, version=None)
- }
-
- for api in api_options:
-
- if api not in loaders:
- raise RuntimeError(
- "Invalid Qt API %r, valid values are: %s" %
- (api, ", ".join(["%r" % k for k in loaders.keys()])))
-
- if not can_import(api):
- continue
-
- #cannot safely recover from an ImportError during this
- result = loaders[api]()
- api = result[-1] # changed if api = QT_API_PYQT_DEFAULT
- commit_api(api)
- return result
- else:
- raise ImportError("""
- Could not load requested Qt binding. Please ensure that
- PyQt4 >= 4.7, PyQt5, PySide >= 1.0.3 or PySide2 is available,
- and only one is imported per session.
-
- Currently-imported Qt library: %r
- PyQt4 available (requires QtCore, QtGui, QtSvg): %s
- PyQt5 available (requires QtCore, QtGui, QtSvg, QtWidgets): %s
- PySide >= 1.0.3 installed: %s
- PySide2 installed: %s
- Tried to load: %r
- """ % (loaded_api(),
- has_binding(QT_API_PYQT),
- has_binding(QT_API_PYQT5),
- has_binding(QT_API_PYSIDE),
- has_binding(QT_API_PYSIDE2),
- api_options))