Skip to content

Commit

Permalink
Merge from 3.x: PR #6961
Browse files Browse the repository at this point in the history
Fixes #6889.
  • Loading branch information
ccordoba12 committed May 21, 2018
2 parents 3be6b63 + 2c6c90f commit f09c67b
Show file tree
Hide file tree
Showing 22 changed files with 38 additions and 101 deletions.
14 changes: 5 additions & 9 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,16 @@ sudo: false
matrix:
include:
- python: "2.7"
env: USE_PYQT=pyqt4
os: linux
- python: "2.7"
env: USE_PYQT=pyqt5
env: USE_PYQT=pyqt5 USE_CONDA=yes
os: linux
- python: "3.5"
env: USE_PYQT=pyqt4
env: USE_PYQT=pyqt5 USE_CONDA=yes
os: linux
# This slot runs our tests only with pip packages
- python: "3.5"
env: USE_PYQT=pyqt5
- python: "3.6"
env: USE_PYQT=pyqt5 USE_CONDA=yes
os: linux
- python: "3.6"
env: USE_PYQT=pyqt5
env: USE_PYQT=pyqt5 USE_CONDA=no
os: linux

before_install:
Expand Down
5 changes: 2 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,8 @@ the directory where your git clone is stored and run:
$ pip install -r requirements/requirements.txt
```

If you are using `pip` and Python 2, you also need to install a Qt binding
package (PyQt4 or PyQt5, with the latter strongly recommended).
This can be achieved by running:
If you are using `pip` and Python 3, you also need to install a Qt binding
package (PyQt5). This can be achieved by running:

```bash
$ pip install pyqt5
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ a Python version greater than 2.7 or 3.4 (Python <=3.3 is no longer supported).
### Runtime dependencies

* **Python** 2.7 or 3.4+: The core language Spyder is written in and for.
* **PyQt5** 5.2+: Python bindings for Qt, used for Spyder's GUI.
* **PyQt5** 5.5+: Python bindings for Qt, used for Spyder's GUI.
* **qtconsole** 4.2.0+: Enhanced Python interpreter.
* **Rope** 0.9.4+ and **Jedi** 0.11.0+: Editor code completion, calltips
and go-to-definition.
Expand Down
11 changes: 2 additions & 9 deletions bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,21 +122,14 @@
print("01. Patched sys.path with %s" % DEVPATH)


# Selecting the GUI toolkit: PyQt5 if installed, otherwise PySide or PyQt4
# (Note: PyQt4 is still the officially supported GUI toolkit for Spyder)
# Selecting the GUI toolkit: PyQt5 if installed
if args.gui is None:
try:
import PyQt5 # analysis:ignore
print("02. PyQt5 is detected, selecting")
os.environ['QT_API'] = 'pyqt5'
except ImportError:
try:
import PyQt4 # analysis:ignore
print("02. PyQt4 is detected, selecting")
os.environ['QT_API'] = 'pyqt'
except ImportError:
print("02. No PyQt5 or PyQt4 detected, using PySide if available "
"(deprecated)")
sys.exit("ERROR: No PyQt5 detected!")
else:
print ("02. Skipping GUI toolkit detection")
os.environ['QT_API'] = args.gui
Expand Down
8 changes: 0 additions & 8 deletions continuous_integration/circle/test-qt5.sh

This file was deleted.

6 changes: 1 addition & 5 deletions continuous_integration/travis/install-qt.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,11 @@
export PATH="$HOME/miniconda/bin:$PATH"
source activate test

# We test with pip packages in Python 3.5 and PyQt5
if [ "$TRAVIS_PYTHON_VERSION" = "3.5" ] && [ "$USE_PYQT" = "pyqt5" ]; then
if [ "$USE_CONDA" = "no" ]; then
pip uninstall -q -y pytest-xvfb
# 5.10 is giving segfaults while collecting tests
pip install -q pyqt5==5.9.2

# Install qtconsole from Github
pip install git+https://github.com/jupyter/qtconsole.git

# Install qtpy from Github
pip install git+https://github.com/spyder-ide/qtpy.git
elif [ "$USE_PYQT" = "pyqt5" ]; then
Expand Down
6 changes: 2 additions & 4 deletions continuous_integration/travis/install.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#!/bin/bash

# We test with pip packages in Python 3.5 and PyQt5
if [ "$TRAVIS_PYTHON_VERSION" = "3.5" ] && [ "$USE_PYQT" = "pyqt5" ]; then
if [ "$USE_CONDA" = "no" ]; then
export PIP_DEPENDENCIES_FLAGS="-q"
export PIP_DEPENDENCIES="coveralls"
export CONDA_DEPENDENCIES=""
Expand All @@ -23,8 +22,7 @@ export PATH="$HOME/miniconda/bin:$PATH"
source activate test


