Skip to content
This repository was archived by the owner on Jul 28, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
;;
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 6 additions & 2 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ jobs:
# condition: eq(variables['Build.Reason'], 'PullRequest')
strategy:
matrix:
Python35:
python.version: '3.5'
Python36:
python.version: '3.6'
Python37:
Expand Down Expand Up @@ -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:
Expand Down
6 changes: 2 additions & 4 deletions qiskit/providers/ibmq/accountprovider.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
3 changes: 2 additions & 1 deletion qiskit/providers/ibmq/api/clients/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions qiskit/providers/ibmq/api/clients/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down
46 changes: 29 additions & 17 deletions qiskit/providers/ibmq/api/clients/websocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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:
Expand All @@ -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:
Expand All @@ -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.')

Expand All @@ -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
Expand Down Expand Up @@ -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()))
Expand Down Expand Up @@ -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 ' \
Expand Down
2 changes: 1 addition & 1 deletion qiskit/providers/ibmq/api/rest/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions qiskit/providers/ibmq/backendjoblimit.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

"""Job limit information related to a backend."""

from typing import Any, Dict
from typing import Any


class BackendJobLimit:
Expand All @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions qiskit/providers/ibmq/backendreservation.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

"""Reservation information related to a backend."""

from typing import Optional, Any
from typing import Optional
from datetime import datetime


Expand Down Expand Up @@ -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
Expand Down
11 changes: 5 additions & 6 deletions qiskit/providers/ibmq/ibmqbackendservice.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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(
Expand Down
4 changes: 2 additions & 2 deletions qiskit/providers/ibmq/job/ibmqjob.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class IBMQJob(BaseJob):
which is a supported attribute.
"""

_data = {} # type: Dict
_data = {}

_executor = futures.ThreadPoolExecutor()
"""Threads used for asynchronous processing."""
Expand Down Expand Up @@ -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:
Expand Down
4 changes: 2 additions & 2 deletions qiskit/providers/ibmq/job/queueinfo.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -27,7 +27,7 @@
class QueueInfo:
"""Queue information for a job."""

_data = {} # type: Dict
_data = {}

def __init__(
self,
Expand Down
Loading