Skip to content

Commit 5aa9c8e

Browse files
reviews part 2
1 parent d65a037 commit 5aa9c8e

File tree

4 files changed

+61
-62
lines changed

4 files changed

+61
-62
lines changed

src/setuptools_scm/config.py

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import warnings
77
from typing import Any
88
from typing import Callable
9+
from typing import cast
910
from typing import Pattern
1011
from typing import TYPE_CHECKING
1112
from typing import Union
@@ -70,7 +71,36 @@ def _lazy_tomli_load(data: str) -> dict[str, Any]:
7071
return loads(data)
7172

7273

73-
VersionT = Union[Version, NonNormalizedVersion]
74+
_VersionT = Union[Version, NonNormalizedVersion]
75+
76+
77+
def _validate_version_cls(
78+
version_cls: type[_VersionT] | str | None, normalize: bool
79+
) -> type[_VersionT]:
80+
if not normalize:
81+
# `normalize = False` means `version_cls = NonNormalizedVersion`
82+
if version_cls is not None:
83+
raise ValueError(
84+
"Providing a custom `version_cls` is not permitted when "
85+
"`normalize=False`"
86+
)
87+
return NonNormalizedVersion
88+
else:
89+
# Use `version_cls` if provided, default to packaging or pkg_resources
90+
if version_cls is None:
91+
return Version
92+
elif isinstance(version_cls, str):
93+
try:
94+
# Not sure this will work in old python
95+
import importlib
96+
97+
pkg, cls_name = version_cls.rsplit(".", 1)
98+
version_cls_host = importlib.import_module(pkg)
99+
return cast(type[_VersionT], getattr(version_cls_host, cls_name))
100+
except: # noqa
101+
raise ValueError(f"Unable to import version_cls='{version_cls}'")
102+
else:
103+
return version_cls
74104

75105

76106
class Configuration:
@@ -79,7 +109,7 @@ class Configuration:
79109
parent: _t.PathT | None
80110
_root: str
81111
_relative_to: str | None
82-
version_cls: type[VersionT]
112+
version_cls: type[_VersionT]
83113

