Skip to content

Commit

Permalink
Drop Python 3.8
Browse files Browse the repository at this point in the history
  • Loading branch information
hattya committed Oct 12, 2024
1 parent bbe6c66 commit f7dd481
Show file tree
Hide file tree
Showing 16 changed files with 71 additions and 84 deletions.
3 changes: 0 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ jobs:
- macOS
- Windows
toxenv:
- py38
- py39
- py310
- py311
Expand All @@ -23,8 +22,6 @@ jobs:
os: macos-latest
- platform: Windows
os: windows-latest
- toxenv: py38
python-version: '3.8'
- toxenv: py39
python-version: '3.9'
- toxenv: py310
Expand Down
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Version 1.8
* Improve error handling when a command is not found.
* Improve support for dotted options in pyproject.toml.
* Load setup.cfg or pyproject.toml in scmver script.
* Drop Python 3.8 support.


Version 1.7
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Installation
Requirements
------------

- Python 3.8+
- Python 3.9+
- setuptools


Expand Down
3 changes: 1 addition & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ classifiers = [
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
Expand All @@ -29,7 +28,7 @@ classifiers = [
"Topic :: System :: Software Distribution",
"Topic :: Utilities",
]
requires-python = ">= 3.8"
requires-python = ">= 3.9"
dynamic = [
"version",
]
Expand Down
15 changes: 5 additions & 10 deletions scmver/_typing.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
#
# scmver._typing
#
# Copyright (c) 2022-2023 Akinori Hattori <[email protected]>
# Copyright (c) 2022-2024 Akinori Hattori <[email protected]>
#
# SPDX-License-Identifier: MIT
#

import os
import sys
from typing import TYPE_CHECKING, Tuple, Union
from typing import Union


__all__ = ['Path', 'Segment', 'RawSegment']

if (TYPE_CHECKING
or sys.version_info >= (3, 9)):
Path = Union[str, os.PathLike[str]]
else:
Path = Union[str, os.PathLike]
Path = Union[str, os.PathLike[str]]

Segment = Tuple[str, int]
RawSegment = Tuple[str, str, str, int]
Segment = tuple[str, int]
RawSegment = tuple[str, str, str, int]
12 changes: 6 additions & 6 deletions scmver/bazaar.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from __future__ import annotations
import re
from typing import cast, Any, Dict, Optional, Tuple, Union
from typing import cast, Any, Optional, Union

from . import core, util
from ._typing import Path
Expand Down Expand Up @@ -69,9 +69,9 @@ def parse(root: Path, name: Optional[str] = '.bzr', **kwargs: Any) -> Optional[c
return None


def _version_info(root: Path) -> Dict[str, str]:
def _version_info(root: Path) -> dict[str, str]:
out = run('version-info', '--check-clean', cwd=root, encoding='utf-8')[0].splitlines()
return dict(cast(Tuple[str, str], (s.strip() for s in l.split(':', 1))) for l in out)
return dict(cast(tuple[str, str], (s.strip() for s in l.split(':', 1))) for l in out)


def _distance_of(root: Path, rev: Optional[Union[int, str]] = None) -> int:
Expand All @@ -83,13 +83,13 @@ def _distance_of(root: Path, rev: Optional[Union[int, str]] = None) -> int:
return len(run('log', '-r', f'{rev}..', '-n', '0', '--line', cwd=root)[0].splitlines()) - off


def version() -> Tuple[Union[int, str], ...]:
def version() -> tuple[Union[int, str], ...]:
out = run('version')[0].splitlines()
m = _version_re.match(out[0] if out else '')
if not m:
return ()

v: Tuple[Union[int, str], ...] = tuple(map(int, m.group('release').split('.')))
v: tuple[Union[int, str], ...] = tuple(map(int, m.group('release').split('.')))
if len(v) < 3:
v += (0,) * (3 - len(v))
if m.group('pre_s'):
Expand All @@ -101,5 +101,5 @@ def version() -> Tuple[Union[int, str], ...]:
return v


def run(*args: str, **kwargs: Any) -> Tuple[str, str]:
def run(*args: str, **kwargs: Any) -> tuple[str, str]:
return util.exec_((util.command('brz', 'bzr'),) + args, **kwargs)
15 changes: 5 additions & 10 deletions scmver/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
#

from __future__ import annotations
from collections.abc import Callable, Sequence
import re
from typing import Any, Callable, Dict, Optional, Sequence
from typing import Any, Optional

try:
import click
Expand Down Expand Up @@ -46,7 +47,7 @@ class _Local(click.ParamType):
CO_VARARGS = 0x0004

def convert(self, value: Any, param: Optional[click.Parameter], ctx: Optional[click.Context]) -> Any:
m: Dict[str, Any] = {}
m: dict[str, Any] = {}
try:
exec(value, {}, m)
except (NameError, SyntaxError):
Expand Down Expand Up @@ -205,14 +206,8 @@ def stat(**opts: Any) -> None:
click.echo(f'Branch: {info.branch}')


def _merge_config(a: Dict[str, Any]) -> Dict[str, Any]:
a = a.copy()
b = setuptools.load_cfg() or core.load_project() or {}
for k, v in b.items():
if (v and
not a.get(k)):
a[k] = v
return a
def _merge_config(a: dict[str, Any]) -> dict[str, Any]:
return (setuptools.load_cfg() or core.load_project() or {}) | a


def _next_version(info: core.SCMInfo, **opts: Any) -> Optional[str]:
Expand Down
24 changes: 12 additions & 12 deletions scmver/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
#

from __future__ import annotations
import collections.abc
from collections.abc import Callable, Mapping, Sequence
import datetime
import importlib
import os
import re
import sys
import textwrap
from typing import cast, Any, Callable, Dict, Mapping, NamedTuple, Optional, Pattern, Tuple, Union
from typing import cast, Any, NamedTuple, Optional, Union

from ._typing import Path, Segment, RawSegment

Expand Down Expand Up @@ -83,7 +83,7 @@


def generate(path: Path, version: Optional[str], info: Optional[SCMInfo] = None, template: str = _TEMPLATE) -> None:
kwargs: Dict[str, Any] = {'version': version or ''}
kwargs: dict[str, Any] = {'version': version or ''}
if info:
kwargs.update(revision=info.revision or '',
branch=info.branch or '')
Expand All @@ -92,7 +92,7 @@ def generate(path: Path, version: Optional[str], info: Optional[SCMInfo] = None,


def get_version(root: Path = '.', **kwargs: Any) -> Optional[str]:
def take(d: Mapping[str, str], *keys: str) -> Dict[str, Any]:
def take(d: Mapping[str, str], *keys: str) -> dict[str, Any]:
return {k: d[k] for k in d if k in keys}

root = os.path.abspath(root)
Expand All @@ -107,7 +107,7 @@ def take(d: Mapping[str, str], *keys: str) -> Dict[str, Any]:
return cast(str, fallback())
elif isinstance(fallback, str):
return load_version(fallback, root)
elif isinstance(fallback, collections.abc.Sequence):
elif isinstance(fallback, Sequence):
return load_version(fallback[0], os.path.join(root, fallback[1]))
return None

Expand All @@ -131,7 +131,7 @@ def load_version(spec: str, path: Optional[Path] = None) -> str:
return cast(str, o() if callable(o) else o)


def next_version(info: SCMInfo, spec: str = 'post', local: str = '{local:%Y-%m-%d}', version: Pattern[str] = _version_re) -> Optional[str]:
def next_version(info: SCMInfo, spec: str = 'post', local: str = '{local:%Y-%m-%d}', version: re.Pattern[str] = _version_re) -> Optional[str]:
m = version.search(info.tag)
if not m:
raise VersionError('cannot parse version from SCM tag')
Expand All @@ -153,7 +153,7 @@ def next_version(info: SCMInfo, spec: str = 'post', local: str = '{local:%Y-%m-%
return str(pv) if not lv else f'{pv}+{lv}'


def load_project(path: Path = 'pyproject.toml') -> Optional[Dict[str, Any]]:
def load_project(path: Path = 'pyproject.toml') -> Optional[dict[str, Any]]:
try:
if sys.version_info >= (3, 11):
import tomllib as toml
Expand All @@ -170,7 +170,7 @@ def load_project(path: Path = 'pyproject.toml') -> Optional[Dict[str, Any]]:
and 'scmver' in proj['tool']):
return None

scmver: Dict[str, Any] = proj['tool']['scmver']
scmver: dict[str, Any] = proj['tool']['scmver']
# root
root = os.path.dirname(os.path.abspath(path))
scmver['root'] = os.path.join(root, scmver['root']) if 'root' in scmver else root
Expand All @@ -179,20 +179,20 @@ def load_project(path: Path = 'pyproject.toml') -> Optional[Dict[str, Any]]:
scmver['write_to'] = scmver.pop('write-to')
# fallback
if ('fallback' in scmver
and isinstance(scmver['fallback'], collections.abc.Mapping)):
and isinstance(scmver['fallback'], Mapping)):
fallback = scmver['fallback']
scmver['fallback'] = [fallback['attr'], fallback['path']] if 'path' in fallback else fallback['attr']
# flatten tables
for k in tuple(scmver):
if isinstance(scmver[k], collections.abc.Mapping):
if isinstance(scmver[k], Mapping):
scmver.update({f'{k}.{sk}': v for sk, v in scmver.pop(k).items()})
return scmver


def stat(path: Path, **kwargs: Any) -> Optional[SCMInfo]:
import importlib.metadata

impls: Tuple[Tuple[str, Callable[..., Optional[SCMInfo]]], ...]
impls: tuple[tuple[str, Callable[..., Optional[SCMInfo]]], ...]
if sys.version_info >= (3, 10):
impls = tuple((ep.name, ep.load()) for ep in importlib.metadata.entry_points(group='scmver.parse'))
else:
Expand Down Expand Up @@ -249,7 +249,7 @@ def __repr__(self) -> str:
return f'<{self.__class__.__name__}({self})>'

def __str__(self) -> str:
def seg(v: RawSegment) -> Tuple[str, ...]:
def seg(v: RawSegment) -> tuple[str, ...]:
return (v[0], v[1], v[2], str(v[3]) if v[3] >= 0 else '')

buf = []
Expand Down
12 changes: 6 additions & 6 deletions scmver/darcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import os
import re
import sys
from typing import Any, Dict, Optional, Tuple, cast
from typing import cast, Any, Optional

from . import core, util
from ._typing import Path
Expand All @@ -20,7 +20,7 @@

_TAG = 'darcs.tag'
# environ
_env: Tuple[str, ...] = ('DARCS_TESTING_PREFS_DIR', 'DARCS_TMPDIR', 'TMPDIR')
_env: tuple[str, ...] = ('DARCS_TESTING_PREFS_DIR', 'DARCS_TMPDIR', 'TMPDIR')
if sys.platform == 'win32':
_env += ('APPDATA', 'TMP', 'TEMP')
else:
Expand Down Expand Up @@ -62,16 +62,16 @@ def parse(root: Path, name: Optional[str] = '_darcs', **kwargs: Any) -> Optional
return None


def _show_repo(root: Path) -> Dict[str, str]:
def _show_repo(root: Path) -> dict[str, str]:
out = run('show', 'repo', cwd=root)[0].replace('\r', '').splitlines()
return dict(cast(Tuple[str, str], (s.strip() for s in l.split(':', 1))) for l in out)
return dict(cast(tuple[str, str], (s.strip() for s in l.split(':', 1))) for l in out)


def _distance_of(root: Path, tag: str) -> int:
return int(run('log', '--from-tag', tag, '--count', cwd=root)[0]) - 1


def version() -> Tuple[int, ...]:
def version() -> tuple[int, ...]:
m = _version_re.match(run('--version')[0].strip())
if (not m
or not m.group('release')):
Expand All @@ -80,7 +80,7 @@ def version() -> Tuple[int, ...]:
return tuple(map(int, m.group('release').split('.')))


def run(*args: str, **kwargs: Any) -> Tuple[str, str]:
def run(*args: str, **kwargs: Any) -> tuple[str, str]:
env = {k: os.environ[k] for k in _env if k in os.environ}
if 'env' in kwargs:
env.update(kwargs['env'])
Expand Down
12 changes: 6 additions & 6 deletions scmver/fossil.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import os
import re
import sys
from typing import Any, Dict, List, Optional, Tuple
from typing import Any, Optional

from . import core, util
from ._typing import Path
Expand All @@ -20,7 +20,7 @@

_TAG = 'fossil.tag'
# environ
_env: Tuple[str, ...] = ('FOSSIL_HOME', 'FOSSIL_USER', 'SQLITE_TMPDIR', 'USER', 'LOGNAME', 'USERNAME', 'TMPDIR')
_env: tuple[str, ...] = ('FOSSIL_HOME', 'FOSSIL_USER', 'SQLITE_TMPDIR', 'USER', 'LOGNAME', 'USERNAME', 'TMPDIR')
if sys.platform == 'win32':
_env += ('LOCALAPPDATA', 'APPDATA', 'HOMEDRIVE', 'HOMEPATH', 'TMP', 'TEMP', 'USERPROFILE')
else:
Expand Down Expand Up @@ -97,9 +97,9 @@ def parse(root: Path, name: Optional[str] = '.fslckout', **kwargs: Any) -> Optio
return None


def _status(root: Path) -> Tuple[Dict[str, str], Dict[str, List[str]]]:
def _status(root: Path) -> tuple[dict[str, str], dict[str, list[str]]]:
info = {}
changes: Dict[str, List[str]] = {}
changes: dict[str, list[str]] = {}
for l in run('status', cwd=root)[0].splitlines():
v = l.split(None, 1)
if v[0].endswith(':'):
Expand All @@ -123,7 +123,7 @@ def _branch_of(root: Path, closed: bool = False) -> Optional[str]:
return None


def version() -> Tuple[int, ...]:
def version() -> tuple[int, ...]:
m = _version_re.match(run('version')[0].strip())
if (not m
or not m.group('release')):
Expand All @@ -132,7 +132,7 @@ def version() -> Tuple[int, ...]:
return tuple(map(int, m.group('release').split('.')))


def run(*args: str, **kwargs: Any) -> Tuple[str, str]:
def run(*args: str, **kwargs: Any) -> tuple[str, str]:
env = {k: os.environ[k] for k in _env if k in os.environ}
if 'env' in kwargs:
env.update(kwargs['env'])
Expand Down
Loading

0 comments on commit f7dd481

Please sign in to comment.