diff --git a/release.py b/release.py index 0116c388..ea6216a1 100644 --- a/release.py +++ b/release.py @@ -8,7 +8,7 @@ from subprocess import CalledProcessError, run from sys import exit, stderr from tempfile import mkdtemp -from typing import Any, Dict, NoReturn, Optional, Sequence, cast +from typing import Any, Dict, NoReturn, Optional, Sequence from click import group as commandGroup from click import option as commandOption @@ -59,7 +59,8 @@ def currentVersion() -> Version: versionInfo: Dict[str, Any] = {} versonFile = Path(__file__).parent / "src" / "klein" / "_version.py" exec(versonFile.read_text(), versionInfo) - return versionInfo["__version__"] + version: Version = versionInfo["__version__"] + return version def fadeToBlack() -> None: @@ -109,7 +110,7 @@ def releaseTagName(version: Version) -> str: """ Compute the name of the release tag for the given version. """ - return cast(str, version.public()) + return version.public() def createReleaseBranch(repository: Repository, version: Version) -> Head: @@ -286,22 +287,32 @@ def publishRelease(final: bool, test: bool = False) -> None: print("Pushing tag to origin:", tag) repository.remotes.origin.push(refspec=tag.path) + print("Pushing branch to origin:", branch) + repository.remotes.origin.push() distribute(repository, tag, test=test) @commandGroup() def main() -> None: - pass + """ + Software release tool for Klein. + """ @main.command() def start() -> None: + """ + Begin a new release process. + """ startRelease() @main.command() def bump() -> None: + """ + Increase the version number for an in-progress release candidate. + """ bumpRelease() @@ -317,6 +328,9 @@ def bump() -> None: default=False, ) def publish(final: bool, test: bool) -> None: + """ + Publish the current version of the software to PyPI. + """ publishRelease(final=final, test=test) diff --git a/requirements/tox-pin-base.txt b/requirements/tox-pin-base.txt index b05d5d17..e73c3339 100644 --- a/requirements/tox-pin-base.txt +++ b/requirements/tox-pin-base.txt @@ -3,7 +3,8 @@ Automat==22.10.0 characteristic==14.3.0 constantly==15.1.0 hyperlink==21.0.0 -incremental==21.3.0 +incremental==22.10.0; python_version <= '3.7' +incremental==24.7.2; python_version > '3.7' PyHamcrest==2.1.0 six==1.16.0 Tubes==0.2.1 diff --git a/setup.py b/setup.py index 401a619c..deeab3bd 100644 --- a/setup.py +++ b/setup.py @@ -48,6 +48,6 @@ ), url="https://github.com/twisted/klein", maintainer="Twisted Matrix Laboratories", - maintainer_email="twisted-python@twistedmatrix.com", + maintainer_email="twisted@python.org", zip_safe=False, ) diff --git a/src/klein/_app.py b/src/klein/_app.py index 5459ac5d..37c7f7c8 100644 --- a/src/klein/_app.py +++ b/src/klein/_app.py @@ -185,7 +185,7 @@ def url_for( registerAdapter(KleinRequest, Request, IKleinRequest) -ErrorHandlers = List[Tuple[List[Type[Exception]], KleinErrorHandler]] +ErrorMethods = List[Tuple[List[Type[Exception]], KleinErrorMethod]] # begin argument-processing hack to copy all args from current installed @@ -271,7 +271,7 @@ class Klein: def __init__(self) -> None: self._url_map = Map() self._endpoints: Dict[str, KleinRouteHandler] = {} - self._error_handlers: ErrorHandlers = [] + self._error_handlers: ErrorMethods = [] self._instance: Optional[Klein] = None self._boundAs: Optional[str] = None diff --git a/src/klein/_resource.py b/src/klein/_resource.py index f0e2148f..b12f711c 100644 --- a/src/klein/_resource.py +++ b/src/klein/_resource.py @@ -21,7 +21,7 @@ if TYPE_CHECKING: # NB: circular import, must not be imported at runtime. from ._app import ( - ErrorHandlers, + ErrorMethods, Klein, KleinRenderable, KleinRouteHandler, @@ -250,7 +250,7 @@ def process(r: object) -> Any: d.addCallback(process) def processing_failed( - failure: Failure, error_handlers: ErrorHandlers + failure: Failure, error_handlers: ErrorMethods ) -> Optional[Deferred]: # The failure processor writes to the request. If the # request is already finished we should suppress failure @@ -288,9 +288,10 @@ def processing_failed( # Each error handler is a tuple of # (list_of_exception_types, handler_fn) if failure.check(*error_handler[0]): + handler_func = error_handler[1] d = maybeDeferred( self._app.execute_error_handler, - error_handler[1], # type: ignore[arg-type] + handler_func, request, failure, ) diff --git a/src/klein/test/test_resource.py b/src/klein/test/test_resource.py index a3da9a99..eeaa0155 100644 --- a/src/klein/test/test_resource.py +++ b/src/klein/test/test_resource.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import os from io import BytesIO from types import MappingProxyType @@ -153,16 +155,16 @@ def __init__(self, name: str) -> None: self._name = name @renderer - def name(self, request: IRequest, tag: Tag) -> Tag: + def name(self, request: IRequest, tag: Tag) -> Tag | Deferred[None]: return tag(self._name) class DeferredElement(SimpleElement): - deferred: "Deferred[None]" + deferred: Deferred[None] @renderer - def name(self, request: IRequest, tag: Tag) -> "Deferred[None]": - self.deferred: "Deferred[None]" = Deferred() + def name(self, request: IRequest, tag: Tag) -> Deferred[None]: + self.deferred: Deferred[None] = Deferred() self.deferred.addCallback(lambda ignored: tag(self._name)) return self.deferred @@ -387,7 +389,7 @@ def wooo(request: IRequest) -> KleinRenderable: def test_deferredRendering(self) -> None: app = self.app - deferredResponse: "Deferred[bytes]" = Deferred() + deferredResponse: Deferred[bytes] = Deferred() @app.route("/deferred") def deferred(request: IRequest) -> KleinRenderable: @@ -1011,7 +1013,7 @@ def test_requestFinishAfterConnectionLost(self) -> None: app = self.app request = MockRequest(b"/") - finished: "Deferred[bytes]" = Deferred() + finished: Deferred[bytes] = Deferred() @app.route("/") def root(request: IRequest) -> KleinRenderable: @@ -1050,7 +1052,7 @@ def test_routeHandlesRequestFinished(self) -> None: @app.route("/") def root(request: IRequest) -> KleinRenderable: assert isinstance(request, Request) - _d: "Deferred[bytes]" = Deferred() + _d: Deferred[bytes] = Deferred() _d.addErrback(cancelled.append) request.notifyFinish().addCallback(lambda _: _d.cancel()) return _d @@ -1090,7 +1092,7 @@ def test_cancelledDeferred(self) -> None: app = self.app request = MockRequest(b"/") - inner_d: "Deferred[bytes]" = Deferred() + inner_d: Deferred[bytes] = Deferred() @app.route("/") def root(request: IRequest) -> KleinRenderable: @@ -1128,7 +1130,7 @@ def test_cancelledIsEatenOnConnectionLost(self) -> None: @app.route("/") def root(request: IRequest) -> KleinRenderable: - _d: "Deferred[bytes]" = Deferred() + _d: Deferred[bytes] = Deferred() assert isinstance(request, Request) request.notifyFinish().addErrback(lambda _: _d.cancel()) return _d @@ -1154,7 +1156,7 @@ def test_cancelsOnConnectionLost(self) -> None: app = self.app request = MockRequest(b"/") - handler_d: "Deferred[bytes]" = Deferred() + handler_d: Deferred[bytes] = Deferred() @app.route("/") def root(request: IRequest) -> KleinRenderable: diff --git a/tox.ini b/tox.ini index 0d09311c..29d1b90c 100644 --- a/tox.ini +++ b/tox.ini @@ -2,7 +2,8 @@ envlist = lint, mypy - coverage-py{37,38,39,310,311,312,py3}-tw{212,221,238,trunk} + coverage-py{38,39,310,311,312,py3}-tw{212,221,238,trunk} + coverage-py37-tw{212,221,238} coverage_report docs, docs-linkcheck packaging