Ejemplo n.º 1
0
def get_provider(ibmq_factory: IBMQFactory,
                 qe_token: str,
                 qe_url: str,
                 default: bool = True) -> AccountProvider:
    """Return a provider for the account.

    Args:
        ibmq_factory: An `IBMQFactory` instance.
        qe_token: IBM Quantum Experience token.
        qe_url: IBM Quantum Experience auth URL.
        default: If `True`, the default open access project provider is returned.
            Otherwise, a non open access project provider is returned.

    Returns:
        A provider, as specified by `default`.
    """
    provider_to_return = ibmq_factory.enable_account(
        qe_token, url=qe_url)  # Default provider.
    if not default:
        # Get a non default provider (i.e.not the default open access project).
        providers = ibmq_factory.providers()
        for provider in providers:
            if provider != provider_to_return:
                provider_to_return = provider
                break
    ibmq_factory.disable_account()

    return provider_to_return
Ejemplo n.º 2
0
    def _wrapper(obj, *args, **kwargs):
        stg_token = os.getenv('QE_STG_TOKEN')
        stg_url = os.getenv('QE_STG_URL')
        stg_hub = os.getenv('QE_STG_HUB')
        if not (stg_token and stg_url and stg_hub):
            raise SkipTest('Skipping staging tests')

        credentials = Credentials(stg_token, stg_url)
        obj.using_ibmq_credentials = credentials.is_ibmq()
        ibmq_factory = IBMQFactory()

        try:
            # Disable account in case one is already in use
            ibmq_factory.disable_account()
        except IBMQAccountError:
            pass

        ibmq_factory.enable_account(credentials.token, credentials.url)
        provider = ibmq_factory.get_provider(hub=stg_hub)
        kwargs.update({'provider': provider})

        return func(obj, *args, **kwargs)