# We test with pip packages in Python 3.5 and PyQt5
if [ "$TRAVIS_PYTHON_VERSION" = "3.5" ] && [ "$USE_PYQT" = "pyqt5" ]; then
if [ "$USE_CONDA" = "no" ]; then
# Install qtconsole from Github
pip install git+https://github.com/jupyter/qtconsole.git

Expand Down
4 changes: 1 addition & 3 deletions doc/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,7 @@ The requirements to run Spyder are:

* `Python <http://www.python.org/>`_ 2.7 or >=3.3

* `PyQt5 <https://www.riverbankcomputing.com/software/pyqt/download5>`_ >=5.2 or
`PyQt4 <https://www.riverbankcomputing.com/software/pyqt/download>`_ >=4.6.0
(PyQt5 is recommended).
* `PyQt5 <https://www.riverbankcomputing.com/software/pyqt/download5>`_ >=5.5

* `Qtconsole <http://jupyter.org/qtconsole/stable/>`_ >=4.2.0 -- for an
enhanced Python interpreter.
Expand Down
6 changes: 3 additions & 3 deletions doc/overview.rst
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,6 @@ Key features:
* :doc:`projects`


Spyder may also be used as a PyQt5 or PyQt4 extension library
(module 'spyder'). For example, the Python interactive shell widget
used in Spyder may be embedded in your own PyQt5 or PyQt4 application.
Spyder may also be used as a PyQt5 extension library (module
'spyder'). For example, the Python interactive shell widget
used in Spyder may be embedded in your own PyQt5 application.
6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,15 +233,15 @@ def run(self):
long_description=
"""Spyder is an interactive Python development environment providing
MATLAB-like features in a simple and light-weighted software.
It also provides ready-to-use pure-Python widgets to your PyQt5 or
PyQt4 application: source code editor with syntax highlighting and
It also provides ready-to-use pure-Python widgets to your PyQt5
application: A source code editor with syntax highlighting and
code introspection/analysis features, NumPy array editor, dictionary
editor, Python console, etc.""",
download_url='%s/files/%s-%s.zip' % (__project_url__, NAME, __version__),
author="The Spyder Project Contributors",
url=__project_url__,
license='MIT',
keywords='PyQt5 PyQt4 editor shell console widgets IDE',
keywords='PyQt5 editor shell console widgets IDE',
platforms=['any'],
packages=get_packages(),
package_data={LIBNAME: get_package_data(LIBNAME, EXTLIST),
Expand Down
2 changes: 1 addition & 1 deletion spyder/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def get_versions(reporev=True):
'python': platform.python_version(), # "2.7.3"
'bitness': 64 if sys.maxsize > 2**32 else 32,
'qt': qtpy.QtCore.__version__,
'qt_api': qtpy.API_NAME, # PyQt5 or PyQt4
'qt_api': qtpy.API_NAME, # PyQt5
'qt_api_ver': qtpy.PYQT_VERSION,
'system': system, # Linux, Windows, ...
'release': platform.release(), # XP, 10.6, 2.2.0, etc.
Expand Down
20 changes: 4 additions & 16 deletions spyder/app/mainwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,8 @@
from qtpy.QtWidgets import (QAction, QApplication, QDockWidget, QMainWindow,
QMenu, QMessageBox, QShortcut, QSplashScreen,
QStyleFactory)

# Avoid a "Cannot mix incompatible Qt library" error on Windows platforms
# when PySide is selected by the QT_API environment variable and when PyQt4
# is also installed (or any other Qt-based application prepending a directory
# containing incompatible Qt DLLs versions in PATH):
from qtpy import QtSvg # analysis:ignore

# Avoid a bug in Qt: https://bugreports.qt.io/browse/QTBUG-46720
Expand Down Expand Up @@ -243,12 +241,6 @@ class MainWindow(QMainWindow):
_("Numpy and Scipy documentation")),
('matplotlib', "http://matplotlib.sourceforge.net/contents.html",
_("Matplotlib documentation")),
('PyQt4',
"http://pyqt.sourceforge.net/Docs/PyQt4/",
_("PyQt4 Reference Guide")),
('PyQt4',
"http://pyqt.sourceforge.net/Docs/PyQt4/classes.html",
_("PyQt4 API Reference")),
('PyQt5',
"http://pyqt.sourceforge.net/Docs/PyQt5/",
_("PyQt5 Reference Guide")),
Expand Down Expand Up @@ -732,11 +724,7 @@ def create_edit_action(text, tr_text, icon):
if qtlact:
break
args = ['-no-opengl'] if os.name == 'nt' else []
qteact = create_python_script_action(self,
_("Qt examples"), 'qt.png', "PyQt4",
osp.join("examples", "demos",
"qtdemo", "qtdemo"), args)
for act in (qtdact, qtlact, qteact):
for act in (qtdact, qtlact):
if act:
additact.append(act)
if additact and is_module_installed('winpython'):
Expand All @@ -757,7 +745,7 @@ def create_edit_action(text, tr_text, icon):
"guidata",
osp.join("tests", "__init__"))
gdgq_act += [guidata_act]
except (ImportError, AssertionError):
except:
pass
try:
from guidata import configtools
Expand All @@ -773,7 +761,7 @@ def create_edit_action(text, tr_text, icon):
sift_icon, "guiqwt", osp.join("tests", "sift"))
if sift_act:
gdgq_act += [sift_act]
except (ImportError, AssertionError):
except:
pass
if gdgq_act:
self.external_tools_menu_actions += [None] + gdgq_act
Expand Down
5 changes: 2 additions & 3 deletions spyder/app/tests/test_mainwindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import numpy as np
from numpy.testing import assert_array_equal
import pytest
from qtpy import PYQT4, PYQT5, PYQT_VERSION
from qtpy import PYQT5, PYQT_VERSION
from qtpy.QtCore import Qt, QTimer, QEvent, QUrl
from qtpy.QtTest import QTest
from qtpy.QtGui import QImage
Expand Down Expand Up @@ -360,8 +360,7 @@ def test_single_instance_and_edit_magic(main_window, qtbot, tmpdir):

