From e0845449d3570e0a6bc90660440fb6f46721fd2b Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 13 Feb 2026 18:13:40 +0000 Subject: [PATCH] Run mypy from tox This avoids the need to duplicate our dependency list in multiple places and allows us to take advantage of tox's dependency management infrastructure, to ensure we always get the latest and greatest version of a package allowed by upper-constraints. Change-Id: I46eac909846b2d6bd41608efedbed7db08df0c20 Signed-off-by: Stephen Finucane --- .pre-commit-config.yaml | 20 +------------------- openstack/config/cloud_region.py | 21 ++++++++++++++------- openstack/exceptions.py | 2 +- openstack/proxy.py | 2 +- pyproject.toml | 13 +++---------- test-requirements.txt | 1 + tox.ini | 19 +++++++++++++++++-- 7 files changed, 38 insertions(+), 40 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5fdf6e375..eec38c36d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,7 +19,7 @@ repos: hooks: - id: doc8 - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.15.0 + rev: v0.15.1 hooks: - id: ruff-check args: ['--fix', '--unsafe-fixes'] @@ -31,21 +31,3 @@ repos: additional_dependencies: - flake8-import-order~=0.19.2 exclude: '^(doc|releasenotes|tools)/.*$' - - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.19.1 - hooks: - - id: mypy - additional_dependencies: - - dogpile.cache - - keystoneauth1>=5.11.0 - - types-decorator - - types-PyYAML - - types-requests - - types-simplejson - # keep this in-sync with '[mypy] exclude' in 'setup.cfg' - exclude: | - (?x)( - doc/.* - | examples/.* - | releasenotes/.* - ) diff --git a/openstack/config/cloud_region.py b/openstack/config/cloud_region.py index 2aa26c921..d15764838 100644 --- a/openstack/config/cloud_region.py +++ b/openstack/config/cloud_region.py @@ -22,7 +22,7 @@ import warnings try: import keyring except ImportError: - keyring = None + keyring = None # type: ignore[assignment] from keystoneauth1.access import service_catalog as ks_service_catalog from keystoneauth1 import discover @@ -41,9 +41,11 @@ except ImportError: try: import prometheus_client except ImportError: - prometheus_client = None + prometheus_client = None # type: ignore[assignment] try: - import influxdb as influxdb_client + # NOTE(stephenfin): This library is EOL so we explicitly don't have it in + # our dependencies + import influxdb as influxdb_client # type: ignore[import-not-found] except ImportError: influxdb_client = None @@ -789,6 +791,9 @@ class CloudRegion: try: state = keyring.get_password('openstacksdk', cache_id) except RuntimeError: # the fail backend raises this + state = None + + if not state: self.log.debug('Failed to fetch auth from keyring') return @@ -802,10 +807,12 @@ class CloudRegion: assert self._auth is not None # narrow type cache_id = self._auth.get_cache_id() - state = self._auth.get_auth_state() + # NOTE(stephenfin): The actual return type of this is a serialized JSON + # object + state = ty.cast(str, self._auth.get_auth_state()) try: - if state: + if cache_id and state: # NOTE: under some conditions the method may be invoked when # auth is empty. This may lead to exception in the keyring lib, # thus do nothing. @@ -1393,7 +1400,7 @@ class CloudRegion: ], registry=registry, ) - registry._openstacksdk_histogram = hist + setattr(registry, '_openstacksdk_histogram', hist) return hist def get_prometheus_counter( @@ -1415,7 +1422,7 @@ class CloudRegion: ], registry=registry, ) - registry._openstacksdk_counter = counter + setattr(registry, '_openstacksdk_counter', counter) return counter def has_service(self, service_type: str) -> bool: diff --git a/openstack/exceptions.py b/openstack/exceptions.py index 2fb600ebf..02617bb28 100644 --- a/openstack/exceptions.py +++ b/openstack/exceptions.py @@ -102,7 +102,7 @@ class HttpException(SDKException, _rex.HTTPError): # Call directly rather than via super to control parameters SDKException.__init__(self, message=message) - _rex.HTTPError.__init__(self, message, response=response) + _rex.HTTPError.__init__(self, message, response=response) # type: ignore if response is not None: self.request_id = response.headers.get('x-openstack-request-id') diff --git a/openstack/proxy.py b/openstack/proxy.py index b75708d98..63227316f 100644 --- a/openstack/proxy.py +++ b/openstack/proxy.py @@ -41,7 +41,7 @@ from openstack import utils from openstack import warnings as os_warnings if ty.TYPE_CHECKING: - import influxdb as influxdb_client + import influxdb as influxdb_client # type: ignore[import-not-found] from keystoneauth1 import plugin import prometheus_client import requests diff --git a/pyproject.toml b/pyproject.toml index eebf048a6..576dfe120 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,7 +43,6 @@ packages = [ python_version = "3.10" show_column_numbers = true show_error_context = true -ignore_missing_imports = true follow_imports = "normal" check_untyped_defs = true warn_unused_ignores = true @@ -58,16 +57,10 @@ disallow_subclassing_any = false disallow_untyped_calls = false disallow_incomplete_defs = true disallow_untyped_defs = false -no_implicit_reexport = false +no_implicit_reexport = true extra_checks = true -# keep this in-sync with 'mypy.exclude' in '.pre-commit-config.yaml' -exclude = ''' -(?x)( - doc - | examples - | releasenotes - ) -''' +disable_error_code = ["import-untyped"] +exclude = '(?x)(doc | examples | releasenotes)' [[tool.mypy.overrides]] module = [ diff --git a/test-requirements.txt b/test-requirements.txt index ad4d20706..846753c01 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -11,3 +11,4 @@ statsd>=3.3.0 stestr>=1.0.0 # Apache-2.0 testscenarios>=0.4 # Apache-2.0/BSD testtools>=2.2.0 # MIT +keyring>=24.0.0 # MIT diff --git a/tox.ini b/tox.ini index 8d91a4779..883fc19d4 100644 --- a/tox.ini +++ b/tox.ini @@ -60,11 +60,26 @@ commands = [testenv:pep8] description = Run style checks. -skip_install = true deps = pre-commit + {[testenv:mypy]deps} commands = - pre-commit run --all-files --show-diff-on-failure + pre-commit run -a + {[testenv:mypy]commands} + +[testenv:mypy] +description = + Run type checks. +deps = + {[testenv]deps} + mypy + types-decorator + types-jmespath + types-PyYAML + types-requests + types-simplejson +commands = + mypy --cache-dir="{envdir}/mypy_cache" {posargs:openstack} [testenv:venv] description =