aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Touhey <thomas@touhey.fr>2021-12-31 22:09:03 +0100
committerThomas Touhey <thomas@touhey.fr>2021-12-31 22:09:03 +0100
commitbbef529d1b7c52f09be399ca27f86d36d1267d50 (patch)
tree32a1fe655e63ceb3e15770b5d172edf83ae3a2fd
parentf7ebc55d149a600ab0d5bdbdb0d3693f394c8d89 (diff)
Reorganized the module to have one level and static type checked
-rw-r--r--setup.cfg2
-rwxr-xr-xtests/test_decoders.py1
-rw-r--r--thcolor/angles.py10
-rw-r--r--thcolor/builtin.py (renamed from thcolor/decoders/builtin.py)6
-rw-r--r--thcolor/colors.py29
-rw-r--r--thcolor/decoders.py (renamed from thcolor/decoders/base.py)46
-rw-r--r--thcolor/decoders/__init__.py20
7 files changed, 50 insertions, 64 deletions
diff --git a/setup.cfg b/setup.cfg
index 7b78c03..6211e52 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -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.