diff options
author | Thomas Touhey <thomas@touhey.fr> | 2021-12-31 22:09:03 +0100 |
---|---|---|
committer | Thomas Touhey <thomas@touhey.fr> | 2021-12-31 22:09:03 +0100 |
commit | bbef529d1b7c52f09be399ca27f86d36d1267d50 (patch) | |
tree | 32a1fe655e63ceb3e15770b5d172edf83ae3a2fd | |
parent | f7ebc55d149a600ab0d5bdbdb0d3693f394c8d89 (diff) |
Reorganized the module to have one level and static type checked
-rw-r--r-- | setup.cfg | 2 | ||||
-rwxr-xr-x | tests/test_decoders.py | 1 | ||||
-rw-r--r-- | thcolor/angles.py | 10 | ||||
-rw-r--r-- | thcolor/builtin.py (renamed from thcolor/decoders/builtin.py) | 6 | ||||
-rw-r--r-- | thcolor/colors.py | 29 | ||||
-rw-r--r-- | thcolor/decoders.py (renamed from thcolor/decoders/base.py) | 46 | ||||
-rw-r--r-- | thcolor/decoders/__init__.py | 20 |
7 files changed, 50 insertions, 64 deletions
@@ -35,7 +35,7 @@ source-dir = docs universal = True [flake8] -ignore = D105,D107,D202,D208,D210,D401,W503 +ignore = D105,D107,D202,D208,D210,D401,T499,W503 exclude = docs/conf.py test.py diff --git a/tests/test_decoders.py b/tests/test_decoders.py index 8dd91eb..975af04 100755 --- a/tests/test_decoders.py +++ b/tests/test_decoders.py @@ -9,6 +9,7 @@ import pytest from thcolor.angles import * # NOQA from thcolor.colors import * # NOQA from thcolor.decoders import * # NOQA +from thcolor.builtin import * # NOQA from thcolor.errors import * # NOQA diff --git a/thcolor/angles.py b/thcolor/angles.py index 6dd36a6..5a581fb 100644 --- a/thcolor/angles.py +++ b/thcolor/angles.py @@ -6,7 +6,7 @@ """ Angle representation and conversions. """ from math import pi as _pi -from typing import Optional as _Optional +from typing import Any as _Any, Optional as _Optional __all__ = [ 'Angle', 'DegreesAngle', 'GradiansAngle', 'RadiansAngle', 'TurnsAngle', @@ -21,6 +21,10 @@ class Angle: __slots__ = () + _value: float + _bottom: float = 0 + _top: float = 1 + def __init__(self): pass @@ -107,7 +111,7 @@ class Angle: def fromtext( cls, expr: str, - decoder: _Optional = None, + decoder: _Optional[_Any] = None, ) -> 'Angle': """ Create a color from a string. @@ -115,7 +119,7 @@ class Angle: """ if decoder is None: - from .decoders.builtin import DefaultColorDecoder + from .builtin import DefaultColorDecoder decoder = DefaultColorDecoder() diff --git a/thcolor/decoders/builtin.py b/thcolor/builtin.py index a512d2d..d3f42cf 100644 --- a/thcolor/decoders/builtin.py +++ b/thcolor/builtin.py @@ -7,12 +7,12 @@ from typing import Union as _Union -from ..angles import Angle as _Angle -from .base import ( +from .angles import Angle as _Angle +from .decoders import ( MetaColorDecoder as _MetaColorDecoder, alias as _alias, fallback as _fallback, ) -from ..colors import ( +from .colors import ( CMYKColor as _CMYKColor, Color as _Color, HSLColor as _HSLColor, HSVColor as _HSVColor, HWBColor as _HWBColor, LABColor as _LABColor, LCHColor as _LCHColor, SRGBColor as _SRGBColor, XYZColor as _XYZColor, diff --git a/thcolor/colors.py b/thcolor/colors.py index d459886..935dc72 100644 --- a/thcolor/colors.py +++ b/thcolor/colors.py @@ -9,8 +9,7 @@ from math import ( atan2 as _atan2, ceil as _ceil, cos as _cos, sin as _sin, sqrt as _sqrt, ) from typing import ( - Optional as _Optional, Tuple as _Tuple, Mapping as _Mapping, - Sequence as _Sequence, + Any as _Any, Optional as _Optional, Tuple as _Tuple, Sequence as _Sequence, ) from .angles import ( @@ -32,7 +31,7 @@ class Color: """ __slots__ = ('_alpha') - _params = () + _params: _Sequence[str] = () def __init__(self, alpha: float = 1.0): super().__init__() @@ -49,7 +48,7 @@ class Color: f'{", ".join(f"{key}={val!r}" for key, val in params)})' ) - def __eq__(self, other: 'Color') -> bool: + def __eq__(self, other: _Any) -> bool: if not isinstance(other, Color): return False @@ -75,7 +74,7 @@ class Color: def fromtext( cls, expr: str, - decoder: _Optional = None, + decoder: _Optional[_Any] = None, ) -> 'Color': """ Create a color from a string. @@ -83,7 +82,7 @@ class Color: """ if decoder is None: - from .decoders.builtin import DefaultColorDecoder + from .builtin import DefaultColorDecoder decoder = DefaultColorDecoder() @@ -155,7 +154,7 @@ class Color: # Operations on colors. # --- - def replace(self, **properties: _Mapping[str, object]) -> 'Color': + def replace(self, **properties) -> 'Color': """ Replace components and obtain a copy of the color. Returns a copy of the color with the property values replaced. @@ -179,7 +178,7 @@ class Color: params = { key: getattr(self, key) - for key in self._params + ('alpha',) + for key in (*self._params, 'alpha') } for key, value in properties.items(): @@ -193,7 +192,7 @@ class Color: return type(self)(**params) - def darker(self, by: float = 0.1) -> 'HSLColor': + def darker(self, by: float = 0.1) -> 'Color': """ Get a darker version of the given color. :param by: Percentage by which the color should be darker. @@ -202,7 +201,7 @@ class Color: color = self.ashsl() return color.replace(lightness=max(color.lightness - by, 0.0)) - def lighter(self, by: float = 0.1) -> 'HSLColor': + def lighter(self, by: float = 0.1) -> 'Color': """ Get a lighter version of the given color. :param by: Percentage by which the color should be lighter. @@ -211,7 +210,7 @@ class Color: color = self.ashsl() return color.replace(lightness=min(color.lightness + by, 1.0)) - def desaturate(self, by: float = 0.1) -> 'HSLColor': + def desaturate(self, by: float = 0.1) -> 'Color': """ Get a less saturated version of the given color. :param by: Percentage by which the color should be @@ -221,7 +220,7 @@ class Color: color = self.ashsl() return color.replace(saturation=max(color.saturation - by, 0.0)) - def saturate(self, by: float = 0.1) -> 'HSLColor': + def saturate(self, by: float = 0.1) -> 'Color': """ Get a more saturated version of the given color. :param by: Percentage by which the color should be @@ -456,7 +455,7 @@ class SRGBColor(Color): chroma = max_value - min_value if chroma == 0: - hue = 0 + hue = 0. elif r == max_value: hue = (g - b) / chroma elif g == max_value: @@ -467,7 +466,7 @@ class SRGBColor(Color): hue = hue * 60 + (hue < 0) * 360 lgt = (min_value + max_value) / 2 if min_value == max_value: - s = 0 + s = 0. else: s = max_value - min_value if lgt < 0.5: @@ -491,7 +490,7 @@ class SRGBColor(Color): value = maxc if minc == maxc: - turns, saturation = 0, 0 + turns, saturation = 0., 0. else: saturation = (maxc - minc) / maxc rc, gc, bc = map(lambda x: (maxc - x) / (maxc - minc), (r, g, b)) diff --git a/thcolor/decoders/base.py b/thcolor/decoders.py index 0f4d7cf..9cda965 100644 --- a/thcolor/decoders/base.py +++ b/thcolor/decoders.py @@ -12,19 +12,19 @@ from collections.abc import Mapping as _Mapping from enum import auto as _auto, Enum as _Enum from typing import ( Any as _Any, Optional as _Optional, Union as _Union, - Sequence as _Sequence, Tuple as _Tuple, + Sequence as _Sequence, Tuple as _Tuple, List as _List, ) from inspect import getfullargspec as _getfullargspec -from ..angles import Angle as _Angle -from ..colors import ( +from .angles import Angle as _Angle +from .colors import ( Color as _Color, HWBColor as _HWBColor, SRGBColor as _SRGBColor, ) -from ..angles import ( +from .angles import ( DegreesAngle as _DegreesAngle, GradiansAngle as _GradiansAngle, RadiansAngle as _RadiansAngle, TurnsAngle as _TurnsAngle, ) -from ..errors import ColorExpressionSyntaxError as _ColorExpressionSyntaxError +from .errors import ColorExpressionSyntaxError as _ColorExpressionSyntaxError __all__ = [ 'ColorDecoder', 'MetaColorDecoder', @@ -76,7 +76,7 @@ def _issubclass(cls, types): except TypeError: pass else: - return any(_issubclass(cls, type_) for type_ in types) + return any(_issubclass(cls, type_) for type_ in types_iter) # We default on the base ``issubclass`` from here. @@ -93,6 +93,7 @@ def _isinstance(value, types): return _issubclass(type(value), types) + def _get_args(func) -> _Sequence[_Tuple[str, _Any, _Any]]: """ Get the arguments from a function in order to call it using optional or make an alias. @@ -156,6 +157,7 @@ def _make_function(func, name: str, args: _Optional[_Sequence[_Any]]): # * ``args_index``: a args index -> proxy index correspondance. args_spec = _get_args(func) + args_index: _List[_Optional[int]] if not args: args_index = list(range(len(args_spec))) @@ -166,7 +168,7 @@ def _make_function(func, name: str, args: _Optional[_Sequence[_Any]]): args_index = [None] * len(args_spec) proxy_args = [] - for proxy_index, arg in enumerate(args): + for proxy_index_i, arg in enumerate(args): try: index = args_names.index(arg) except ValueError: @@ -174,7 +176,7 @@ def _make_function(func, name: str, args: _Optional[_Sequence[_Any]]): f'{arg!r} is not an argument of the aliased function' ) - args_index[index] = proxy_index + args_index[index] = proxy_index_i proxy_args.append(args_spec[index]) # We want to check that no value without a default value was @@ -238,14 +240,14 @@ def _make_function(func, name: str, args: _Optional[_Sequence[_Any]]): else: yield aname - proxy_args = ', '.join(_iter_proxy_args(locals_, proxy_args)) - final_args = ', '.join(_iter_final_args(locals_, args_spec, args_index)) + proxy_args_s = ', '.join(_iter_proxy_args(locals_, proxy_args)) + final_args_s = ', '.join(_iter_final_args(locals_, args_spec, args_index)) keys = ', '.join(locals_.keys()) code = ( f'def __define_alias({keys}):\n' - f' def {name}({proxy_args}):\n' - f' return __func({final_args})\n' + f' def {name}({proxy_args_s}):\n' + f' return __func({final_args_s})\n' f' return {name}\n' '\n' f'__func = __define_alias({keys})\n' @@ -393,8 +395,8 @@ _colorexpressionpattern = _re.compile( def _get_color_tokens(string: str): """ Get color tokens. """ - start = 0 - was_call_end = False + start: int = 0 + was_call_end: bool = False while string: match = _colorexpressionpattern.match(string) @@ -465,14 +467,14 @@ def _get_color_tokens(string: str): rawtext=result['ncol'], ) elif result['hex'] is not None: - value = result['hex'] - if len(value) <= 4: - value = ''.join(map(lambda x: x + x, value)) + value_s = result['hex'] + if len(value_s) <= 4: + value_s = ''.join(map(lambda x: x + x, value_s)) - r = int(value[0:2], 16) - g = int(value[2:4], 16) - b = int(value[4:6], 16) - a = int(value[6:8], 16) / 255.0 if len(value) == 8 else 1.0 + r = int(value_s[0:2], 16) + g = int(value_s[2:4], 16) + b = int(value_s[4:6], 16) + a = int(value_s[6:8], 16) / 255.0 if len(value_s) == 8 else 1.0 yield _ColorExpressionToken( _ColorExpressionToken.TYPE_HEX, @@ -659,7 +661,7 @@ class ColorDecoder(_Mapping): # Parsing stage; the results will be in ``current``. - stack = [] + stack: _List[_List[_ColorExpressionToken]] = [] func_stack = [_ColorExpressionToken( _ColorExpressionToken.TYPE_NAME, value=None, diff --git a/thcolor/decoders/__init__.py b/thcolor/decoders/__init__.py deleted file mode 100644 index f2d1863..0000000 --- a/thcolor/decoders/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env python3 -# ***************************************************************************** -# Copyright (C) 2019-2022 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr> -# This file is part of the thcolor project, which is MIT-licensed. -# ***************************************************************************** -""" Function and data reference. """ - -from .base import ColorDecoder, MetaColorDecoder, alias, fallback -from .builtin import ( - CSS1ColorDecoder, CSS2ColorDecoder, CSS3ColorDecoder, - CSS4ColorDecoder, DefaultColorDecoder -) - -__all__ = [ - 'ColorDecoder', 'CSS1ColorDecoder', 'CSS2ColorDecoder', - 'CSS3ColorDecoder', 'CSS4ColorDecoder', 'DefaultColorDecoder', - 'MetaColorDecoder', 'alias', 'fallback', -] - -# End of file. |