def test_defaults(self):
        with self.assertRaises(ValueError):
            DWaveAPIClient()

        endpoint = constants.DEFAULT_METADATA_API_ENDPOINT
        client = DWaveAPIClient(endpoint=endpoint)

        defaults = DWaveAPIClient.DEFAULTS.copy()
        defaults.update(endpoint=endpoint)

        self.assertEqual(client.config, defaults)
        self.assertIsInstance(client.session, requests.Session)

        # verify Retry object config
        retry = client.session.get_adapter('https://').max_retries
        conf = DWaveAPIClient.DEFAULTS['retry']
        client.close()
        self.assertEqual(retry.total, conf['total'])
class ResourceBase:
    """A class for interacting with a SAPI resource."""

    resource_path = None

    def _patch_session(self):
        # anchor all session requests at the new base path
        if self.resource_path and self.session:
            self.session.base_url = self.session.create_url(self.resource_path)

    def __init__(self, **config):
        self.client = DWaveAPIClient(**config)
        self.session = self.client.session
        self._patch_session()

    def close(self):
        self.client.close()

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        self.close()

    @classmethod
    def from_client_config(cls,
                           client: Union[DWaveAPIClient,
                                         'dwave.cloud.client.base.Client']):
        """Create Resource instance configured from a
        :class:`~dwave.cloud.client.base.Client' instance.
        """
        # TODO: also accept configuration dict/dataclass when config/client refactored
        if isinstance(client, DWaveAPIClient):
            return cls(**client.config)
        else:  # assume isinstance(client, dwave.cloud.Client), without importing
            sapiclient = SolverAPIClient.from_client_config(client)
            return cls(**sapiclient.config)