Repository: dwavesystems/dwave-cloud-client

Issue:
Circular import error
In the last refactor we introduced an import error:
```
>>> from dwave.cloud.exceptions import ConfigFileError
...
ImportError: cannot import name 'ConfigFileReadError' from partially initialized module 'dwave.cloud.exceptions' (most likely due to a circular import)
```


Discussion:
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/dwavesystems/dwave-cloud-client/pull/670?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dwavesystems) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 88.88%. Comparing base [(`f0bda47`)](https://app.codecov.io/gh/dwavesystems/dwave-cloud-client/commit/f0bda4798326113cfde88cc6b7b15a5242980b4a?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dwavesystems) to head [(`1c65f83`)](https://app.codecov.io/gh/dwavesystems/dwave-cloud-client/commit/1c65f838a38a2e35de1438d7e20f96d83e120db8?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dwavesystems).

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master     #670      +/-   ##
==========================================
+ Coverage   88.86%   88.88%   +0.01%     
==========================================
  Files          42       44       +2     
  Lines        4814     4821       +7     
==========================================
+ Hits         4278     4285       +7     
  Misses        536      536              
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/dwavesystems/dwave-cloud-client/pull/670?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dwavesystems).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=dwavesystems).


Patch:
diff --git a/dwave/cloud/api/client.py b/dwave/cloud/api/client.py
index a169baf..55acf92 100644
--- a/dwave/cloud/api/client.py
+++ b/dwave/cloud/api/client.py
@@ -29,8 +29,8 @@ import urllib3
 import werkzeug
 from packaging.specifiers import SpecifierSet
 
-import dwave.cloud.config   # don't use `from` to break circular import (config <> api.constants)
-from dwave.cloud.api import constants, exceptions
+import dwave.cloud.config
+from dwave.cloud.api import exceptions
 from dwave.cloud.utils.exception import is_caused_by
 from dwave.cloud.utils.http import PretimedHTTPAdapter, BaseUrlSession, default_user_agent
 from dwave.cloud.utils.time import epochnow
@@ -729,7 +729,7 @@ class SolverAPIClient(DWaveAPIClient):
     def __init__(self, **config):
         # TODO: make endpoint region-sensitive
         self.DEFAULTS = super().DEFAULTS.copy()
-        self.DEFAULTS.update(endpoint=constants.DEFAULT_SOLVER_API_ENDPOINT)
+        self.DEFAULTS.update(endpoint=dwave.cloud.config.constants.DEFAULT_SOLVER_API_ENDPOINT)
 
         super().__init__(**config)
 
@@ -740,7 +740,7 @@ class MetadataAPIClient(DWaveAPIClient):
     def __init__(self, **config):
         # TODO: make endpoint region-sensitive
         self.DEFAULTS = super().DEFAULTS.copy()
-        self.DEFAULTS.update(endpoint=constants.DEFAULT_METADATA_API_ENDPOINT)
+        self.DEFAULTS.update(endpoint=dwave.cloud.config.constants.DEFAULT_METADATA_API_ENDPOINT)
 
         super().__init__(**config)
 
@@ -761,7 +761,7 @@ class LeapAPIClient(DWaveAPIClient):
     def __init__(self, **config):
         # TODO: make endpoint region-sensitive
         self.DEFAULTS = super().DEFAULTS.copy()
-        self.DEFAULTS.update(endpoint=constants.DEFAULT_LEAP_API_ENDPOINT)
+        self.DEFAULTS.update(endpoint=dwave.cloud.config.constants.DEFAULT_LEAP_API_ENDPOINT)
 
         super().__init__(**config)
 
diff --git a/dwave/cloud/api/constants.py b/dwave/cloud/api/constants.py
index 6d87375..e99f86b 100644
--- a/dwave/cloud/api/constants.py
+++ b/dwave/cloud/api/constants.py
@@ -14,15 +14,11 @@
 
 import enum
 
-
-# Default API endpoints
-DEFAULT_SOLVER_API_ENDPOINT = 'https://cloud.dwavesys.com/sapi/'
-
-DEFAULT_METADATA_API_ENDPOINT = 'https://cloud.dwavesys.com/metadata/v1/'
-
-DEFAULT_LEAP_API_ENDPOINT = 'https://cloud.dwavesys.com/leap/api/'
-
-DEFAULT_REGION = 'na-west-1'
+# note: for backwards compatibility in 0.13.1+
+# TODO: remove in 0.14.0
+from dwave.cloud.config.constants import (
+    DEFAULT_METADATA_API_ENDPOINT, DEFAULT_REGION,
+    DEFAULT_SOLVER_API_ENDPOINT, DEFAULT_LEAP_API_ENDPOINT)
 
 
 # Default API version