class TestIBMQFactoryAccounts(IBMQTestCase):
    """Tests for account handling."""
    @classmethod
    def setUpClass(cls):
        """Initial class setup."""
        super().setUpClass()
        cls.token = 'API_TOKEN'

    def setUp(self):
        """Initial test setup."""
        super().setUp()

        # Reference for saving accounts.
        self.factory = IBMQFactory()

    def test_save_account(self):
        """Test saving an account."""
        with custom_qiskitrc():
            self.factory.save_account(self.token, url=AUTH_URL)
            stored_cred = self.factory.stored_account()

        self.assertEqual(stored_cred['token'], self.token)
        self.assertEqual(stored_cred['url'], AUTH_URL)

    def test_save_account_specified_provider(self):
        """Test saving an account with a specified provider."""
        default_hgp_to_save = 'default_hub/default_group/default_project'

        with custom_qiskitrc() as custom_qiskitrc_cm:
            hgp = HubGroupProject.from_stored_format(default_hgp_to_save)
            self.factory.save_account(token=self.token,
                                      url=AUTH_URL,
                                      hub=hgp.hub,
                                      group=hgp.group,
                                      project=hgp.project)

            # Ensure the `default_provider` name was written to the config file.
            config_parser = ConfigParser()
            config_parser.read(custom_qiskitrc_cm.tmp_file.name)

            for name in config_parser.sections():
                single_credentials = dict(config_parser.items(name))
                self.assertIn('default_provider', single_credentials)
                self.assertEqual(single_credentials['default_provider'],
                                 default_hgp_to_save)

    def test_save_account_specified_provider_invalid(self):
        """Test saving an account without specifying all the hub/group/project fields."""
        invalid_hgps_to_save = [
            HubGroupProject('', 'default_group', ''),
            HubGroupProject('default_hub', None, 'default_project')
        ]
        for invalid_hgp in invalid_hgps_to_save:
            with self.subTest(invalid_hgp=invalid_hgp), custom_qiskitrc():
                with self.assertRaises(
                        IBMQAccountValueError) as context_manager:
                    self.factory.save_account(token=self.token,
                                              url=AUTH_URL,
                                              hub=invalid_hgp.hub,
                                              group=invalid_hgp.group,
                                              project=invalid_hgp.project)
                self.assertIn(
                    'The hub, group, and project parameters must all be specified',
                    str(context_manager.exception))

    def test_delete_account(self):
        """Test deleting an account."""
        with custom_qiskitrc():
            self.factory.save_account(self.token, url=AUTH_URL)
            self.factory.delete_account()
            stored_cred = self.factory.stored_account()

        self.assertEqual(len(stored_cred), 0)

    @requires_qe_access
    def test_load_account(self, qe_token, qe_url):
        """Test loading an account."""
        if qe_url != QX_AUTH_URL:
            # .save_account() expects an auth production URL.
            self.skipTest('Test requires production auth URL')

        with no_file('Qconfig.py'), custom_qiskitrc(), no_envs(
                CREDENTIAL_ENV_VARS):
            self.factory.save_account(qe_token, url=qe_url)
            self.factory.load_account()

        self.assertEqual(self.factory._credentials.token, qe_token)
        self.assertEqual(self.factory._credentials.url, qe_url)

    @requires_qe_access
    def test_load_account_saved_provider(self, qe_token, qe_url):
        """Test loading an account that contains a saved provider."""
        if qe_url != QX_AUTH_URL:
            # .save_account() expects an auth production URL.
            self.skipTest('Test requires production auth URL')

        # Get a non default provider.
        non_default_provider = get_provider(self.factory,
                                            qe_token,
                                            qe_url,
                                            default=False)

        with no_file('Qconfig.py'), custom_qiskitrc(), no_envs(
                CREDENTIAL_ENV_VARS):
            self.factory.save_account(
                token=qe_token,
                url=qe_url,
                hub=non_default_provider.credentials.hub,
                group=non_default_provider.credentials.group,
                project=non_default_provider.credentials.project)
            saved_provider = self.factory.load_account()
            if saved_provider != non_default_provider:
                # Prevent tokens from being logged.
                saved_provider.credentials.token = None
                non_default_provider.credentials.token = None
                self.fail(
                    "loaded default provider ({}) != expected ({})".format(
                        saved_provider.credentials.__dict__,
                        non_default_provider.credentials.__dict__))

        self.assertEqual(self.factory._credentials.token, qe_token)
        self.assertEqual(self.factory._credentials.url, qe_url)

    @requires_qe_access
    def test_load_account_saved_provider_invalid_hgp(self, qe_token, qe_url):
        """Test loading an account that contains a saved provider that does not exist."""
        if qe_url != QX_AUTH_URL:
            # .save_account() expects an auth production URL.
            self.skipTest('Test requires production auth URL')

        # Hub, group, project in correct format but does not exists.
        invalid_hgp_to_store = 'invalid_hub/invalid_group/invalid_project'
        with no_file('Qconfig.py'), custom_qiskitrc(), no_envs(
                CREDENTIAL_ENV_VARS):
            hgp = HubGroupProject.from_stored_format(invalid_hgp_to_store)
            self.factory.save_account(token=qe_token,
                                      url=qe_url,
                                      hub=hgp.hub,
                                      group=hgp.group,
                                      project=hgp.project)
            with self.assertRaises(IBMQAccountError) as context_manager:
                self.factory.load_account()
            self.assertIn(
                '(hub/group/project) stored on disk could not be found',
                str(context_manager.exception))

    def test_load_account_saved_provider_invalid_format(self):
        """Test loading an account that contains a saved provider in an invalid format."""
        # Format {'test_case_input': 'error message from raised exception'}
        invalid_hgps = {
            'hub_group_project':
            'Use the "<hub_name>/<group_name>/<project_name>" format',
            'default_hub//default_project': 'Every field must be specified',
            'default_hub/default_group/': 'Every field must be specified'
        }

        for invalid_hgp, error_message in invalid_hgps.items():
            with self.subTest(invalid_hgp=invalid_hgp):
                with no_file('Qconfig.py'), custom_qiskitrc() as temp_qiskitrc, \
                        no_envs(CREDENTIAL_ENV_VARS):
                    # Save the account.
                    self.factory.save_account(token=self.token, url=AUTH_URL)
                    # Add an invalid provider field to the account stored.
                    with open(temp_qiskitrc.tmp_file.name, 'a') as _file:
                        _file.write(
                            'default_provider = {}'.format(invalid_hgp))
                    # Ensure an error is raised if the stored provider is in an invalid format.
                    with self.assertRaises(
                            IBMQAccountError) as context_manager:
                        self.factory.load_account()
                    self.assertIn(error_message,
                                  str(context_manager.exception))

    @requires_qe_access
    def test_disable_account(self, qe_token, qe_url):
        """Test disabling an account """
        self.factory.enable_account(qe_token, qe_url)
        self.factory.disable_account()
        self.assertIsNone(self.factory._credentials)

    @requires_qe_access
    def test_active_account(self, qe_token, qe_url):
        """Test active_account for an account """
        self.assertIsNone(self.factory.active_account())

        self.factory.enable_account(qe_token, qe_url)
        active_account = self.factory.active_account()
        self.assertIsNotNone(active_account)
        self.assertEqual(active_account['token'], qe_token)
        self.assertEqual(active_account['url'], qe_url)

    def test_save_token_invalid(self):
        """Test saving an account with invalid tokens. See #391."""
        invalid_tokens = [None, '', 0]
        for invalid_token in invalid_tokens:
            with self.subTest(invalid_token=invalid_token):
                with self.assertRaises(
                        IBMQAccountCredentialsInvalidToken) as context_manager:
                    self.factory.save_account(token=invalid_token)
                self.assertIn('Invalid IBM Quantum Experience token',
                              str(context_manager.exception))
