From 34f7a524bc2cbcbf23d9b3a396fc132bcc000421 Mon Sep 17 00:00:00 2001 From: Dan Yeaw Date: Fri, 28 Aug 2020 22:08:26 -0400 Subject: [PATCH] Add isort, check-toml, and check-yaml to pre-commit Signed-off-by: Dan Yeaw --- .flake8 | 10 ++++++++++ .gitignore | 6 ++++++ .pre-commit-config.yaml | 19 ++++++++++++++++--- docs/conf.py | 3 ++- generic/event.py | 10 ++++------ generic/multidispatch.py | 13 ++++++------- generic/multimethod.py | 20 +++++++++----------- generic/registry.py | 18 +++++++++--------- pyproject.toml | 9 +++++++++ tests/test_event.py | 1 + tests/test_multidispatch.py | 5 +++-- tests/test_registry.py | 3 ++- 12 files changed, 77 insertions(+), 40 deletions(-) create mode 100644 .flake8 diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..c7fbe44 --- /dev/null +++ b/.flake8 @@ -0,0 +1,10 @@ +[flake8] +# E501 (Line too long) is handled by Black (reformatting) +# W503 (Line break occurred before a binary operator) conflicts with Black formatting +# E203 (whitespace before ':') is not PEP8 compliant +ignore = E501, W503, E203 +max-line-length = 88 +max-complexity = 18 +select = B,C,E,F,W,T4,B9 +exclude = .venv, dist, __init__.py +show-source = True \ No newline at end of file diff --git a/.gitignore b/.gitignore index b62a7f8..ade271e 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,9 @@ __pycache__ cc-test-reporter htmlcov/ .python-version + +# Virtualenv +.venv + +# Tox +.tox diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6c1a610..668aa95 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,11 +1,24 @@ repos: - repo: https://github.com/ambv/black - rev: 19.10b0 + rev: 20.8b1 hooks: - id: black language_version: python3 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v0.740 + rev: v0.770 hooks: - id: mypy - args: [ --show-error-codes ] +# - repo: https://gitlab.com/pycqa/flake8 +# rev: 3.8.3 +# hooks: +# - id: flake8 +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v3.2.0 + hooks: + - id: check-toml + - id: check-yaml +- repo: https://github.com/pre-commit/mirrors-isort + rev: v5.4.2 + hooks: + - id: isort + additional_dependencies: [toml] diff --git a/docs/conf.py b/docs/conf.py index 0f6547f..eff386e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -11,7 +11,8 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys, os +import os +import sys from pathlib import Path project_dir = Path(__file__).resolve().parent.parent diff --git a/generic/event.py b/generic/event.py index 628df8c..c30a68b 100644 --- a/generic/event.py +++ b/generic/event.py @@ -16,7 +16,6 @@ from typing import Callable, Set, Type from generic.registry import Registry, TypeAxis - __all__ = "Manager" Event = object @@ -25,7 +24,7 @@ HandlerSet = Set[Handler] class Manager: - """ Event manager + """Event manager Provides API for subscribing for and firing events. There's also global event manager instantiated at module level with functions @@ -53,7 +52,7 @@ class Manager: handler_set.remove(handler) def handle(self, event: Event) -> None: - """ Fire ``event`` + """Fire ``event`` All subscribers will be executed with no determined order. """ @@ -64,14 +63,13 @@ class Manager: handler(event) def _register_handler_set(self, event_type: Type[Event]) -> HandlerSet: - """ Register new handler set for ``event_type``. - """ + """Register new handler set for ``event_type``.""" handler_set: HandlerSet = set() self.registry.register(handler_set, event_type) return handler_set def subscriber(self, event_type: Type[Event]) -> Callable[[Handler], Handler]: - """ Decorator for subscribing handlers + """Decorator for subscribing handlers Works like this: diff --git a/generic/multidispatch.py b/generic/multidispatch.py index c7bf8ba..f708a06 100644 --- a/generic/multidispatch.py +++ b/generic/multidispatch.py @@ -11,10 +11,9 @@ Note that this module does not support annotated functions. from __future__ import annotations -from typing import cast, Any, Callable, Generic, TypeVar, Union - import functools import inspect +from typing import Any, Callable, Generic, TypeVar, Union, cast from generic.registry import Registry, TypeAxis @@ -25,7 +24,7 @@ KeyType = Union[type, None] def multidispatch(*argtypes: KeyType) -> Callable[[T], FunctionDispatcher[T]]: - """ Declare function as multidispatch + """Declare function as multidispatch This decorator takes ``argtypes`` argument types and replace decorated function with :class:`.FunctionDispatcher` object, which is responsible for @@ -53,7 +52,7 @@ def multidispatch(*argtypes: KeyType) -> Callable[[T], FunctionDispatcher[T]]: class FunctionDispatcher(Generic[T]): - """ Multidispatcher for functions + """Multidispatcher for functions This object dispatch calls to function by its argument types. Usually it is produced by :func:`.multidispatch` decorator. @@ -64,7 +63,7 @@ class FunctionDispatcher(Generic[T]): registry: Registry[T] def __init__(self, argspec: inspect.FullArgSpec, params_arity: int) -> None: - """ Initialize dispatcher with ``argspec`` of type + """Initialize dispatcher with ``argspec`` of type :class:`inspect.ArgSpec` and ``params_arity`` that represent number params.""" # Check if we have enough positional arguments for number of type params @@ -81,7 +80,7 @@ class FunctionDispatcher(Generic[T]): self.registry = Registry(*axis) def check_rule(self, rule: T, *argtypes: KeyType) -> None: - """ Check if the argument types match wrt number of arguments. + """Check if the argument types match wrt number of arguments. Raise TypeError in case of failure. """ @@ -106,7 +105,7 @@ class FunctionDispatcher(Generic[T]): self.registry.register(rule, *argtypes) def register(self, *argtypes: KeyType) -> Callable[[T], T]: - """ Decorator for registering new case for multidispatch + """Decorator for registering new case for multidispatch New case will be registered for types identified by ``argtypes``. The length of ``argtypes`` should be equal to the length of ``argtypes`` diff --git a/generic/multimethod.py b/generic/multimethod.py index 1afe06e..12a2e62 100644 --- a/generic/multimethod.py +++ b/generic/multimethod.py @@ -5,15 +5,13 @@ to provide generic methods. from __future__ import annotations -from typing import cast, Any, Callable, Type, TypeVar, Union - -import inspect import functools +import inspect import threading import types +from typing import Any, Callable, Type, TypeVar, Union, cast -from generic.multidispatch import FunctionDispatcher, _arity, KeyType - +from generic.multidispatch import FunctionDispatcher, KeyType, _arity __all__ = ("multimethod", "has_multimethods") @@ -22,8 +20,8 @@ T = TypeVar("T", bound=Union[Callable[..., Any], type]) def multimethod(*argtypes: KeyType) -> Callable[[T], MethodDispatcher[T]]: - """ Declare method as multimethod - + """Declare method as multimethod + This decorator works exactly the same as :func:`.multidispatch` decorator but replaces decorated method with :class:`.MethodDispatcher` object instead. @@ -49,7 +47,7 @@ def multimethod(*argtypes: KeyType) -> Callable[[T], MethodDispatcher[T]]: def has_multimethods(cls: Type[C]) -> Type[C]: - """ Declare class as one that have multimethods + """Declare class as one that have multimethods Should only be used for decorating classes which have methods decorated with :func:`.multimethod` decorator. @@ -61,11 +59,11 @@ def has_multimethods(cls: Type[C]) -> Type[C]: class MethodDispatcher(FunctionDispatcher[T]): - """ Multiple dispatch for methods + """Multiple dispatch for methods This object dispatch call to method by its class and arguments types. Usually it is produced by :func:`.multimethod` decorator. - + You should not manually create objects of this type. """ @@ -77,7 +75,7 @@ class MethodDispatcher(FunctionDispatcher[T]): self.local.unbound_rules = [] def register_unbound_rule(self, func, *argtypes) -> None: - """ Register unbound rule that should be processed by + """Register unbound rule that should be processed by ``proceed_unbound_rules`` later.""" self.local.unbound_rules.append((argtypes, func)) diff --git a/generic/registry.py b/generic/registry.py index 2499d25..e597d52 100644 --- a/generic/registry.py +++ b/generic/registry.py @@ -7,15 +7,13 @@ This implementation was borrowed from happy[1] project by Chris Rossi. from __future__ import annotations -__all__ = ("Registry", "SimpleAxis", "TypeAxis") - from typing import ( Any, Dict, + Generator, Generic, KeysView, List, - Generator, Optional, Sequence, Tuple, @@ -23,6 +21,8 @@ from typing import ( Union, ) +__all__ = ("Registry", "SimpleAxis", "TypeAxis") + K = TypeVar("K") S = TypeVar("S") T = TypeVar("T") @@ -70,9 +70,9 @@ class Registry(Generic[T]): def _query( self, tree_node: _TreeNode[T], objs: Sequence[Optional[V]], axes: Sequence[Axis] ) -> Generator[Optional[T], None, None]: - """ Recursively traverse registration tree, from left to right, most + """Recursively traverse registration tree, from left to right, most specific to least specific, returning the first target found on a - matching node. """ + matching node.""" if not objs: yield tree_node.target else: @@ -92,9 +92,9 @@ class Registry(Generic[T]): def _align_with_axes( self, args: Sequence[S], kw: Dict[str, S] ) -> Sequence[Optional[S]]: - """ Create a list matching up all args and kwargs with their + """Create a list matching up all args and kwargs with their corresponding axes, in order, using ``None`` as a placeholder for - skipped axes. """ + skipped axes.""" axes_dict = self._axes_dict aligned: List[Optional[S]] = [None for i in range(len(axes_dict))] @@ -133,7 +133,7 @@ class _TreeNode(Generic[T], Dict[Any, Any]): class SimpleAxis: - """ A simple axis where the key into the axis is the same as the object to + """A simple axis where the key into the axis is the same as the object to be matched (aka the identity axis). This axis behaves just like a dictionary. You might use this axis if you are interested in registering something by name, where you're registering an object with the string that @@ -152,7 +152,7 @@ class SimpleAxis: class TypeAxis: - """ An axis which matches the class and super classes of an object in + """An axis which matches the class and super classes of an object in method resolution order. """ diff --git a/pyproject.toml b/pyproject.toml index 32edb30..8a7cf5f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,3 +59,12 @@ commands = poetry install -v xvfb-run -a pytest """ + +[tool.isort] +multi_line_output = 3 +include_trailing_comma = true +force_grid_wrap = 0 +use_parentheses = true +line_length = 88 +known_third_party = ["pytest"] +skip = ".venv,build,dist" diff --git a/tests/test_event.py b/tests/test_event.py index 63609d8..5cb4cce 100644 --- a/tests/test_event.py +++ b/tests/test_event.py @@ -3,6 +3,7 @@ from __future__ import annotations from typing import Callable, List + from generic.event import Manager diff --git a/tests/test_multidispatch.py b/tests/test_multidispatch.py index a99d5a0..d7f9caf 100644 --- a/tests/test_multidispatch.py +++ b/tests/test_multidispatch.py @@ -1,9 +1,10 @@ """ Tests for :module:`generic.multidispatch`.""" +from inspect import FullArgSpec + import pytest -from inspect import FullArgSpec -from generic.multidispatch import multidispatch, FunctionDispatcher +from generic.multidispatch import FunctionDispatcher, multidispatch def create_dispatcher( diff --git a/tests/test_registry.py b/tests/test_registry.py index d02384f..af9b707 100644 --- a/tests/test_registry.py +++ b/tests/test_registry.py @@ -1,8 +1,9 @@ """ Tests for :module:`generic.registry`.""" +from typing import Union + import pytest -from typing import Union from generic.registry import Registry, SimpleAxis, TypeAxis