diff --git a/dwave/cloud/api/resources.py b/dwave/cloud/api/resources.py
index 2686f60..f863cb3 100644
--- a/dwave/cloud/api/resources.py
+++ b/dwave/cloud/api/resources.py
@@ -21,9 +21,9 @@ from functools import wraps
 
 from pydantic import TypeAdapter
 
+from dwave.cloud.api import constants, models
 from dwave.cloud.api.client import (
     DWaveAPIClient, SolverAPIClient, MetadataAPIClient, LeapAPIClient)
-from dwave.cloud.api import constants, models
 
 if TYPE_CHECKING:
     from dwave.cloud.config.models import ClientConfig
diff --git a/dwave/cloud/client/base.py b/dwave/cloud/client/base.py
index 90f73d7..9a0efdf 100644
--- a/dwave/cloud/client/base.py
+++ b/dwave/cloud/client/base.py
@@ -67,6 +67,7 @@ from dwave.cloud.package_info import __packagename__, __version__
 from dwave.cloud.exceptions import *    # TODO: fix
 from dwave.cloud.computation import Future
 from dwave.cloud.config import load_config, update_config, validate_config_v1
+from dwave.cloud.config import constants as config_constants
 from dwave.cloud.config.models import ClientConfig, PollingStrategy
 from dwave.cloud.solver import available_solvers, StructuredSolver, UnstructuredSolver
 from dwave.cloud.concurrency import PriorityThreadPoolExecutor
@@ -283,8 +284,8 @@ class Client(object):
 
     # Default API endpoint
     # TODO: remove when refactored to use `dwave.cloud.api`?