class TestIBMQFactoryAccounts(IBMQTestCase):
    """Tests for account handling."""
    @classmethod
    def setUpClass(cls):
        """Initial class setup."""
        super().setUpClass()
        cls.token = 'API_TOKEN'

    def setUp(self):
        """Initial test setup."""
        super().setUp()

        # Reference for saving accounts.
        self.factory = IBMQFactory()

    def test_save_account(self):
        """Test saving an account."""
        with custom_qiskitrc():
            self.factory.save_account(self.token, url=AUTH_URL)
            stored_cred = self.factory.stored_account()

        self.assertEqual(stored_cred['token'], self.token)
        self.assertEqual(stored_cred['url'], AUTH_URL)

    def test_delete_account(self):
        """Test deleting an account."""
        with custom_qiskitrc():
            self.factory.save_account(self.token, url=AUTH_URL)
            self.factory.delete_account()
            stored_cred = self.factory.stored_account()

        self.assertEqual(len(stored_cred), 0)

    @requires_qe_access
    def test_load_account(self, qe_token, qe_url):
        """Test loading an account."""
        if qe_url != QX_AUTH_URL:
            # .save_account() expects an auth production URL.
            self.skipTest('Test requires production auth URL')

        with no_file('Qconfig.py'), custom_qiskitrc(), no_envs(
                CREDENTIAL_ENV_VARS):
            self.factory.save_account(qe_token, url=qe_url)
            self.factory.load_account()

        self.assertEqual(self.factory._credentials.token, qe_token)
        self.assertEqual(self.factory._credentials.url, qe_url)

    @requires_qe_access
    def test_disable_account(self, qe_token, qe_url):
        """Test disabling an account """
        self.factory.enable_account(qe_token, qe_url)
        self.factory.disable_account()
        self.assertIsNone(self.factory._credentials)

    @requires_qe_access
    def test_active_account(self, qe_token, qe_url):
        """Test active_account for an account """
        self.assertIsNone(self.factory.active_account())

        self.factory.enable_account(qe_token, qe_url)
        active_account = self.factory.active_account()
        self.assertIsNotNone(active_account)
        self.assertEqual(active_account['token'], qe_token)
        self.assertEqual(active_account['url'], qe_url)

    def test_save_none_token(self):
        """Test saving an account with token=None. See #391"""
        with self.assertRaises(
                IBMQAccountCredentialsInvalidToken) as context_manager:
            self.factory.save_account(None)
        self.assertIn('Invalid IBM Quantum Experience token',
                      str(context_manager.exception))

    def test_save_empty_token(self):
        """Test saving an account with token=''. See #391"""
        with self.assertRaises(
                IBMQAccountCredentialsInvalidToken) as context_manager:
            self.factory.save_account('')
        self.assertIn('Invalid IBM Quantum Experience token',
                      str(context_manager.exception))

    def test_save_zero_token(self):
        """Test saving an account with token=0. See #391"""
        with self.assertRaises(
                IBMQAccountCredentialsInvalidToken) as context_manager:
            self.factory.save_account(0)
        self.assertIn('Invalid IBM Quantum Experience token',
                      str(context_manager.exception))
