Merge "Add typing"
This commit is contained in:
@@ -13,7 +13,7 @@ repos:
|
||||
- id: check-yaml
|
||||
files: .*\.(yaml|yml)$
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.14.7
|
||||
rev: v0.14.8
|
||||
hooks:
|
||||
- id: ruff-check
|
||||
args: ['--fix', '--unsafe-fixes']
|
||||
|
||||
@@ -30,5 +30,5 @@ _C = _translators.contextual_form
|
||||
_P = _translators.plural_form
|
||||
|
||||
|
||||
def get_available_languages():
|
||||
def get_available_languages() -> list[str]:
|
||||
return oslo_i18n.get_available_languages(DOMAIN)
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_policy import opts as policy_opts
|
||||
from oslo_config import cfg # type: ignore
|
||||
from oslo_policy import opts as policy_opts # type: ignore
|
||||
from oslo_utils import fileutils
|
||||
|
||||
from oslo_upgradecheck import upgradecheck
|
||||
@@ -20,7 +21,9 @@ Common checks which can be used by multiple services.
|
||||
"""
|
||||
|
||||
|
||||
def check_policy_json(self, conf):
|
||||
def check_policy_json(
|
||||
self: upgradecheck.UpgradeCommands, conf: cfg.ConfigOpts
|
||||
) -> upgradecheck.Result:
|
||||
"Checks to see if policy file is JSON-formatted policy file."
|
||||
|
||||
# NOTE(gmann): This method need [oslo_policy].policy_file
|
||||
|
||||
@@ -15,11 +15,11 @@ import os.path
|
||||
import tempfile
|
||||
import yaml
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_config import cfg # type: ignore
|
||||
from oslo_config import fixture as config
|
||||
from oslo_policy import opts as policy_opts
|
||||
from oslo_serialization import jsonutils
|
||||
from oslotest import base
|
||||
from oslo_policy import opts as policy_opts # type: ignore
|
||||
from oslo_serialization import jsonutils # type: ignore
|
||||
from oslotest import base # type: ignore
|
||||
|
||||
from oslo_upgradecheck import common_checks
|
||||
from oslo_upgradecheck import upgradecheck
|
||||
|
||||
@@ -22,8 +22,8 @@ import subprocess
|
||||
import sys
|
||||
from unittest import mock
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslotest import base
|
||||
from oslo_config import cfg # type: ignore
|
||||
from oslotest import base # type: ignore
|
||||
|
||||
from oslo_upgradecheck import upgradecheck
|
||||
|
||||
@@ -54,8 +54,13 @@ class TestCommands(upgradecheck.UpgradeCommands):
|
||||
)
|
||||
|
||||
|
||||
class SuccessCommands(TestCommands):
|
||||
_upgrade_checks = ()
|
||||
class SuccessCommands(upgradecheck.UpgradeCommands):
|
||||
def success(self):
|
||||
return upgradecheck.Result(
|
||||
upgradecheck.Code.SUCCESS, 'Always succeeds'
|
||||
)
|
||||
|
||||
_upgrade_checks = (('always succeeds', success),)
|
||||
|
||||
|
||||
class TestUpgradeCommands(base.BaseTestCase):
|
||||
|
||||
@@ -13,18 +13,20 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from collections.abc import Callable, Iterable
|
||||
import json
|
||||
import sys
|
||||
import textwrap
|
||||
import traceback
|
||||
from typing import Any, TypedDict
|
||||
|
||||
import enum
|
||||
from oslo_config import cfg
|
||||
from oslo_config import cfg # type: ignore
|
||||
import prettytable
|
||||
|
||||
from oslo_upgradecheck._i18n import _
|
||||
|
||||
CONF = None
|
||||
CONF: cfg.ConfigOpts | None = None
|
||||
|
||||
|
||||
class Code(enum.IntEnum):
|
||||
@@ -59,12 +61,23 @@ class Result:
|
||||
information on what issue was discovered along with any remediation.
|
||||
"""
|
||||
|
||||
def __init__(self, code, details=None):
|
||||
def __init__(self, code: Code, details: str | None = None) -> None:
|
||||
super().__init__()
|
||||
self.code = code
|
||||
self.details = details
|
||||
|
||||
|
||||
class _OutputCheck(TypedDict):
|
||||
check: str
|
||||
result: Code
|
||||
details: str | None
|
||||
|
||||
|
||||
class _Output(TypedDict):
|
||||
name: str
|
||||
checks: list[_OutputCheck]
|
||||
|
||||
|
||||
class UpgradeCommands:
|
||||
"""Base class for upgrade checks
|
||||
|
||||
@@ -79,18 +92,27 @@ class UpgradeCommands:
|
||||
"""
|
||||
|
||||
display_title = _('Upgrade Check Results')
|
||||
_upgrade_checks = ()
|
||||
_upgrade_checks: tuple[
|
||||
tuple[
|
||||
str,
|
||||
Callable[..., Result]
|
||||
| tuple[Callable[..., Result], dict[str, Any]],
|
||||
],
|
||||
...,
|
||||
] = ()
|
||||
|
||||
def _get_details(self, upgrade_check_result):
|
||||
if upgrade_check_result.details is not None:
|
||||
# wrap the text on the details to 60 characters
|
||||
return '\n'.join(
|
||||
textwrap.wrap(
|
||||
upgrade_check_result.details, 60, subsequent_indent=' '
|
||||
)
|
||||
def _get_details(self, upgrade_check_result: Result) -> str | None:
|
||||
if upgrade_check_result.details is None:
|
||||
return None
|
||||
|
||||
# wrap the text on the details to 60 characters
|
||||
return '\n'.join(
|
||||
textwrap.wrap(
|
||||
upgrade_check_result.details, 60, subsequent_indent=' '
|
||||
)
|
||||
)
|
||||
|
||||
def check(self):
|
||||
def check(self) -> Code:
|
||||
"""Performs checks to see if the deployment is ready for upgrade.
|
||||
|
||||
These checks are expected to be run BEFORE services are restarted with
|
||||
@@ -130,14 +152,15 @@ class UpgradeCommands:
|
||||
# Since registering opts can be overridden by consuming code, we can't
|
||||
# assume that our locally defined option exists.
|
||||
if (
|
||||
hasattr(CONF, 'command')
|
||||
CONF is not None
|
||||
and hasattr(CONF, 'command')
|
||||
and hasattr(CONF.command, 'json')
|
||||
and CONF.command.json
|
||||
):
|
||||
# NOTE(bnemec): We use str on the translated string to
|
||||
# force immediate translation if lazy translation is in use.
|
||||
# See lp1801761 for details.
|
||||
output = {'name': str(self.display_title), 'checks': []}
|
||||
output: _Output = {'name': str(self.display_title), 'checks': []}
|
||||
for name, result in check_results:
|
||||
output['checks'].append(
|
||||
{
|
||||
@@ -169,7 +192,9 @@ class UpgradeCommands:
|
||||
return return_code
|
||||
|
||||
|
||||
def register_cli_options(conf, upgrade_command):
|
||||
def register_cli_options(
|
||||
conf: cfg.ConfigOpts, upgrade_command: UpgradeCommands
|
||||
) -> None:
|
||||
"""Set up the command line options.
|
||||
|
||||
Adds a subcommand to support 'upgrade check' on the command line.
|
||||
@@ -179,7 +204,7 @@ def register_cli_options(conf, upgrade_command):
|
||||
:param upgrade_command: The UpgradeCommands instance.
|
||||
"""
|
||||
|
||||
def add_parsers(subparsers):
|
||||
def add_parsers(subparsers: Any) -> None:
|
||||
upgrade_action = subparsers.add_parser('upgrade')
|
||||
upgrade_action.add_argument('check')
|
||||
upgrade_action.set_defaults(action_fn=upgrade_command.check)
|
||||
@@ -194,14 +219,14 @@ def register_cli_options(conf, upgrade_command):
|
||||
conf.register_cli_opt(opt)
|
||||
|
||||
|
||||
def run(conf):
|
||||
def run(conf: cfg.ConfigOpts) -> int:
|
||||
"""Run the requested command.
|
||||
|
||||
:param conf: An oslo.confg ConfigOpts instance on which the upgrade
|
||||
commands have been previously registered.
|
||||
"""
|
||||
try:
|
||||
return conf.command.action_fn()
|
||||
return conf.command.action_fn() # type: ignore
|
||||
except Exception:
|
||||
print(_('Error:\n%s') % traceback.format_exc())
|
||||
# This is 255 so it's not confused with the upgrade check exit codes.
|
||||
@@ -209,12 +234,12 @@ def run(conf):
|
||||
|
||||
|
||||
def main(
|
||||
conf,
|
||||
project,
|
||||
upgrade_command,
|
||||
argv=sys.argv[1:],
|
||||
default_config_files=None,
|
||||
):
|
||||
conf: cfg.ConfigOpts,
|
||||
project: str,
|
||||
upgrade_command: UpgradeCommands,
|
||||
argv: list[str] = sys.argv[1:],
|
||||
default_config_files: Iterable[str] | None = None,
|
||||
) -> int:
|
||||
"""Simple implementation of main for upgrade checks
|
||||
|
||||
This can be used in upgrade check commands to provide the minimum
|
||||
|
||||
@@ -35,6 +35,20 @@ packages = [
|
||||
"oslo_upgradecheck"
|
||||
]
|
||||
|
||||
[tool.mypy]
|
||||
python_version = "3.10"
|
||||
show_column_numbers = true
|
||||
show_error_context = true
|
||||
strict = true
|
||||
exclude = '(?x)(doc | examples | releasenotes)'
|
||||
|
||||
[[tool.mypy.overrides]]
|
||||
module = ["oslo_upgradecheck.tests.*"]
|
||||
disallow_untyped_calls = false
|
||||
disallow_untyped_defs = false
|
||||
disallow_subclassing_any = false
|
||||
disallow_any_generics = false
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 79
|
||||
|
||||
|
||||
14
tox.ini
14
tox.ini
@@ -15,11 +15,25 @@ deps =
|
||||
commands = stestr run --slowest {posargs}
|
||||
|
||||
[testenv:pep8]
|
||||
description =
|
||||
Run style checks.
|
||||
skip_install = true
|
||||
deps =
|
||||
pre-commit
|
||||
{[testenv:mypy]deps}
|
||||
commands =
|
||||
pre-commit run -a
|
||||
{[testenv:mypy]commands}
|
||||
|
||||
[testenv:mypy]
|
||||
description =
|
||||
Run type checks.
|
||||
deps =
|
||||
{[testenv]deps}
|
||||
mypy
|
||||
types-PyYAML
|
||||
commands =
|
||||
mypy --cache-dir="{envdir}/mypy_cache" {posargs:oslo_upgradecheck}
|
||||
|
||||
[testenv:venv]
|
||||
commands = {posargs}
|
||||
|
||||
Reference in New Issue
Block a user