84114
def __init__(
85115
self,
@@ -98,11 +128,7 @@ def __init__(
98128
parse: Any | None = None,
99129
git_describe_command: _t.CMD_TYPE | None = None,
100130
dist_name: str | None = None,
101-
version_cls: type[Version]
102-
| type[NonNormalizedVersion]
103-
| type
104-
| str
105-
| None = None,
131+
version_cls: type[_VersionT] | type | str | None = None,
106132
normalize: bool = True,
107133
search_parent_directories: bool = False,
108134
):
@@ -125,30 +151,7 @@ def __init__(
125151
self.search_parent_directories = search_parent_directories
126152
self.parent = None
127153

128-
if not normalize:
129-
# `normalize = False` means `version_cls = NonNormalizedVersion`
130-
if version_cls is not None:
131-
raise ValueError(
132-
"Providing a custom `version_cls` is not permitted when "
133-
"`normalize=False`"
134-
)
135-
self.version_cls = NonNormalizedVersion
136-
else:
137-
# Use `version_cls` if provided, default to packaging or pkg_resources
138-
if version_cls is None:
139-
self.version_cls = Version
140-
elif isinstance(version_cls, str):
141-
try:
142-
# Not sure this will work in old python
143-
import importlib
144-
145-
pkg, cls_name = version_cls.rsplit(".", 1)
146-
version_cls_host = importlib.import_module(pkg)
147-
self.version_cls = getattr(version_cls_host, cls_name)
148-
except: # noqa
149-
raise ValueError(f"Unable to import version_cls='{version_cls}'")
150-
else:
151-
self.version_cls = version_cls
154+
self.version_cls = _validate_version_cls(version_cls, normalize)
152155

153156
@property
154157
def fallback_root(self) -> str:

src/setuptools_scm/utils.py

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
"""
44
from __future__ import annotations
55

6-
import inspect
76
import os
87
import platform
98
import shlex
109
import subprocess
1110
import sys
1211
import warnings
12+
from types import CodeType
13+
from types import FunctionType
1314
from typing import Iterator
1415
from typing import Mapping
1516

@@ -52,11 +53,10 @@ def ensure_stripped_str(str_or_bytes: str | bytes) -> str:
5253
return str_or_bytes.decode("utf-8", "surrogateescape").strip()
5354

5455

55-
def _popen_pipes(cmd: _t.CMD_TYPE, cwd: _t.PathT) -> subprocess.Popen[bytes]:
56-
return subprocess.Popen(
56+
def _run(cmd: _t.CMD_TYPE, cwd: _t.PathT) -> subprocess.CompletedProcess[bytes]:
57+
return subprocess.run(
5758
cmd,
58-
stdout=subprocess.PIPE,
59-
stderr=subprocess.PIPE,
59+
capture_output=True,
6060
cwd=str(cwd),
6161
env=dict(
6262
no_git_env(os.environ),
@@ -75,16 +75,15 @@ def do_ex(cmd: _t.CMD_TYPE, cwd: _t.PathT = ".") -> _t.CmdResult:
7575
if os.name == "posix" and not isinstance(cmd, (list, tuple)):
7676
cmd = shlex.split(cmd)
7777

78-
p = _popen_pipes(cmd, cwd)
79-
out, err = p.communicate()
80-
if out:
81-
trace("out", repr(out))
82-
if err:
83-
trace("err", repr(err))
84-
if p.returncode:
85-
trace("ret", p.returncode)
78+
res = _run(cmd, cwd)
79+
if res.stdout:
80+
trace("out", repr(res.stdout))
81+
if res.stderr:
82+
trace("err", repr(res.stderr))
83+
if res.returncode:
84+
trace("ret", res.returncode)
8685
return _t.CmdResult(
87-
ensure_stripped_str(out), ensure_stripped_str(err), p.returncode
86+
ensure_stripped_str(res.stdout), ensure_stripped_str(res.stderr), res.returncode
8887
)
8988

9089

@@ -105,23 +104,20 @@ def data_from_mime(path: _t.PathT) -> dict[str, str]:
105104
return data
106105

107106

108-
def function_has_arg(fn: object, argname: str) -> bool:
109-
assert inspect.isfunction(fn)
110-
111-
argspec = inspect.signature(fn).parameters
112-
113-
return argname in argspec
107+
def function_has_arg(fn: object | FunctionType, argname: str) -> bool:
108+
assert isinstance(fn, FunctionType)
109+
code: CodeType = fn.__code__
110+
return argname in code.co_varnames
114111

115112

116113
def has_command(name: str, args: list[str] | None = None, warn: bool = True) -> bool:
117114
try:
118115
cmd = [name, "help"] if args is None else [name, *args]
119-
p = _popen_pipes(cmd, ".")
116+
p = _run(cmd, ".")
120117
except OSError:
121118
trace(*sys.exc_info())
122119
res = False
123120
else:
124-
p.communicate()
125121
res = not p.returncode
126122
if not res and warn:
127123
warnings.warn("%r was not found" % name, category=RuntimeWarning)

src/setuptools_scm/version.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from . import _types as _t
2323
from ._version_cls import Version as PkgVersion
2424
from .config import Configuration
25-
from .config import VersionT
25+
from .config import _VersionT
2626
from .utils import trace
2727

2828
SEMVER_MINOR = 2
@@ -67,8 +67,8 @@ def callable_or_entrypoint(group: str, callable_or_name: str | Any) -> Any:
6767

6868

6969
def tag_to_version(
70-
tag: VersionT | str, config: Configuration | None = None
71-
) -> VersionT | None:
70+
tag: _VersionT | str, config: Configuration | None = None
71+
) -> _VersionT | None:
7272
"""
7373
take a tag that might be prefixed with a keyword and return only the version part
7474
:param config: optional configuration object
@@ -101,13 +101,13 @@ def tag_to_version(
101101

102102
def tags_to_versions(
103103
tags: list[str], config: Configuration | None = None
104-
) -> list[VersionT]:
104+
) -> list[_VersionT]:
105105
"""
106106
take tags that might be prefixed with a keyword and return only the version part
107107
:param tags: an iterable of tags
108108
:param config: optional configuration object
109109
"""
110-
result: list[VersionT] = []
110+
result: list[_VersionT] = []
111111
for tag in tags:
112112
parsed = tag_to_version(tag, config=config)
113113
if parsed:
@@ -192,8 +192,8 @@ def format_next_version(
192192

193193

194194
def _parse_tag(
195-
tag: VersionT | str, preformatted: bool, config: Configuration | None
196-
) -> VersionT | str:
195+
tag: _VersionT | str, preformatted: bool, config: Configuration | None
196+
) -> _VersionT | str:
197197
if preformatted:
198198
return tag
199199
elif config is None or not isinstance(tag, config.version_cls):
@@ -205,7 +205,7 @@ def _parse_tag(
205205

206206

207207
def meta(
208-
tag: str | VersionT,
208+
tag: str | _VersionT,
209209
distance: int | None = None,
210210
dirty: bool = False,
211211
node: str | None = None,

tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[tox]
2-
envlist=py{36,37,38,39,310}-{test,selfcheck},check_readme,check-dist
2+
envlist=py{37,38,39,310}-{test,selfcheck},check_readme,check-dist
33

44
[pytest]
55
testpaths=testing

0 commit comments

Comments
 (0)