class TestIBMQFactoryAccounts(IBMQTestCase):
    """Tests for the IBMQ account handling."""
    @classmethod
    def setUpClass(cls):
        cls.v2_token = 'API2_TOKEN'
        cls.v1_token = 'API1_TOKEN'

    def setUp(self):
        super().setUp()

        # Reference for saving accounts.
        self.factory = IBMQFactory()
        self.provider = IBMQProvider()

    def test_save_account_v2(self):
        """Test saving an API 2 account."""
        with custom_qiskitrc():
            self.factory.save_account(self.v2_token, url=AUTH_URL)
            stored_cred = self.factory.stored_account()

        self.assertEqual(stored_cred['token'], self.v2_token)
        self.assertEqual(stored_cred['url'], AUTH_URL)

    def test_stored_account_v1(self):
        """Test listing a stored API 1 account."""
        with custom_qiskitrc():
            self.provider.save_account(self.v1_token, url=API1_URL)
            with self.assertRaises(IBMQAccountError):
                self.factory.stored_account()

    def test_delete_account_v2(self):
        """Test deleting an API 2 account."""
        with custom_qiskitrc():
            self.factory.save_account(self.v2_token, url=AUTH_URL)
            self.factory.delete_account()
            stored_cred = self.factory.stored_account()

        self.assertEqual(len(stored_cred), 0)

    def test_delete_account_v1(self):
        """Test deleting an API 1 account."""
        with custom_qiskitrc():
            self.provider.save_account(self.v1_token, url=API1_URL)
            with self.assertRaises(IBMQAccountError):
                self.factory.delete_account()

    @requires_qe_access
    @requires_new_api_auth
    def test_load_account_v2(self, qe_token, qe_url):
        """Test loading an API 2 account."""
        if qe_url != QX_AUTH_URL:
            # .save_account() expects an auth 2 production URL.
            self.skipTest('Test requires production auth URL')

        with no_file('Qconfig.py'), custom_qiskitrc(), no_envs(
                CREDENTIAL_ENV_VARS):
            self.factory.save_account(qe_token, url=qe_url)
            self.factory.load_account()

        self.assertEqual(self.factory._credentials.token, qe_token)
        self.assertEqual(self.factory._credentials.url, qe_url)
        self.assertEqual(self.factory._v1_provider._accounts, {})

    def test_load_account_v1(self):
        """Test loading an API 1 account."""
        with no_file('Qconfig.py'), custom_qiskitrc(), no_envs(
                CREDENTIAL_ENV_VARS):
            self.provider.save_account(self.v1_token, url=API1_URL)
            with self.assertRaises(IBMQAccountError):
                self.factory.load_account()

    @requires_qe_access
    @requires_new_api_auth
    def test_disable_account_v2(self, qe_token, qe_url):
        """Test disabling an API 2 account """
        self.factory.enable_account(qe_token, qe_url)
        self.factory.disable_account()
        self.assertIsNone(self.factory._credentials)

    @requires_qe_access
    @requires_classic_api
    def test_disable_account_v1(self, qe_token, qe_url):
        """Test disabling an API 1 account """
        self.factory.enable_account(qe_token, qe_url)
        with self.assertRaises(IBMQAccountError):
            self.factory.disable_account()

    @requires_qe_access
    @requires_new_api_auth
    def test_active_account_v2(self, qe_token, qe_url):
        """Test active_account for an API 2 account """
        self.assertIsNone(self.factory.active_account())

        self.factory.enable_account(qe_token, qe_url)
        active_account = self.factory.active_account()
        self.assertIsNotNone(active_account)
        self.assertEqual(active_account['token'], qe_token)
        self.assertEqual(active_account['url'], qe_url)

    @requires_qe_access
    @requires_classic_api
    def test_active_account_v1(self, qe_token, qe_url):
        """Test active_account for an API 1 account """
        self.factory.enable_account(qe_token, qe_url)
        with self.assertRaises(IBMQAccountError):
            self.factory.active_account()