@pytest.mark.slow
@flaky(max_runs=3)
@pytest.mark.skipif(os.name == 'nt' or PY2 or PYQT4,
reason="It fails sometimes")
@pytest.mark.skipif(os.name == 'nt' or PY2, reason="It fails sometimes")
def test_move_to_first_breakpoint(main_window, qtbot):
"""Test that we move to the first breakpoint if there's one present."""
# Wait until the window is fully up
Expand Down
1 change: 0 additions & 1 deletion spyder/plugins/tests/test_editor_introspection.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
from unittest.mock import Mock
except ImportError:
from mock import Mock # Python 2
from qtpy import PYQT4
from qtpy.QtWidgets import QWidget, QApplication
from qtpy.QtCore import Qt

Expand Down
7 changes: 3 additions & 4 deletions spyder/plugins/tests/test_ipythonconsole.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import ipykernel
from pygments.token import Name
import pytest
from qtpy import PYQT4, PYQT5
from qtpy import PYQT5
from qtpy.QtCore import Qt
import zmq

Expand Down Expand Up @@ -112,8 +112,7 @@ def close_console():
@pytest.mark.slow
@flaky(max_runs=3)
@pytest.mark.auto_backend
@pytest.mark.skipif(os.name == 'nt' or PYQT4,
reason="It times out sometimes on Windows and it's not needed in PyQt4")
@pytest.mark.skipif(os.name == 'nt', reason="It times out sometimes on Windows")
@pytest.mark.xfail(zmq.__version__ >= '17.0.0' and ipykernel.__version__ <= "4.8.1",
reason="A bug with pyzmq 17 and ipykernel 4.8.1")
def test_auto_backend(ipyconsole, qtbot):
Expand Down Expand Up @@ -630,7 +629,7 @@ def add(x, y):

