diff --git a/.travis.yml b/.travis.yml index 1c522e629..97425d1c9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,7 +45,7 @@ stage_linux: &stage_linux <<: *stage_generic os: linux language: python - python: 3.6 + python: 3.5 stage_osx: &stage_osx <<: *stage_generic @@ -82,6 +82,9 @@ stage_win: &stage_win | export PATH="/c/Python${PYTHON_VERSION}:/c/Python${PYTHON_VERSION}/Scripts:${PATH}" case $PYTHON_VERSION in + 35) + choco install python --version 3.5.4 + ;; 36) choco install python --version 3.6.5 ;; @@ -112,7 +115,7 @@ jobs: include: # "lint and and pure python test" stage ########################################################################### - # Linter and style check (GNU/Linux, Python 3.7) + # Linter and style check (GNU/Linux, Python 3.5) - stage: lint and pure python test <<: *stage_linux if: type != cron @@ -126,7 +129,7 @@ jobs: if: type != cron script: make mypy - # Run the tests against without compilation (GNU/Linux, Python 3.6) + # Run the tests against without compilation (GNU/Linux, Python 3.5) - stage: lint and pure python test <<: *stage_linux if: type != cron @@ -153,6 +156,14 @@ jobs: dist: xenial python: 3.8 + # OSX, Python 3.5.6 (via pyenv) + - stage: test + <<: *stage_osx + if: type != cron + env: + - MPLBACKEND=ps + - PYTHON_VERSION=3.5.6 + # OSX, Python 3.6.5 (via pyenv) - stage: test <<: *stage_osx @@ -217,6 +228,11 @@ jobs: <<: *stage_win env: - PYTHON_VERSION=36 + # Windows, Python 3.5 + - if: type = cron + <<: *stage_win + env: + - PYTHON_VERSION=35 - if: tag IS present language: python python: "3.6" diff --git a/Makefile b/Makefile index 86fbb93bc..2607e4449 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ lint: pylint -rn qiskit/providers/ibmq test mypy: - mypy --module qiskit.providers.ibmq --show-error-codes --no-site-packages + mypy --module qiskit.providers.ibmq --show-error-codes style: pycodestyle qiskit test diff --git a/azure-pipelines.yml b/azure-pipelines.yml index f8c0b58cf..e74f0b0c0 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -13,6 +13,8 @@ jobs: # condition: eq(variables['Build.Reason'], 'PullRequest') strategy: matrix: + Python35: + python.version: '3.5' Python36: python.version: '3.6' Python37: @@ -42,8 +44,10 @@ jobs: condition: eq(variables['Build.Reason'], 'Schedule') strategy: matrix: - Python36: - python.version: '3.6' + Python35: + python.version: '3.5' +# Python36: +# python.version: '3.6' # Python37: # python.version: '3.7' steps: diff --git a/qiskit/providers/ibmq/accountprovider.py b/qiskit/providers/ibmq/accountprovider.py index 9481bb41e..6059aab64 100644 --- a/qiskit/providers/ibmq/accountprovider.py +++ b/qiskit/providers/ibmq/accountprovider.py @@ -142,12 +142,10 @@ def _discover_remote_backends(self, timeout: Optional[float] = None) -> Dict[str return ret - def __eq__( + def __eq__( # type: ignore[override] self, - other: Any + other: 'AccountProvider' ) -> bool: - if not isinstance(other, AccountProvider): - return False return self.credentials == other.credentials def __repr__(self) -> str: diff --git a/qiskit/providers/ibmq/api/clients/account.py b/qiskit/providers/ibmq/api/clients/account.py index a5fc769b4..e60301ddc 100644 --- a/qiskit/providers/ibmq/api/clients/account.py +++ b/qiskit/providers/ibmq/api/clients/account.py @@ -19,7 +19,8 @@ import time from typing import List, Dict, Any, Optional, Union -from datetime import datetime +# Disabled unused-import because datetime is used only for type hints. +from datetime import datetime # pylint: disable=unused-import from qiskit.providers.ibmq.apiconstants import (API_JOB_FINAL_STATES, ApiJobStatus, ApiJobShareLevel) diff --git a/qiskit/providers/ibmq/api/clients/auth.py b/qiskit/providers/ibmq/api/clients/auth.py index 398dd87e2..06263e2a4 100644 --- a/qiskit/providers/ibmq/api/clients/auth.py +++ b/qiskit/providers/ibmq/api/clients/auth.py @@ -14,7 +14,7 @@ """Client for accessing IBM Quantum Experience authentication services.""" -from typing import Dict, List, Optional, Any, Union +from typing import Dict, List, Optional, Any from requests.exceptions import RequestException from ..exceptions import AuthenticationLicenseError, RequestsApiError @@ -140,7 +140,7 @@ def user_hubs(self) -> List[Dict[str, str]]: # Miscellaneous public functions. - def api_version(self) -> Dict[str, Union[str, bool]]: + def api_version(self) -> Dict[str, str]: """Return the version of the API. Returns: diff --git a/qiskit/providers/ibmq/api/clients/websocket.py b/qiskit/providers/ibmq/api/clients/websocket.py index 63035cafa..fc0385a6e 100644 --- a/qiskit/providers/ibmq/api/clients/websocket.py +++ b/qiskit/providers/ibmq/api/clients/websocket.py @@ -20,7 +20,7 @@ import logging import time from abc import ABC, abstractmethod -from typing import Dict, Union, Optional, Any +from typing import Dict, Union, Generator, Optional, Any from concurrent import futures from ssl import SSLError import warnings @@ -57,6 +57,10 @@ except RuntimeError: LOOP = asyncio.new_event_loop() nest_asyncio.apply(LOOP) +# TODO Replace coroutine with async def once Python 3.5 is dropped. +# Also can upgrade to websocket 8 to avoid other deprecation warning. +warnings.filterwarnings("ignore", category=DeprecationWarning, + message="\"@coroutine\" decorator is deprecated") class WebsocketMessage(ABC): @@ -147,7 +151,8 @@ def __init__(self, websocket_url: str, access_token: str) -> None: self.websocket_url = websocket_url.rstrip('/') self.access_token = access_token - async def _connect(self, url: str) -> WebSocketClientProtocol: + @asyncio.coroutine + def _connect(self, url: str) -> Generator[Any, None, WebSocketClientProtocol]: """Authenticate with the websocket server and return the connection. Returns: @@ -164,7 +169,9 @@ async def _connect(self, url: str) -> WebSocketClientProtocol: try: logger.debug('Starting new websocket connection: %s', url) with warnings.catch_warnings(): - websocket = await connect(url) + # Suppress websockets deprecation warnings until the fix is available + warnings.filterwarnings("ignore", category=DeprecationWarning) + websocket = yield from connect(url) # Isolate specific exceptions, so they are not retried in `get_job_status`. except (SSLError, InvalidURI) as ex: @@ -182,19 +189,20 @@ async def _connect(self, url: str) -> WebSocketClientProtocol: # Authenticate against the server. auth_request = self._authentication_message() with warnings.catch_warnings(): - await websocket.send(auth_request.as_json()) + # Suppress websockets deprecation warnings until the fix is available + warnings.filterwarnings("ignore", category=DeprecationWarning) + yield from websocket.send(auth_request.as_json()) # Verify that the server acknowledged our authentication. - auth_response_raw = await websocket.recv() + auth_response_raw = yield from websocket.recv() - auth_response = WebsocketResponseMethod.from_bytes( - auth_response_raw) # type: ignore[arg-type] + auth_response = WebsocketResponseMethod.from_bytes(auth_response_raw) if auth_response.type_ != 'authenticated': raise WebsocketIBMQProtocolError('Failed to authenticate against the server: {}' .format(auth_response.as_json())) except ConnectionClosed as ex: - await websocket.close() + yield from websocket.close() exception_to_raise = WebsocketAuthenticationError( 'Unexpected error occurred when authenticating against the server.') @@ -204,14 +212,15 @@ async def _connect(self, url: str) -> WebSocketClientProtocol: return websocket - async def get_job_status( + @asyncio.coroutine + def get_job_status( self, job_id: str, timeout: Optional[float] = None, retries: int = 5, backoff_factor: float = 0.5, status_queue: Optional[RefreshQueue] = None - ) -> Dict[str, str]: + ) -> Generator[Any, None, Dict[str, str]]: """Return the status of a job. Read status messages from the server, which are issued at regular @@ -260,23 +269,24 @@ async def get_job_status( while current_retry_attempt <= retries: try: - websocket = await self._connect(url) + websocket = yield from self._connect(url) # Read messages from the server until the connection is closed or # a timeout has been reached. while True: try: with warnings.catch_warnings(): + # Suppress websockets deprecation warnings until the fix is available + warnings.filterwarnings("ignore", category=DeprecationWarning) if timeout: - response_raw = await asyncio.wait_for( + response_raw = yield from asyncio.wait_for( websocket.recv(), timeout=timeout) # Decrease the timeout. timeout = original_timeout - (time.time() - start_time) else: - response_raw = await websocket.recv() + response_raw = yield from websocket.recv() - response = WebsocketResponseMethod.from_bytes( - response_raw) # type: ignore[arg-type] + response = WebsocketResponseMethod.from_bytes(response_raw) if logger.getEffectiveLevel() is logging.DEBUG: logger.debug('Received message from websocket: %s', filter_data(response.get_data())) @@ -346,14 +356,16 @@ async def get_job_status( backoff_time = self._backoff_time(backoff_factor, current_retry_attempt) logger.info('Retrying get_job_status via websocket after %s seconds: ' 'Attempt #%s', backoff_time, current_retry_attempt) - await asyncio.sleep(backoff_time) # Block asyncio loop for given backoff time. + yield from asyncio.sleep(backoff_time) # Block asyncio loop for given backoff time. continue # Continues next iteration after `finally` block. finally: with warnings.catch_warnings(): + # Suppress websockets deprecation warnings until the fix is available + warnings.filterwarnings("ignore", category=DeprecationWarning) if websocket is not None: - await websocket.close() + yield from websocket.close() # Execution should not reach here, sanity check. exception_message = 'Max retries exceeded: Failed to establish a websocket ' \ diff --git a/qiskit/providers/ibmq/api/rest/backend.py b/qiskit/providers/ibmq/api/rest/backend.py index 1d6215305..3629f8392 100644 --- a/qiskit/providers/ibmq/api/rest/backend.py +++ b/qiskit/providers/ibmq/api/rest/backend.py @@ -16,7 +16,7 @@ import json from typing import Dict, Optional, Any, List -from datetime import datetime +from datetime import datetime # pylint: disable=unused-import from .base import RestAdapterBase from ..session import RetrySession diff --git a/qiskit/providers/ibmq/backendjoblimit.py b/qiskit/providers/ibmq/backendjoblimit.py index 850e8d2b6..ea0dfcfb5 100644 --- a/qiskit/providers/ibmq/backendjoblimit.py +++ b/qiskit/providers/ibmq/backendjoblimit.py @@ -14,7 +14,7 @@ """Job limit information related to a backend.""" -from typing import Any, Dict +from typing import Any class BackendJobLimit: @@ -31,7 +31,7 @@ class BackendJobLimit: this provider. """ - _data = {} # type:Dict + _data = {} def __init__(self, maximum_jobs: int, running_jobs: int, **kwargs: Any) -> None: """BackendJobLimit constructor. diff --git a/qiskit/providers/ibmq/backendreservation.py b/qiskit/providers/ibmq/backendreservation.py index 70170de05..56fcbcba9 100644 --- a/qiskit/providers/ibmq/backendreservation.py +++ b/qiskit/providers/ibmq/backendreservation.py @@ -14,7 +14,7 @@ """Reservation information related to a backend.""" -from typing import Optional, Any +from typing import Optional from datetime import datetime @@ -87,7 +87,7 @@ def __repr__(self) -> str: out_str += ')>' return out_str - def __eq__(self, other: Any) -> bool: + def __eq__(self, other): if isinstance(other, BackendReservation) and self.backend_name == other.backend_name: if self.reservation_id and self.reservation_id == other.reservation_id: return True diff --git a/qiskit/providers/ibmq/ibmqbackendservice.py b/qiskit/providers/ibmq/ibmqbackendservice.py index 37126c8a7..e356c9d51 100644 --- a/qiskit/providers/ibmq/ibmqbackendservice.py +++ b/qiskit/providers/ibmq/ibmqbackendservice.py @@ -21,8 +21,7 @@ from typing import Dict, List, Callable, Optional, Any, Union from datetime import datetime -from qiskit.providers.jobstatus import JobStatus -from qiskit.providers.exceptions import QiskitBackendNotFoundError +from qiskit.providers import JobStatus, QiskitBackendNotFoundError # type: ignore[attr-defined] from qiskit.providers.providerutils import filter_backends from qiskit.providers.ibmq import accountprovider # pylint: disable=unused-import @@ -360,13 +359,13 @@ def _update_creation_date_filter( lt_list.append(cur_dt_filter.pop('between')[1]) lte_dt = min(lt_list) if lt_list else None - new_dt_filter = {} # type: Dict[str, Union[str, List[str]]] + new_dt_filter = {} if gte_dt and lte_dt: new_dt_filter['between'] = [gte_dt, lte_dt] elif gte_dt: - new_dt_filter['gte'] = gte_dt + new_dt_filter['gte'] = gte_dt # type: ignore[assignment] elif lte_dt: - new_dt_filter['lte'] = lte_dt + new_dt_filter['lte'] = lte_dt # type: ignore[assignment] return new_dt_filter @@ -432,7 +431,7 @@ def _get_status_filter(self, status: Union[JobStatus, str]) -> Dict[str, Any]: elif status == JobStatus.DONE: _status_filter = {'status': ApiJobStatus.COMPLETED.value} elif status == JobStatus.ERROR: - _status_filter = {'status': {'regexp': '^ERROR'}} + _status_filter = {'status': {'regexp': '^ERROR'}} # type: ignore[assignment] else: raise IBMQBackendValueError( '"{}" is not a valid status value. Valid values are {}'.format( diff --git a/qiskit/providers/ibmq/job/ibmqjob.py b/qiskit/providers/ibmq/job/ibmqjob.py index 1033fa890..077a86d45 100644 --- a/qiskit/providers/ibmq/job/ibmqjob.py +++ b/qiskit/providers/ibmq/job/ibmqjob.py @@ -98,7 +98,7 @@ class IBMQJob(BaseJob): which is a supported attribute. """ - _data = {} # type: Dict + _data = {} _executor = futures.ThreadPoolExecutor() """Threads used for asynchronous processing.""" @@ -890,7 +890,7 @@ def _wait_for_completion( return self._status in required_status - def _retrieve_result(self, refresh: bool = False) -> None: + def _retrieve_result(self, refresh: bool = False): """Retrieve the job result response. Args: diff --git a/qiskit/providers/ibmq/job/queueinfo.py b/qiskit/providers/ibmq/job/queueinfo.py index 4c4af55d0..5c26f6c09 100644 --- a/qiskit/providers/ibmq/job/queueinfo.py +++ b/qiskit/providers/ibmq/job/queueinfo.py @@ -14,7 +14,7 @@ """Queue information for a job.""" -from typing import Any, Optional, Union, Dict +from typing import Any, Optional, Union from datetime import datetime import warnings @@ -27,7 +27,7 @@ class QueueInfo: """Queue information for a job.""" - _data = {} # type: Dict + _data = {} def __init__( self, diff --git a/qiskit/providers/ibmq/managed/managedresults.py b/qiskit/providers/ibmq/managed/managedresults.py index 207548be6..a22a5a878 100644 --- a/qiskit/providers/ibmq/managed/managedresults.py +++ b/qiskit/providers/ibmq/managed/managedresults.py @@ -17,6 +17,7 @@ from typing import List, Optional, Union, Tuple, Dict import copy +# TODO Use TYPE_CHECKING instead of pylint disable after dropping python 3.5 import numpy # pylint: disable=unused-import from qiskit.result import Result from qiskit.circuit import QuantumCircuit @@ -56,7 +57,7 @@ def __init__( self._job_set = job_set self.backend_name = backend_name self.success = success - self._combined_results = None # type: Optional[Result] + self._combined_results = None # type: Result def data(self, experiment: Union[str, QuantumCircuit, Schedule, int]) -> Dict: """Get the raw data for an experiment. diff --git a/qiskit/providers/ibmq/managed/utils.py b/qiskit/providers/ibmq/managed/utils.py index cfbe57112..58b29e8b8 100644 --- a/qiskit/providers/ibmq/managed/utils.py +++ b/qiskit/providers/ibmq/managed/utils.py @@ -58,7 +58,7 @@ def _wrapper( return value of the decorated function. """ futures = [managed_job.future for managed_job - in job_set._managed_jobs if managed_job.future] # type: ignore[unreachable] + in job_set._managed_jobs if managed_job.future] wait(futures) return func(job_set, *args, **kwargs) diff --git a/qiskit/providers/ibmq/random/baserandomservice.py b/qiskit/providers/ibmq/random/baserandomservice.py index 08d9e9312..0d825ccd7 100644 --- a/qiskit/providers/ibmq/random/baserandomservice.py +++ b/qiskit/providers/ibmq/random/baserandomservice.py @@ -15,7 +15,7 @@ """Module for interfacing with a remote extractor.""" import logging -from typing import List, Any +from typing import List from abc import ABC, abstractmethod @@ -49,6 +49,6 @@ def __init__( self.methods = methods @abstractmethod - def run(self, *args: Any, **kwargs: Any) -> Any: + def run(self, *args, **kwargs): """Execute the service.""" pass diff --git a/qiskit/providers/ibmq/random/cqcextractor.py b/qiskit/providers/ibmq/random/cqcextractor.py index 0ab5d17df..8280be038 100644 --- a/qiskit/providers/ibmq/random/cqcextractor.py +++ b/qiskit/providers/ibmq/random/cqcextractor.py @@ -28,7 +28,7 @@ class CQCExtractor(BaseRandomService): """Class for interfacing with a CQC remote extractor.""" - def run( # type: ignore[override] + def run( self, ext1_in_num_bits: int, ext1_out_num_bits: int, @@ -36,8 +36,7 @@ def run( # type: ignore[override] ext1_wsr_bytes: bytes, ext2_seed_num_bits: int, ext2_wsr_multiplier: int, - ext2_wsr_generator: Optional[Callable] = None - ) -> List[int]: + ext2_wsr_generator: Optional[Callable] = None) -> List[int]: """Process input data synchronously. Args: @@ -118,7 +117,7 @@ def run_ext2( Extracted random bits. """ logger.info("Starting second extraction.") - ext2_seed = bitarray_to_bytes(ext2_seed[:ext2_seed_num_bits]) # type: ignore[assignment] + ext2_seed = bitarray_to_bytes(ext2_seed[:ext2_seed_num_bits]) if ext2_wsr_generator is None: ext2_wsr_generator = generate_wsr ext2_wsr = ext2_wsr_generator(ext2_seed_num_bits*ext2_wsr_multiplier) @@ -130,7 +129,7 @@ def run_ext2( raw_data = self._client.extract(name='cqc', method='ext2', data=ext2_data, files=ext2_files) return bytes_to_bitarray(raw_data, (ext2_wsr_multiplier-1)*ext2_seed_num_bits) - def __repr__(self) -> str: + def __repr__(self): return "<{}('{}') from {}>".format(self.__class__.__name__, self.name, self._provider) diff --git a/qiskit/providers/ibmq/random/ibmqrandomservice.py b/qiskit/providers/ibmq/random/ibmqrandomservice.py index 00fdfde20..9f9ca154d 100644 --- a/qiskit/providers/ibmq/random/ibmqrandomservice.py +++ b/qiskit/providers/ibmq/random/ibmqrandomservice.py @@ -15,7 +15,7 @@ """IBMQ random number service.""" import logging -from typing import Dict, List, Any +from typing import Dict, List from qiskit.providers.ibmq import accountprovider # pylint: disable=unused-import from .baserandomservice import BaseRandomService @@ -105,11 +105,11 @@ def get_service(self, name: str) -> BaseRandomService: return service - def __dir__(self) -> Dict: + def __dir__(self): self._discover_services() return self.__dict__ - def __getattr__(self, item: str) -> Any: + def __getattr__(self, item): self._discover_services() try: return self._services[item] diff --git a/qiskit/providers/ibmq/version.py b/qiskit/providers/ibmq/version.py index 9cd1eb2fc..a9cfdcafa 100644 --- a/qiskit/providers/ibmq/version.py +++ b/qiskit/providers/ibmq/version.py @@ -21,12 +21,11 @@ import os import subprocess -from typing import List ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) -def _minimal_ext_cmd(cmd: List[str]) -> bytes: +def _minimal_ext_cmd(cmd): # construct minimal environment env = {} for k in ['SYSTEMROOT', 'PATH']: @@ -46,7 +45,7 @@ def _minimal_ext_cmd(cmd: List[str]) -> bytes: return out -def git_version() -> str: +def git_version(): """Get the current git head sha1.""" # Determine if we're at master try: @@ -62,7 +61,7 @@ def git_version() -> str: VERSION = version_file.read().strip() -def get_version_info() -> str: +def get_version_info(): """Get the full version string.""" # Adding the git rev number needs to be done inside # write_version_py(), otherwise the import of scipy.version messes diff --git a/releasenotes/notes/drop-py35-0eec8b799e9ae407.yaml b/releasenotes/notes/drop-py35-0eec8b799e9ae407.yaml deleted file mode 100644 index e0a8872de..000000000 --- a/releasenotes/notes/drop-py35-0eec8b799e9ae407.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -upgrade: - - | - The deprecated support for running qiskit-ibmq-provider with Python 3.5 has - been removed. To use qiskit-ibmq-provider >=0.10.0 you will now need at - least Python 3.6. If you are using Python 3.5 the last version which will - work is qiskit-ibmq-provider 0.9.x. diff --git a/releasenotes/notes/websockets-8-b02a2cdc133c2a25.yaml b/releasenotes/notes/websockets-8-b02a2cdc133c2a25.yaml deleted file mode 100644 index cc140aaf8..000000000 --- a/releasenotes/notes/websockets-8-b02a2cdc133c2a25.yaml +++ /dev/null @@ -1,6 +0,0 @@ ---- -upgrade: - - | - Prior to this release, ``websockets`` 7.0 was used for Python 3.6. - With this release, ``websockets`` 8.0 or above is required for all Python versions. - The package requirements have been updated to reflect this. diff --git a/requirements-dev.txt b/requirements-dev.txt index 5bc26f7a8..5c0ecb2fe 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -3,8 +3,9 @@ pycodestyle pylint>=2.4 pylintfileheader>=0.0.2 vcrpy -pproxy==2.1.8 -Sphinx>=1.8.3 +pproxy==1.2.2; python_version <= '3.5' +pproxy==2.1.8; python_version > '3.5' +Sphinx>=1.8.3,<3.1.0 sphinx-rtd-theme>=0.4.0 sphinx-tabs>=1.1.11 sphinx-automodapi diff --git a/requirements.txt b/requirements.txt index 81c5fe624..7a1174977 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,8 @@ nest-asyncio>=1.0.0,!=1.1.0 qiskit-terra>=0.14 requests>=2.19 requests_ntlm>=1.1.0 -websockets>=8 +websockets>=7,<8;python_version <= '3.6' +websockets>=8;python_version > '3.6' numpy>=1.13 urllib3>=1.21.1 python-dateutil>=2.8.0 diff --git a/setup.py b/setup.py index bd50e5cb8..c02c8265e 100644 --- a/setup.py +++ b/setup.py @@ -21,7 +21,8 @@ "qiskit-terra>=0.14", "requests>=2.19", "requests-ntlm>=1.1.0", - "websockets>=8", + "websockets>=7,<8;python_version <= '3.6'", + "websockets>=8;python_version > '3.6'", "numpy>=1.13", "urllib3>=1.21.1", "python-dateutil>=2.8.0" @@ -60,6 +61,7 @@ "Operating System :: MacOS", "Operating System :: POSIX :: Linux", "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", @@ -82,7 +84,7 @@ 'qiskit.providers.ibmq.random'], install_requires=REQUIREMENTS, include_package_data=True, - python_requires=">=3.6", + python_requires=">=3.5", zip_safe=False, extras_require={'visualization': ['matplotlib>=2.1', 'ipywidgets>=7.3.0', "seaborn>=0.9.0", "plotly>=4.4", diff --git a/test/ibmq/websocket/websocket_server.py b/test/ibmq/websocket/websocket_server.py index 38dd1550d..0161d37c1 100644 --- a/test/ibmq/websocket/websocket_server.py +++ b/test/ibmq/websocket/websocket_server.py @@ -16,6 +16,7 @@ import asyncio import json +import warnings from qiskit.providers.ibmq.api.clients.websocket import WebsocketResponseMethod @@ -29,11 +30,12 @@ TOKEN_WEBSOCKET_JOB_NOT_FOUND = 'token_websocket_job_not_found' -async def websocket_handler(websocket, path): +@asyncio.coroutine +def websocket_handler(websocket, path): """Entry point for the websocket mock server.""" # pylint: disable=unused-argument # Receive the authentication message. - msg_in = await websocket.recv() + msg_in = yield from websocket.recv() auth_message = json.loads(msg_in) # Check for valid access tokens. @@ -46,77 +48,86 @@ async def websocket_handler(websocket, path): TOKEN_WEBSOCKET_RETRY_FAILURE, TOKEN_WEBSOCKET_JOB_NOT_FOUND): msg_out = json.dumps({'type': 'authenticated'}) - await websocket.send(msg_out.encode('utf8')) + yield from websocket.send(msg_out.encode('utf8')) else: # Close the connection. - await websocket.close() + yield from websocket.close() # Depending on the access token, perform different actions: if token == TOKEN_JOB_COMPLETED: - await handle_token_job_completed(websocket) + yield from handle_token_job_completed(websocket) elif token == TOKEN_JOB_TRANSITION: - await handle_token_job_transition(websocket) + yield from handle_token_job_transition(websocket) elif token == TOKEN_TIMEOUT: - await handle_token_timeout(websocket) + yield from handle_token_timeout(websocket) elif token == TOKEN_WRONG_FORMAT: - await handle_token_wrong_format(websocket) + yield from handle_token_wrong_format(websocket) elif token == TOKEN_WEBSOCKET_RETRY_SUCCESS: - await handle_token_retry_success(websocket) + yield from handle_token_retry_success(websocket) elif token == TOKEN_WEBSOCKET_RETRY_FAILURE: - await handle_token_retry_failure(websocket) + yield from handle_token_retry_failure(websocket) elif token == TOKEN_WEBSOCKET_JOB_NOT_FOUND: - await handle_token_job_not_found(websocket) + yield from handle_token_job_not_found(websocket) -async def handle_token_job_completed(websocket): +@asyncio.coroutine +def handle_token_job_completed(websocket): """Return a final job status, and close with 4002.""" msg_out = WebsocketResponseMethod(type_='job-status', data={'status': 'COMPLETED'}) - await websocket.send(msg_out.as_json().encode('utf8')) - await websocket.close(code=4002) + yield from websocket.send(msg_out.as_json().encode('utf8')) + yield from websocket.close(code=4002) -async def handle_token_job_transition(websocket): +@asyncio.coroutine +def handle_token_job_transition(websocket): """Send several job status, and close with 4002.""" msg_out = WebsocketResponseMethod(type_='job-status', data={'status': 'RUNNING'}) - await websocket.send(msg_out.as_json().encode('utf8')) + yield from websocket.send(msg_out.as_json().encode('utf8')) - await asyncio.sleep(1) + yield from asyncio.sleep(1) msg_out = WebsocketResponseMethod(type_='job-status', data={'status': 'COMPLETED'}) - await websocket.send(msg_out.as_json().encode('utf8')) + yield from websocket.send(msg_out.as_json().encode('utf8')) - await websocket.close(code=4002) + yield from websocket.close(code=4002) -async def handle_token_timeout(websocket): +@asyncio.coroutine +def handle_token_timeout(websocket): """Close the socket after 10 seconds, without replying.""" - await asyncio.sleep(10) - await websocket.close() + yield from asyncio.sleep(10) + yield from websocket.close() -async def handle_token_wrong_format(websocket): +@asyncio.coroutine +def handle_token_wrong_format(websocket): """Return a status in an invalid format.""" - await websocket.send('INVALID'.encode('utf8')) - await websocket.close() + yield from websocket.send('INVALID'.encode('utf8')) + yield from websocket.close() -async def handle_token_retry_success(websocket): +@asyncio.coroutine +def handle_token_retry_success(websocket): """Close the socket once and force a retry.""" if not hasattr(handle_token_retry_success, 'retry_attempt'): setattr(handle_token_retry_success, 'retry_attempt', True) - await handle_token_retry_failure(websocket) + yield from handle_token_retry_failure(websocket) else: - await handle_token_job_completed(websocket) + yield from handle_token_job_completed(websocket) -async def handle_token_retry_failure(websocket): +@asyncio.coroutine +def handle_token_retry_failure(websocket): """Continually close the socket, until both the first attempt and retry fail.""" - await websocket.close() + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning) + yield from websocket.close() -async def handle_token_job_not_found(websocket): +@asyncio.coroutine +def handle_token_job_not_found(websocket): """Close the socket, specifying code for job not found.""" - await websocket.close(code=4003) + yield from websocket.close(code=4003) diff --git a/tox.ini b/tox.ini index 526382ea4..9397053df 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] minversion = 2.1 -envlist = py36, py37, lint, docs +envlist = py35, py36, py37, lint, docs skipsdist = True [testenv]