From c6c39f75e47d14f5aa9913bd799b360c39151e40 Mon Sep 17 00:00:00 2001 From: merav-aharoni Date: Thu, 7 Sep 2023 17:09:22 +0000 Subject: [PATCH 1/7] Making account code more generic by defining subclasses for channel types --- qiskit_ibm_runtime/accounts/account.py | 227 +++++++++++++------ qiskit_ibm_runtime/accounts/management.py | 23 +- qiskit_ibm_runtime/qiskit_runtime_service.py | 6 +- test/unit/test_account.py | 24 +- 4 files changed, 190 insertions(+), 90 deletions(-) diff --git a/qiskit_ibm_runtime/accounts/account.py b/qiskit_ibm_runtime/accounts/account.py index b28fd52e7..76c7c0840 100644 --- a/qiskit_ibm_runtime/accounts/account.py +++ b/qiskit_ibm_runtime/accounts/account.py @@ -12,6 +12,7 @@ """Account related classes and functions.""" +from abc import abstractmethod import logging from typing import Optional, Literal from urllib.parse import urlparse @@ -22,7 +23,6 @@ from .exceptions import InvalidAccountError, CloudResourceNameResolutionError from ..api.auth import QuantumAuth, CloudAuth - from ..utils import resolve_crn AccountType = Optional[Literal["cloud", "legacy"]] @@ -38,9 +38,7 @@ class Account: def __init__( self, - channel: ChannelType, token: str, - url: Optional[str] = None, instance: Optional[str] = None, proxies: Optional[ProxyConfiguration] = None, verify: Optional[bool] = True, @@ -57,12 +55,7 @@ def __init__( verify: Whether to verify server's TLS certificate. channel_strategy: Error mitigation strategy. """ - resolved_url = url or ( - IBM_QUANTUM_API_URL if channel == "ibm_quantum" else IBM_CLOUD_API_URL - ) - self.channel = channel self.token = token - self.url = resolved_url self.instance = instance self.proxies = proxies self.verify = verify @@ -78,56 +71,63 @@ def to_saved_format(self) -> dict: @classmethod def from_saved_format(cls, data: dict) -> "Account": """Creates an account instance from data saved on disk.""" + print(data) + channel = data.get("channel") proxies = data.get("proxies") - return cls( - channel=data.get("channel"), - url=data.get("url"), - token=data.get("token"), - instance=data.get("instance"), - proxies=ProxyConfiguration(**proxies) if proxies else None, - verify=data.get("verify", True), - channel_strategy=data.get("channel_strategy"), + proxies = ProxyConfiguration(**proxies) if proxies else None + url = data.get("url") + token = data.get("token") + instance = data.get("instance") + verify = data.get("verify", True) + channel_strategy = data.get("channel_strategy") + return cls.create_account( + channel=channel, + url=url, + token=token, + instance=instance, + proxies=proxies, + verify=verify, + channel_strategy=channel_strategy, ) - def resolve_crn(self) -> None: - """Resolves the corresponding unique Cloud Resource Name (CRN) for the given non-unique service - instance name and updates the ``instance`` attribute accordingly. - - No-op if ``channel`` attribute is set to ``ibm_quantum``. - No-op if ``instance`` attribute is set to a Cloud Resource Name (CRN). - - Raises: - CloudResourceNameResolutionError: if CRN value cannot be resolved. - """ - if self.channel == "ibm_cloud": - crn = resolve_crn( - channel=self.channel, - url=self.url, - token=self.token, - instance=self.instance, + @classmethod + def create_account( + cls, + channel: str, + token: str, + url: Optional[str] = None, + instance: Optional[str] = None, + proxies: Optional[ProxyConfiguration] = None, + verify: Optional[bool] = True, + channel_strategy: Optional[str] = None, + ) -> "Account": + if channel == "ibm_quantum": + return QuantumAccount( + url=url, + token=token, + instance=instance, + proxies=proxies, + verify=verify, + channel_strategy=channel_strategy, + ) + elif channel == "ibm_cloud": + return CloudAccount( + url=url, + token=token, + instance=instance, + proxies=proxies, + verify=verify, + channel_strategy=channel_strategy, + ) + else: + raise InvalidAccountError( + f"Invalid `channel` value. Expected one of " + f"{['ibm_cloud', 'ibm_quantum']}, got '{channel}'." ) - if len(crn) == 0: - raise CloudResourceNameResolutionError( - f"Failed to resolve CRN value for the provided service name {self.instance}." - ) - if len(crn) > 1: - # handle edge-case where multiple service instances with the same name exist - logger.warning( - "Multiple CRN values found for service name %s: %s. Using %s.", - self.instance, - crn, - crn[0], - ) - - # overwrite with CRN value - self.instance = crn[0] - - def get_auth_handler(self) -> AuthBase: - """Returns the respective authentication handler.""" - if self.channel == "ibm_cloud": - return CloudAuth(api_key=self.token, crn=self.instance) - return QuantumAuth(access_token=self.token) + @abstractmethod + def resolve_crn(self) -> None: + pass def __eq__(self, other: object) -> bool: if not isinstance(other, Account): @@ -203,19 +203,118 @@ def _assert_valid_proxies(config: ProxyConfiguration) -> None: if config is not None: config.validate() + +class QuantumAccount(Account): + """Class that represents an account with channel 'ibm_quantum.""" + + def __init__( + self, + token: str, + url: Optional[str] = None, + instance: Optional[str] = None, + proxies: Optional[ProxyConfiguration] = None, + verify: Optional[bool] = True, + channel_strategy: Optional[str] = None, + ): + """Account constructor. + + Args: + channel: Channel type, ``ibm_cloud`` or ``ibm_quantum``. + token: Account token to use. + url: Authentication URL. + instance: Service instance to use. + proxies: Proxy configuration. + verify: Whether to verify server's TLS certificate. + channel_strategy: Error mitigation strategy. + """ + resolved_url = url or IBM_QUANTUM_API_URL + self.channel = "ibm_quantum" + self.url = resolved_url + super().__init__(token, instance, proxies, verify, channel_strategy) + + def get_auth_handler(self) -> AuthBase: + """Returns the Quantum authentication handler.""" + return QuantumAuth(access_token=self.token) + @staticmethod def _assert_valid_instance(channel: ChannelType, instance: str) -> None: """Assert that the instance name is valid for the given account type.""" - if channel == "ibm_cloud": - if not (isinstance(instance, str) and len(instance) > 0): + if instance is not None: + try: + from_instance_format(instance) + except: raise InvalidAccountError( - f"Invalid `instance` value. Expected a non-empty string, got '{instance}'." + f"Invalid `instance` value. Expected hub/group/project format, got {instance}" ) - if channel == "ibm_quantum": - if instance is not None: - try: - from_instance_format(instance) - except: - raise InvalidAccountError( - f"Invalid `instance` value. Expected hub/group/project format, got {instance}" - ) + + +class CloudAccount(Account): + """Class that represents an account.""" + + def __init__( + self, + token: str, + url: Optional[str] = None, + instance: Optional[str] = None, + proxies: Optional[ProxyConfiguration] = None, + verify: Optional[bool] = True, + channel_strategy: Optional[str] = None, + ): + """Account constructor. + + Args: + token: Account token to use. + url: Authentication URL. + instance: Service instance to use. + proxies: Proxy configuration. + verify: Whether to verify server's TLS certificate. + channel_strategy: Error mitigation strategy. + """ + resolved_url = url or IBM_CLOUD_API_URL + self.channel = "ibm_cloud" + self.url = resolved_url + super().__init__(token, instance, proxies, verify, channel_strategy) + + def get_auth_handler(self) -> AuthBase: + """Returns the Cloud authentication handler.""" + return CloudAuth(api_key=self.token, crn=self.instance) + + def resolve_crn(self) -> None: + """Resolves the corresponding unique Cloud Resource Name (CRN) for the given non-unique service + instance name and updates the ``instance`` attribute accordingly. + + No-op if ``channel`` attribute is set to ``ibm_quantum``. + No-op if ``instance`` attribute is set to a Cloud Resource Name (CRN). + + Raises: + CloudResourceNameResolutionError: if CRN value cannot be resolved. + """ + crn = resolve_crn( + channel=self.channel, + url=self.url, + token=self.token, + instance=self.instance, + ) + if len(crn) == 0: + raise CloudResourceNameResolutionError( + f"Failed to resolve CRN value for the provided service name {self.instance}." + ) + if len(crn) > 1: + # handle edge-case where multiple service instances with the same name exist + logger.warning( + "Multiple CRN values found for service name %s: %s. Using %s.", + self.instance, + crn, + crn[0], + ) + + # overwrite with CRN value + self.instance = crn[0] + + @staticmethod + def _assert_valid_instance(channel: ChannelType, instance: str) -> None: + """Assert that the instance name is valid for the given account type.""" + if not (isinstance(instance, str) and len(instance) > 0): + raise InvalidAccountError( + f"Invalid `instance` value. Expected a non-empty string, got '{instance}'." + ) diff --git a/qiskit_ibm_runtime/accounts/management.py b/qiskit_ibm_runtime/accounts/management.py index 6e80c9e03..f0f84b3d7 100644 --- a/qiskit_ibm_runtime/accounts/management.py +++ b/qiskit_ibm_runtime/accounts/management.py @@ -57,19 +57,20 @@ def save( name = name or cls._get_default_account_name(channel) filename = filename if filename else _DEFAULT_ACCOUNT_CONFIG_JSON_FILE filename = os.path.expanduser(filename) + config = Account.create_account( + channel=channel, + token=token, + url=url, + instance=instance, + proxies=proxies, + verify=verify, + channel_strategy=channel_strategy, + ) return save_config( filename=filename, name=name, overwrite=overwrite, - config=Account( - token=token, - url=url, - instance=instance, - channel=channel, - proxies=proxies, - verify=verify, - channel_strategy=channel_strategy, - ) + config=config # avoid storing invalid accounts .validate().to_saved_format(), ) @@ -249,7 +250,7 @@ def _from_env_variables(cls, channel: Optional[ChannelType]) -> Optional[Account url = os.getenv("QISKIT_IBM_URL") if not (token and url): return None - return Account( + return Account.create_account( token=token, url=url, instance=os.getenv("QISKIT_IBM_INSTANCE"), @@ -277,7 +278,7 @@ def _from_qiskitrc_file(cls) -> Optional[Account]: filename=_DEFAULT_ACCOUNT_CONFIG_JSON_FILE, name=_DEFAULT_ACCOUNT_NAME_IBM_QUANTUM, overwrite=False, - config=Account( + config=Account.create_account( token=qiskitrc_data.get("token", None), url=qiskitrc_data.get("url", None), instance=qiskitrc_data.get("default_provider", None), diff --git a/qiskit_ibm_runtime/qiskit_runtime_service.py b/qiskit_ibm_runtime/qiskit_runtime_service.py index a1ea28103..1066d3b5c 100644 --- a/qiskit_ibm_runtime/qiskit_runtime_service.py +++ b/qiskit_ibm_runtime/qiskit_runtime_service.py @@ -272,7 +272,7 @@ def _discover_account( raise ValueError("'channel' can only be 'ibm_cloud' or 'ibm_quantum'") channel = channel or self._get_channel_for_auth(auth=auth) if token: - account = Account( + account = Account.create_account( channel=channel, token=token, url=url, @@ -302,8 +302,8 @@ def _discover_account( account.verify = verify # resolve CRN if needed - if account.channel == "ibm_cloud": - self._resolve_crn(account) + # if account.channel == "ibm_cloud": + self._resolve_crn(account) # ensure account is valid, fail early if not account.validate() diff --git a/test/unit/test_account.py b/test/unit/test_account.py index dce40f931..d89944257 100644 --- a/test/unit/test_account.py +++ b/test/unit/test_account.py @@ -44,14 +44,14 @@ custom_envs, ) -_TEST_IBM_QUANTUM_ACCOUNT = Account( +_TEST_IBM_QUANTUM_ACCOUNT = Account.create_account( channel="ibm_quantum", token="token-x", url="https://auth.quantum-computing.ibm.com/api", instance="ibm-q/open/main", ) -_TEST_IBM_CLOUD_ACCOUNT = Account( +_TEST_IBM_CLOUD_ACCOUNT = Account.create_account( channel="ibm_cloud", token="token-y", url="https://cloud.ibm.com", @@ -101,7 +101,7 @@ def test_invalid_channel(self): with self.assertRaises(InvalidAccountError) as err: invalid_channel: Any = "phantom" - Account( + Account.create_account( channel=invalid_channel, token=self.dummy_token, url=self.dummy_ibm_cloud_url, @@ -115,7 +115,7 @@ def test_invalid_token(self): for token in invalid_tokens: with self.subTest(token=token): with self.assertRaises(InvalidAccountError) as err: - Account( + Account.create_account( channel="ibm_cloud", token=token, url=self.dummy_ibm_cloud_url, @@ -131,7 +131,7 @@ def test_invalid_url(self): for params in subtests: with self.subTest(params=params): with self.assertRaises(InvalidAccountError) as err: - Account(**params, token=self.dummy_token).validate() + Account.create_account(**params, token=self.dummy_token).validate() self.assertIn("Invalid `url` value.", str(err.exception)) def test_invalid_instance(self): @@ -145,7 +145,7 @@ def test_invalid_instance(self): for params in subtests: with self.subTest(params=params): with self.assertRaises(InvalidAccountError) as err: - Account( + Account.create_account( **params, token=self.dummy_token, url=self.dummy_ibm_cloud_url ).validate() self.assertIn("Invalid `instance` value.", str(err.exception)) @@ -158,7 +158,7 @@ def test_invalid_channel_strategy(self): for params in subtests: with self.subTest(params=params): with self.assertRaises(InvalidAccountError) as err: - Account( + Account.create_account( **params, token=self.dummy_token, url=self.dummy_ibm_cloud_url, @@ -183,7 +183,7 @@ def test_invalid_proxy_config(self): for params in subtests: with self.subTest(params=params): with self.assertRaises(ValueError) as err: - Account( + Account.create_account( **params, channel="ibm_quantum", token=self.dummy_token, @@ -476,11 +476,11 @@ def test_list(self): contents={ "key1": _TEST_IBM_CLOUD_ACCOUNT.to_saved_format(), "key2": _TEST_IBM_QUANTUM_ACCOUNT.to_saved_format(), - _DEFAULT_ACCOUNT_NAME_IBM_CLOUD: Account( - "ibm_cloud", "token-ibm-cloud", instance="crn:123" + _DEFAULT_ACCOUNT_NAME_IBM_CLOUD: Account.create_account( + channel="ibm_cloud", token="token-ibm-cloud", instance="crn:123" ).to_saved_format(), - _DEFAULT_ACCOUNT_NAME_IBM_QUANTUM: Account( - "ibm_quantum", "token-ibm-quantum" + _DEFAULT_ACCOUNT_NAME_IBM_QUANTUM: Account.create_account( + channel="ibm_quantum", token="token-ibm-quantum" ).to_saved_format(), } ), self.subTest("filtered list of accounts"): From febbf9efd4bbc061ccd74b41413b349d8b60cca3 Mon Sep 17 00:00:00 2001 From: merav-aharoni Date: Thu, 7 Sep 2023 17:26:26 +0000 Subject: [PATCH 2/7] Removed channel parameter from _assert_valid_instance --- qiskit_ibm_runtime/accounts/account.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/qiskit_ibm_runtime/accounts/account.py b/qiskit_ibm_runtime/accounts/account.py index 76c7c0840..4e5af6e77 100644 --- a/qiskit_ibm_runtime/accounts/account.py +++ b/qiskit_ibm_runtime/accounts/account.py @@ -71,7 +71,6 @@ def to_saved_format(self) -> dict: @classmethod def from_saved_format(cls, data: dict) -> "Account": """Creates an account instance from data saved on disk.""" - print(data) channel = data.get("channel") proxies = data.get("proxies") proxies = ProxyConfiguration(**proxies) if proxies else None @@ -101,6 +100,7 @@ def create_account( verify: Optional[bool] = True, channel_strategy: Optional[str] = None, ) -> "Account": + """Creates an account for a specific channel.""" if channel == "ibm_quantum": return QuantumAccount( url=url, @@ -127,6 +127,9 @@ def create_account( @abstractmethod def resolve_crn(self) -> None: + """Resolves the corresponding unique Cloud Resource Name (CRN) for the given non-unique service + instance name and updates the ``instance`` attribute accordingly. + Relevant for "ibm_cloud" channel only.""" pass def __eq__(self, other: object) -> bool: @@ -156,7 +159,7 @@ def validate(self) -> "Account": self._assert_valid_channel(self.channel) self._assert_valid_token(self.token) self._assert_valid_url(self.url) - self._assert_valid_instance(self.channel, self.instance) + self._assert_valid_instance(self.instance) self._assert_valid_proxies(self.proxies) self._assert_valid_channel_strategy(self.channel_strategy) return self @@ -237,7 +240,7 @@ def get_auth_handler(self) -> AuthBase: return QuantumAuth(access_token=self.token) @staticmethod - def _assert_valid_instance(channel: ChannelType, instance: str) -> None: + def _assert_valid_instance(instance: str) -> None: """Assert that the instance name is valid for the given account type.""" if instance is not None: try: @@ -247,6 +250,12 @@ def _assert_valid_instance(channel: ChannelType, instance: str) -> None: f"Invalid `instance` value. Expected hub/group/project format, got {instance}" ) + def resolve_crn(self) -> None: + """Resolves the corresponding unique Cloud Resource Name (CRN) for the given non-unique service + instance name and updates the ``instance`` attribute accordingly. + Relevant for "ibm_cloud" channel only.""" + pass + class CloudAccount(Account): """Class that represents an account.""" @@ -312,7 +321,7 @@ def resolve_crn(self) -> None: self.instance = crn[0] @staticmethod - def _assert_valid_instance(channel: ChannelType, instance: str) -> None: + def _assert_valid_instance(instance: str) -> None: """Assert that the instance name is valid for the given account type.""" if not (isinstance(instance, str) and len(instance) > 0): raise InvalidAccountError( From c2850f0b9ce70c42cd9a203619cc389cc27ce254 Mon Sep 17 00:00:00 2001 From: merav-aharoni Date: Thu, 7 Sep 2023 17:37:50 +0000 Subject: [PATCH 3/7] mypy, lint and black --- qiskit_ibm_runtime/accounts/account.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/qiskit_ibm_runtime/accounts/account.py b/qiskit_ibm_runtime/accounts/account.py index 4e5af6e77..767b6128b 100644 --- a/qiskit_ibm_runtime/accounts/account.py +++ b/qiskit_ibm_runtime/accounts/account.py @@ -55,6 +55,8 @@ def __init__( verify: Whether to verify server's TLS certificate. channel_strategy: Error mitigation strategy. """ + self.channel: str = None + self.url: str = None self.token = token self.instance = instance self.proxies = proxies @@ -206,6 +208,12 @@ def _assert_valid_proxies(config: ProxyConfiguration) -> None: if config is not None: config.validate() + @abstractmethod + @staticmethod + def _assert_valid_instance(instance: str) -> None: + """Assert that the instance name is valid for the given account type.""" + pass + class QuantumAccount(Account): """Class that represents an account with channel 'ibm_quantum.""" @@ -230,10 +238,10 @@ def __init__( verify: Whether to verify server's TLS certificate. channel_strategy: Error mitigation strategy. """ + super().__init__(token, instance, proxies, verify, channel_strategy) resolved_url = url or IBM_QUANTUM_API_URL self.channel = "ibm_quantum" self.url = resolved_url - super().__init__(token, instance, proxies, verify, channel_strategy) def get_auth_handler(self) -> AuthBase: """Returns the Quantum authentication handler.""" @@ -279,10 +287,10 @@ def __init__( verify: Whether to verify server's TLS certificate. channel_strategy: Error mitigation strategy. """ + super().__init__(token, instance, proxies, verify, channel_strategy) resolved_url = url or IBM_CLOUD_API_URL self.channel = "ibm_cloud" self.url = resolved_url - super().__init__(token, instance, proxies, verify, channel_strategy) def get_auth_handler(self) -> AuthBase: """Returns the Cloud authentication handler.""" From 332558d995d92931939ffe3c5a52994368f4deb4 Mon Sep 17 00:00:00 2001 From: merav-aharoni Date: Thu, 7 Sep 2023 18:30:12 +0000 Subject: [PATCH 4/7] Changed order of decorators --- qiskit_ibm_runtime/accounts/account.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit_ibm_runtime/accounts/account.py b/qiskit_ibm_runtime/accounts/account.py index 767b6128b..c34326f8a 100644 --- a/qiskit_ibm_runtime/accounts/account.py +++ b/qiskit_ibm_runtime/accounts/account.py @@ -208,8 +208,8 @@ def _assert_valid_proxies(config: ProxyConfiguration) -> None: if config is not None: config.validate() - @abstractmethod @staticmethod + @abstractmethod def _assert_valid_instance(instance: str) -> None: """Assert that the instance name is valid for the given account type.""" pass From baa24c131c1b9c5c127db893d3ac94e00ee60466 Mon Sep 17 00:00:00 2001 From: merav-aharoni Date: Sun, 10 Sep 2023 08:54:59 +0000 Subject: [PATCH 5/7] Code cleanup --- qiskit_ibm_runtime/accounts/account.py | 12 +----------- qiskit_ibm_runtime/qiskit_runtime_service.py | 1 - 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/qiskit_ibm_runtime/accounts/account.py b/qiskit_ibm_runtime/accounts/account.py index c34326f8a..33e82a4b7 100644 --- a/qiskit_ibm_runtime/accounts/account.py +++ b/qiskit_ibm_runtime/accounts/account.py @@ -127,7 +127,6 @@ def create_account( f"{['ibm_cloud', 'ibm_quantum']}, got '{channel}'." ) - @abstractmethod def resolve_crn(self) -> None: """Resolves the corresponding unique Cloud Resource Name (CRN) for the given non-unique service instance name and updates the ``instance`` attribute accordingly. @@ -230,7 +229,6 @@ def __init__( """Account constructor. Args: - channel: Channel type, ``ibm_cloud`` or ``ibm_quantum``. token: Account token to use. url: Authentication URL. instance: Service instance to use. @@ -258,13 +256,6 @@ def _assert_valid_instance(instance: str) -> None: f"Invalid `instance` value. Expected hub/group/project format, got {instance}" ) - def resolve_crn(self) -> None: - """Resolves the corresponding unique Cloud Resource Name (CRN) for the given non-unique service - instance name and updates the ``instance`` attribute accordingly. - Relevant for "ibm_cloud" channel only.""" - pass - - class CloudAccount(Account): """Class that represents an account.""" @@ -300,14 +291,13 @@ def resolve_crn(self) -> None: """Resolves the corresponding unique Cloud Resource Name (CRN) for the given non-unique service instance name and updates the ``instance`` attribute accordingly. - No-op if ``channel`` attribute is set to ``ibm_quantum``. No-op if ``instance`` attribute is set to a Cloud Resource Name (CRN). Raises: CloudResourceNameResolutionError: if CRN value cannot be resolved. """ crn = resolve_crn( - channel=self.channel, + channel="ibm_cloud", url=self.url, token=self.token, instance=self.instance, diff --git a/qiskit_ibm_runtime/qiskit_runtime_service.py b/qiskit_ibm_runtime/qiskit_runtime_service.py index 1066d3b5c..dfb243b05 100644 --- a/qiskit_ibm_runtime/qiskit_runtime_service.py +++ b/qiskit_ibm_runtime/qiskit_runtime_service.py @@ -302,7 +302,6 @@ def _discover_account( account.verify = verify # resolve CRN if needed - # if account.channel == "ibm_cloud": self._resolve_crn(account) # ensure account is valid, fail early if not From f9c6af6e61ec16adc66e64dc5e139fd09777b16e Mon Sep 17 00:00:00 2001 From: merav-aharoni Date: Sun, 10 Sep 2023 08:58:11 +0000 Subject: [PATCH 6/7] Documentation fixes --- qiskit_ibm_runtime/accounts/account.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/qiskit_ibm_runtime/accounts/account.py b/qiskit_ibm_runtime/accounts/account.py index 33e82a4b7..892eb46ab 100644 --- a/qiskit_ibm_runtime/accounts/account.py +++ b/qiskit_ibm_runtime/accounts/account.py @@ -34,7 +34,7 @@ class Account: - """Class that represents an account.""" + """Class that represents an account. This is an abstract class.""" def __init__( self, @@ -215,7 +215,7 @@ def _assert_valid_instance(instance: str) -> None: class QuantumAccount(Account): - """Class that represents an account with channel 'ibm_quantum.""" + """Class that represents an account with channel 'ibm_quantum.' """ def __init__( self, @@ -257,7 +257,7 @@ def _assert_valid_instance(instance: str) -> None: ) class CloudAccount(Account): - """Class that represents an account.""" + """Class that represents an account with channel 'ibm_cloud'.""" def __init__( self, From 26a70d5df036312ca20e2b2fd3ab7bb47713e876 Mon Sep 17 00:00:00 2001 From: merav-aharoni Date: Sun, 10 Sep 2023 09:20:09 +0000 Subject: [PATCH 7/7] black --- qiskit_ibm_runtime/accounts/account.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qiskit_ibm_runtime/accounts/account.py b/qiskit_ibm_runtime/accounts/account.py index 892eb46ab..7e71b95dc 100644 --- a/qiskit_ibm_runtime/accounts/account.py +++ b/qiskit_ibm_runtime/accounts/account.py @@ -215,7 +215,7 @@ def _assert_valid_instance(instance: str) -> None: class QuantumAccount(Account): - """Class that represents an account with channel 'ibm_quantum.' """ + """Class that represents an account with channel 'ibm_quantum.'""" def __init__( self, @@ -256,6 +256,7 @@ def _assert_valid_instance(instance: str) -> None: f"Invalid `instance` value. Expected hub/group/project format, got {instance}" ) + class CloudAccount(Account): """Class that represents an account with channel 'ibm_cloud'."""