@pytest.mark.slow
@flaky(max_runs=3)
@pytest.mark.skipif(os.name == 'nt' or (PY2 and PYQT5) or PYQT4,
@pytest.mark.skipif(os.name == 'nt' or (PY2 and PYQT5),
reason="It times out frequently")
def test_mpl_backend_change(ipyconsole, qtbot):
"""
Expand Down
2 changes: 1 addition & 1 deletion spyder/requirements.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def check_path():

def check_qt():
"""Check Qt binding requirements"""
qt_infos = dict(pyqt5=("PyQt5", "5.2"), pyqt=("PyQt4", "4.6"))
qt_infos = dict(pyqt5=("PyQt5", "5.5"))
try:
import qtpy
package_name, required_ver = qt_infos[qtpy.API]
Expand Down
4 changes: 2 additions & 2 deletions spyder/utils/dochelpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ def getsource(obj):
def getsignaturefromtext(text, objname):
"""Get object signatures from text (object documentation)
Return a list containing a single string in most cases
Example of multiple signatures: PyQt4 objects"""
Example of multiple signatures: PyQt5 objects"""
if isinstance(text, dict):
text = text.get('docstring', '')
# Regexps
Expand Down Expand Up @@ -242,7 +242,7 @@ def getargs(obj):
if args is not None:
return args
else:
# Example: PyQt4
# Example: PyQt5
return getargsfromdoc(obj)
args, _, _ = inspect.getargs(func_obj.func_code)
if not args:
Expand Down
11 changes: 0 additions & 11 deletions spyder/widgets/editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
from collections import MutableSequence

# Third party imports
from qtpy import is_pyqt46
from qtpy.compat import getsavefilename
from qtpy.QtCore import (QByteArray, QFileInfo, QObject, QPoint, QSize, Qt,
QThread, QTimer, Signal, Slot)
Expand Down Expand Up @@ -844,8 +843,6 @@ def closeEvent(self, event):
self.outlineexplorer.remove_editor(finfo.editor)

QWidget.closeEvent(self, event)
if is_pyqt46:
self.destroyed.emit()

def clone_editor_from(self, other_finfo, set_current):
fname = other_finfo.filename
Expand Down Expand Up @@ -2571,8 +2568,6 @@ def closeEvent(self, event):
receives a window close request from a top-level widget.
"""
QSplitter.closeEvent(self, event)
if is_pyqt46:
self.destroyed.emit()

def __give_focus_to_remaining_editor(self):
focus_widget = self.plugin.get_focus_widget()
Expand Down Expand Up @@ -2918,12 +2913,6 @@ def resizeEvent(self, event):
def closeEvent(self, event):
"""Reimplement Qt method"""
QMainWindow.closeEvent(self, event)
if is_pyqt46:
self.destroyed.emit()
for editorstack in self.editorwidget.editorstacks[:]:
if DEBUG_EDITOR:
print("--> destroy_editorstack:", editorstack, file=STDOUT)
editorstack.destroyed.emit()

def get_layout_settings(self):
"""Return layout state"""
Expand Down
13 changes: 5 additions & 8 deletions spyder/widgets/explorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import mimetypes as mime

# Third party imports
from qtpy import API, is_pyqt46
from qtpy.compat import getsavefilename, getexistingdirectory
from qtpy.QtCore import (QDir, QFileInfo, QMimeData, QSize,
QSortFilterProxyModel, Qt, QTimer, QUrl,
Expand Down Expand Up @@ -219,9 +218,8 @@ def install_model(self):
def setup_view(self):
"""Setup view"""
self.install_model()
if not is_pyqt46:
self.fsmodel.directoryLoaded.connect(
lambda: self.resizeColumnToContents(0))
self.fsmodel.directoryLoaded.connect(
lambda: self.resizeColumnToContents(0))
self.setAnimated(False)
self.setSortingEnabled(True)
self.sortByColumn(0, Qt.AscendingOrder)
Expand Down Expand Up @@ -915,7 +913,7 @@ def restore_directory_state(self, fname):
self._to_be_loaded = []
self._to_be_loaded.append(path)
self.setExpanded(self.get_index(path), True)
if not self.__expanded_state and not is_pyqt46:
if not self.__expanded_state:
self.fsmodel.directoryLoaded.disconnect(self.restore_directory_state)

def follow_directories_loaded(self, fname):
Expand All @@ -925,8 +923,7 @@ def follow_directories_loaded(self, fname):
path = osp.normpath(to_text_string(fname))
if path in self._to_be_loaded:
self._to_be_loaded.remove(path)
if self._to_be_loaded is not None and len(self._to_be_loaded) == 0 \
and not is_pyqt46:
if self._to_be_loaded is not None and len(self._to_be_loaded) == 0:
self.fsmodel.directoryLoaded.disconnect(
self.follow_directories_loaded)
if self._scrollbar_positions is not None:
Expand All @@ -937,7 +934,7 @@ def restore_expanded_state(self):
"""Restore all items expanded state"""
if self.__expanded_state is not None:
# In the old project explorer, the expanded state was a dictionnary:
if isinstance(self.__expanded_state, list) and not is_pyqt46:
if isinstance(self.__expanded_state, list):
self.fsmodel.directoryLoaded.connect(
self.restore_directory_state)
self.fsmodel.directoryLoaded.connect(
Expand Down
Loading

0 comments on commit f09c67b

Please sign in to comment.