New Upstream Snapshot - python-quamash

Ready changes

Summary

Merged new upstream version: 0.6.1+git20211220.1.d9520f4~dfsg (was: 0.6.1~dfsg).

Resulting package

Built on 2023-01-03T16:05 (took 3m50s)

The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:

apt install -t fresh-snapshots python3-quamash

Lintian Result

Diff

diff --git a/.coveragerc b/.coveragerc
deleted file mode 100644
index 7469c66..0000000
--- a/.coveragerc
+++ /dev/null
@@ -1,25 +0,0 @@
-[run]
-branch=True
-
-[report]
-# Regexes for lines to exclude from consideration
-exclude_lines =
-    # Have to re-enable the standard pragma
-    pragma: no cover
-
-    # Don't complain about missing debug-only code:
-    def __repr__
-    if self\.debug
-
-    # Don't complain if tests don't hit defensive assertion code:
-    raise AssertionError
-    raise NotImplementedError
-
-    # Don't complain if non-runnable code isn't run:
-    if 0:
-    if __name__ == .__main__.:
-
-[paths]
-source=
-	/quamash/  # change to linux source path
-	C:\quamash\ # change to windows source path
diff --git a/.dockerignore b/.dockerignore
deleted file mode 100644
index a26935f..0000000
--- a/.dockerignore
+++ /dev/null
@@ -1,7 +0,0 @@
-*.env
-.tox
-.git
-__pycache__
-*.pyc
-*.egg-info
-.cache
diff --git a/.editorconfig b/.editorconfig
deleted file mode 100644
index d56be6e..0000000
--- a/.editorconfig
+++ /dev/null
@@ -1,12 +0,0 @@
-# Top-most EditorConfig file
-root = true
-
-# Unix-style newlines with a newline ending every file
-[*]
-end_of_line = lf
-insert_final_newline = true
-
-# 4 space tabbed indentation
-[*.py]
-indent_style = tab
-indent_size = 4
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 6fb1979..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,75 +0,0 @@
-language: python
-python:
-  - "3.4"
-  - "3.5"
-  - "3.6"
-before_install:
-  - export DISPLAY=:99.0
-  - sh -e /etc/init.d/xvfb start
-  # Cached Downloads
-  - sudo mkdir -p /downloads
-  - sudo chmod a+rw /downloads
-  - if [ ! -f /downloads/sip.tar.gz ];   then curl -L -o /downloads/sip.tar.gz https://sourceforge.net/projects/pyqt/files/sip/sip-4.19.3/sip-4.19.3.tar.gz; fi
-  - if [ ! -f /downloads/pyqt4.tar.gz ]; then curl -L -o /downloads/pyqt4.tar.gz https://sourceforge.net/projects/pyqt/files/PyQt4/PyQt-4.12.1/PyQt4_gpl_x11-4.12.1.tar.gz; fi
-  - if [ ! -f /downloads/pyqt5.tar.gz ]; then curl -L -o /downloads/pyqt5.tar.gz https://sourceforge.net/projects/pyqt/files/PyQt5/PyQt-5.9/PyQt5_gpl-5.9.tar.gz; fi
-  - echo '4708187f74a4188cb4e294060707106f  /downloads/sip.tar.gz' | md5sum -c -
-  - echo '0112e15858cd7d318a09e7366922f874  /downloads/pyqt4.tar.gz' | md5sum -c -
-  - echo 'a409ac0d65ead9178b90c2822759a84b  /downloads/pyqt5.tar.gz' | md5sum -c -
-  # Builds
-  - sudo mkdir -p /builds
-  - sudo chmod a+rw /builds
-install:
-  # Qt4
-  - sudo apt-get update
-  - sudo apt-get install -y libqt4-dev
-  # Qt5
-  - sudo add-apt-repository -y ppa:beineri/opt-qt591-trusty
-  - sudo apt-get update
-  - sudo apt-get install -y qt59base
-  # Builds
-  - pushd /builds
-  # SIP
-  - tar xzf /downloads/sip.tar.gz --keep-newer-files
-  - pushd sip-4.19.3
-  - python configure.py
-  - make
-  - sudo make install
-  - popd
-  # PyQt4
-  - tar xzf /downloads/pyqt4.tar.gz --keep-newer-files
-  - pushd PyQt4_gpl_x11-4.12.1
-  - python configure.py -c --confirm-license --no-designer-plugin -e QtCore -e QtGui
-  - make
-  - sudo make install
-  - popd
-  # PyQt5
-  - source /opt/qt59/bin/qt59-env.sh  # switch to Qt5
-  - tar xzf /downloads/pyqt5.tar.gz --keep-newer-files
-  - pushd PyQt5_gpl-5.9
-  - python configure.py -c --confirm-license --no-designer-plugin -e QtCore -e QtGui -e QtWidgets
-  - make
-  - sudo make install
-  - popd
-  # Builds Complete
-  - popd
-  # PySide
-  - if [ $TRAVIS_PYTHON_VERSION != '3.5' && $TRAVIS_PYTHON_VERSION != '3.6' ]; then pip install --find-links wheelhouse/ pyside; fi
-  # flake8 style checker
-  - pip install flake8 pep8-naming flake8-debugger flake8-docstrings pytest-timeout flake8-commas
-script:
-  - flake8
-  - flake8 --select=D1 quamash/*.py
-  - if [ $TRAVIS_PYTHON_VERSION != '3.5' && $TRAVIS_PYTHON_VERSION != '3.6']; then QUAMASH_QTIMPL=PySide py.test; fi
-  - QUAMASH_QTIMPL=PyQt4 py.test
-  - QUAMASH_QTIMPL=PyQt5 py.test
-cache:
-  directories:
-    - /downloads
-  apt: true
-notifications:
-  webhooks:
-    urls:
-      - https://webhooks.gitter.im/e/0ed6fa8828890c4a49ea
-    on_success: change
-    on_failure: always
-    on_start: false
diff --git a/Dockerfile b/Dockerfile
deleted file mode 100644
index 2801b38..0000000
--- a/Dockerfile
+++ /dev/null
@@ -1,41 +0,0 @@
-FROM ubuntu:14.04
-RUN apt-get update -y && apt-get install -y curl build-essential software-properties-common python-software-properties
-
-RUN \
-  sudo mkdir -p /downloads && \
-  sudo chmod a+rw /downloads && \
-  if [ ! -f /downloads/sip.tar.gz ];   then curl -L -o /downloads/sip.tar.gz https://sourceforge.net/projects/pyqt/files/sip/sip-4.19.3/sip-4.19.3.tar.gz; fi && \
-  if [ ! -f /downloads/pyqt4.tar.gz ]; then curl -L -o /downloads/pyqt4.tar.gz https://sourceforge.net/projects/pyqt/files/PyQt4/PyQt-4.12.1/PyQt4_gpl_x11-4.12.1.tar.gz; fi && \
-  if [ ! -f /downloads/pyqt5.tar.gz ]; then curl -L -o /downloads/pyqt5.tar.gz https://sourceforge.net/projects/pyqt/files/PyQt5/PyQt-5.9/PyQt5_gpl-5.9.tar.gz; fi && \
-  echo '4708187f74a4188cb4e294060707106f  /downloads/sip.tar.gz' | md5sum -c - && \
-  echo '0112e15858cd7d318a09e7366922f874  /downloads/pyqt4.tar.gz' | md5sum -c - && \
-  echo 'a409ac0d65ead9178b90c2822759a84b  /downloads/pyqt5.tar.gz' | md5sum -c - && \
-  sudo mkdir -p /builds && \
-  sudo chmod a+rw /builds && \
-  cd /builds && \
-  tar xzf /downloads/sip.tar.gz --keep-newer-files && \
-  tar xzf /downloads/pyqt4.tar.gz --keep-newer-files && \
-  tar xzf /downloads/pyqt5.tar.gz --keep-newer-files && \
-  sudo apt-get install -y libqt4-dev && \
-  sudo add-apt-repository -y ppa:beineri/opt-qt591-trusty && \
-  sudo add-apt-repository -y ppa:deadsnakes/ppa && \
-  sudo apt-get update && \
-  sudo apt-get install -y qt59base python3.4-dev python3.5-dev python3.6-dev
-SHELL ["/bin/bash", "-c"]
-RUN \
-  for python in python3.4 python3.5 python3.6; do \
-    cd /builds/sip-4.19.3 && \
-    $python configure.py && \
-    make clean && make && make install && \
-    cd /builds/PyQt4_gpl_x11-4.12.1 && \
-    $python configure.py -c --confirm-license --no-designer-plugin -e QtCore -e QtGui && \
-    make clean && make && make install && \
-    cd /builds/PyQt5_gpl-5.9 && \
-    ( \
-    . /opt/qt59/bin/qt59-env.sh && \
-    $python configure.py -c --confirm-license --no-designer-plugin -e QtCore -e QtGui -e QtWidgets && \
-    make clean && make && make install; \
-    ) \
-  done
-ADD . /quamash
-WORKDIR /quamash
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..e7388ad
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,288 @@
+Metadata-Version: 2.1
+Name: Quamash
+Version: 0.6.1
+Summary: Implementation of the PEP 3156 Event-Loop with Qt.
+Home-page: https://github.com/harvimt/quamash
+Author: Mark Harviston, Arve Knudsen
+Author-email: mark.harviston@gmail.com, arve.knudsen@gmail.com
+License: BSD
+Keywords: Qt,asyncio
+Classifier: Development Status :: 3 - Alpha
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Intended Audience :: Developers
+Classifier: Operating System :: Microsoft :: Windows
+Classifier: Operating System :: MacOS :: MacOS X
+Classifier: Operating System :: POSIX
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3 :: Only
+Classifier: Environment :: X11 Applications :: Qt
+Provides-Extra: test
+License-File: LICENSE
+
+=======
+Quamash
+=======
+Implementation of the `PEP 3156`_ Event-Loop with Qt
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+:author: Mark Harviston <mark.harviston@gmail.com>, Arve Knudsen <arve.knudsen@gmail.com>
+
+.. image:: https://img.shields.io/pypi/v/quamash.svg
+    :target: https://pypi.python.org/pypi/quamash/
+    :alt: Latest Version
+
+.. image:: https://img.shields.io/pypi/dm/quamash.svg
+    :target: https://pypi.python.org/pypi/quamash/
+    :alt: Downloads
+
+.. image:: https://img.shields.io/pypi/pyversions/quamash.svg
+    :target: https://pypi.python.org/pypi/quamash/
+    :alt: Supported Python versions
+
+.. image:: https://img.shields.io/pypi/l/quamash.svg
+    :target: https://pypi.python.org/pypi/quamash/
+    :alt: License
+
+.. image:: https://img.shields.io/pypi/status/Django.svg
+    :target: https://pypi.python.org/pypi/quamash/
+    :alt: Development Status
+
+.. image:: https://travis-ci.org/harvimt/quamash.svg?branch=master
+    :target: https://travis-ci.org/harvimt/quamash
+    :alt: Linux (Travis CI) Build Status
+
+.. image:: https://img.shields.io/appveyor/ci/harvimt/quamash.svg
+    :target: https://ci.appveyor.com/project/harvimt/quamash/branch/master
+    :alt: Windows (Appveyor) Build Status
+
+.. image:: https://badges.gitter.im/Join%20Chat.svg
+    :target: https://gitter.im/harvimt/quamash?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge
+    :alt: Gitter
+
+Requirements
+============
+Quamash requires Python 3.4 or Python 3.3 with the backported ``asyncio`` library and either PyQt4, PyQt5 or PySide.
+
+Installation
+============
+``pip install quamash``
+
+Upgrade from Version 0.4 to 0.5
+===============================
+The loop context manager will no longer set the event loop only close it.
+
+Instead of:
+
+.. code:: python
+
+    with loop:
+        loop.run_forever()
+
+do:
+
+.. code:: python
+
+    asyncio.set_event_loop(loop)
+    # ...
+    with loop:
+        loop.run_forever()
+
+It is recommended that you call ``asyncio.set_event_loop`` as early as possible (immediately after instantiating the loop),
+to avoid running asynchronous code before ``asyncio.set_event_loop`` is called.
+
+If you're using multiple different loops in the same application, you know what you're doing (or at least you hope you do),
+then you can ignore this advice.
+
+
+Usage
+=====
+
+.. code:: python
+
+    import sys
+    import asyncio
+    import time
+
+    from PyQt5.QtWidgets import QApplication, QProgressBar
+    from quamash import QEventLoop, QThreadExecutor
+
+    app = QApplication(sys.argv)
+    loop = QEventLoop(app)
+    asyncio.set_event_loop(loop)  # NEW must set the event loop
+
+    progress = QProgressBar()
+    progress.setRange(0, 99)
+    progress.show()
+
+    async def master():
+        await first_50()
+        with QThreadExecutor(1) as exec:
+            await loop.run_in_executor(exec, last_50)
+        # TODO announce completion?
+
+    async def first_50():
+        for i in range(50):
+            progress.setValue(i)
+            await asyncio.sleep(.1)
+
+    def last_50():
+        for i in range(50,100):
+            loop.call_soon_threadsafe(progress.setValue, i)
+            time.sleep(.1)
+
+    with loop: ## context manager calls .close() when loop completes, and releases all resources
+        loop.run_until_complete(master())
+
+Changelog
+=========
+
+Version 0.6.1
+* Python 3.7 support (no automated test coverage)
+
+Version 0.6.0
+-------------
+* Lots of bugfixes and performance improvements.
+
+
+Version 0.5.5
+-------------
+* Fix `#62`_ a serious memory leak by switching from ``QTimer`` to ``QObject.timerEvent``.
+
+Version 0.5.4
+-------------
+* Remove unnecessary QObjects
+* Officially add Python 3.5 support (CI configuration and setup.py change)
+* Fix `#55`_
+* Better compatibility with behavior of default event loop (`#59`_)
+* Remove _easycallback and replace with _makeSignaller
+
+Version 0.5.3
+-------------
+* Fix to `#34`_
+
+Version 0.5.2
+-------------
+* Fixes to tests, and CI configuration
+* Fixes `#35`_ and `#31`_ (both minor bugs)
+* Uploade wheels to PyPI
+
+Version 0.5.1
+-------------
+* Fixes rst syntax error in this README
+
+Version 0.5
+-----------
+* Deprecation of event loop as means to ``asyncio.set_event_loop``, now must be called explicitly.
+* Possible fix to notifiers being called out-of-order (see #25, #27, and e64119e)
+* Better loop cleanup
+* CI Tests pass on windows now
+* Testing improvements
+* Python 3.3 Support. (probably always supported, but it's offially supported/tested now)
+
+Version 0.4.1
+-------------
+
+* Improvements to PEP-3156 Conformance
+* Minor Test Improvements
+
+Version 0.4
+-----------
+* Major improvements to tests
+
+  - integration with Travis CI
+  - more tests
+  - all tests pass
+  - cross platform/configuration tests
+
+* Bug #13 discovered and fixed
+* Force which Qt Implementation to use with ``QUAMASH_QTIMPL`` environment variable.
+* Implement ``QEventLoop.remove_reader`` and ``QEventLoop.remove_writer``
+* PyQt4 Support
+* PyQt5 Support
+* Support ``multiprocessing`` executors (``ProcessPoolExecutor``))
+* Improvements to code quality
+
+Version 0.3
+-----------
+First version worth using.
+
+
+Testing
+=======
+Quamash is tested with pytest_; in order to run the test suite, just install pytest
+and execute py.test on the commandline. The tests themselves are beneath the 'tests' directory.
+
+Testing can also be done with tox_. The current tox setup in tox.ini requires PyQT4/5 and PySide to
+be installed globally. (pip can't install PyQt into a virtualenv which is what tox will try to do).
+For this reason it may be good to run tox tests while specificying which environments to run. e.g.
+``tox -e py34-pyqt5`` to test python 3.4 with PyQt5. It is unlikely this tox configuration will
+work well on Windows especially since PyQt5 and PyQt4 cannot coexist in the same python installation
+on Windows. Also the PyQt4 w/ Qt5 oddity appears to be mostly a windows only thing too.
+
+Style testing is also handled by tox. Run ``tox -e flake8``.
+
+Code Coverage
+-------------
+Getting a full coverage support is quite time consuming. In theory this could by done with `pytest-xdist`_,
+but I haven't had time to make that work. Install ``pytest-cov`` with ``pip install pytest-cov`` then
+run ``py.test --cov quamash`` then append a dot and an identifier the generated ``.coverage`` file. For example,
+``mv .coverage .coverage.nix.p33.pyside`` then repeat on all the platforms you want to run on. (at least linux
+and windows). Put all the ``.coverage.*`` files in one directory that also has quamash source code in it.
+``cd`` to that directory and run ``coverage combine`` finally run ``coverage html`` for html based reports
+or ``coverage report`` for a simple report. These last commands may fail with errors about not being able to
+find source code. Use the ``.coveragerc`` file to specify equivelant paths.  The default configuration has linux
+source code in ``/quamash`` and windows source at ``C:\quamash``.
+
+Continuous Integration & Supported Platforms
+--------------------------------------------
+This project uses Travis CI to perform tests on linux (Ubuntu 12.04 LTS "Precise Pangolin") and
+Appveyor (Windows Server 2012 R2, similar to Windows 8) to perform continuous integration.
+
+On linux, Python 3.3 and 3.4 with PySide, PyQt4, and PyQt5 are tested. On windows, Python 3.4 with
+PySide, PyQt4 and PyQt5 are tested, but Python 3.3 is only tested with PySide since binary installers
+for PyQt are not provided for Python 3.3 (at least not the newest versions of PyQt), and compiling 
+from source probably isn't worth it.
+
+Python 3.5 is now tested on linux with PyQt4 and PyQt5.
+
+Testing Matrix
+~~~~~~~~~~~~~~
+
++----------------------+---------+---------+--------------+----------------+
+|                      | PyQt4   | PyQt5   | PySide (Qt4) | PySide 2 (Qt5) |
++======================+=========+=========+==============+================+
+| Linux - Python 3.3   | yes     | yes     | yes          | planned        |
++----------------------+---------+---------+--------------+----------------+
+| Linux - Python 3.4   | yes     | yes     | yes          | planned        |
++----------------------+---------+---------+--------------+----------------+
+| Linux - Python 3.5   | yes     | yes     | n/a          | planned        |
++----------------------+---------+---------+--------------+----------------+
+| Windows - Python 3.3 | no      | no      | yes          | no             |
++----------------------+---------+---------+--------------+----------------+
+| Windows - Python 3.4 | yes     | yes     | yes          | planned        |
++----------------------+---------+---------+--------------+----------------+
+| Windows - Python 3.5 | planned | planned | planned      | planned        |
++----------------------+---------+---------+--------------+----------------+
+
+License
+=======
+You may use, modify, and redistribute this software under the terms of the `BSD License`_.
+See LICENSE.
+
+Name
+====
+Tulip related projects are being named after other flowers, Quamash is one of the few flowers that
+starts with a "Q".
+
+.. _`PEP 3156`: http://python.org/dev/peps/pep-3156/
+.. _`pytest`: http://pytest.org
+.. _`BSD License`: http://opensource.org/licenses/BSD-2-Clause
+.. _tox: https://tox.readthedocs.org/
+.. _pytest-xdist: https://pypi.python.org/pypi/pytest-xdist
+.. _#31: https://github.com/harvimt/quamash/issues/31
+.. _#34: https://github.com/harvimt/quamash/issues/34
+.. _#35: https://github.com/harvimt/quamash/issues/35
+.. _#55: https://github.com/harvimt/quamash/issues/55
+.. _#59: https://github.com/harvimt/quamash/pull/59
+.. _#62: https://github.com/harvimt/quamash/pull/62
diff --git a/Quamash.egg-info/PKG-INFO b/Quamash.egg-info/PKG-INFO
new file mode 100644
index 0000000..e7388ad
--- /dev/null
+++ b/Quamash.egg-info/PKG-INFO
@@ -0,0 +1,288 @@
+Metadata-Version: 2.1
+Name: Quamash
+Version: 0.6.1
+Summary: Implementation of the PEP 3156 Event-Loop with Qt.
+Home-page: https://github.com/harvimt/quamash
+Author: Mark Harviston, Arve Knudsen
+Author-email: mark.harviston@gmail.com, arve.knudsen@gmail.com
+License: BSD
+Keywords: Qt,asyncio
+Classifier: Development Status :: 3 - Alpha
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Intended Audience :: Developers
+Classifier: Operating System :: Microsoft :: Windows
+Classifier: Operating System :: MacOS :: MacOS X
+Classifier: Operating System :: POSIX
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3 :: Only
+Classifier: Environment :: X11 Applications :: Qt
+Provides-Extra: test
+License-File: LICENSE
+
+=======
+Quamash
+=======
+Implementation of the `PEP 3156`_ Event-Loop with Qt
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+:author: Mark Harviston <mark.harviston@gmail.com>, Arve Knudsen <arve.knudsen@gmail.com>
+
+.. image:: https://img.shields.io/pypi/v/quamash.svg
+    :target: https://pypi.python.org/pypi/quamash/
+    :alt: Latest Version
+
+.. image:: https://img.shields.io/pypi/dm/quamash.svg
+    :target: https://pypi.python.org/pypi/quamash/
+    :alt: Downloads
+
+.. image:: https://img.shields.io/pypi/pyversions/quamash.svg
+    :target: https://pypi.python.org/pypi/quamash/
+    :alt: Supported Python versions
+
+.. image:: https://img.shields.io/pypi/l/quamash.svg
+    :target: https://pypi.python.org/pypi/quamash/
+    :alt: License
+
+.. image:: https://img.shields.io/pypi/status/Django.svg
+    :target: https://pypi.python.org/pypi/quamash/
+    :alt: Development Status
+
+.. image:: https://travis-ci.org/harvimt/quamash.svg?branch=master
+    :target: https://travis-ci.org/harvimt/quamash
+    :alt: Linux (Travis CI) Build Status
+
+.. image:: https://img.shields.io/appveyor/ci/harvimt/quamash.svg
+    :target: https://ci.appveyor.com/project/harvimt/quamash/branch/master
+    :alt: Windows (Appveyor) Build Status
+
+.. image:: https://badges.gitter.im/Join%20Chat.svg
+    :target: https://gitter.im/harvimt/quamash?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge
+    :alt: Gitter
+
+Requirements
+============
+Quamash requires Python 3.4 or Python 3.3 with the backported ``asyncio`` library and either PyQt4, PyQt5 or PySide.
+
+Installation
+============
+``pip install quamash``
+
+Upgrade from Version 0.4 to 0.5
+===============================
+The loop context manager will no longer set the event loop only close it.
+
+Instead of:
+
+.. code:: python
+
+    with loop:
+        loop.run_forever()
+
+do:
+
+.. code:: python
+
+    asyncio.set_event_loop(loop)
+    # ...
+    with loop:
+        loop.run_forever()
+
+It is recommended that you call ``asyncio.set_event_loop`` as early as possible (immediately after instantiating the loop),
+to avoid running asynchronous code before ``asyncio.set_event_loop`` is called.
+
+If you're using multiple different loops in the same application, you know what you're doing (or at least you hope you do),
+then you can ignore this advice.
+
+
+Usage
+=====
+
+.. code:: python
+
+    import sys
+    import asyncio
+    import time
+
+    from PyQt5.QtWidgets import QApplication, QProgressBar
+    from quamash import QEventLoop, QThreadExecutor
+
+    app = QApplication(sys.argv)
+    loop = QEventLoop(app)
+    asyncio.set_event_loop(loop)  # NEW must set the event loop
+
+    progress = QProgressBar()
+    progress.setRange(0, 99)
+    progress.show()
+
+    async def master():
+        await first_50()
+        with QThreadExecutor(1) as exec:
+            await loop.run_in_executor(exec, last_50)
+        # TODO announce completion?
+
+    async def first_50():
+        for i in range(50):
+            progress.setValue(i)
+            await asyncio.sleep(.1)
+
+    def last_50():
+        for i in range(50,100):
+            loop.call_soon_threadsafe(progress.setValue, i)
+            time.sleep(.1)
+
+    with loop: ## context manager calls .close() when loop completes, and releases all resources
+        loop.run_until_complete(master())
+
+Changelog
+=========
+
+Version 0.6.1
+* Python 3.7 support (no automated test coverage)
+
+Version 0.6.0
+-------------
+* Lots of bugfixes and performance improvements.
+
+
+Version 0.5.5
+-------------
+* Fix `#62`_ a serious memory leak by switching from ``QTimer`` to ``QObject.timerEvent``.
+
+Version 0.5.4
+-------------
+* Remove unnecessary QObjects
+* Officially add Python 3.5 support (CI configuration and setup.py change)
+* Fix `#55`_
+* Better compatibility with behavior of default event loop (`#59`_)
+* Remove _easycallback and replace with _makeSignaller
+
+Version 0.5.3
+-------------
+* Fix to `#34`_
+
+Version 0.5.2
+-------------
+* Fixes to tests, and CI configuration
+* Fixes `#35`_ and `#31`_ (both minor bugs)
+* Uploade wheels to PyPI
+
+Version 0.5.1
+-------------
+* Fixes rst syntax error in this README
+
+Version 0.5
+-----------
+* Deprecation of event loop as means to ``asyncio.set_event_loop``, now must be called explicitly.
+* Possible fix to notifiers being called out-of-order (see #25, #27, and e64119e)
+* Better loop cleanup
+* CI Tests pass on windows now
+* Testing improvements
+* Python 3.3 Support. (probably always supported, but it's offially supported/tested now)
+
+Version 0.4.1
+-------------
+
+* Improvements to PEP-3156 Conformance
+* Minor Test Improvements
+
+Version 0.4
+-----------
+* Major improvements to tests
+
+  - integration with Travis CI
+  - more tests
+  - all tests pass
+  - cross platform/configuration tests
+
+* Bug #13 discovered and fixed
+* Force which Qt Implementation to use with ``QUAMASH_QTIMPL`` environment variable.
+* Implement ``QEventLoop.remove_reader`` and ``QEventLoop.remove_writer``
+* PyQt4 Support
+* PyQt5 Support
+* Support ``multiprocessing`` executors (``ProcessPoolExecutor``))
+* Improvements to code quality
+
+Version 0.3
+-----------
+First version worth using.
+
+
+Testing
+=======
+Quamash is tested with pytest_; in order to run the test suite, just install pytest
+and execute py.test on the commandline. The tests themselves are beneath the 'tests' directory.
+
+Testing can also be done with tox_. The current tox setup in tox.ini requires PyQT4/5 and PySide to
+be installed globally. (pip can't install PyQt into a virtualenv which is what tox will try to do).
+For this reason it may be good to run tox tests while specificying which environments to run. e.g.
+``tox -e py34-pyqt5`` to test python 3.4 with PyQt5. It is unlikely this tox configuration will
+work well on Windows especially since PyQt5 and PyQt4 cannot coexist in the same python installation
+on Windows. Also the PyQt4 w/ Qt5 oddity appears to be mostly a windows only thing too.
+
+Style testing is also handled by tox. Run ``tox -e flake8``.
+
+Code Coverage
+-------------
+Getting a full coverage support is quite time consuming. In theory this could by done with `pytest-xdist`_,
+but I haven't had time to make that work. Install ``pytest-cov`` with ``pip install pytest-cov`` then
+run ``py.test --cov quamash`` then append a dot and an identifier the generated ``.coverage`` file. For example,
+``mv .coverage .coverage.nix.p33.pyside`` then repeat on all the platforms you want to run on. (at least linux
+and windows). Put all the ``.coverage.*`` files in one directory that also has quamash source code in it.
+``cd`` to that directory and run ``coverage combine`` finally run ``coverage html`` for html based reports
+or ``coverage report`` for a simple report. These last commands may fail with errors about not being able to
+find source code. Use the ``.coveragerc`` file to specify equivelant paths.  The default configuration has linux
+source code in ``/quamash`` and windows source at ``C:\quamash``.
+
+Continuous Integration & Supported Platforms
+--------------------------------------------
+This project uses Travis CI to perform tests on linux (Ubuntu 12.04 LTS "Precise Pangolin") and
+Appveyor (Windows Server 2012 R2, similar to Windows 8) to perform continuous integration.
+
+On linux, Python 3.3 and 3.4 with PySide, PyQt4, and PyQt5 are tested. On windows, Python 3.4 with
+PySide, PyQt4 and PyQt5 are tested, but Python 3.3 is only tested with PySide since binary installers
+for PyQt are not provided for Python 3.3 (at least not the newest versions of PyQt), and compiling 
+from source probably isn't worth it.
+
+Python 3.5 is now tested on linux with PyQt4 and PyQt5.
+
+Testing Matrix
+~~~~~~~~~~~~~~
+
++----------------------+---------+---------+--------------+----------------+
+|                      | PyQt4   | PyQt5   | PySide (Qt4) | PySide 2 (Qt5) |
++======================+=========+=========+==============+================+
+| Linux - Python 3.3   | yes     | yes     | yes          | planned        |
++----------------------+---------+---------+--------------+----------------+
+| Linux - Python 3.4   | yes     | yes     | yes          | planned        |
++----------------------+---------+---------+--------------+----------------+
+| Linux - Python 3.5   | yes     | yes     | n/a          | planned        |
++----------------------+---------+---------+--------------+----------------+
+| Windows - Python 3.3 | no      | no      | yes          | no             |
++----------------------+---------+---------+--------------+----------------+
+| Windows - Python 3.4 | yes     | yes     | yes          | planned        |
++----------------------+---------+---------+--------------+----------------+
+| Windows - Python 3.5 | planned | planned | planned      | planned        |
++----------------------+---------+---------+--------------+----------------+
+
+License
+=======
+You may use, modify, and redistribute this software under the terms of the `BSD License`_.
+See LICENSE.
+
+Name
+====
+Tulip related projects are being named after other flowers, Quamash is one of the few flowers that
+starts with a "Q".
+
+.. _`PEP 3156`: http://python.org/dev/peps/pep-3156/
+.. _`pytest`: http://pytest.org
+.. _`BSD License`: http://opensource.org/licenses/BSD-2-Clause
+.. _tox: https://tox.readthedocs.org/
+.. _pytest-xdist: https://pypi.python.org/pypi/pytest-xdist
+.. _#31: https://github.com/harvimt/quamash/issues/31
+.. _#34: https://github.com/harvimt/quamash/issues/34
+.. _#35: https://github.com/harvimt/quamash/issues/35
+.. _#55: https://github.com/harvimt/quamash/issues/55
+.. _#59: https://github.com/harvimt/quamash/pull/59
+.. _#62: https://github.com/harvimt/quamash/pull/62
diff --git a/Quamash.egg-info/SOURCES.txt b/Quamash.egg-info/SOURCES.txt
new file mode 100644
index 0000000..c5f89c3
--- /dev/null
+++ b/Quamash.egg-info/SOURCES.txt
@@ -0,0 +1,14 @@
+LICENSE
+MANIFEST.in
+README.rst
+setup.cfg
+setup.py
+Quamash.egg-info/PKG-INFO
+Quamash.egg-info/SOURCES.txt
+Quamash.egg-info/dependency_links.txt
+Quamash.egg-info/requires.txt
+Quamash.egg-info/top_level.txt
+quamash/__init__.py
+quamash/_common.py
+quamash/_unix.py
+quamash/_windows.py
\ No newline at end of file
diff --git a/Quamash.egg-info/dependency_links.txt b/Quamash.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/Quamash.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/Quamash.egg-info/requires.txt b/Quamash.egg-info/requires.txt
new file mode 100644
index 0000000..0678ebb
--- /dev/null
+++ b/Quamash.egg-info/requires.txt
@@ -0,0 +1,3 @@
+
+[test]
+pytest
diff --git a/Quamash.egg-info/top_level.txt b/Quamash.egg-info/top_level.txt
new file mode 100644
index 0000000..a6d82fc
--- /dev/null
+++ b/Quamash.egg-info/top_level.txt
@@ -0,0 +1 @@
+quamash
diff --git a/README.rst b/README.rst
index 21e8be1..ce02448 100644
--- a/README.rst
+++ b/README.rst
@@ -173,7 +173,7 @@ Version 0.4
   - cross platform/configuration tests
 
 * Bug #13 discovered and fixed
-* Force which Qt Implementation to use with ``QUQMASH_QTIMPL`` environment variable.
+* Force which Qt Implementation to use with ``QUAMASH_QTIMPL`` environment variable.
 * Implement ``QEventLoop.remove_reader`` and ``QEventLoop.remove_writer``
 * PyQt4 Support
 * PyQt5 Support
diff --git a/appveyor.yml b/appveyor.yml
deleted file mode 100644
index 0093bac..0000000
--- a/appveyor.yml
+++ /dev/null
@@ -1,53 +0,0 @@
-environment:
-
-  matrix:
-    - PYTHON: "C:\\Python34-x64"
-      PYTHON_VERSION: "3.4.x"
-      PYTHON_ARCH: "64"
-      QTIMPL: "PySide"
-
-    - PYTHON: "C:\\Python34-x64"
-      PYTHON_VERSION: "3.4.x"
-      PYTHON_ARCH: "64"
-      QTIMPL: "PyQt4"
-
-    - PYTHON: "C:\\Python34-x64"
-      PYTHON_VERSION: "3.4.x"
-      PYTHON_ARCH: "64"
-      QTIMPL: "PyQt5"
-   
-    - PYTHON: "C:\\Python35-x64"
-      PYTHON_VERSION: "3.5.x"
-      PYTHON_ARCH: "64"
-      QTIMPL: "PyQt4"
-
-    - PYTHON: "C:\\Python36-x64"
-      PYTHON_VERSION: "3.6.x"
-      PYTHON_ARCH: "64"
-      QTIMPL: "PyQt4"
-
-    - PYTHON: "C:\\Python36-x64"
-      PYTHON_VERSION: "3.6.x"
-      PYTHON_ARCH: "64"
-      QTIMPL: "PyQt5"
-
-    - PYTHON: "C:\\Python36"
-      PYTHON_VERSION: "3.6.x"
-      PYTHON_ARCH: "32"
-      QTIMPL: "PyQt5"
-init:
-  - "ECHO %PYTHON% %PYTHON_VERSION% %PYTHON_ARCH% %QTIMPL%"
-
-install:
-  - "powershell appveyor\\install.ps1"
-
-build: off
-
-test_script:
-  - "%PYTHON%\\Scripts\\py.test.exe"
-
-notifications:
-  - provider: Webhook
-    url: https://webhooks.gitter.im/e/9723bec82b34a9f3faf0
-    on_build_success: false
-    on_build_failure: True
diff --git a/appveyor/install.ps1 b/appveyor/install.ps1
deleted file mode 100644
index 282be19..0000000
--- a/appveyor/install.ps1
+++ /dev/null
@@ -1,47 +0,0 @@
-# Adapted from Sample script to install Python and pip under Windows
-# Authors: Olivier Grisel and Kyle Kastner
-# License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/
-# Adapted by Mark Harviston <mark.harviston@gmail.com>
-
-$GET_PIP_URL = "https://bootstrap.pypa.io/get-pip.py"
-$GET_PIP_PATH = "C:\get-pip.py"
-
-function InstallPip ($python_home) {
-	$pip_path = $python_home + "\Scripts\pip.exe"
-	$python_path = $python_home + "\python.exe"
-	if (-not(Test-Path $pip_path)) {
-		Write-Host "Installing pip..."
-		$webclient = New-Object System.Net.WebClient
-		$webclient.DownloadFile($GET_PIP_URL, $GET_PIP_PATH)
-		Write-Host "Executing:" $python_path $GET_PIP_PATH
-		Start-Process -FilePath "$python_path" -ArgumentList "$GET_PIP_PATH" -Wait -Passthru
-	} else {
-		Write-Host "pip already installed."
-	}
-}
-
-function InstallPackage ($python_home, $pkg) {
-	$pip_path = $python_home + "\Scripts\pip.exe"
-	& $pip_path install --only-binary=PySide --only-binary=PyQt4 --only-binary=PyQt5 --find-links .\wheelhouse $pkg
-}
-
-function main () {
-	$PYTHON_MAJ_VERSION = $env:PYTHON_VERSION -replace '(\d+)\.(\d+)\.(\d+)', '$1.$2'
-	& REG ADD "HKCU\Software\Python\PythonCore\${PYTHON_MAJ_VERSION}\InstallPath" /f /ve /t REG_SZ /d $env:PYTHON
-	InstallPip $env:PYTHON
-	InstallPackage $env:PYTHON wheel
-	InstallPackage $env:PYTHON pytest
-	switch ($env:QTIMPL){
-		"PySide" {
-			InstallPackage $env:Python PySide
-		}
-		"PyQt4" {
-			InstallPackage $env:Python PyQt4
-		}
-		"PyQt5" {
-			InstallPackage $env:Python PyQt5
-		}
-	}
-}
-
-main
diff --git a/conftest.py b/conftest.py
deleted file mode 100644
index c1078d3..0000000
--- a/conftest.py
+++ /dev/null
@@ -1,42 +0,0 @@
-import sys
-import os.path
-import logging
-from pytest import fixture
-sys.path.insert(0, os.path.dirname(__file__))
-
-try:
-	import colorlog
-	handler = colorlog.StreamHandler()
-
-	formatter = colorlog.ColoredFormatter(
-		"%(log_color)s%(levelname)-8s%(reset)s %(name)-32s %(message)s",
-		datefmt=None,
-		reset=True,
-		log_colors={
-			'DEBUG': 'cyan',
-			'INFO': 'green',
-			'WARNING': 'yellow',
-			'ERROR': 'red',
-			'CRITICAL': 'red,bg_white',
-		},
-		secondary_log_colors={},
-		style='%',
-	)
-	handler.setFormatter(formatter)
-	logger = colorlog.getLogger()
-	logger.addHandler(handler)
-	logger.setLevel(logging.DEBUG)
-except ImportError:
-	logging.basicConfig(
-		level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(name)s - %(message)s')
-
-if os.name == 'nt':
-	collect_ignore = ['quamash/_unix.py']
-else:
-	collect_ignore = ['quamash/_windows.py']
-
-
-@fixture(scope='session')
-def application():
-	from quamash import QApplication
-	return QApplication([])
diff --git a/debian/changelog b/debian/changelog
index 004134f..222c3c1 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+python-quamash (0.6.1+git20211220.1.d9520f4~dfsg-1) UNRELEASED; urgency=low
+
+  * New upstream snapshot.
+  * Drop patch Add-compatibility-with-Python-3.10.patch, present upstream.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Tue, 03 Jan 2023 16:02:51 -0000
+
 python-quamash (0.6.1~dfsg-2) unstable; urgency=medium
 
   * Team upload
diff --git a/debian/patches/Add-compatibility-with-Python-3.10.patch b/debian/patches/Add-compatibility-with-Python-3.10.patch
deleted file mode 100644
index 2f75ab9..0000000
--- a/debian/patches/Add-compatibility-with-Python-3.10.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-Origin: upstream, https://github.com/harvimt/quamash/commit/1e9047bec739dbc9d6ab337fc1a111a8b1090244
-From: rr- <dash@wind.garden>
-Date: Mon, 20 Dec 2021 18:44:49 +0100
-Subject: Add compatibility with Python 3.10
-
----
- quamash/_unix.py | 7 +++++--
- 1 file changed, 5 insertions(+), 2 deletions(-)
-
-diff --git a/quamash/_unix.py b/quamash/_unix.py
-index 0e7137e..97b58d9 100644
---- a/quamash/_unix.py
-+++ b/quamash/_unix.py
-@@ -6,7 +6,10 @@
- 
- import asyncio
- import selectors
--import collections
-+try:
-+	from collections import Mapping
-+except ImportError:
-+	from collections.abc import Mapping
- 
- from . import QtCore, with_logger
- 
-@@ -41,7 +44,7 @@ def _fileobj_to_fd(fileobj):
- 	return fd
- 
- 
--class _SelectorMapping(collections.Mapping):
-+class _SelectorMapping(Mapping):
- 
- 	"""Mapping of file objects to selector keys."""
- 
diff --git a/debian/patches/series b/debian/patches/series
index 859a7b3..e69de29 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1 +0,0 @@
-Add-compatibility-with-Python-3.10.patch
diff --git a/quamash/_unix.py b/quamash/_unix.py
index 0e7137e..97b58d9 100644
--- a/quamash/_unix.py
+++ b/quamash/_unix.py
@@ -6,7 +6,10 @@
 
 import asyncio
 import selectors
-import collections
+try:
+	from collections import Mapping
+except ImportError:
+	from collections.abc import Mapping
 
 from . import QtCore, with_logger
 
@@ -41,7 +44,7 @@ def _fileobj_to_fd(fileobj):
 	return fd
 
 
-class _SelectorMapping(collections.Mapping):
+class _SelectorMapping(Mapping):
 
 	"""Mapping of file objects to selector keys."""
 
diff --git a/setup.cfg b/setup.cfg
index a19bc41..da26fd5 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,3 +1,8 @@
 [metadata]
 license-file = LICENSE
 description-file = README.rst
+
+[egg_info]
+tag_build = 
+tag_date = 0
+
diff --git a/tests/test_qeventloop.py b/tests/test_qeventloop.py
deleted file mode 100644
index ba6f674..0000000
--- a/tests/test_qeventloop.py
+++ /dev/null
@@ -1,741 +0,0 @@
-# © 2013 Mark Harviston <mark.harviston@gmail.com>
-# © 2014 Arve Knudsen <arve.knudsen@gmail.com>
-# BSD License
-import asyncio
-import logging
-import sys
-import os
-import ctypes
-import multiprocessing
-from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
-import socket
-import subprocess
-
-import quamash
-
-import pytest
-
-
-@pytest.fixture
-def loop(request, application):
-	lp = quamash.QEventLoop(application)
-	asyncio.set_event_loop(lp)
-
-	additional_exceptions = []
-
-	def fin():
-		sys.excepthook = orig_excepthook
-
-		try:
-			lp.close()
-		finally:
-			asyncio.set_event_loop(None)
-
-		for exc in additional_exceptions:
-			if (
-				os.name == 'nt' and
-				isinstance(exc['exception'], WindowsError) and
-				exc['exception'].winerror == 6
-			):
-				# ignore Invalid Handle Errors
-				continue
-			raise exc['exception']
-
-	def except_handler(loop, ctx):
-		additional_exceptions.append(ctx)
-
-	def excepthook(type, *args):
-		lp.stop()
-		orig_excepthook(type, *args)
-
-	orig_excepthook = sys.excepthook
-	sys.excepthook = excepthook
-	lp.set_exception_handler(except_handler)
-
-	request.addfinalizer(fin)
-	return lp
-
-
-@pytest.fixture(
-	params=[None, quamash.QThreadExecutor, ThreadPoolExecutor, ProcessPoolExecutor],
-)
-def executor(request):
-	exc_cls = request.param
-	if exc_cls is None:
-		return None
-
-	exc = exc_cls(1)  # FIXME? fixed number of workers?
-	request.addfinalizer(exc.shutdown)
-	return exc
-
-
-ExceptionTester = type('ExceptionTester', (Exception,), {})  # to make flake8 not complain
-
-
-class TestCanRunTasksInExecutor:
-
-	"""
-	Test Cases Concerning running jobs in Executors.
-
-	This needs to be a class because pickle can't serialize closures,
-	but can serialize bound methods.
-	multiprocessing can only handle pickleable functions.
-	"""
-
-	def test_can_run_tasks_in_executor(self, loop, executor):
-		"""Verify that tasks can be run in an executor."""
-		logging.debug('Loop: {!r}'.format(loop))
-		logging.debug('Executor: {!r}'.format(executor))
-
-		manager = multiprocessing.Manager()
-		was_invoked = manager.Value(ctypes.c_int, 0)
-		logging.debug('running until complete')
-		loop.run_until_complete(self.blocking_task(loop, executor, was_invoked))
-		logging.debug('ran')
-
-		assert was_invoked.value == 1
-
-	def test_can_handle_exception_in_executor(self, loop, executor):
-		with pytest.raises(ExceptionTester) as excinfo:
-			loop.run_until_complete(asyncio.wait_for(
-				loop.run_in_executor(executor, self.blocking_failure),
-				timeout=3.0,
-			))
-
-		assert str(excinfo.value) == 'Testing'
-
-	def blocking_failure(self):
-		logging.debug('raising')
-		try:
-			raise ExceptionTester('Testing')
-		finally:
-			logging.debug('raised!')
-
-	def blocking_func(self, was_invoked):
-		logging.debug('start blocking_func()')
-		was_invoked.value = 1
-		logging.debug('end blocking_func()')
-
-	@asyncio.coroutine
-	def blocking_task(self, loop, executor, was_invoked):
-		logging.debug('start blocking task()')
-		fut = loop.run_in_executor(executor, self.blocking_func, was_invoked)
-		yield from asyncio.wait_for(fut, timeout=5.0)
-		logging.debug('start blocking task()')
-
-
-def test_can_execute_subprocess(loop):
-	"""Verify that a subprocess can be executed."""
-	@asyncio.coroutine
-	def mycoro():
-		process = yield from asyncio.create_subprocess_exec(
-			sys.executable or 'python', '-c', 'import sys; sys.exit(5)')
-		yield from process.wait()
-		assert process.returncode == 5
-	loop.run_until_complete(asyncio.wait_for(mycoro(), timeout=3))
-
-
-def test_can_read_subprocess(loop):
-	"""Verify that a subprocess's data can be read from stdout."""
-	@asyncio.coroutine
-	def mycoro():
-		process = yield from asyncio.create_subprocess_exec(
-			sys.executable or 'python', '-c', 'print("Hello async world!")', stdout=subprocess.PIPE)
-		received_stdout = yield from process.stdout.readexactly(len(b'Hello async world!\n'))
-		yield from process.wait()
-		assert process.returncode == 0
-		assert received_stdout.strip() == b'Hello async world!'
-
-	loop.run_until_complete(asyncio.wait_for(mycoro(), timeout=3))
-
-
-def test_can_communicate_subprocess(loop):
-	"""Verify that a subprocess's data can be passed in/out via stdin/stdout."""
-	@asyncio.coroutine
-	def mycoro():
-		process = yield from asyncio.create_subprocess_exec(
-			sys.executable or 'python', '-c', 'print(input())', stdout=subprocess.PIPE, stdin=subprocess.PIPE)
-		received_stdout, received_stderr = yield from process.communicate(b'Hello async world!\n')
-		yield from process.wait()
-		assert process.returncode == 0
-		assert received_stdout.strip() == b'Hello async world!'
-	loop.run_until_complete(asyncio.wait_for(mycoro(), timeout=3))
-
-
-def test_can_terminate_subprocess(loop):
-	"""Verify that a subprocess can be terminated."""
-	# Start a never-ending process
-	@asyncio.coroutine
-	def mycoro():
-		process = yield from asyncio.create_subprocess_exec(
-			sys.executable or 'python', '-c', 'import time\nwhile True: time.sleep(1)')
-		process.terminate()
-		yield from process.wait()
-		assert process.returncode != 0
-	loop.run_until_complete(mycoro())
-
-
-@pytest.mark.raises(ExceptionTester)
-def test_loop_callback_exceptions_bubble_up(loop):
-	"""Verify that test exceptions raised in event loop callbacks bubble up."""
-	def raise_test_exception():
-		raise ExceptionTester("Test Message")
-	loop.call_soon(raise_test_exception)
-	loop.run_until_complete(asyncio.sleep(.1))
-
-
-def test_loop_running(loop):
-	"""Verify that loop.is_running returns True when running."""
-	@asyncio.coroutine
-	def is_running():
-		nonlocal loop
-		assert loop.is_running()
-
-	loop.run_until_complete(is_running())
-
-
-def test_loop_not_running(loop):
-	"""Verify that loop.is_running returns False when not running."""
-	assert not loop.is_running()
-
-
-def test_can_function_as_context_manager(application):
-	"""Verify that a QEventLoop can function as its own context manager."""
-	with quamash.QEventLoop(application) as loop:
-		assert isinstance(loop, quamash.QEventLoop)
-		loop.call_soon(loop.stop)
-		loop.run_forever()
-
-
-def test_future_not_done_on_loop_shutdown(loop):
-	"""Verify RuntimError occurs when loop stopped before Future completed with run_until_complete."""
-	loop.call_later(.1, loop.stop)
-	fut = asyncio.Future()
-	with pytest.raises(RuntimeError):
-		loop.run_until_complete(fut)
-
-
-def test_call_later_must_not_coroutine(loop):
-	"""Verify TypeError occurs call_later is given a coroutine."""
-	mycoro = asyncio.coroutine(lambda: None)
-
-	with pytest.raises(TypeError):
-		loop.call_soon(mycoro)
-
-
-def test_call_later_must_be_callable(loop):
-	"""Verify TypeError occurs call_later is not given a callable."""
-	not_callable = object()
-	with pytest.raises(TypeError):
-		loop.call_soon(not_callable)
-
-
-def test_call_at(loop):
-	"""Verify that loop.call_at works as expected."""
-	def mycallback():
-		nonlocal was_invoked
-		was_invoked = True
-	was_invoked = False
-
-	loop.call_at(loop.time() + .05, mycallback)
-	loop.run_until_complete(asyncio.sleep(.1))
-
-	assert was_invoked
-
-
-def test_get_set_debug(loop):
-	"""Verify get_debug and set_debug work as expected."""
-	loop.set_debug(True)
-	assert loop.get_debug()
-	loop.set_debug(False)
-	assert not loop.get_debug()
-
-
-@pytest.fixture
-def sock_pair(request):
-	"""Create socket pair.
-
-	If socket.socketpair isn't available, we emulate it.
-	"""
-	def fin():
-		if client_sock is not None:
-			client_sock.close()
-		if srv_sock is not None:
-			srv_sock.close()
-
-	client_sock = srv_sock = None
-	request.addfinalizer(fin)
-
-	# See if socketpair() is available.
-	have_socketpair = hasattr(socket, 'socketpair')
-	if have_socketpair:
-		client_sock, srv_sock = socket.socketpair()
-		return client_sock, srv_sock
-
-	# Create a non-blocking temporary server socket
-	temp_srv_sock = socket.socket()
-	temp_srv_sock.setblocking(False)
-	temp_srv_sock.bind(('', 0))
-	port = temp_srv_sock.getsockname()[1]
-	temp_srv_sock.listen(1)
-
-	# Create non-blocking client socket
-	client_sock = socket.socket()
-	client_sock.setblocking(False)
-	try:
-		client_sock.connect(('localhost', port))
-	except socket.error as err:
-		# Error 10035 (operation would block) is not an error, as we're doing this with a
-		# non-blocking socket.
-		if err.errno != 10035:
-			raise
-
-	# Use select to wait for connect() to succeed.
-	import select
-	timeout = 1
-	readable = select.select([temp_srv_sock], [], [], timeout)[0]
-	if temp_srv_sock not in readable:
-		raise Exception('Client socket not connected in {} second(s)'.format(timeout))
-	srv_sock, _ = temp_srv_sock.accept()
-
-	return client_sock, srv_sock
-
-
-def test_can_add_reader(loop, sock_pair):
-	"""Verify that we can add a reader callback to an event loop."""
-	def can_read():
-		if fut.done():
-			return
-
-		data = srv_sock.recv(1)
-		if len(data) != 1:
-			return
-
-		nonlocal got_msg
-		got_msg = data
-		# Indicate that we're done
-		fut.set_result(None)
-		srv_sock.close()
-
-	def write():
-		client_sock.send(ref_msg)
-		client_sock.close()
-
-	ref_msg = b'a'
-	client_sock, srv_sock = sock_pair
-	loop.call_soon(write)
-
-	exp_num_notifiers = len(loop._read_notifiers) + 1
-	got_msg = None
-	fut = asyncio.Future()
-	loop.add_reader(srv_sock.fileno(), can_read)
-	assert len(loop._read_notifiers) == exp_num_notifiers, 'Notifier should be added'
-	loop.run_until_complete(asyncio.wait_for(fut, timeout=1.0))
-
-	assert got_msg == ref_msg
-
-
-def test_can_remove_reader(loop, sock_pair):
-	"""Verify that we can remove a reader callback from an event loop."""
-	def can_read():
-		data = srv_sock.recv(1)
-		if len(data) != 1:
-			return
-
-		nonlocal got_msg
-		got_msg = data
-
-	client_sock, srv_sock = sock_pair
-
-	got_msg = None
-	loop.add_reader(srv_sock.fileno(), can_read)
-	exp_num_notifiers = len(loop._read_notifiers) - 1
-	loop.remove_reader(srv_sock.fileno())
-	assert len(loop._read_notifiers) == exp_num_notifiers, 'Notifier should be removed'
-	client_sock.send(b'a')
-	client_sock.close()
-	# Run for a short while to see if we get a read notification
-	loop.call_later(0.1, loop.stop)
-	loop.run_forever()
-
-	assert got_msg is None, 'Should not have received a read notification'
-
-
-def test_remove_reader_after_closing(loop, sock_pair):
-	"""Verify that we can remove a reader callback from an event loop."""
-	client_sock, srv_sock = sock_pair
-
-	loop.add_reader(srv_sock.fileno(), lambda: None)
-	loop.close()
-	loop.remove_reader(srv_sock.fileno())
-
-
-def test_remove_writer_after_closing(loop, sock_pair):
-	"""Verify that we can remove a reader callback from an event loop."""
-	client_sock, srv_sock = sock_pair
-
-	loop.add_writer(client_sock.fileno(), lambda: None)
-	loop.close()
-	loop.remove_writer(client_sock.fileno())
-
-
-def test_add_reader_after_closing(loop, sock_pair):
-	"""Verify that we can remove a reader callback from an event loop."""
-	client_sock, srv_sock = sock_pair
-
-	loop.close()
-	with pytest.raises(RuntimeError):
-		loop.add_reader(srv_sock.fileno(), lambda: None)
-
-
-def test_add_writer_after_closing(loop, sock_pair):
-	"""Verify that we can remove a reader callback from an event loop."""
-	client_sock, srv_sock = sock_pair
-
-	loop.close()
-	with pytest.raises(RuntimeError):
-		loop.add_writer(client_sock.fileno(), lambda: None)
-
-
-def test_can_add_writer(loop, sock_pair):
-	"""Verify that we can add a writer callback to an event loop."""
-	def can_write():
-		if not fut.done():
-			# Indicate that we're done
-			fut.set_result(None)
-			client_sock.close()
-
-	client_sock, _ = sock_pair
-	fut = asyncio.Future()
-	loop.add_writer(client_sock.fileno(), can_write)
-	assert len(loop._write_notifiers) == 1, 'Notifier should be added'
-	loop.run_until_complete(asyncio.wait_for(fut, timeout=1.0))
-
-
-def test_can_remove_writer(loop, sock_pair):
-	"""Verify that we can remove a writer callback from an event loop."""
-	client_sock, _ = sock_pair
-	loop.add_writer(client_sock.fileno(), lambda: None)
-	loop.remove_writer(client_sock.fileno())
-	assert not loop._write_notifiers, 'Notifier should be removed'
-
-
-def test_add_reader_should_disable_qsocket_notifier_on_callback(loop, sock_pair):
-	"""Verify that add_reader disables QSocketNotifier during callback."""
-	def can_read():
-		nonlocal num_calls
-		num_calls += 1
-
-		if num_calls == 2:
-			# Since we get called again, the QSocketNotifier should've been re-enabled before
-			# this call (although disabled during)
-			assert not notifier.isEnabled()
-			srv_sock.recv(1)
-			fut.set_result(None)
-			srv_sock.close()
-			return
-
-		assert not notifier.isEnabled()
-
-	def write():
-		client_sock.send(b'a')
-		client_sock.close()
-
-	num_calls = 0
-	client_sock, srv_sock = sock_pair
-	loop.call_soon(write)
-
-	fut = asyncio.Future()
-	loop.add_reader(srv_sock.fileno(), can_read)
-	notifier = loop._read_notifiers[srv_sock.fileno()]
-	loop.run_until_complete(asyncio.wait_for(fut, timeout=1.0))
-
-
-def test_add_writer_should_disable_qsocket_notifier_on_callback(loop, sock_pair):
-	"""Verify that add_writer disables QSocketNotifier during callback."""
-	def can_write():
-		nonlocal num_calls
-		num_calls += 1
-
-		if num_calls == 2:
-			# Since we get called again, the QSocketNotifier should've been re-enabled before
-			# this call (although disabled during)
-			assert not notifier.isEnabled()
-			fut.set_result(None)
-			client_sock.close()
-			return
-
-		assert not notifier.isEnabled()
-
-	num_calls = 0
-	client_sock, _ = sock_pair
-	fut = asyncio.Future()
-	loop.add_writer(client_sock.fileno(), can_write)
-	notifier = loop._write_notifiers[client_sock.fileno()]
-	loop.run_until_complete(asyncio.wait_for(fut, timeout=1.0))
-
-
-def test_reader_writer_echo(loop, sock_pair):
-	"""Verify readers and writers can send data to each other."""
-	c_sock, s_sock = sock_pair
-
-	@asyncio.coroutine
-	def mycoro():
-		c_reader, c_writer = yield from asyncio.open_connection(sock=c_sock)
-		s_reader, s_writer = yield from asyncio.open_connection(sock=s_sock)
-
-		data = b'Echo... Echo... Echo...'
-		s_writer.write(data)
-		yield from s_writer.drain()
-		read_data = yield from c_reader.readexactly(len(data))
-		assert data == read_data
-		s_writer.close()
-
-	loop.run_until_complete(asyncio.wait_for(mycoro(), timeout=1.0))
-
-
-def test_regression_bug13(loop, sock_pair):
-	"""Verify that a simple handshake between client and server works as expected."""
-	c_sock, s_sock = sock_pair
-	client_done, server_done = asyncio.Future(), asyncio.Future()
-
-	@asyncio.coroutine
-	def server_coro():
-		s_reader, s_writer = yield from asyncio.open_connection(sock=s_sock)
-
-		s_writer.write(b'1')
-		yield from s_writer.drain()
-		assert (yield from s_reader.readexactly(1)) == b'2'
-		s_writer.write(b'3')
-		yield from s_writer.drain()
-		server_done.set_result(True)
-
-	result1 = None
-	result3 = None
-
-	@asyncio.coroutine
-	def client_coro():
-		def cb1():
-			nonlocal result1
-			assert result1 is None
-			loop.remove_reader(c_sock.fileno())
-			result1 = c_sock.recv(1)
-			loop.add_writer(c_sock.fileno(), cb2)
-
-		def cb2():
-			nonlocal result3
-			assert result3 is None
-			c_sock.send(b'2')
-			loop.remove_writer(c_sock.fileno())
-			loop.add_reader(c_sock.fileno(), cb3)
-
-		def cb3():
-			nonlocal result3
-			assert result3 is None
-			result3 = c_sock.recv(1)
-			client_done.set_result(True)
-
-		loop.add_reader(c_sock.fileno(), cb1)
-
-	asyncio.ensure_future(client_coro())
-	asyncio.ensure_future(server_coro())
-
-	both_done = asyncio.gather(client_done, server_done)
-	loop.run_until_complete(asyncio.wait_for(both_done, timeout=1.0))
-	assert result1 == b'1'
-	assert result3 == b'3'
-
-
-def test_add_reader_replace(loop, sock_pair):
-	c_sock, s_sock = sock_pair
-	callback_invoked = asyncio.Future()
-
-	called1 = False
-	called2 = False
-
-	def any_callback():
-		if not callback_invoked.done():
-			callback_invoked.set_result(True)
-		loop.remove_reader(c_sock.fileno())
-
-	def callback1():
-		# the "bad" callback: if this gets invoked, something went wrong
-		nonlocal called1
-		called1 = True
-		any_callback()
-
-	def callback2():
-		# the "good" callback: this is the one which should get called
-		nonlocal called2
-		called2 = True
-		any_callback()
-
-	@asyncio.coroutine
-	def server_coro():
-		s_reader, s_writer = yield from asyncio.open_connection(
-			sock=s_sock)
-		s_writer.write(b"foo")
-		yield from s_writer.drain()
-
-	@asyncio.coroutine
-	def client_coro():
-		loop.add_reader(c_sock.fileno(), callback1)
-		loop.add_reader(c_sock.fileno(), callback2)
-		yield from callback_invoked
-		loop.remove_reader(c_sock.fileno())
-		assert (yield from loop.sock_recv(c_sock, 3)) == b"foo"
-
-	client_done = asyncio.ensure_future(client_coro())
-	server_done = asyncio.ensure_future(server_coro())
-
-	both_done = asyncio.wait(
-		[server_done, client_done],
-		return_when=asyncio.FIRST_EXCEPTION)
-	loop.run_until_complete(asyncio.wait_for(both_done, timeout=0.1))
-	assert not called1
-	assert called2
-
-
-def test_add_writer_replace(loop, sock_pair):
-	c_sock, s_sock = sock_pair
-	callback_invoked = asyncio.Future()
-
-	called1 = False
-	called2 = False
-
-	def any_callback():
-		if not callback_invoked.done():
-			callback_invoked.set_result(True)
-		loop.remove_writer(c_sock.fileno())
-
-	def callback1():
-		# the "bad" callback: if this gets invoked, something went wrong
-		nonlocal called1
-		called1 = True
-		any_callback()
-
-	def callback2():
-		# the "good" callback: this is the one which should get called
-		nonlocal called2
-		called2 = True
-		any_callback()
-
-	@asyncio.coroutine
-	def client_coro():
-		loop.add_writer(c_sock.fileno(), callback1)
-		loop.add_writer(c_sock.fileno(), callback2)
-		yield from callback_invoked
-		loop.remove_writer(c_sock.fileno())
-
-	loop.run_until_complete(asyncio.wait_for(client_coro(), timeout=0.1))
-	assert not called1
-	assert called2
-
-
-def test_remove_reader_idempotence(loop, sock_pair):
-	fd = sock_pair[0].fileno()
-
-	def cb():
-		pass
-
-	removed0 = loop.remove_reader(fd)
-	loop.add_reader(fd, cb)
-	removed1 = loop.remove_reader(fd)
-	removed2 = loop.remove_reader(fd)
-
-	assert not removed0
-	assert removed1
-	assert not removed2
-
-
-def test_remove_writer_idempotence(loop, sock_pair):
-	fd = sock_pair[0].fileno()
-
-	def cb():
-		pass
-
-	removed0 = loop.remove_writer(fd)
-	loop.add_writer(fd, cb)
-	removed1 = loop.remove_writer(fd)
-	removed2 = loop.remove_writer(fd)
-
-	assert not removed0
-	assert removed1
-	assert not removed2
-
-
-def test_scheduling(loop, sock_pair):
-	s1, s2 = sock_pair
-	fd = s1.fileno()
-	cb_called = asyncio.Future()
-
-	def writer_cb(fut):
-		if fut.done():
-			cb_called.set_exception(ValueError("writer_cb called twice"))
-		fut.set_result(None)
-
-	def fut_cb(fut):
-		loop.remove_writer(fd)
-		cb_called.set_result(None)
-
-	fut = asyncio.Future()
-	fut.add_done_callback(fut_cb)
-	loop.add_writer(fd, writer_cb, fut)
-	loop.run_until_complete(cb_called)
-
-
-@pytest.mark.xfail(
-	'sys.version_info < (3,4)',
-	reason="Doesn't work on python older than 3.4",
-)
-def test_exception_handler(loop):
-	handler_called = False
-	coro_run = False
-	loop.set_debug(True)
-
-	@asyncio.coroutine
-	def future_except():
-		nonlocal coro_run
-		coro_run = True
-		loop.stop()
-		raise ExceptionTester()
-
-	def exct_handler(loop, data):
-		nonlocal handler_called
-		handler_called = True
-
-	loop.set_exception_handler(exct_handler)
-	asyncio.ensure_future(future_except())
-	loop.run_forever()
-
-	assert coro_run
-	assert handler_called
-
-
-def test_exception_handler_simple(loop):
-	handler_called = False
-
-	def exct_handler(loop, data):
-		nonlocal handler_called
-		handler_called = True
-
-	loop.set_exception_handler(exct_handler)
-	fut1 = asyncio.Future()
-	fut1.set_exception(ExceptionTester())
-	asyncio.ensure_future(fut1)
-	del fut1
-	loop.call_later(0.1, loop.stop)
-	loop.run_forever()
-	assert handler_called
-
-
-def test_not_running_immediately_after_stopped(loop):
-	@asyncio.coroutine
-	def mycoro():
-		assert loop.is_running()
-		yield from asyncio.sleep(0)
-		loop.stop()
-		assert not loop.is_running()
-	assert not loop.is_running()
-	loop.run_until_complete(mycoro())
-	assert not loop.is_running()
diff --git a/tests/test_qthreadexec.py b/tests/test_qthreadexec.py
deleted file mode 100644
index 27f0710..0000000
--- a/tests/test_qthreadexec.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# © 2014 Mark Harviston <mark.harviston@gmail.com>
-# © 2014 Arve Knudsen <arve.knudsen@gmail.com>
-# BSD License
-import pytest
-import quamash
-
-
-@pytest.fixture
-def executor(request):
-	exe = quamash.QThreadExecutor(5)
-	request.addfinalizer(exe.shutdown)
-	return exe
-
-
-@pytest.fixture
-def shutdown_executor():
-	exe = quamash.QThreadExecutor(5)
-	exe.shutdown()
-	return exe
-
-
-def test_shutdown_after_shutdown(shutdown_executor):
-	with pytest.raises(RuntimeError):
-		shutdown_executor.shutdown()
-
-
-def test_ctx_after_shutdown(shutdown_executor):
-	with pytest.raises(RuntimeError):
-		with shutdown_executor:
-			pass
-
-
-def test_submit_after_shutdown(shutdown_executor):
-	with pytest.raises(RuntimeError):
-		shutdown_executor.submit(None)
diff --git a/tox.ini b/tox.ini
deleted file mode 100644
index acd5e9d..0000000
--- a/tox.ini
+++ /dev/null
@@ -1,44 +0,0 @@
-[tox]
-envlist=flake8,py36-pyqt5,{py34,py35,py36}-pyqt4,py34-pyside
-
-[testenv]
-install_command = pip install --only-binary=PySide --only-binary=PyQt4 --only-binary=PyQt5 --find-links .\wheelhouse {opts} {packages}
-sitepackages=True
-deps=
-  colorlog
-  pytest
-  pyqt4: PyQt4
-  pyqt5: PyQt5
-  pyside: PySide
-commands=py.test
-setenv=
-  pyqt4: QUAMASH_QTIMPL=PyQt4
-  pyqt5: QUAMASH_QTIMPL=PyQt5
-  pyside: QUAMASH_QTIMPL=PySide
-
-[pytest]
-addopts=-rxs --doctest-modules quamash quamash tests
-timeout=10
-
-[testenv:py34-pyside]
-commands=-py.test
-
-[testenv:flake8]
-setenv=QUAMASH_QTIMPL=PyQt5
-basepython=python3.6
-deps=
-  PyQt5
-  flake8
-  pep8-naming
-  flake8-debugger
-  flake8-docstrings
-  flake8-commas
-commands=
-# different parameters for different parts of the project
-  flake8
-  flake8 --select=D1 quamash/*.py
-
-[flake8]
-max-complexity=15
-ignore=D1,W191,E501,E402,E704,E701,D211
-exclude=build,.git,__pycache__,wheelhouse,htmlcov,dist,.cache,*.egg-info,appveyor,*.env,.tox

Debdiff

File lists identical (after any substitutions)

No differences were encountered in the control files

More details

Full run details