add type annotations
This commit is contained in:
parent
79e00d6b6a
commit
5b33095b00
|
@ -0,0 +1,8 @@
|
|||
[mypy]
|
||||
strict=true
|
||||
warn_unused_configs=true
|
||||
show_error_codes=true
|
||||
|
||||
[mypy-incremental.tests.*]
|
||||
allow_untyped_defs=true
|
||||
check_untyped_defs=false
|
|
@ -19,6 +19,8 @@ classifiers =
|
|||
license = MIT
|
||||
description = "A small library that versions your Python projects."
|
||||
long_description = file: README.rst
|
||||
install_requires =
|
||||
typing >= 3.7.4.3; python_version < '3.5'
|
||||
|
||||
[options]
|
||||
packages = find:
|
||||
|
@ -37,6 +39,9 @@ distutils.setup_keywords =
|
|||
scripts =
|
||||
click>=6.0
|
||||
twisted>=16.4.0
|
||||
mypy =
|
||||
%(scripts)s
|
||||
mypy==0.812
|
||||
|
||||
[bdist_wheel]
|
||||
universal = 1
|
||||
|
|
|
@ -11,91 +11,43 @@ from __future__ import division, absolute_import
|
|||
|
||||
import sys
|
||||
import warnings
|
||||
from typing import TYPE_CHECKING, Any, TypeVar, Generic, Union, Optional, Dict
|
||||
|
||||
#
|
||||
# Compat functions
|
||||
#
|
||||
|
||||
if sys.version_info < (3, 0):
|
||||
_PY3 = False
|
||||
_T = TypeVar("_T", contravariant=True)
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing_extensions import Literal
|
||||
from distutils.dist import Distribution as _Distribution
|
||||
|
||||
def _cmp(a, b): # type: (Any, Any) -> int
|
||||
return 0
|
||||
|
||||
|
||||
else:
|
||||
_PY3 = True
|
||||
_Distribution = object
|
||||
|
||||
try:
|
||||
_cmp = cmp
|
||||
except NameError:
|
||||
try:
|
||||
_cmp = cmp
|
||||
except NameError:
|
||||
|
||||
def _cmp(a, b):
|
||||
"""
|
||||
Compare two objects.
|
||||
def _cmp(a, b): # type: (Any, Any) -> int
|
||||
"""
|
||||
Compare two objects.
|
||||
|
||||
Returns a negative number if C{a < b}, zero if they are equal, and a
|
||||
positive number if C{a > b}.
|
||||
"""
|
||||
if a < b:
|
||||
return -1
|
||||
elif a == b:
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
|
||||
|
||||
def _comparable(klass):
|
||||
"""
|
||||
Class decorator that ensures support for the special C{__cmp__} method.
|
||||
|
||||
On Python 2 this does nothing.
|
||||
|
||||
On Python 3, C{__eq__}, C{__lt__}, etc. methods are added to the class,
|
||||
relying on C{__cmp__} to implement their comparisons.
|
||||
"""
|
||||
# On Python 2, __cmp__ will just work, so no need to add extra methods:
|
||||
if not _PY3:
|
||||
return klass
|
||||
|
||||
def __eq__(self, other):
|
||||
c = self.__cmp__(other)
|
||||
if c is NotImplemented:
|
||||
return c
|
||||
return c == 0
|
||||
|
||||
def __ne__(self, other):
|
||||
c = self.__cmp__(other)
|
||||
if c is NotImplemented:
|
||||
return c
|
||||
return c != 0
|
||||
|
||||
def __lt__(self, other):
|
||||
c = self.__cmp__(other)
|
||||
if c is NotImplemented:
|
||||
return c
|
||||
return c < 0
|
||||
|
||||
def __le__(self, other):
|
||||
c = self.__cmp__(other)
|
||||
if c is NotImplemented:
|
||||
return c
|
||||
return c <= 0
|
||||
|
||||
def __gt__(self, other):
|
||||
c = self.__cmp__(other)
|
||||
if c is NotImplemented:
|
||||
return c
|
||||
return c > 0
|
||||
|
||||
def __ge__(self, other):
|
||||
c = self.__cmp__(other)
|
||||
if c is NotImplemented:
|
||||
return c
|
||||
return c >= 0
|
||||
|
||||
klass.__lt__ = __lt__
|
||||
klass.__gt__ = __gt__
|
||||
klass.__le__ = __le__
|
||||
klass.__ge__ = __ge__
|
||||
klass.__eq__ = __eq__
|
||||
klass.__ne__ = __ne__
|
||||
return klass
|
||||
Returns a negative number if C{a < b}, zero if they are equal, and a
|
||||
positive number if C{a > b}.
|
||||
"""
|
||||
if a < b:
|
||||
return -1
|
||||
elif a == b:
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
|
||||
|
||||
#
|
||||
|
@ -103,13 +55,12 @@ def _comparable(klass):
|
|||
#
|
||||
|
||||
|
||||
@_comparable
|
||||
class _inf(object):
|
||||
class _Inf(object):
|
||||
"""
|
||||
An object that is bigger than all other objects.
|
||||
"""
|
||||
|
||||
def __cmp__(self, other):
|
||||
def __cmp__(self, other): # type: (object) -> int
|
||||
"""
|
||||
@param other: Another object.
|
||||
@type other: any
|
||||
|
@ -121,8 +72,46 @@ class _inf(object):
|
|||
return 0
|
||||
return 1
|
||||
|
||||
if sys.version_info >= (3, 0):
|
||||
|
||||
_inf = _inf()
|
||||
def __eq__(self, other): # type: (object) -> bool
|
||||
c = self.__cmp__(other)
|
||||
if c is NotImplemented:
|
||||
return c # type: ignore[return-value]
|
||||
return c == 0
|
||||
|
||||
def __ne__(self, other): # type: (object) -> bool
|
||||
c = self.__cmp__(other)
|
||||
if c is NotImplemented:
|
||||
return c # type: ignore[return-value]
|
||||
return c != 0
|
||||
|
||||
def __lt__(self, other): # type: (object) -> bool
|
||||
c = self.__cmp__(other)
|
||||
if c is NotImplemented:
|
||||
return c # type: ignore[return-value]
|
||||
return c < 0
|
||||
|
||||
def __le__(self, other): # type: (object) -> bool
|
||||
c = self.__cmp__(other)
|
||||
if c is NotImplemented:
|
||||
return c # type: ignore[return-value]
|
||||
return c <= 0
|
||||
|
||||
def __gt__(self, other): # type: (object) -> bool
|
||||
c = self.__cmp__(other)
|
||||
if c is NotImplemented:
|
||||
return c # type: ignore[return-value]
|
||||
return c > 0
|
||||
|
||||
def __ge__(self, other): # type: (object) -> bool
|
||||
c = self.__cmp__(other)
|
||||
if c is NotImplemented:
|
||||
return c # type: ignore[return-value]
|
||||
return c >= 0
|
||||
|
||||
|
||||
_inf = _Inf()
|
||||
|
||||
|
||||
class IncomparableVersions(TypeError):
|
||||
|
@ -131,7 +120,6 @@ class IncomparableVersions(TypeError):
|
|||
"""
|
||||
|
||||
|
||||
@_comparable
|
||||
class Version(object):
|
||||
"""
|
||||
An encapsulation of a version for a project, with support for outputting
|
||||
|
@ -143,14 +131,14 @@ class Version(object):
|
|||
|
||||
def __init__(
|
||||
self,
|
||||
package,
|
||||
major,
|
||||
minor,
|
||||
micro,
|
||||
release_candidate=None,
|
||||
prerelease=None,
|
||||
post=None,
|
||||
dev=None,
|
||||
package, # type: str
|
||||
major, # type: Union[Literal["NEXT"], int]
|
||||
minor, # type: int
|
||||
micro, # type: int
|
||||
release_candidate=None, # type: Optional[int]
|
||||
prerelease=None, # type: Optional[int]
|
||||
post=None, # type: Optional[int]
|
||||
dev=None, # type: Optional[int]
|
||||
):
|
||||
"""
|
||||
@param package: Name of the package that this is a version of.
|
||||
|
@ -199,7 +187,7 @@ class Version(object):
|
|||
self.dev = dev
|
||||
|
||||
@property
|
||||
def prerelease(self):
|
||||
def prerelease(self): # type: () -> Optional[int]
|
||||
warnings.warn(
|
||||
(
|
||||
"Accessing incremental.Version.prerelease was "
|
||||
|
@ -211,7 +199,7 @@ class Version(object):
|
|||
),
|
||||
return self.release_candidate
|
||||
|
||||
def public(self):
|
||||
def public(self): # type: () -> str
|
||||
"""
|
||||
Return a PEP440-compatible "public" representation of this L{Version}.
|
||||
|
||||
|
@ -246,7 +234,7 @@ class Version(object):
|
|||
short = public
|
||||
local = public
|
||||
|
||||
def __repr__(self):
|
||||
def __repr__(self): # type: () -> str
|
||||
|
||||
if self.release_candidate is None:
|
||||
release_candidate = ""
|
||||
|
@ -274,10 +262,10 @@ class Version(object):
|
|||
dev,
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
def __str__(self): # type: () -> str
|
||||
return "[%s, version %s]" % (self.package, self.short())
|
||||
|
||||
def __cmp__(self, other):
|
||||
def __cmp__(self, other): # type: (Version) -> int
|
||||
"""
|
||||
Compare two versions, considering major versions, minor versions, micro
|
||||
versions, then release candidates, then postreleases, then dev
|
||||
|
@ -306,12 +294,12 @@ class Version(object):
|
|||
raise IncomparableVersions("%r != %r" % (self.package, other.package))
|
||||
|
||||
if self.major == "NEXT":
|
||||
major = _inf
|
||||
major = _inf # type: Union[int, _Inf]
|
||||
else:
|
||||
major = self.major
|
||||
|
||||
if self.release_candidate is None:
|
||||
release_candidate = _inf
|
||||
release_candidate = _inf # type: Union[int, _Inf]
|
||||
else:
|
||||
release_candidate = self.release_candidate
|
||||
|
||||
|
@ -321,17 +309,17 @@ class Version(object):
|
|||
post = self.post
|
||||
|
||||
if self.dev is None:
|
||||
dev = _inf
|
||||
dev = _inf # type: Union[int, _Inf]
|
||||
else:
|
||||
dev = self.dev
|
||||
|
||||
if other.major == "NEXT":
|
||||
othermajor = _inf
|
||||
othermajor = _inf # type: Union[int, _Inf]
|
||||
else:
|
||||
othermajor = other.major
|
||||
|
||||
if other.release_candidate is None:
|
||||
otherrc = _inf
|
||||
otherrc = _inf # type: Union[int, _Inf]
|
||||
else:
|
||||
otherrc = other.release_candidate
|
||||
|
||||
|
@ -341,7 +329,7 @@ class Version(object):
|
|||
otherpost = other.post
|
||||
|
||||
if other.dev is None:
|
||||
otherdev = _inf
|
||||
otherdev = _inf # type: Union[int, _Inf]
|
||||
else:
|
||||
otherdev = other.dev
|
||||
|
||||
|
@ -351,8 +339,46 @@ class Version(object):
|
|||
)
|
||||
return x
|
||||
|
||||
if sys.version_info >= (3, 0):
|
||||
|
||||
def getVersionString(version):
|
||||
def __eq__(self, other): # type: (Any) -> bool
|
||||
c = self.__cmp__(other)
|
||||
if c is NotImplemented:
|
||||
return c # type: ignore[return-value]
|
||||
return c == 0
|
||||
|
||||
def __ne__(self, other): # type: (Any) -> bool
|
||||
c = self.__cmp__(other)
|
||||
if c is NotImplemented:
|
||||
return c # type: ignore[return-value]
|
||||
return c != 0
|
||||
|
||||
def __lt__(self, other): # type: (Version) -> bool
|
||||
c = self.__cmp__(other)
|
||||
if c is NotImplemented:
|
||||
return c # type: ignore[return-value]
|
||||
return c < 0
|
||||
|
||||
def __le__(self, other): # type: (Version) -> bool
|
||||
c = self.__cmp__(other)
|
||||
if c is NotImplemented:
|
||||
return c # type: ignore[return-value]
|
||||
return c <= 0
|
||||
|
||||
def __gt__(self, other): # type: (Version) -> bool
|
||||
c = self.__cmp__(other)
|
||||
if c is NotImplemented:
|
||||
return c # type: ignore[return-value]
|
||||
return c > 0
|
||||
|
||||
def __ge__(self, other): # type: (Version) -> bool
|
||||
c = self.__cmp__(other)
|
||||
if c is NotImplemented:
|
||||
return c # type: ignore[return-value]
|
||||
return c >= 0
|
||||
|
||||
|
||||
def getVersionString(version): # type: (Version) -> str
|
||||
"""
|
||||
Get a friendly string for the given version object.
|
||||
|
||||
|
@ -363,7 +389,7 @@ def getVersionString(version):
|
|||
return result
|
||||
|
||||
|
||||
def _get_version(dist, keyword, value):
|
||||
def _get_version(dist, keyword, value): # type: (_Distribution, object, object) -> None
|
||||
"""
|
||||
Get the version from the package listed in the Distribution.
|
||||
"""
|
||||
|
@ -375,12 +401,12 @@ def _get_version(dist, keyword, value):
|
|||
sp_command = build_py.build_py(dist)
|
||||
sp_command.finalize_options()
|
||||
|
||||
for item in sp_command.find_all_modules():
|
||||
for item in sp_command.find_all_modules(): # type: ignore[attr-defined]
|
||||
if item[1] == "_version":
|
||||
version_file = {}
|
||||
version_file = {} # type: Dict[str, Version]
|
||||
|
||||
with open(item[2]) as f:
|
||||
exec(f.read(), version_file)
|
||||
exec (f.read(), version_file)
|
||||
|
||||
dist.metadata.version = version_file["__version__"].public()
|
||||
return None
|
||||
|
@ -391,7 +417,7 @@ def _get_version(dist, keyword, value):
|
|||
from ._version import __version__ # noqa
|
||||
|
||||
|
||||
def _setuptools_version():
|
||||
def _setuptools_version(): # type: () -> str
|
||||
return __version__.public()
|
||||
|
||||
|
||||
|
|
|
@ -6,9 +6,51 @@ from __future__ import absolute_import, division, print_function
|
|||
import click
|
||||
import os
|
||||
import datetime
|
||||
from typing import TYPE_CHECKING, Dict, Optional, Callable, Union, Iterable
|
||||
|
||||
from incremental import Version
|
||||
from twisted.python.filepath import FilePath
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing_extensions import Protocol
|
||||
|
||||
class _ReadableWritable(Protocol):
|
||||
def read(self): # type: () -> bytes
|
||||
pass
|
||||
|
||||
def write(self, v): # type: (bytes) -> object
|
||||
pass
|
||||
|
||||
def __enter__(self): # type: () -> _ReadableWritable
|
||||
pass
|
||||
|
||||
def __exit__(self, *args, **kwargs): # type: (object, object) -> Optional[bool]
|
||||
pass
|
||||
|
||||
class FilePath(object):
|
||||
def __init__(self, path): # type: (str) -> None
|
||||
self.path = path
|
||||
|
||||
def child(self, v): # type: (str) -> FilePath
|
||||
pass
|
||||
|
||||
def isdir(self): # type: () -> bool
|
||||
pass
|
||||
|
||||
def isfile(self): # type: () -> bool
|
||||
pass
|
||||
|
||||
def getContent(self): # type: () -> bytes
|
||||
pass
|
||||
|
||||
def open(self, mode): # type: (str) -> _ReadableWritable
|
||||
pass
|
||||
|
||||
def walk(self): # type: () -> Iterable[FilePath]
|
||||
pass
|
||||
|
||||
|
||||
else:
|
||||
from twisted.python.filepath import FilePath
|
||||
|
||||
_VERSIONPY_TEMPLATE = '''"""
|
||||
Provides {package} version information.
|
||||
|
@ -26,7 +68,7 @@ __all__ = ["__version__"]
|
|||
_YEAR_START = 2000
|
||||
|
||||
|
||||
def _findPath(path, package):
|
||||
def _findPath(path, package): # type: (str, str) -> FilePath
|
||||
|
||||
cwd = FilePath(path)
|
||||
|
||||
|
@ -48,28 +90,28 @@ def _findPath(path, package):
|
|||
)
|
||||
|
||||
|
||||
def _existing_version(path):
|
||||
version_info = {}
|
||||
def _existing_version(path): # type: (FilePath) -> Version
|
||||
version_info = {} # type: Dict[str, Version]
|
||||
|
||||
with path.child("_version.py").open("r") as f:
|
||||
exec(f.read(), version_info)
|
||||
exec (f.read(), version_info)
|
||||
|
||||
return version_info["__version__"]
|
||||
|
||||
|
||||
def _run(
|
||||
package,
|
||||
path,
|
||||
newversion,
|
||||
patch,
|
||||
rc,
|
||||
post,
|
||||
dev,
|
||||
create,
|
||||
_date=None,
|
||||
_getcwd=None,
|
||||
_print=print,
|
||||
):
|
||||
package, # type: str
|
||||
path, # type: Optional[str]
|
||||
newversion, # type: Optional[str]
|
||||
patch, # type: bool
|
||||
rc, # type: bool
|
||||
post, # type: bool
|
||||
dev, # type: bool
|
||||
create, # type: bool
|
||||
_date=None, # type: Optional[datetime.date]
|
||||
_getcwd=None, # type: Optional[Callable[[], str]]
|
||||
_print=print, # type: Callable[[object], object]
|
||||
): # type: (...) -> None
|
||||
|
||||
if not _getcwd:
|
||||
_getcwd = os.getcwd
|
||||
|
@ -77,13 +119,10 @@ def _run(
|
|||
if not _date:
|
||||
_date = datetime.date.today()
|
||||
|
||||
if type(package) != str:
|
||||
if not TYPE_CHECKING and type(package) != str:
|
||||
package = package.encode("utf8")
|
||||
|
||||
if not path:
|
||||
path = _findPath(_getcwd(), package)
|
||||
else:
|
||||
path = FilePath(path)
|
||||
_path = FilePath(path) if path else _findPath(_getcwd(), package)
|
||||
|
||||
if (
|
||||
newversion
|
||||
|
@ -117,22 +156,31 @@ def _run(
|
|||
if newversion:
|
||||
from pkg_resources import parse_version
|
||||
|
||||
existing = _existing_version(path)
|
||||
st_version = parse_version(newversion)._version
|
||||
existing = _existing_version(_path)
|
||||
st_version = parse_version(newversion)._version # type: ignore[attr-defined]
|
||||
|
||||
release = list(st_version.release)
|
||||
|
||||
minor = 0
|
||||
micro = 0
|
||||
if len(release) == 1:
|
||||
release.append(0)
|
||||
if len(release) == 2:
|
||||
release.append(0)
|
||||
(major,) = release
|
||||
elif len(release) == 2:
|
||||
(
|
||||
major,
|
||||
minor,
|
||||
) = release
|
||||
else:
|
||||
major, minor, micro = release
|
||||
|
||||
v = Version(
|
||||
package,
|
||||
*release,
|
||||
major,
|
||||
minor,
|
||||
micro,
|
||||
release_candidate=st_version.pre[1] if st_version.pre else None,
|
||||
post=st_version.post[1] if st_version.post else None,
|
||||
dev=st_version.dev[1] if st_version.dev else None
|
||||
dev=st_version.dev[1] if st_version.dev else None,
|
||||
)
|
||||
|
||||
elif create:
|
||||
|
@ -140,7 +188,7 @@ def _run(
|
|||
existing = v
|
||||
|
||||
elif rc and not patch:
|
||||
existing = _existing_version(path)
|
||||
existing = _existing_version(_path)
|
||||
|
||||
if existing.release_candidate:
|
||||
v = Version(
|
||||
|
@ -154,16 +202,17 @@ def _run(
|
|||
v = Version(package, _date.year - _YEAR_START, _date.month, 0, 1)
|
||||
|
||||
elif patch:
|
||||
if rc:
|
||||
rc = 1
|
||||
else:
|
||||
rc = None
|
||||
|
||||
existing = _existing_version(path)
|
||||
v = Version(package, existing.major, existing.minor, existing.micro + 1, rc)
|
||||
existing = _existing_version(_path)
|
||||
v = Version(
|
||||
package,
|
||||
existing.major,
|
||||
existing.minor,
|
||||
existing.micro + 1,
|
||||
1 if rc else None,
|
||||
)
|
||||
|
||||
elif post:
|
||||
existing = _existing_version(path)
|
||||
existing = _existing_version(_path)
|
||||
|
||||
if existing.post is None:
|
||||
_post = 0
|
||||
|
@ -173,7 +222,7 @@ def _run(
|
|||
v = Version(package, existing.major, existing.minor, existing.micro, post=_post)
|
||||
|
||||
elif dev:
|
||||
existing = _existing_version(path)
|
||||
existing = _existing_version(_path)
|
||||
|
||||
if existing.dev is None:
|
||||
_dev = 0
|
||||
|
@ -190,7 +239,7 @@ def _run(
|
|||
)
|
||||
|
||||
else:
|
||||
existing = _existing_version(path)
|
||||
existing = _existing_version(_path)
|
||||
|
||||
if existing.release_candidate:
|
||||
v = Version(package, existing.major, existing.minor, existing.micro)
|
||||
|
@ -208,7 +257,7 @@ def _run(
|
|||
|
||||
_print("Updating codebase to %s" % (v.public()))
|
||||
|
||||
for x in path.walk():
|
||||
for x in _path.walk():
|
||||
|
||||
if not x.isfile():
|
||||
continue
|
||||
|
@ -241,8 +290,8 @@ def _run(
|
|||
with x.open("w") as f:
|
||||
f.write(content)
|
||||
|
||||
_print("Updating %s/_version.py" % (path.path))
|
||||
with path.child("_version.py").open("w") as f:
|
||||
_print("Updating %s/_version.py" % (_path.path))
|
||||
with _path.child("_version.py").open("w") as f:
|
||||
f.write(
|
||||
(
|
||||
_VERSIONPY_TEMPLATE.format(package=package, version_repr=version_repr)
|
||||
|
@ -259,8 +308,26 @@ def _run(
|
|||
@click.option("--post", is_flag=True)
|
||||
@click.option("--dev", is_flag=True)
|
||||
@click.option("--create", is_flag=True)
|
||||
def run(*args, **kwargs):
|
||||
return _run(*args, **kwargs)
|
||||
def run(
|
||||
package, # type: str
|
||||
path, # type: Optional[str]
|
||||
newversion, # type: Optional[str]
|
||||
patch, # type: bool
|
||||
rc, # type: bool
|
||||
post, # type: bool
|
||||
dev, # type: bool
|
||||
create, # type: bool
|
||||
): # type: (...) -> None
|
||||
return _run(
|
||||
package=package,
|
||||
path=path,
|
||||
newversion=newversion,
|
||||
patch=patch,
|
||||
rc=rc,
|
||||
post=post,
|
||||
dev=dev,
|
||||
create=create,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__": # pragma: no cover
|
||||
|
|
5
tox.ini
5
tox.ini
|
@ -20,6 +20,9 @@ deps =
|
|||
check-manifest: check-manifest
|
||||
black: black
|
||||
black-reformat: black
|
||||
extras =
|
||||
mypy: mypy
|
||||
tests: scripts
|
||||
|
||||
setenv =
|
||||
black: BLACK_LINT_ARGS=--check
|
||||
|
@ -33,7 +36,6 @@ commands =
|
|||
|
||||
check-manifest: check-manifest -v
|
||||
|
||||
tests: pip install incremental[scripts]
|
||||
tests: coverage --version
|
||||
tests: {envbindir}/trial --version
|
||||
tests: coverage erase
|
||||
|
@ -43,6 +45,7 @@ commands =
|
|||
tests: coverage combine
|
||||
tests: coverage report
|
||||
tests: coverage html
|
||||
mypy: mypy src
|
||||
|
||||
[testenv:black-reformat]
|
||||
setenv =
|
||||
|
|
Loading…
Reference in New Issue