From 0ccda576f0c1263674af0720a3aa30a00a7ddfd6 Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Wed, 8 Jan 2025 13:45:39 +0100 Subject: [PATCH 1/2] Remove Python 3.8 support --- .github/workflows/ci.yml | 4 +--- pyproject.toml | 5 ++--- tox.ini | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bb61239ee..97e0b2261 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -80,11 +80,9 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: [3.8, 3.9, '3.10', '3.11', '3.12'] + python-version: [3.9, '3.10', '3.11', '3.12'] os: [ "macos-latest", "ubuntu-latest", "windows-latest" ] exclude: - - os: "macos-latest" - python-version: 3.8 - os: "macos-latest" python-version: 3.9 env: diff --git a/pyproject.toml b/pyproject.toml index 02d7d64ea..28ed2511a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [tool.black] line-length = 100 -target-version = ['py38', 'py39', 'py310', 'py311', 'py312'] +target-version = ['py39', 'py310', 'py311', 'py312'] [tool.towncrier] single_file = false @@ -68,7 +68,6 @@ classifiers=[ "Operating System :: MacOS", "Operating System :: POSIX :: Linux", "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", @@ -78,7 +77,7 @@ classifiers=[ keywords = ["qiskit", "sdk", "quantum", "api", "runtime", "ibm"] -requires-python=">=3.8" +requires-python=">=3.9" dependencies = [ "requests>=2.19", diff --git a/tox.ini b/tox.ini index 0f8b64d58..91aafbd34 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] minversion = 3.15 -envlist = py38, py39, py310, py311, py312, lint, docs +envlist = py39, py310, py311, py312, lint, docs isolated_build = True [testenv] From 4c0066220579a6bc8fdddd5e58a65eb39512784b Mon Sep 17 00:00:00 2001 From: Luciano Bello Date: Wed, 8 Jan 2025 21:43:49 +0100 Subject: [PATCH 2/2] black and release note --- release-notes/unreleased/2097.upgrade.rst | 1 + test/integration/test_account.py | 5 +- test/unit/test_account.py | 120 +++++++++++++--------- 3 files changed, 78 insertions(+), 48 deletions(-) create mode 100644 release-notes/unreleased/2097.upgrade.rst diff --git a/release-notes/unreleased/2097.upgrade.rst b/release-notes/unreleased/2097.upgrade.rst new file mode 100644 index 000000000..01a4acfab --- /dev/null +++ b/release-notes/unreleased/2097.upgrade.rst @@ -0,0 +1 @@ +Python 3.8 reached end-of-life on Oct 7th, 2024. Qiskit SDK dropped support for 3.8 in `qiskit 1.3`. In the same vein, `qiskit-ibm-runtime` does not support Python 3.8 anymore. diff --git a/test/integration/test_account.py b/test/integration/test_account.py index 521509a60..88635699e 100644 --- a/test/integration/test_account.py +++ b/test/integration/test_account.py @@ -86,8 +86,9 @@ def test_resolve_crn_for_invalid_service_instance_name(self): self._skip_on_ibm_quantum() service_instance_name = "-non-existing-service-name-" - with self.subTest(instance="-non-existing-service-name-"), self.assertRaises( - CloudResourceNameResolutionError + with ( + self.subTest(instance="-non-existing-service-name-"), + self.assertRaises(CloudResourceNameResolutionError), ): QiskitRuntimeService( channel="ibm_cloud", diff --git a/test/unit/test_account.py b/test/unit/test_account.py index 6e6bf54d0..e22be3663 100644 --- a/test/unit/test_account.py +++ b/test/unit/test_account.py @@ -275,30 +275,36 @@ def test_save_get(self): def test_list(self): """Test list.""" - with temporary_account_config_file( - contents={ - "key1": _TEST_IBM_CLOUD_ACCOUNT.to_saved_format(), - "key2": _TEST_IBM_QUANTUM_ACCOUNT.to_saved_format(), - } - ), self.subTest("non-empty list of accounts"): + with ( + temporary_account_config_file( + contents={ + "key1": _TEST_IBM_CLOUD_ACCOUNT.to_saved_format(), + "key2": _TEST_IBM_QUANTUM_ACCOUNT.to_saved_format(), + } + ), + self.subTest("non-empty list of accounts"), + ): accounts = AccountManager.list() self.assertEqual(len(accounts), 2) self.assertEqual(accounts["key1"], _TEST_IBM_CLOUD_ACCOUNT) self.assertTrue(accounts["key2"], _TEST_IBM_QUANTUM_ACCOUNT) - with temporary_account_config_file( - contents={ - "key1": _TEST_IBM_CLOUD_ACCOUNT.to_saved_format(), - "key2": _TEST_IBM_QUANTUM_ACCOUNT.to_saved_format(), - _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.create_account( - channel="ibm_quantum", token="token-ibm-quantum" - ).to_saved_format(), - } - ), self.subTest("filtered list of accounts"): + with ( + temporary_account_config_file( + contents={ + "key1": _TEST_IBM_CLOUD_ACCOUNT.to_saved_format(), + "key2": _TEST_IBM_QUANTUM_ACCOUNT.to_saved_format(), + _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.create_account( + channel="ibm_quantum", token="token-ibm-quantum" + ).to_saved_format(), + } + ), + self.subTest("filtered list of accounts"), + ): accounts = list(AccountManager.list(channel="ibm_cloud").keys()) self.assertEqual(len(accounts), 2) self.assertListEqual(accounts, ["key1", _DEFAULT_ACCOUNT_NAME_IBM_CLOUD]) @@ -383,8 +389,9 @@ def test_default_env_channel(self): subtests = ["ibm_quantum", "ibm_cloud"] for channel in subtests: channel_env = {"QISKIT_IBM_CHANNEL": channel} - with temporary_account_config_file(channel=channel, token=token), custom_envs( - channel_env + with ( + temporary_account_config_file(channel=channel, token=token), + custom_envs(channel_env), ): service = FakeRuntimeService() self.assertEqual(service.channel, channel) @@ -481,25 +488,31 @@ def test_set_channel_precedence(self): } # 'name' parameter - with temporary_account_config_file(contents=contents), custom_envs(channel_env), no_envs( - "QISKIT_IBM_TOKEN" + with ( + temporary_account_config_file(contents=contents), + custom_envs(channel_env), + no_envs("QISKIT_IBM_TOKEN"), ): service = FakeRuntimeService(name="any-quantum") self.assertEqual(service.channel, "ibm_quantum") self.assertEqual(service._account.token, any_token) # No name or channel params, no env vars, get the account specified as "is_default_account" - with temporary_account_config_file(contents=contents), no_envs( - "QISKIT_IBM_CHANNEL" - ), no_envs("QISKIT_IBM_TOKEN"): + with ( + temporary_account_config_file(contents=contents), + no_envs("QISKIT_IBM_CHANNEL"), + no_envs("QISKIT_IBM_TOKEN"), + ): service = FakeRuntimeService() self.assertEqual(service.channel, "ibm_quantum") self.assertEqual(service._account.token, preferred_token) # parameter 'channel' is specified, it overrides channel in env # account specified as "is_default_account" - with temporary_account_config_file(contents=contents), custom_envs(channel_env), no_envs( - "QISKIT_IBM_TOKEN" + with ( + temporary_account_config_file(contents=contents), + custom_envs(channel_env), + no_envs("QISKIT_IBM_TOKEN"), ): service = FakeRuntimeService(channel="ibm_quantum") self.assertEqual(service.channel, "ibm_quantum") @@ -507,8 +520,10 @@ def test_set_channel_precedence(self): # account with default name for the channel contents["preferred-ibm-quantum"]["is_default_account"] = False - with temporary_account_config_file(contents=contents), custom_envs(channel_env), no_envs( - "QISKIT_IBM_TOKEN" + with ( + temporary_account_config_file(contents=contents), + custom_envs(channel_env), + no_envs("QISKIT_IBM_TOKEN"), ): service = FakeRuntimeService(channel="ibm_quantum") self.assertEqual(service.channel, "ibm_quantum") @@ -517,8 +532,10 @@ def test_set_channel_precedence(self): # any account for this channel del contents["default-ibm-quantum"] # channel_env = {"QISKIT_IBM_CHANNEL": "ibm_quantum"} - with temporary_account_config_file(contents=contents), custom_envs(channel_env), no_envs( - "QISKIT_IBM_TOKEN" + with ( + temporary_account_config_file(contents=contents), + custom_envs(channel_env), + no_envs("QISKIT_IBM_TOKEN"), ): service = FakeRuntimeService(channel="ibm_quantum") self.assertEqual(service.channel, "ibm_quantum") @@ -527,8 +544,10 @@ def test_set_channel_precedence(self): # no channel param, get account that is specified as "is_default_account" # for channel from env contents["preferred-ibm-quantum"]["is_default_account"] = True - with temporary_account_config_file(contents=contents), custom_envs(channel_env), no_envs( - "QISKIT_IBM_TOKEN" + with ( + temporary_account_config_file(contents=contents), + custom_envs(channel_env), + no_envs("QISKIT_IBM_TOKEN"), ): service = FakeRuntimeService() self.assertEqual(service.channel, "ibm_quantum") @@ -541,8 +560,10 @@ def test_set_channel_precedence(self): "token": default_token, } channel_env = {"QISKIT_IBM_CHANNEL": "ibm_quantum"} - with temporary_account_config_file(contents=contents), custom_envs(channel_env), no_envs( - "QISKIT_IBM_TOKEN" + with ( + temporary_account_config_file(contents=contents), + custom_envs(channel_env), + no_envs("QISKIT_IBM_TOKEN"), ): service = FakeRuntimeService() self.assertEqual(service.channel, "ibm_quantum") @@ -550,8 +571,10 @@ def test_set_channel_precedence(self): # no channel param, any account for the channel from env del contents["default-ibm-quantum"] - with temporary_account_config_file(contents=contents), custom_envs(channel_env), no_envs( - "QISKIT_IBM_TOKEN" + with ( + temporary_account_config_file(contents=contents), + custom_envs(channel_env), + no_envs("QISKIT_IBM_TOKEN"), ): service = FakeRuntimeService() self.assertEqual(service.channel, "ibm_quantum") @@ -657,8 +680,9 @@ def test_enable_account_by_channel_url(self): for channel in subtests: with self.subTest(channel=channel): token = uuid.uuid4().hex - with temporary_account_config_file(channel=channel, token=token), no_envs( - ["QISKIT_IBM_TOKEN"] + with ( + temporary_account_config_file(channel=channel, token=token), + no_envs(["QISKIT_IBM_TOKEN"]), ): with self.assertLogs("qiskit_ibm_runtime", logging.WARNING) as logged: service = FakeRuntimeService(channel=channel, url="some_url") @@ -675,8 +699,9 @@ def test_enable_account_by_only_channel(self): for channel in subtests: with self.subTest(channel=channel): token = uuid.uuid4().hex - with temporary_account_config_file(channel=channel, token=token), no_envs( - ["QISKIT_IBM_TOKEN"] + with ( + temporary_account_config_file(channel=channel, token=token), + no_envs(["QISKIT_IBM_TOKEN"]), ): service = FakeRuntimeService() self.assertTrue(service._account) @@ -691,8 +716,9 @@ def test_enable_account_both_channel(self): contents = get_account_config_contents(channel="ibm_cloud", token=token) contents.update(get_account_config_contents(channel="ibm_quantum", token=uuid.uuid4().hex)) - with temporary_account_config_file(contents=contents), no_envs( - ["QISKIT_IBM_TOKEN", "QISKIT_IBM_CHANNEL"] + with ( + temporary_account_config_file(contents=contents), + no_envs(["QISKIT_IBM_TOKEN", "QISKIT_IBM_CHANNEL"]), ): service = FakeRuntimeService() self.assertTrue(service._account) @@ -794,9 +820,11 @@ def test_enable_account_by_channel_pref(self): ] for channel in ["ibm_cloud", "ibm_quantum"]: for extra in subtests: - with self.subTest(channel=channel, extra=extra), temporary_account_config_file( - channel=channel, verify=True, proxies={} - ), no_envs(["QISKIT_IBM_TOKEN"]): + with ( + self.subTest(channel=channel, extra=extra), + temporary_account_config_file(channel=channel, verify=True, proxies={}), + no_envs(["QISKIT_IBM_TOKEN"]), + ): service = FakeRuntimeService(channel=channel, **extra) self.assertTrue(service._account) self._verify_prefs(extra, service._account)