Repository: dwavesystems/dwave-cloud-client
Pull request #191 (2018-06-07 03:20:23)

Change Client for better .solvers() experience and more
Use nicer Solver object representation (e.g. `Solver(id='DW_2000Q_2')`
instead of `<dwave.cloud.solver.Solver object at 0x7f6c0f4b06d8>`).

Make `Client.from_config` more consistent with `Client` constructor
by defaulting to creating an instance of the actual `Client` class used
(generic in `client`, QPU in `qpu`, or software in `sw`).


Patch:
diff --git a/dwave/cloud/client.py b/dwave/cloud/client.py
index b8333be..86638b7 100644
--- a/dwave/cloud/client.py
+++ b/dwave/cloud/client.py
@@ -374,8 +374,8 @@ class Client(object):
         config.update(kwargs)
 
         from dwave.cloud import qpu, sw
-        _clients = {'qpu': qpu.Client, 'sw': sw.Client}
-        _client = config.pop('client', None) or 'qpu'
+        _clients = {'qpu': qpu.Client, 'sw': sw.Client, 'base': cls}
+        _client = config.pop('client', None) or 'base'
 
         _LOGGER.debug("Final config used for %s.Client(): %r", _client, config)
         return _clients[_client](**config)
@@ -625,6 +625,13 @@ class Client(object):
         Returns:
             list[Solver]: List of all solvers that satisfy the above conditions.
 
+        Note:
+            Client subclasses (e.g. :class:`dwave.cloud.qpu.Client` or
+            :class:`dwave.cloud.sw.Client`) already filter solvers by resource
+            type, so for ``qpu`` and ``software`` filters to have effect, you
+            need to call :meth:`.solvers` on the base :class:`~dwave.cloud.client.Client`
+            class.
+
         Examples:
             Get a solver not based on VFYC, with 2048 qubits:
 
diff --git a/dwave/cloud/solver.py b/dwave/cloud/solver.py
index 683186f..8f24b92 100644
--- a/dwave/cloud/solver.py
+++ b/dwave/cloud/solver.py
@@ -131,7 +131,7 @@ class Solver(object):
         if 'annealing_time_range' in self.properties:
             self._params[self._PARAMETER_ENABLE_HARDWARE] = True
 
-    def __str__(self):
+    def __repr__(self):
         return "Solver(id={!r})".format(self.id)
 
     @property


Test patch:
diff --git a/tests/test_client.py b/tests/test_client.py
index 48ea57a..8ac6746 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -8,7 +8,7 @@ from __future__ import absolute_import
 import unittest
 
 from dwave.cloud.config import load_config
-from dwave.cloud.qpu import Client
+from dwave.cloud.client import Client
 from dwave.cloud.solver import Solver
 from dwave.cloud.exceptions import SolverAuthenticationError
 from dwave.cloud.testing import mock
@@ -79,8 +79,34 @@ class ClientFactory(unittest.TestCase):
             with dwave.cloud.Client.from_config() as client:
                 self.assertEqual(client.endpoint, 'endpoint')
                 self.assertEqual(client.token, 'token')
-                self.assertIsInstance(client, dwave.cloud.qpu.Client)
+                self.assertIsInstance(client, dwave.cloud.client.Client)
                 self.assertNotIsInstance(client, dwave.cloud.sw.Client)
+                self.assertNotIsInstance(client, dwave.cloud.qpu.Client)
+
+    def test_client_type(self):
+        conf = {k: k for k in 'endpoint token'.split()}
+        def mocked_load_config(**kwargs):
+            kwargs.update(conf)
+            return kwargs
+
+        with mock.patch("dwave.cloud.client.load_config", mocked_load_config):
+            with dwave.cloud.Client.from_config() as client:
+                self.assertIsInstance(client, dwave.cloud.client.Client)
+
+            with dwave.cloud.client.Client.from_config() as client:
+                self.assertIsInstance(client, dwave.cloud.client.Client)
+
+            with dwave.cloud.qpu.Client.from_config() as client:
+                self.assertIsInstance(client, dwave.cloud.qpu.Client)
+
+            with dwave.cloud.sw.Client.from_config() as client:
+                self.assertIsInstance(client, dwave.cloud.sw.Client)
+
+            with dwave.cloud.Client.from_config(client='qpu') as client:
+                self.assertIsInstance(client, dwave.cloud.qpu.Client)
+
+            with dwave.cloud.qpu.Client.from_config(client='base') as client:
+                self.assertIsInstance(client, dwave.cloud.client.Client)
 
     def test_custom_kwargs(self):
         conf = {k: k for k in 'endpoint token'.split()}