From b7f2eeb0915c8b1540fc758400c2f4930696b9c1 Mon Sep 17 00:00:00 2001 From: Manuel Barkhau Date: Mon, 7 Jan 2019 18:47:04 +0100 Subject: [PATCH] more mypy coverage --- src/pycalver/config.py | 21 +++++--- stubs/pathlib2.pyi | 120 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+), 8 deletions(-) create mode 100644 stubs/pathlib2.pyi diff --git a/src/pycalver/config.py b/src/pycalver/config.py index 942abe2..2e644fd 100644 --- a/src/pycalver/config.py +++ b/src/pycalver/config.py @@ -147,7 +147,7 @@ OptionVal = typ.Union[str, bool, None] BOOL_OPTIONS: typ.Mapping[str, OptionVal] = {'commit': False, 'tag': None, 'push': None} -def _parse_cfg(cfg_buffer: typ.TextIO) -> RawConfig: +def _parse_cfg(cfg_buffer: typ.IO[str]) -> RawConfig: cfg_parser = _ConfigParser() if hasattr(cfg_parser, 'read_file'): @@ -171,7 +171,7 @@ def _parse_cfg(cfg_buffer: typ.TextIO) -> RawConfig: return raw_cfg -def _parse_toml(cfg_buffer: typ.TextIO) -> RawConfig: +def _parse_toml(cfg_buffer: typ.IO[str]) -> RawConfig: raw_full_cfg = toml.load(cfg_buffer) raw_cfg = raw_full_cfg.get('pycalver', {}) @@ -182,10 +182,11 @@ def _parse_toml(cfg_buffer: typ.TextIO) -> RawConfig: def _normalize_file_patterns(raw_cfg: RawConfig) -> FilePatterns: - version_str = raw_cfg['current_version'] - version_pattern = raw_cfg['version_pattern'] - pep440_version = version.to_pep440(version_str) - file_patterns = raw_cfg['file_patterns'] + version_str : str = raw_cfg['current_version'] + version_pattern: str = raw_cfg['version_pattern'] + pep440_version : str = version.to_pep440(version_str) + + file_patterns: FilePatterns = raw_cfg['file_patterns'] for filepath, patterns in list(file_patterns.items()): if not os.path.exists(filepath): @@ -216,10 +217,10 @@ def _parse_config(raw_cfg: RawConfig) -> Config: if 'current_version' not in raw_cfg: raise ValueError("Missing 'pycalver.current_version'") - version_str = raw_cfg['current_version'] + version_str: str = raw_cfg['current_version'] version_str = raw_cfg['current_version'] = version_str.strip("'\" ") - version_pattern = raw_cfg.get('version_pattern', "{pycalver}") + version_pattern: str = raw_cfg.get('version_pattern', "{pycalver}") version_pattern = raw_cfg['version_pattern'] = version_pattern.strip("'\" ") # NOTE (mb 2019-01-05): Provoke ValueError if version_pattern @@ -264,6 +265,8 @@ def parse(ctx: ProjectContext) -> MaybeConfig: log.warning(f"File not found: {ctx.config_filepath}") return None + fh : typ.IO[str] + try: with ctx.config_filepath.open(mode="rt", encoding="utf-8") as fh: if ctx.config_format == 'toml': @@ -428,6 +431,8 @@ def write_content(ctx: ProjectContext) -> None: # config_format : str # vcs_type : typ.Optional[str] + fh: typ.IO[str] + cfg_content = default_config(ctx) if os.path.exists("pyproject.toml"): with io.open("pyproject.toml", mode="at", encoding="utf-8") as fh: diff --git a/stubs/pathlib2.pyi b/stubs/pathlib2.pyi new file mode 100644 index 0000000..e9cf3fe --- /dev/null +++ b/stubs/pathlib2.pyi @@ -0,0 +1,120 @@ +# Stubs for pathlib2 (adapted for Python 2 from Python 3.4 typeshed) + +from typing import Any, Generator, IO, Optional, Sequence, Tuple, Type, TypeVar, Union, List +import os +import sys + +_P = TypeVar('_P', bound='PurePath') + +if sys.version_info >= (3, 6): + _PurePathBase = os.PathLike[str] +else: + _PurePathBase = object + +class PurePath(_PurePathBase): + parts = ... # type: Tuple[str, ...] + drive = ... # type: str + root = ... # type: str + anchor = ... # type: str + name = ... # type: str + suffix = ... # type: str + suffixes = ... # type: List[str] + stem = ... # type: str + if sys.version_info < (3, 5): + def __init__(self, *pathsegments: str) -> None: ... + elif sys.version_info < (3, 6): + def __new__(cls: Type[_P], *args: Union[str, PurePath]) -> _P: ... + else: + def __new__(cls: Type[_P], *args: Union[str, os.PathLike[str]]) -> _P: ... + def __hash__(self) -> int: ... + def __lt__(self, other: PurePath) -> bool: ... + def __le__(self, other: PurePath) -> bool: ... + def __gt__(self, other: PurePath) -> bool: ... + def __div__(self: _P, key: Union[str, PurePath]) -> _P: ... + def __rdiv__(self: _P, key: Union[str, PurePath]) -> _P: ... + def __truediv__(self: _P, key: Union[str, PurePath]) -> _P: ... + def __rtruediv__(self: _P, key: Union[str, PurePath]) -> _P: ... + def __ge__(self, other: PurePath) -> bool: ... + def __bytes__(self) -> bytes: ... + def as_posix(self) -> str: ... + def as_uri(self) -> str: ... + def is_absolute(self) -> bool: ... + def is_reserved(self) -> bool: ... + def match(self, path_pattern: str) -> bool: ... + def relative_to(self: _P, *other: Union[str, PurePath]) -> _P: ... + def with_name(self: _P, name: str) -> _P: ... + def with_suffix(self: _P, suffix: str) -> _P: ... + def joinpath(self: _P, *other: Union[str, PurePath]) -> _P: ... + + @property + def parents(self: _P) -> Sequence[_P]: ... + @property + def parent(self: _P) -> _P: ... + +class PurePosixPath(PurePath): ... +class PureWindowsPath(PurePath): ... + +class Path(PurePath): + @classmethod + def cwd(cls: Type[_P]) -> _P: ... + def stat(self) -> os.stat_result: ... + def chmod(self, mode: int) -> None: ... + def exists(self) -> bool: ... + def glob(self, pattern: str) -> Generator[Path, None, None]: ... + def group(self) -> str: ... + def is_dir(self) -> bool: ... + def is_file(self) -> bool: ... + def is_symlink(self) -> bool: ... + def is_socket(self) -> bool: ... + def is_fifo(self) -> bool: ... + def is_block_device(self) -> bool: ... + def is_char_device(self) -> bool: ... + def iterdir(self) -> Generator[Path, None, None]: ... + def lchmod(self, mode: int) -> None: ... + def lstat(self) -> os.stat_result: ... + if sys.version_info < (3, 5): + def mkdir(self, mode: int = ..., + parents: bool = ...) -> None: ... + else: + def mkdir(self, mode: int = ..., parents: bool = ..., + exist_ok: bool = ...) -> None: ... + def open(self, mode: str = ..., buffering: int = ..., + encoding: Optional[str] = ..., errors: Optional[str] = ..., + newline: Optional[str] = ...) -> IO[Any]: ... + def owner(self) -> str: ... + def rename(self, target: Union[str, PurePath]) -> None: ... + def replace(self, target: Union[str, PurePath]) -> None: ... + if sys.version_info < (3, 6): + def resolve(self: _P) -> _P: ... + else: + def resolve(self: _P, strict: bool = ...) -> _P: ... + def rglob(self, pattern: str) -> Generator[Path, None, None]: ... + def rmdir(self) -> None: ... + def symlink_to(self, target: Union[str, Path], + target_is_directory: bool = ...) -> None: ... + def touch(self, mode: int = ..., exist_ok: bool = ...) -> None: ... + def unlink(self) -> None: ... + + if sys.version_info >= (3, 5): + @classmethod + def home(cls: Type[_P]) -> _P: ... + if sys.version_info < (3, 6): + def __new__(cls: Type[_P], *args: Union[str, PurePath], + **kwargs: Any) -> _P: ... + else: + def __new__(cls: Type[_P], *args: Union[str, os.PathLike[str]], + **kwargs: Any) -> _P: ... + + def absolute(self: _P) -> _P: ... + def expanduser(self: _P) -> _P: ... + def read_bytes(self) -> bytes: ... + def read_text(self, encoding: Optional[str] = ..., + errors: Optional[str] = ...) -> str: ... + def samefile(self, other_path: Union[str, bytes, int, Path]) -> bool: ... + def write_bytes(self, data: bytes) -> int: ... + def write_text(self, data: str, encoding: Optional[str] = ..., + errors: Optional[str] = ...) -> int: ... + + +class PosixPath(Path, PurePosixPath): ... +class WindowsPath(Path, PureWindowsPath): ...