Skip to content

Commit 7f82bf9

Browse files
authored
Fixes related to Python 3.10 syntax, gitignore, workflow and contributing (#917)
1 parent e58d641 commit 7f82bf9

13 files changed

Lines changed: 35 additions & 52 deletions

File tree

.github/workflows/manual.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ jobs:
2323
3.10
2424
3.11
2525
3.12
26+
3.13
27+
3.14
2628
- run: pip install -e ".[dev]"
2729
- run: tox -- --cov=../jsonargparse --cov-append
2830
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1

.gitignore

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# Only ignore files produced by working as described in CONTRIBUTING.rst.
2+
# For other untracked files, consider `git config status.showUntrackedFiles no`.
13
__pycache__
24
*.egg-info
35
.coverage
@@ -12,15 +14,3 @@ build
1214
dist
1315
htmlcov
1416
**/tests_argparse*
15-
16-
# JetBrains IDEs
17-
.idea/
18-
19-
# some agnetic files
20-
.claude/logs/
21-
.claude/state/
22-
tasks/
23-
*.local.md
24-
25-
# local dev environment files
26-
uv.lock

CONTRIBUTING.rst

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,6 @@ tests.
125125
126126
tox # Run tests using tox on available python versions
127127
pytest # Run tests using pytest on the python of the environment
128-
pytest --cov # Run tests and generate coverage report
129128
pre-commit run -a --hook-stage pre-push # Run pre-push git hooks (tests, doctests, mypy, coverage)
130129
131130
Tests can be run in any environment without the source code. Before v4.47.0, the

DOCUMENTATION.rst

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -426,10 +426,9 @@ syntax. For example, an argument that can be ``None`` or a float in the range
426426

427427
.. testcode::
428428

429-
from typing import Optional, Union
430429
from jsonargparse.typing import PositiveInt, OpenUnitInterval
431430

432-
parser.add_argument("--op", type=Optional[Union[PositiveInt, OpenUnitInterval]])
431+
parser.add_argument("--op", type=PositiveInt | OpenUnitInterval | None)
433432

434433
The types in :py:mod:`jsonargparse.typing` are included for convenience since
435434
they are useful in argument parsing use cases and not available in standard
@@ -1373,11 +1372,8 @@ Take for example a class with its init and a method with docstrings as follows:
13731372

13741373
.. testcode:: class_method
13751374

1376-
from typing import Union
1377-
1378-
13791375
class MyClass(MyBaseClass):
1380-
def __init__(self, foo: dict[str, Union[int, list[int]]], **kwargs):
1376+
def __init__(self, foo: dict[str, int | list[int]], **kwargs):
13811377
"""Initializer for MyClass.
13821378
13831379
Args:
@@ -2453,14 +2449,14 @@ An example of a target being in a subclass is:
24532449
.. testcode::
24542450

24552451
class Logger:
2456-
def __init__(self, save_dir: Optional[str] = None):
2452+
def __init__(self, save_dir: str | None = None):
24572453
self.save_dir = save_dir
24582454

24592455
class Trainer:
24602456
def __init__(
24612457
self,
2462-
save_dir: Optional[str] = None,
2463-
logger: Union[bool, Logger, list[Logger]] = False,
2458+
save_dir: str | None = None,
2459+
logger: bool | Logger | list[Logger] = False,
24642460
):
24652461
self.logger = logger
24662462

@@ -2967,11 +2963,10 @@ instructions to the user for guidance. Take for example the parser:
29672963

29682964
#!/usr/bin/env python3
29692965

2970-
from typing import Optional
29712966
from jsonargparse import ArgumentParser
29722967

29732968
parser = ArgumentParser()
2974-
parser.add_argument("--bool", type=Optional[bool])
2969+
parser.add_argument("--bool", type=bool | None)
29752970

29762971
parser.parse_args()
29772972

@@ -2982,7 +2977,7 @@ matches, then the value is completed without printing guidance. For example:
29822977
.. code-block:: bash
29832978
29842979
$ example.py --bool <TAB><TAB>
2985-
Expected type: Optional[bool]; 3/3 matched choices
2980+
Expected type: bool | None; 3/3 matched choices
29862981
true false null
29872982
$ example.py --bool f<TAB>
29882983
$ example.py --bool false

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ Powerful argparse-like low level parsers:
6060
6161
parser = ArgumentParser()
6262
parser.add_argument("--config", action="config") # support config files
63-
parser.add_argument("--opt", type=Union[int, Literal["off"]]) # complex arguments via type hints
63+
parser.add_argument("--opt", type=int | Literal["off"]) # complex arguments via type hints
6464
parser.add_function_arguments(main_function, "function") # add function parameters
6565
parser.add_class_arguments(SomeClass, "class") # add class parameters
6666
...

jsonargparse/_cli.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import inspect
44
from collections.abc import Callable
5-
from typing import Any, Optional, Union
5+
from typing import Any
66

77
from ._actions import ActionConfigFile, _ActionPrintConfig, remove_actions
88
from ._core import ArgumentParser
@@ -14,9 +14,9 @@
1414
__all__ = ["auto_cli", "auto_parser"]
1515

1616

17-
ComponentType = Union[Callable, type]
18-
DictComponentsType = dict[str, Union[ComponentType, "DictComponentsType"]]
19-
ComponentsType = Optional[Union[ComponentType, list[ComponentType], DictComponentsType]]
17+
ComponentType = Callable | type
18+
DictComponentsType = dict[str, "ComponentType | DictComponentsType"]
19+
ComponentsType = ComponentType | list[ComponentType] | DictComponentsType | None
2020

2121

2222
def CLI(*args, **kwargs):

jsonargparse/_common.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from contextvars import ContextVar
99
from typing import ( # type: ignore[attr-defined]
1010
Generic,
11-
Optional,
1211
Protocol,
1312
TypeVar,
1413
_GenericAlias,
@@ -117,7 +116,7 @@ def set_parsing_settings(
117116
validate_defaults: bool | None = None,
118117
config_read_mode_urls_enabled: bool | None = None,
119118
config_read_mode_fsspec_enabled: bool | None = None,
120-
docstring_parse_style: Optional["docstring_parser.DocstringStyle"] = None,
119+
docstring_parse_style: "docstring_parser.DocstringStyle | None" = None,
121120
docstring_parse_attribute_docstrings: bool | None = None,
122121
parse_optionals_as_positionals: bool | None = None,
123122
add_print_completion_argument: bool | None = None,

jsonargparse/_core.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
from typing import (
1212
Any,
1313
NoReturn,
14-
Union,
1514
)
1615

1716
from ._actions import (
@@ -226,7 +225,7 @@ class ArgumentGroup(ActionsContainer, argparse._ArgumentGroup):
226225
"""Extension of argparse._ArgumentGroup to support additional functionalities."""
227226

228227
dest: str | None = None
229-
parser: Union["ArgumentParser", ActionsContainer] | None = None
228+
parser: "ArgumentParser | ActionsContainer | None" = None
230229

231230

232231
class ArgumentParser(ParserDeprecations, ActionsContainer, argparse.ArgumentParser):

jsonargparse/_namespace.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import argparse
44
from collections import OrderedDict
55
from collections.abc import Iterator
6-
from typing import Any, Optional, Union
6+
from typing import Any
77

88
__all__ = ["Namespace"]
99

@@ -33,12 +33,6 @@ def is_meta_key(key: str) -> bool:
3333
return leaf_key in meta_keys
3434

3535

36-
def remove_meta(cfg: Union["Namespace", dict]):
37-
if cfg:
38-
cfg = recreate_branches(cfg, skip_keys=meta_keys)
39-
return cfg
40-
41-
4236
def recreate_branches(data, skip_keys=None):
4337
new_data = data
4438
if isinstance(data, (Namespace, dict)) and not isinstance(data, OrderedDict):
@@ -70,7 +64,7 @@ def __init__(self, *args, **kwargs):
7064
for key, val in args[0].items() if isinstance(args[0], dict) else vars(args[0]).items():
7165
self[key] = val
7266

73-
def _parse_key(self, key: str) -> tuple[str, Optional["Namespace"], str]:
67+
def _parse_key(self, key: str) -> tuple[str, "Namespace | None", str]:
7468
"""Parses a key for the nested namespace.
7569
7670
Args:
@@ -224,7 +218,7 @@ def clone(self, with_meta: bool = True) -> "Namespace":
224218
"""
225219
return recreate_branches(self, skip_keys=None if with_meta else meta_keys)
226220

227-
def update(self, value: Union["Namespace", Any], key: str | None = None, only_unset: bool = False) -> "Namespace":
221+
def update(self, value: "Namespace | Any", key: str | None = None, only_unset: bool = False) -> "Namespace":
228222
"""Sets or replaces all items from the given nested namespace.
229223
230224
Args:
@@ -293,6 +287,12 @@ def dict_to_namespace(data: dict[str, Any]) -> Namespace:
293287
return expand_dict(data)
294288

295289

290+
def remove_meta(cfg: Namespace | dict):
291+
if cfg:
292+
cfg = recreate_branches(cfg, skip_keys=meta_keys)
293+
return cfg
294+
295+
296296
def get_non_meta_sorted_keys(namespace: Namespace) -> list[str]:
297297
keys = [k for k in namespace.keys(branches=True) if not is_meta_key(k)]
298298
keys.sort(key=lambda x: -len(split_key(x)))

jsonargparse/_paths.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from contextvars import ContextVar
99
from dataclasses import dataclass
1010
from io import StringIO
11-
from typing import IO, Any, Union
11+
from typing import IO, Any
1212

1313
from ._deprecated import PathDeprecations
1414
from ._optionals import (
@@ -113,7 +113,7 @@ class Path(PathDeprecations):
113113

114114
def __init__(
115115
self,
116-
path: Union[str, os.PathLike, "Path"],
116+
path: "str | os.PathLike | Path",
117117
mode: str = "fr",
118118
cwd: str | os.PathLike | None = None,
119119
**kwargs,

0 commit comments

Comments
 (0)