Skip to content

Commit

Permalink
Merge branch 'master' into release/v0.31.0
Browse files Browse the repository at this point in the history
  • Loading branch information
neithere authored Oct 23, 2023
2 parents a620f2b + ee0bc82 commit 3ca2bbc
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 15 deletions.
19 changes: 19 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,25 @@ Enhancements:

- Added `always_flush` argument to `dispatch()` (issue #145)

Version 0.30.1
--------------

Bugs fixed:

- Regression: certain special values in argument default value would cause an
exception (#204)

Enhancements:

- Improved the tutorial.
- Added a more informative error message when the reason is likely to be
related to the migration from Argh v0.29 to a version with a new argument
name mapping policy.

Other changes:

- Added `py.typed` marker file for :pep:`561`.

Version 0.30.0
--------------

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "flit_core.buildapi"

[project]
name = "argh"
version = "0.30.0"
version = "0.30.1"
description = "An unobtrusive argparse wrapper with natural syntax"
readme = "README.rst"
requires-python = ">=3.8"
Expand Down
23 changes: 10 additions & 13 deletions src/argh/assembling.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import inspect
from argparse import OPTIONAL, ZERO_OR_MORE, ArgumentParser
from collections import OrderedDict
from dataclasses import asdict
from enum import Enum
from typing import Any, Callable, Dict, Iterator, List, Optional, Tuple

Expand Down Expand Up @@ -315,9 +314,9 @@ def set_default_command(
raise AssemblingError(f"{function.__name__}: {exc}") from exc

# add the fully formed argument specs to the parser
for orig_spec in parser_add_argument_specs:
spec = _prepare_parser_add_argument_spec(
parser_add_argument_spec=orig_spec, parser_adds_help_arg=parser.add_help
for spec in parser_add_argument_specs:
_extend_parser_add_argument_spec(
spec=spec, parser_adds_help_arg=parser.add_help
)

try:
Expand Down Expand Up @@ -347,12 +346,9 @@ def set_default_command(
)


def _prepare_parser_add_argument_spec(
parser_add_argument_spec: ParserAddArgumentSpec, parser_adds_help_arg: bool
) -> ParserAddArgumentSpec:
# deep copy
spec = ParserAddArgumentSpec(**asdict(parser_add_argument_spec))

def _extend_parser_add_argument_spec(
spec: ParserAddArgumentSpec, parser_adds_help_arg: bool
) -> None:
# add types, actions, etc. (e.g. default=3 implies type=int)
spec.other_add_parser_kwargs.update(
guess_extra_parser_add_argument_spec_kwargs(spec)
Expand All @@ -369,8 +365,6 @@ def _prepare_parser_add_argument_spec(
if parser_adds_help_arg and "-h" in spec.cli_arg_names:
spec.cli_arg_names = [name for name in spec.cli_arg_names if name != "-h"]

return spec


def _merge_inferred_and_declared_args(
inferred_args: List[ParserAddArgumentSpec],
Expand Down Expand Up @@ -421,7 +415,10 @@ def _merge_inferred_and_declared_args(
kind_declared = kinds[decl_positional]
raise AssemblingError(
f'argument "{func_arg_name}" declared as {kind_inferred} '
f"(in function signature) and {kind_declared} (via decorator)"
f"(in function signature) and {kind_declared} (via decorator). "
"If you've just migrated from Argh v.0.29, please check "
"the new default NameMappingPolicy. Perhaps you need "
"to replace `func(x=1)` with `func(*, x=1)`?"
)

# merge explicit argument declaration into the inferred one
Expand Down
1 change: 1 addition & 0 deletions src/argh/py.typed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Marker file for PEP-561
23 changes: 22 additions & 1 deletion tests/test_regressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
Regression tests
~~~~~~~~~~~~~~~~
"""
import sys
from typing import TextIO

import pytest

import argh
Expand Down Expand Up @@ -113,7 +116,9 @@ def func(foo_bar):
parser.set_default_command(func)
msg = (
'func: argument "foo_bar" declared as positional (in function '
"signature) and optional (via decorator)"
"signature) and optional (via decorator). If you've just migrated "
"from Argh v.0.29, please check the new default NameMappingPolicy. "
"Perhaps you need to replace `func(x=1)` with `func(*, x=1)`?"
)
assert excinfo.exconly().endswith(msg)

Expand Down Expand Up @@ -150,3 +155,19 @@ def cmd(foo_foo, bar_bar, *, baz_baz=5, bip_bip=9, **kwargs):
parser.set_default_command(cmd)
expected = "abc\ndef\n8\n9\n{}\n"
assert run(parser, "abc def --baz-baz 8").out == expected


def test_regression_issue204():
"""
Issue #204: `asdict(ParserAddArgumentSpec)` used `deepcopy` which would
lead to "TypeError: cannot pickle..." if e.g. a default value contained an
un-pickle-able object.
We should avoid `deepcopy()` in standard operations.
"""

def func(x: TextIO = sys.stdout) -> None:
...

parser = DebugArghParser()
parser.set_default_command(func)

0 comments on commit 3ca2bbc

Please sign in to comment.