From 3c823b4f5dae332d37edd735a3d50c94b1881d78 Mon Sep 17 00:00:00 2001 From: Mauricio Villegas <5780272+mauvilsa@users.noreply.github.com> Date: Mon, 18 May 2026 06:44:09 +0200 Subject: [PATCH] Use commit hashes in pre-commit config and actions --- .github/workflows/codeql.yaml | 6 +-- .github/workflows/manual.yaml | 6 +-- .github/workflows/tests.yaml | 74 +++++++++++++------------- .pre-commit-config.yaml | 8 +-- jsonargparse/_common.py | 2 +- jsonargparse/_formatters.py | 27 +++++----- jsonargparse/_instantiation.py | 2 +- jsonargparse/_parameter_resolvers.py | 4 +- jsonargparse/_postponed_annotations.py | 2 +- jsonargparse/_signatures.py | 4 +- jsonargparse/_typehints.py | 4 +- jsonargparse/_util.py | 2 +- jsonargparse/typing.py | 2 +- 13 files changed, 73 insertions(+), 70 deletions(-) diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml index f46d0b68..a7c64cbe 100644 --- a/.github/workflows/codeql.yaml +++ b/.github/workflows/codeql.yaml @@ -22,16 +22,16 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Initialize CodeQL - uses: github/codeql-action/init@v4 + uses: github/codeql-action/init@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 with: languages: python queries: +security-and-quality config-file: ./.github/codeql-config.yaml - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v4 + uses: github/codeql-action/analyze@9e0d7b8d25671d64c341c19c0152d693099fb5ba # v4.35.5 with: category: "/language:python" diff --git a/.github/workflows/manual.yaml b/.github/workflows/manual.yaml index b50ae4ed..b09dbc48 100644 --- a/.github/workflows/manual.yaml +++ b/.github/workflows/manual.yaml @@ -16,8 +16,8 @@ jobs: tox-coverage: runs-on: ${{ inputs.OS }} steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: | 3.9 @@ -26,7 +26,7 @@ jobs: 3.12 - run: pip install -e ".[dev]" - run: tox -- --cov=../jsonargparse --cov-append - - uses: actions/upload-artifact@v7 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: coverage path: jsonargparse_tests/.coverage diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index dc6277f6..49d3a5c2 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -21,8 +21,8 @@ jobs: matrix: python: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"] steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: ${{ matrix.python }} cache: pip @@ -45,11 +45,11 @@ jobs: pytest --cov --cov-report=term --cov-report=xml --junit-xml=junit.xml mv coverage.xml coverage_py${{ matrix.python }}_types.xml mv junit.xml junit_py${{ matrix.python }}_types.xml - - uses: actions/upload-artifact@v7 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: coverage_py${{ matrix.python }} path: ./coverage_py* - - uses: actions/upload-artifact@v7 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: junit_py${{ matrix.python }} path: ./junit_py* @@ -60,8 +60,8 @@ jobs: matrix: python: ["3.10", "3.11", "3.12", "3.13", "3.14"] steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: ${{ matrix.python }} cache: pip @@ -75,8 +75,8 @@ jobs: matrix: python: ["3.10", "3.11", "3.12", "3.13", "3.14"] steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: ${{ matrix.python }} cache: pip @@ -90,8 +90,8 @@ jobs: matrix: python: ["3.12", "3.14"] steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: ${{ matrix.python }} cache: pip @@ -101,8 +101,8 @@ jobs: omegaconf: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.12" cache: pip @@ -112,8 +112,8 @@ jobs: pydantic-v1: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.12" cache: pip @@ -132,11 +132,11 @@ jobs: pytest --cov --cov-report=term --cov-report=xml --junit-xml=junit.xml jsonargparse_tests/test_pydantic.py mv coverage.xml coverage_pydantic2.xml mv junit.xml junit_pydantic2.xml - - uses: actions/upload-artifact@v7 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: coverage_pydantic path: ./coverage_py* - - uses: actions/upload-artifact@v7 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: junit_pydantic path: ./junit_py* @@ -144,8 +144,8 @@ jobs: build-package: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.12" - name: Build package @@ -155,7 +155,7 @@ jobs: cd jsonargparse_tests python -m build --wheel mv dist/*.whl ../dist/ - - uses: actions/upload-artifact@v7 + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: package path: ./dist/* @@ -164,12 +164,12 @@ jobs: runs-on: ubuntu-latest needs: [build-package] steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.12" cache: pip - - uses: actions/download-artifact@v8 + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: package path: dist @@ -188,8 +188,8 @@ jobs: doctest: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.12" cache: pip @@ -200,14 +200,14 @@ jobs: mypy: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.12" cache: pip - - uses: actions/cache@v5 + - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: - key: pre-commit-cache + key: pre-commit-cache-${{ hashFiles('.pre-commit-config.yaml') }} path: ~/.cache/pre-commit - run: pip install pre-commit - run: pre-commit run -a --hook-stage pre-push mypy @@ -218,16 +218,16 @@ jobs: permissions: id-token: write steps: - - uses: actions/checkout@v6 - - uses: actions/download-artifact@v8 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: merge-multiple: true - - uses: codecov/codecov-action@v6 + - uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0 with: fail_ci_if_error: true files: ./coverage_*.xml use_oidc: true - - uses: codecov/codecov-action@v6 + - uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0 with: fail_ci_if_error: true report_type: test_results @@ -242,10 +242,10 @@ jobs: (github.event_name == 'pull_request' && !github.event.pull_request.head.repo.fork) needs: [linux, pydantic-v1] steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 # Shallow clone disabled for a better relevancy of analysis - - uses: actions/download-artifact@v8 + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: merge-multiple: true - name: Get version @@ -257,7 +257,7 @@ jobs: VERSION="$(git describe --tags --abbrev=0 | sed 's/^v//')+$(git rev-parse --short HEAD)" fi echo "VERSION=$VERSION" >> $GITHUB_ENV - - uses: SonarSource/sonarqube-scan-action@v8 + - uses: SonarSource/sonarqube-scan-action@59db25f34e16620e48ab4bb9e4a5dce155cb5432 # v8.0.0 with: args: > -Dsonar.organization=omni-us @@ -282,9 +282,9 @@ jobs: permissions: id-token: write steps: - - uses: actions/download-artifact@v8 + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: package path: dist - name: Publish to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 + uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 18764af1..02e1ab39 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,7 +13,7 @@ ci: repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v6.0.0 + rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # v6.0.0 hooks: - id: check-added-large-files - id: check-ast @@ -25,20 +25,20 @@ repos: exclude: .bumpversion.cfg - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.15.12 + rev: 5e2fb545eba1ea9dc051f6f962d52fe8f76a9794 # v0.15.13 hooks: - id: ruff-check - id: ruff-format - repo: https://github.com/crate-ci/typos - rev: v1.46.0 + rev: aca895bf05aec0cb7dffa6f94495e923224d9f17 # v1.46.2 hooks: - id: typos args: [] verbose: true - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.20.2 + rev: d2823d321df3af8f878f7ee3414dc94d037145b9 # v2.1.0 hooks: - id: mypy files: jsonargparse.*/.*.py diff --git a/jsonargparse/_common.py b/jsonargparse/_common.py index aa0cc67c..e99dbd38 100644 --- a/jsonargparse/_common.py +++ b/jsonargparse/_common.py @@ -230,7 +230,7 @@ def validate_default(container: ActionsContainer, action: argparse.Action): from ._core import ArgumentGroup if isinstance(container, ArgumentGroup): - container = container.parser # type: ignore[assignment] + container = container.parser with parser_context(parent_parser=container, validating_defaults=True): default = action.default action.default = None diff --git a/jsonargparse/_formatters.py b/jsonargparse/_formatters.py index bcd05a86..1da43cee 100644 --- a/jsonargparse/_formatters.py +++ b/jsonargparse/_formatters.py @@ -59,28 +59,31 @@ def __init__(self, help_formatter: HelpFormatter): def add_yaml_comments(self, cfg: str) -> str: """Adds help text as yaml comments.""" + from ._core import ArgumentParser + ruyaml = import_ruamel("add_yaml_comments") yaml = ruyaml.YAML() cfg = yaml.load(cfg) - def get_subparsers(parser, prefix=""): - subparsers = {} + def get_parsers(parser: ArgumentParser, prefix="") -> dict[Optional[str], ArgumentParser]: + parsers = {} if parser._subparsers is not None: - for key, subparser in parser._subparsers._group_actions[0].choices.items(): + for key, subparser in parser._subparsers._group_actions[0].choices.items(): # type: ignore[union-attr] full_key = (prefix + "." if prefix else "") + key - subparsers[full_key] = subparser - subparsers.update(get_subparsers(subparser, prefix=full_key)) - return subparsers + parsers[full_key] = subparser + parsers.update(get_parsers(subparser, prefix=full_key)) + parsers[None] = parser + return parsers parser = parent_parser.get() - parsers = get_subparsers(parser) - parsers[None] = parser + assert isinstance(parser, ArgumentParser) + parsers = get_parsers(parser) group_titles = {} - for parser_key, parser in parsers.items(): - group_titles[parser_key] = parser.description - prefix = "" if parser_key is None else parser_key + "." - for group in parser._action_groups: + for parser_n_key, parser_n in parsers.items(): + group_titles[parser_n_key] = parser_n.description + prefix = "" if parser_n_key is None else parser_n_key + "." + for group in parser_n._action_groups: actions = filter_non_parsing_actions(group._group_actions) actions = [ a for a in actions if not isinstance(a, (_ActionConfigLoad, ActionConfigFile, ActionSubCommands)) diff --git a/jsonargparse/_instantiation.py b/jsonargparse/_instantiation.py index f1d7e916..a93263b9 100644 --- a/jsonargparse/_instantiation.py +++ b/jsonargparse/_instantiation.py @@ -101,7 +101,7 @@ def instantiate( applied_instantiation_links=cfg.get("__applied_instantiation_links__"), ): parent[key] = component.instantiate_classes(value) - else: + elif hasattr(component, "instantiate_class"): with parser_context( load_value_mode=self.parser_mode, # type: ignore[attr-defined] class_instantiators=get_class_instantiators(self), diff --git a/jsonargparse/_parameter_resolvers.py b/jsonargparse/_parameter_resolvers.py index 44fe1c4e..8f631512 100644 --- a/jsonargparse/_parameter_resolvers.py +++ b/jsonargparse/_parameter_resolvers.py @@ -488,7 +488,7 @@ def get_component_and_parent( function_or_class = function_or_class.wrapped_function # type: ignore[union-attr] if isinstance(function_or_class, MethodType): method_or_property = function_or_class.__name__ - function_or_class = function_or_class.__self__ # type: ignore[assignment] + function_or_class = function_or_class.__self__ else: method_or_property = None elif inspect.isclass(get_generic_origin(function_or_class)) and method_or_property is None: @@ -1052,7 +1052,7 @@ def get_parameters_from_stubs( return None except Exception: pass # only from stubs if getting signature fails - params = None + params: Optional[ParamList] = None resolver = get_stubs_resolver() stub_import = resolver.get_component_imported_info(component, parent) if stub_import: diff --git a/jsonargparse/_postponed_annotations.py b/jsonargparse/_postponed_annotations.py index 1985deee..1d250fd6 100644 --- a/jsonargparse/_postponed_annotations.py +++ b/jsonargparse/_postponed_annotations.py @@ -324,7 +324,7 @@ def get_types(obj: Any, logger: Optional[logging.Logger] = None) -> dict: try: types = get_type_hints(obj, global_vars) except Exception as ex1: - types = ex1 # type: ignore[assignment] + types = ex1 if isinstance(types, dict) and all(not type_requires_eval(t) for t in types.values()): return types diff --git a/jsonargparse/_signatures.py b/jsonargparse/_signatures.py index 0c8bb65b..c503e427 100644 --- a/jsonargparse/_signatures.py +++ b/jsonargparse/_signatures.py @@ -124,7 +124,7 @@ def add_class_arguments( if skip_not_added: skip.update(skip_not_added) # skip init=False if defaults: - defaults = {prefix + k: v for k, v in defaults.items() if k not in skip} + defaults = {prefix + k: v for k, v in defaults.items() if k not in skip} # type: ignore[union-attr] self.set_defaults(**defaults) # type: ignore[attr-defined] return added_args @@ -483,7 +483,7 @@ def add_subclass_arguments( ValueError: When given an invalid base class. """ if type(baseclass) is not tuple: - baseclass = (baseclass,) # type: ignore[assignment] + baseclass = (baseclass,) assert isinstance(baseclass, tuple) if not baseclass or not all(ActionTypeHint.is_subclass_typehint(c, also_lists=True) for c in baseclass): raise ValueError(f"Expected 'baseclass' to be a subclass type or a tuple of subclass types: {baseclass}") diff --git a/jsonargparse/_typehints.py b/jsonargparse/_typehints.py index 78c12768..301fbb7b 100644 --- a/jsonargparse/_typehints.py +++ b/jsonargparse/_typehints.py @@ -304,7 +304,7 @@ def __init__(self, typehint: Optional[type] = None, enable_path: bool = False, * discard = {typehint.__args__[n] for n, s in enumerate(subtype_supported) if not s} kwargs["logger"].debug(f"Discarding unsupported subtypes {discard} from {typehint}") subtypes = tuple(t for t, s in zip(typehint.__args__, subtype_supported) if s) - typehint = Union[subtypes] # type: ignore[assignment] + typehint = Union[subtypes] self._typehint = typehint self._enable_path = False if is_pathlike(typehint) else enable_path elif "_typehint" not in kwargs: @@ -1432,7 +1432,7 @@ def add_subclasses(cl): cls = cls.__args__[-1] # type: ignore[attr-defined] if get_typehint_origin(cls) in {Union, Type, type}: - for arg in cls.__args__: # type: ignore[attr-defined] + for arg in cls.__args__: # type: ignore[union-attr] if ActionTypeHint.is_subclass_typehint(arg, also_lists=True) and arg not in {object, type}: add_subclasses(arg) else: diff --git a/jsonargparse/_util.py b/jsonargparse/_util.py index d50caccf..379380cd 100644 --- a/jsonargparse/_util.py +++ b/jsonargparse/_util.py @@ -182,7 +182,7 @@ def import_object(name: str): return getattr(parent, name_object) -unresolvable_import_paths = {} +unresolvable_import_paths: dict[Any, str] = {} def register_unresolvable_import_paths(*modules: ModuleType): diff --git a/jsonargparse/typing.py b/jsonargparse/typing.py index 51d28141..3a497a4c 100644 --- a/jsonargparse/typing.py +++ b/jsonargparse/typing.py @@ -165,7 +165,7 @@ def __init__(self, class_type: type, lazy_kwargs: dict): lazy_method = partial(self._lazy_init_then_call_method, name) if name == "__call__": - lazy_method = staticmethod(lazy_method) # type: ignore[assignment] + lazy_method = staticmethod(lazy_method) self._lazy.__call__ = lazy_method # type: ignore[method-assign] self.__dict__[name] = lazy_method seen_methods[id(member)] = lazy_method