-    DEFAULT_API_ENDPOINT = api.constants.DEFAULT_SOLVER_API_ENDPOINT
-    DEFAULT_API_REGION = api.constants.DEFAULT_REGION
+    DEFAULT_API_ENDPOINT = config_constants.DEFAULT_SOLVER_API_ENDPOINT
+    DEFAULT_API_REGION = config_constants.DEFAULT_REGION
 
     # Class-level defaults for all constructor and factory arguments
     DEFAULTS = {
@@ -293,7 +294,7 @@ class Client(object):
         'profile': None,
         'client': 'base',
         # constructor (and factory)
-        'metadata_api_endpoint': api.constants.DEFAULT_METADATA_API_ENDPOINT,
+        'metadata_api_endpoint': config_constants.DEFAULT_METADATA_API_ENDPOINT,
         'region': DEFAULT_API_REGION,
         'leap_api_endpoint': None,
         'leap_client_id': None,
@@ -406,10 +407,10 @@ class Client(object):
                 Appropriate instance of a QPU/software/hybrid client.
 
         Raises:
-            :exc:`~dwave.cloud.exceptions.ConfigFileReadError`:
+            :exc:`~dwave.cloud.config.exceptions.ConfigFileReadError`:
                 Config file specified or detected could not be opened or read.
 
-            :exc:`~dwave.cloud.exceptions.ConfigFileParseError`:
+            :exc:`~dwave.cloud.config.exceptions.ConfigFileParseError`:
                 Config file parse failed.
 
             :exc:`ValueError`:
diff --git a/dwave/cloud/config/__init__.py b/dwave/cloud/config/__init__.py
index 5398cab..254aeec 100644
--- a/dwave/cloud/config/__init__.py
+++ b/dwave/cloud/config/__init__.py
@@ -158,5 +158,7 @@ Examples:
     >>> client.close() # doctest: +SKIP
 """
 
+from .constants import *
+from .exceptions import *
 from .loaders import *
 from .models import *
diff --git a/dwave/cloud/config/constants.py b/dwave/cloud/config/constants.py
new file mode 100644
index 0000000..5bd518a
--- /dev/null
+++ b/dwave/cloud/config/constants.py
@@ -0,0 +1,33 @@
+# Copyright 2024 D-Wave Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Configuration defaults.
+
+.. versionchanged:: 0.13.1
+   Some of these constants previously lived under ``dwave.cloud.api.constants``.
+
+"""
+
+__all__ = ['DEFAULT_METADATA_API_ENDPOINT', 'DEFAULT_REGION',
+           'DEFAULT_SOLVER_API_ENDPOINT', 'DEFAULT_LEAP_API_ENDPOINT']
+
+
+# Default API endpoints
+DEFAULT_METADATA_API_ENDPOINT = 'https://cloud.dwavesys.com/metadata/v1/'
+
+DEFAULT_REGION = 'na-west-1'
+
+DEFAULT_SOLVER_API_ENDPOINT = 'https://cloud.dwavesys.com/sapi/'
+
+DEFAULT_LEAP_API_ENDPOINT = 'https://cloud.dwavesys.com/leap/api/'
diff --git a/dwave/cloud/config/exceptions.py b/dwave/cloud/config/exceptions.py
new file mode 100644
index 0000000..ad3edf5
--- /dev/null
+++ b/dwave/cloud/config/exceptions.py
@@ -0,0 +1,32 @@
+# Copyright 2024 D-Wave Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Config-related exceptions.
+
+.. versionchanged:: 0.13.1
+   These exceptions previously lived under ``dwave.cloud.exceptions``.
+
+"""
+
+__all__ = ['ConfigFileError', 'ConfigFileReadError', 'ConfigFileParseError']
+
+
+class ConfigFileError(Exception):
+    """Base exception for all config file processing errors."""
+
+class ConfigFileReadError(ConfigFileError):
+    """Non-existing or unreadable config file specified or implied."""
+
+class ConfigFileParseError(ConfigFileError):
+    """Invalid format of config file."""
diff --git a/dwave/cloud/config/loaders.py b/dwave/cloud/config/loaders.py
index 3ae2349..6086410 100644
--- a/dwave/cloud/config/loaders.py
+++ b/dwave/cloud/config/loaders.py
@@ -20,7 +20,7 @@ from typing import List, Optional, Union
 
 import homebase
 
-from dwave.cloud.exceptions import ConfigFileReadError, ConfigFileParseError
+from dwave.cloud.config.exceptions import ConfigFileReadError, ConfigFileParseError
 from dwave.cloud.package_info import __version__, __packagename__
 
 __all__ = ['get_configfile_paths', 'get_configfile_path',
@@ -282,10 +282,10 @@ def load_config_from_files(filenames=None):
             mapping of per-profile keys holding values.
 
     Raises:
-        :exc:`~dwave.cloud.exceptions.ConfigFileReadError`:
+        :exc:`~dwave.cloud.config.exceptions.ConfigFileReadError`:
             Config file specified or detected could not be opened or read.
 
-        :exc:`~dwave.cloud.exceptions.ConfigFileParseError`:
+        :exc:`~dwave.cloud.config.exceptions.ConfigFileParseError`:
             Config file parse failed.
 
     """
@@ -339,10 +339,10 @@ def load_profile_from_files(filenames=None, profile=None):
             is found, returns an empty dict.
 
     Raises:
-        :exc:`~dwave.cloud.exceptions.ConfigFileReadError`:
+        :exc:`~dwave.cloud.config.exceptions.ConfigFileReadError`:
             Config file specified or detected could not be opened or read.
 
-        :exc:`~dwave.cloud.exceptions.ConfigFileParseError`:
+        :exc:`~dwave.cloud.config.exceptions.ConfigFileParseError`:
             Config file parse failed.
 
         :exc:`ValueError`:
@@ -484,8 +484,8 @@ def load_config(config_file: Optional[Union[str, bool]] = None,
 
     If a configuration file explicitly specified, via an argument or
     environment variable, does not exist or is unreadable, loading fails with
-    :exc:`~dwave.cloud.exceptions.ConfigFileReadError`. Loading fails
-    with :exc:`~dwave.cloud.exceptions.ConfigFileParseError` if the file is
+    :exc:`~dwave.cloud.config.exceptions.ConfigFileReadError`. Loading fails
+    with :exc:`~dwave.cloud.config.exceptions.ConfigFileParseError` if the file is
     readable but invalid as a configuration file.
 
     Similarly, if a profile explicitly specified, via an argument or
@@ -539,10 +539,10 @@ def load_config(config_file: Optional[Union[str, bool]] = None,
         :exc:`ValueError`:
             Invalid (non-existing) profile name.
 
-        :exc:`~dwave.cloud.exceptions.ConfigFileReadError`:
+        :exc:`~dwave.cloud.config.exceptions.ConfigFileReadError`:
             Config file specified or detected could not be opened or read.
 
-        :exc:`~dwave.cloud.exceptions.ConfigFileParseError`:
+        :exc:`~dwave.cloud.config.exceptions.ConfigFileParseError`:
             Config file parse failed.
 
     Note:
diff --git a/dwave/cloud/config/models.py b/dwave/cloud/config/models.py
index 21bedb5..d79240a 100644
--- a/dwave/cloud/config/models.py
+++ b/dwave/cloud/config/models.py
@@ -24,9 +24,8 @@ from typing_extensions import Annotated     # backport for py37, py38
 import urllib3
 from pydantic import BaseModel, BeforeValidator, NonNegativeInt
 
+from dwave.cloud.config import constants
 from dwave.cloud.config.loaders import update_config
-from dwave.cloud.api.constants import (
-    DEFAULT_REGION, DEFAULT_METADATA_API_ENDPOINT, DEFAULT_LEAP_API_ENDPOINT)
 
 __all__ = ['RequestRetryConfig', 'ClientConfig',
            'BackoffPollingSchedule', 'LongPollingSchedule',
@@ -133,7 +132,7 @@ def _literal_eval(obj):
 
 class ClientConfig(BaseModel, GetterMixin):
     # api region
-    metadata_api_endpoint: Optional[str] = DEFAULT_METADATA_API_ENDPOINT
+    metadata_api_endpoint: Optional[str] = constants.DEFAULT_METADATA_API_ENDPOINT
     region: Optional[str] = None
 
     # resolved api endpoint
@@ -301,9 +300,9 @@ def dump_config_v1(config: ClientConfig) -> dict:
 # XXX: replace with model defaults?
 _V1_CONFIG_DEFAULTS = {
     'client': 'base',
-    'metadata_api_endpoint': DEFAULT_METADATA_API_ENDPOINT,
-    'leap_api_endpoint': DEFAULT_LEAP_API_ENDPOINT,
-    'region': DEFAULT_REGION,
+    'metadata_api_endpoint': constants.DEFAULT_METADATA_API_ENDPOINT,
+    'leap_api_endpoint': constants.DEFAULT_LEAP_API_ENDPOINT,
+    'region': constants.DEFAULT_REGION,
     'endpoint': None,
     'token': None,
     'leap_client_id': None,
diff --git a/dwave/cloud/exceptions.py b/dwave/cloud/exceptions.py
index fc95674..47ce4d2 100644
--- a/dwave/cloud/exceptions.py
+++ b/dwave/cloud/exceptions.py
@@ -19,16 +19,6 @@ from dwave.cloud.api import exceptions as _api
 SAPIError = _api.RequestError
 
 
-class ConfigFileError(Exception):
-    """Base exception for all config file processing errors."""
-
-class ConfigFileReadError(ConfigFileError):
-    """Non-existing or unreadable config file specified or implied."""
-
-class ConfigFileParseError(ConfigFileError):
-    """Invalid format of config file."""
-
-
 class SolverError(_api.RequestError):
     """Generic solver-related error"""
 
@@ -64,9 +54,6 @@ class Timeout(_api.RequestError):
 class PollingTimeout(Exception):
     """Problem polling timed out."""
 
-# for backward compatibility
-from dwave.cloud.api.exceptions import RequestTimeout
-
 
 class CanceledFutureError(Exception):
     """An exception raised when code tries to read from a canceled future."""
@@ -88,3 +75,9 @@ class ProblemStructureError(InvalidProblemError):   # inherit for backwards comp
 
 class ProblemUploadError(Exception):
     """Problem multipart upload failed."""
+
+
+# for backward compatibility
+from dwave.cloud.api.exceptions import RequestTimeout
+
+from dwave.cloud.config.exceptions import *
diff --git a/dwave/cloud/regions.py b/dwave/cloud/regions.py
index 3aa10ab..cccfa42 100644
--- a/dwave/cloud/regions.py
+++ b/dwave/cloud/regions.py
@@ -18,7 +18,7 @@ from typing import Dict, List, Optional, Union
 from urllib.parse import urlsplit
 
 from dwave.cloud import api
-from dwave.cloud.api.constants import (
+from dwave.cloud.config.constants import (
     DEFAULT_REGION, DEFAULT_SOLVER_API_ENDPOINT, DEFAULT_LEAP_API_ENDPOINT,
     DEFAULT_METADATA_API_ENDPOINT)
 from dwave.cloud.config.models import ClientConfig, validate_config_v1
diff --git a/releasenotes/notes/fix-mod-deps-exceptions-api-config-8b7106aaffc9d778.yaml b/releasenotes/notes/fix-mod-deps-exceptions-api-config-8b7106aaffc9d778.yaml
new file mode 100644
index 0000000..9f0ec47
--- /dev/null
+++ b/releasenotes/notes/fix-mod-deps-exceptions-api-config-8b7106aaffc9d778.yaml
@@ -0,0 +1,23 @@
+---
+features:
+  - |
+    Configuration constants like default region and default API endpoints are
+    now available in a new module ``dwave.cloud.config.constants``.
+
+    Configuration-related exceptions are now available in a new module
+    ``dwave.cloud.config.exceptions``.
+
+    ``dwave.cloud.config`` module (with submodules) is now free from dependencies
+    on other submodules, and it's safe to be imported in any cloud-client context.
+
+deprecations:
+  - |
+    Use of ``dwave.cloud.api.constants`` to access default configuration
+    constants is deprecated in ``dwave-cloud-client==0.13.1`` in favor of
+    a new config module ``dwave.cloud.config.constants``, and will be disabled
+    in ``dwave-cloud-client==0.14.0``.
+
+fixes:
+  - |
+    Fix a circular import error.
+    See `#669 <https://github.com/dwavesystems/dwave-cloud-client/issues/669>`_.


Test patch:
diff --git a/tests/__init__.py b/tests/__init__.py
index a131ba2..094b1ec 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -16,7 +16,7 @@ import os
 import warnings
 
 from dwave.cloud.config import load_config
-from dwave.cloud.exceptions import ConfigFileError
+from dwave.cloud.config.exceptions import ConfigFileError
 
 
 # try to load client config needed for live tests on SAPI web service
diff --git a/tests/api/test_api_clients.py b/tests/api/test_api_clients.py
index a1df6aa..b0a2366 100644
--- a/tests/api/test_api_clients.py
+++ b/tests/api/test_api_clients.py
@@ -22,10 +22,10 @@ import requests
 import requests_mock
 from parameterized import parameterized
 
-from dwave.cloud.api import exceptions, constants
+from dwave.cloud.api import exceptions
 from dwave.cloud.api.client import (
     DWaveAPIClient, SolverAPIClient, MetadataAPIClient, LeapAPIClient)
-from dwave.cloud.config import ClientConfig
+from dwave.cloud.config import ClientConfig, constants
 from dwave.cloud.package_info import __packagename__, __version__
 
 
diff --git a/tests/auth/test_flows.py b/tests/auth/test_flows.py
index ee46f50..b007345 100644
--- a/tests/auth/test_flows.py
+++ b/tests/auth/test_flows.py
@@ -26,8 +26,7 @@ import requests_mock
 from dwave.cloud.auth.flows import AuthFlow, LeapAuthFlow, OAuthError
 from dwave.cloud.auth.config import OCEAN_SDK_CLIENT_ID, OCEAN_SDK_SCOPES
 from dwave.cloud.auth.creds import Credentials
-from dwave.cloud.config import ClientConfig
-from dwave.cloud.api.constants import DEFAULT_LEAP_API_ENDPOINT
+from dwave.cloud.config import ClientConfig, DEFAULT_LEAP_API_ENDPOINT
 
 
 class TestAuthFlow(unittest.TestCase):
diff --git a/tests/test_client.py b/tests/test_client.py
index e30a83d..349e810 100644
--- a/tests/test_client.py
+++ b/tests/test_client.py
@@ -30,8 +30,9 @@ import requests
 from parameterized import parameterized
 from plucky import merge
 
-from dwave.cloud.api import constants, models, Regions
+from dwave.cloud.api import models, Regions
 from dwave.cloud.client import Client
+from dwave.cloud.config import constants
 from dwave.cloud.config.models import dump_config_v1, PollingStrategy
 from dwave.cloud.exceptions import (
     SolverAuthenticationError, SolverError, SolverNotFoundError)
diff --git a/tests/test_config.py b/tests/test_config.py
index b072fea..23a4f9e 100644
--- a/tests/test_config.py
+++ b/tests/test_config.py
@@ -22,13 +22,13 @@ from typing import Any, Dict, Callable
 
 from parameterized import parameterized
 
-from dwave.cloud.api import constants
 from dwave.cloud.package_info import __packagename__, __version__
-from dwave.cloud.exceptions import ConfigFileParseError, ConfigFileReadError
 from dwave.cloud.testing import iterable_mock_open
 from dwave.cloud.config import (
     get_configfile_paths, load_config_from_files, load_config,
     parse_float, parse_int, parse_boolean, get_cache_dir, update_config)
+from dwave.cloud.config.constants import DEFAULT_METADATA_API_ENDPOINT
+from dwave.cloud.config.exceptions import ConfigFileParseError, ConfigFileReadError
 from dwave.cloud.config.models import ClientConfig, PollingStrategy
 from dwave.cloud.config.models import validate_config_v1, load_config_v1, dump_config_v1
 
@@ -591,7 +591,7 @@ class TestConfigModel(unittest.TestCase):
         ("null meta", "metadata_api_endpoint", None, None),
         ("null leap", "leap_api_endpoint", None, None),
         ("null sapi", "endpoint", None, None),
-        ("omitted meta", "metadata_api_endpoint", OMITTED, constants.DEFAULT_METADATA_API_ENDPOINT),
+        ("omitted meta", "metadata_api_endpoint", OMITTED, DEFAULT_METADATA_API_ENDPOINT),
         ("omitted leap", "leap_api_endpoint", OMITTED, None),
         ("omitted sapi", "endpoint", OMITTED, None),
         ("url meta", "metadata_api_endpoint", "https://metadata.api/v1", "https://metadata.api/v1"),
diff --git a/tests/test_regions.py b/tests/test_regions.py
index 6e084be..377ce50 100644
--- a/tests/test_regions.py
+++ b/tests/test_regions.py
@@ -21,8 +21,8 @@ from parameterized import parameterized
 from pydantic import TypeAdapter
 
 from dwave.cloud.api.models import Region
-from dwave.cloud.api import constants
 from dwave.cloud.api.exceptions import ResourceAccessForbiddenError
+from dwave.cloud.config.constants import DEFAULT_METADATA_API_ENDPOINT
 from dwave.cloud.config.models import ClientConfig
 from dwave.cloud.regions import get_regions, resolve_endpoints
 
@@ -135,7 +135,7 @@ class ResolveEndpointsMocked(unittest.TestCase):
                         self.mock_regions[0].code):
             resolve_endpoints(config, inplace=True, shortcircuit=False)
 
-        self.assertEqual(config.metadata_api_endpoint, constants.DEFAULT_METADATA_API_ENDPOINT)
+        self.assertEqual(config.metadata_api_endpoint, DEFAULT_METADATA_API_ENDPOINT)
         self.assertEqual(config.region, self.mock_regions[0].code)
         self.assertEqual(config.endpoint, self.mock_regions[0].endpoint)
         self.assertEqual(config.leap_api_endpoint, self.mock_regions[0].leap_api_endpoint)
@@ -146,7 +146,7 @@ class ResolveEndpointsMocked(unittest.TestCase):
 
         resolve_endpoints(config, inplace=True)
 
-        self.assertEqual(config.metadata_api_endpoint, constants.DEFAULT_METADATA_API_ENDPOINT)
+        self.assertEqual(config.metadata_api_endpoint, DEFAULT_METADATA_API_ENDPOINT)
         self.assertIsNone(config.region)
         self.assertEqual(config.endpoint, endpoint)
         self.assertIsNotNone(config.leap_api_endpoint)
@@ -157,7 +157,7 @@ class ResolveEndpointsMocked(unittest.TestCase):
 
         resolve_endpoints(config, inplace=True)
 
-        self.assertEqual(config.metadata_api_endpoint, constants.DEFAULT_METADATA_API_ENDPOINT)
+        self.assertEqual(config.metadata_api_endpoint, DEFAULT_METADATA_API_ENDPOINT)
         self.assertIsNone(config.region)
         self.assertEqual(config.leap_api_endpoint, leap_api_endpoint)
         self.assertIsNotNone(config.endpoint)