aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Touhey <thomas@touhey.fr>2022-01-01 17:23:37 +0100
committerThomas Touhey <thomas@touhey.fr>2022-01-01 17:23:37 +0100
commitc2be6ab5f053b4a18c91a397173ac5704af848bd (patch)
tree9fa2af3f9fd156ef32e626e70fe8ee41668028c1
parent56adca4f8f7ca27f9549f6e2ecdbf4191e35af4b (diff)
Wrote more documentation
-rw-r--r--README.rst45
-rw-r--r--docs/Makefile5
-rw-r--r--docs/api.rst7
-rw-r--r--docs/api/angles.rst6
-rw-r--r--docs/api/builtin.rst16
-rw-r--r--docs/api/colors.rst39
-rw-r--r--docs/api/decoders.rst18
-rw-r--r--docs/api/errors.rst10
-rw-r--r--docs/conf.py11
-rw-r--r--docs/discuss.rst3
-rw-r--r--docs/discuss/color-expressions.rst58
-rw-r--r--docs/discuss/colors.rst138
-rw-r--r--docs/favicon.icobin0 -> 16958 bytes
-rw-r--r--docs/favicon.pngbin0 -> 8752 bytes
-rw-r--r--docs/guides.rst8
-rw-r--r--docs/guides/defining-decoders.rst217
-rw-r--r--docs/index.rst30
-rw-r--r--docs/onboarding.rst4
-rw-r--r--docs/onboarding/installing.rst17
-rw-r--r--docs/onboarding/trying.rst47
-rw-r--r--docs/onboarding/tweaking.rst16
-rw-r--r--docs/requirements.txt4
-rw-r--r--thcolor/builtin.py8
-rw-r--r--thcolor/colors.py24
-rw-r--r--thcolor/decoders.py32
-rwxr-xr-xthcolor/errors.py5
26 files changed, 638 insertions, 130 deletions
diff --git a/README.rst b/README.rst
index 0ced2f7..357b918 100644
--- a/README.rst
+++ b/README.rst
@@ -10,48 +10,11 @@ module. It provides the following features:
For more information, consult `the official website`_.
-Examples
---------
-
-Converting an RGB color to HSL:
-
-.. code-block:: python
-
- from thcolor.colors import SRGBColor
-
- color = SRGBColor.frombytes(55, 23, 224)
- print(color.ashsl())
-
-Converting a HSL color to RGB with an alpha value:
-
-.. code-block:: python
-
- from thcolor.colors import HSLColor
- from thcolor.angles import DegreesAngle
-
- color = HSLColor(DegreesAngle(180), 0.5, 1.0, 0.75)
- print(color.assrgb())
-
-Converting a textual representation to the RGBA color components:
-
-.. code-block:: python
-
- from thcolor.colors import Color
-
- color = Color.fromtext('darker(10%, hsl(0, 1, 50.0%))')
- print(color.assrgb())
-
-Getting the CSS color representations (with compatibility for earlier CSS
-versions) from a textual representation:
-
-.. code-block:: python
-
- from thcolor.colors import Color
-
- color = Color.fromtext('gray(red( #123456 )/0.2/)')
- for repres in color.css():
- print(f'color: {repres}')
+For getting started with the module, an onboarding is available on
+`the official documentation`_, as well as guides, discussion topics and
+references.
.. _Thomas Touhey: https://thomas.touhey.fr/
.. _textoutpc: https://textout.touhey.pro/
.. _the official website: https://thcolor.touhey.pro/
+.. _the official documentation: https://thcolor.touhey.pro/docs/
diff --git a/docs/Makefile b/docs/Makefile
index cd5fe80..26375a4 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -3,10 +3,9 @@
# You can set these variables from the command line.
-PE = pipenv run
SPHINXOPTS =
-SPHINXBUILD = $(PE) sphinx-build
-SPHINXWATCH = $(PE) sphinx-autobuild
+SPHINXBUILD = sphinx-build
+SPHINXWATCH = sphinx-autobuild
SOURCEDIR = .
BUILDDIR = _build
WEBROOT = hercule:thcolor/docs
diff --git a/docs/api.rst b/docs/api.rst
index 2ad7a43..3b41a3b 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -6,5 +6,8 @@ this part of the documentation is for you.
.. toctree::
- api/angles
- api/colors
+ api/errors
+ api/angles
+ api/colors
+ api/decoders
+ api/builtin
diff --git a/docs/api/angles.rst b/docs/api/angles.rst
index 609bb33..1525dfc 100644
--- a/docs/api/angles.rst
+++ b/docs/api/angles.rst
@@ -1,5 +1,5 @@
-Angles
-======
+Angles API
+==========
.. py:module:: thcolor.angles
@@ -7,7 +7,7 @@ Some color representations use angles as some of their properties. The base
class for angles is the following:
.. autoclass:: Angle
- :members: asdegrees, asgradians, asradians, asturns
+ :members: asdegrees, asgradians, asradians, asturns, fromtext
Subclasses are the following:
diff --git a/docs/api/builtin.rst b/docs/api/builtin.rst
new file mode 100644
index 0000000..68c92a5
--- /dev/null
+++ b/docs/api/builtin.rst
@@ -0,0 +1,16 @@
+Builtin API
+===========
+
+.. py:module:: thcolor.builtin
+
+The following color decoders are defined:
+
+.. autoclass:: CSS1ColorDecoder
+
+.. autoclass:: CSS2ColorDecoder
+
+.. autoclass:: CSS3ColorDecoder
+
+.. autoclass:: CSS4ColorDecoder
+
+.. autoclass:: DefaultColorDecoder
diff --git a/docs/api/colors.rst b/docs/api/colors.rst
index 937cd61..ddd1988 100644
--- a/docs/api/colors.rst
+++ b/docs/api/colors.rst
@@ -1,34 +1,43 @@
-Colors
-======
+Colors API
+==========
.. py:module:: thcolor.colors
The base class for colors is the following:
.. autoclass:: Color
- :members: alpha, assrgb, ashsl, ashwb, ascmyk, aslab, aslch, asxyz,
- replace, darker, lighter, desaturate, saturate,
- css, from_text
+ :members: alpha, assrgb, ashsl, ashsv, ashwb, ascmyk, aslab, aslch, asxyz,
+ asyiq, asyuv, fromtext, replace, darker, lighter, desaturate,
+ saturate, css
Subclasses are the following:
-.. autoclass:: SRGBColor
- :members: red, green, blue, alpha, frombytes, fromnetscapecolorname
+.. autoclass:: CMYKColor
+ :members: cyan, magenta, yellow, black, alpha
.. autoclass:: HSLColor
- :members: hue, saturation, lightness, alpha
+ :members: hue, saturation, lightness, alpha
-.. autoclass:: HWBColor
- :members: hue, whiteness, blackness, alpha
+.. autoclass:: HSVColor
+ :members: hue, saturation, value, alpha
-.. autoclass:: CMYKColor
- :members: cyan, magenta, yellow, black, alpha
+.. autoclass:: HWBColor
+ :members: hue, whiteness, blackness, alpha
.. autoclass:: LABColor
- :members: lightness, a, b, alpha
+ :members: lightness, a, b, alpha
.. autoclass:: LCHColor
- :members: lightness, chroma, hue, alpha
+ :members: lightness, chroma, hue, alpha
+
+.. autoclass:: SRGBColor
+ :members: red, green, blue, alpha, frombytes, fromnetscapecolorname
.. autoclass:: XYZColor
- :members: x, y, z, alpha
+ :members: x, y, z, alpha
+
+.. autoclass:: YIQColor
+ :members: y, i, q, alpha
+
+.. autoclass:: YUVColor
+ :members: y, u, v, alpha
diff --git a/docs/api/decoders.rst b/docs/api/decoders.rst
new file mode 100644
index 0000000..9825c8c
--- /dev/null
+++ b/docs/api/decoders.rst
@@ -0,0 +1,18 @@
+Decoders API
+============
+
+.. py:module:: thcolor.decoders
+
+The ``thcolor.decoders`` module defines base utilities for decoding color
+expressions.
+
+.. autoclass:: ColorDecoder
+ :members: decode
+
+For convenience, the following class is defined to define color decoders:
+
+.. autoclass:: MetaColorDecoder
+
+.. autoclass:: alias
+
+.. autofunction:: fallback
diff --git a/docs/api/errors.rst b/docs/api/errors.rst
new file mode 100644
index 0000000..11a8cdc
--- /dev/null
+++ b/docs/api/errors.rst
@@ -0,0 +1,10 @@
+Errors API
+==========
+
+.. py:module:: thcolor.errors
+
+In this section, are defined all non-standard errors that are raised by
+all submodules.
+
+.. autoclass:: ColorExpressionSyntaxError
+ :members: text, column, func
diff --git a/docs/conf.py b/docs/conf.py
index 22cfb36..9b6148e 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -30,9 +30,9 @@ author = 'Thomas Touhey'
def _get_release():
- from thcolor.version import _version
+ from thcolor.version import version
- return _version
+ return version
release = _get_release()
@@ -56,7 +56,9 @@ templates_path = []
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
-exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', '.goutput*']
+exclude_patterns = [
+ '_build', 'Thumbs.db', '.DS_Store', '.goutput*', 'requirements.txt',
+]
# -- Options for HTML output -------------------------------------------------
@@ -64,7 +66,8 @@ exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', '.goutput*']
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
-html_theme = 'sphinx_rtd_theme'
+html_theme = 'bizstyle'
+html_favicon = 'favicon.png'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
diff --git a/docs/discuss.rst b/docs/discuss.rst
index d7e2055..4e3a254 100644
--- a/docs/discuss.rst
+++ b/docs/discuss.rst
@@ -7,4 +7,5 @@ discussion topics in the following sections.
.. toctree::
- discuss/color-expressions
+ discuss/colors
+ discuss/color-expressions
diff --git a/docs/discuss/color-expressions.rst b/docs/discuss/color-expressions.rst
index 0109057..0bd3d89 100644
--- a/docs/discuss/color-expressions.rst
+++ b/docs/discuss/color-expressions.rst
@@ -1,15 +1,17 @@
.. _expr:
-Expressions
-===========
+Color expressions
+=================
One of the aims of thcolor was to decode text-based expressions
representing colors with possibilities challenging and even outdo
-CSS color expression possibilities. This is what the following static method
-is for:
+CSS color expression possibilities. In thcolor, these expressions are
+evaluated using :py:meth:`thcolor.decoders.ColorDecoder.decode`,
+:py:meth:`thcolor.colors.Color.fromtext` or
+:py:meth:`thcolor.angles.Angle.fromtext`.
-Expression concepts
--------------------
+Concepts
+--------
The goal of these expressions was to embrace and extend CSS syntax, so they
are basically either basic expressions or function calls, with the following
@@ -43,11 +45,45 @@ Here are some example calls:
hsl (0 1 50 % / 22)
gray ( red( #123456 )/0.2/)
-Defining a reference
---------------------
+.. _explain-decoders:
-Functions and color names are defined in a reference:
+Decoders
+--------
-.. todo::
+Decoders are the tools within thcolor that handle the actual evaluation of
+expressions. They have two important components aside from the decoding
+function:
- More about this.
+* Options defining the behaviour of base parsing and evaluating.
+* A reference of functions, colors and other data indexed by name.
+
+The options currently available are the following:
+
+* Whether natural colors are enabled or not; see :ref:`natural-colors`.
+* Whether extended hexadecimal colors, i.e. 4 or 8 digit hexadecimal digits
+ preceded with a '#' sign, which includes transparency, are enabled or not.
+* Whether names that are not found should be resolved using Netscape-like
+ color parsing or not, what is also known as "quirks mode".
+
+The reference contains three kinds of elements, all indexed by name:
+
+* Constants, always to be used as values, e.g. the ``navy`` color.
+* Functions, always to be used by calling them, e.g. the ``rgb`` function.
+* Functions with fallbacks, which have a behaviour when called and a fallback
+ value when used as a value, e.g. the ``red`` function in the extended
+ color decoder which extracts the red channel value as a function and acts
+ as the color ``red`` if used as a value.
+
+Decoders can be defined using two base classes which act in a very different
+way:
+
+* **The manual way.**
+ You can define a decoder manually by making it inherit from
+ :py:class:`thcolor.decoders.ColorDecoder` and overriding
+ ``__mapping__`` to define the reference, and other double-underscore
+ properties for options.
+* **The user-friendly way.**
+ You can define a decoder in an easier way by making it inherit from
+ :py:class:`thcolor.decoders.MetaColorDecoder` and defining options,
+ functions and data by defining them directly in the class body;
+ see :ref:`defining-decoders` for more information.
diff --git a/docs/discuss/colors.rst b/docs/discuss/colors.rst
new file mode 100644
index 0000000..fb5c20d
--- /dev/null
+++ b/docs/discuss/colors.rst
@@ -0,0 +1,138 @@
+Color representations
+=====================
+
+thcolor allows you to represent colors in different colorspaces and using
+different kind of coordinates. This page regroups the information about these
+representations.
+
+Note that all color representations have an ``alpha`` component.
+
+sRGB colors
+-----------
+
+sRGB colors are colors represented using the red, green and blue channel
+intensities in the `standard RGB color space`_.
+
+In thcolor, such a color is represented by the
+:py:class:`thcolor.colors.SRGBColor` class, and other representations can be
+converted to this one using the :py:meth:`thcolor.colors.Color.assrgb`
+("as sRGB") method.
+
+CMYK colors
+-----------
+
+CMYK colors are colors represented using the cyan, magenta, yellow and
+black values in the `CMYK color model`_.
+
+In thcolor, such a color is represented by the
+:py:class:`thcolor.colors.CMYKColor` class, and other representations can be
+converted to this one using the :py:meth:`thcolor.colors.Color.ascmyk` method.
+
+HSL colors
+----------
+
+HSL colors are colors represented using the hue, saturation and lightness
+as polar coordinates in the sRGB color space. See `HSL and HSV`_ for more
+information.
+
+In thcolor, such a color is represented by the
+:py:class:`thcolor.colors.HSLColor` class, and other representations can be
+converted to this one using the :py:meth:`thcolor.colors.Color.ashsl` method.
+
+HSV colors
+----------
+
+HSV colors are colors represented using the hue, saturation and value
+as polar coordinates in the sRGB color space. See `HSL and HSV`_ for
+more information.
+
+In thcolor, such a color is represented by the
+:py:class:`thcolor.colors.HSVColor` class, and other representations can be
+converted to this one using the :py:meth:`thcolor.colors.Color.ashsv` method.
+
+.. _hwb-colors:
+
+HWB colors
+----------
+
+HWB colors are colors represented using the hue, whiteness and blackness
+in the `HWB color model`_.
+
+In thcolor, such a color is represented by the
+:py:class:`thcolor.colors.HWBColor` class, and other representations can be
+converted to this one using the :py:meth:`thcolor.colors.Color.ashwb` method.
+
+LAB colors
+----------
+
+LAB colors are colors represented using the lightness and A and B coordinates
+in the `CIELAB color space`_.
+
+In thcolor, such a color is represented by the
+:py:class:`thcolor.colors.LABColor` class, and other representations can be
+converted to this one using the :py:meth:`thcolor.colors.Color.aslab` method.
+
+LCH colors
+----------
+
+LCH colors are colors represented using the lightness, chroma and hue
+in the `CIELAB color space`_.
+
+In thcolor, such a color is represented by the
+:py:class:`thcolor.colors.LCHColor` class, and other representations can be
+converted to this one using the :py:meth:`thcolor.colors.Color.aslch` method.
+
+XYZ colors
+----------
+
+XYZ colors are colors represented using its x, y and z coordinates
+in the `CIE 1931 XYZ color space`_.
+
+In thcolor, such a color is represented by the
+:py:class:`thcolor.colors.XYZColor` class, and other representations can be
+converted to this one using the :py:meth:`thcolor.colors.Color.asxyz`
+method.
+
+YIQ colors
+----------
+
+YIQ colors are colors represented using its coordinates in the
+`YIQ color space`_.
+
+In thcolor, such a color is represented by the
+:py:class:`thcolor.colors.YIQColor` class, and other representations can be
+converted to this one using the :py:meth:`thcolor.colors.Color.asyiq` method.
+
+YUV colors
+----------
+
+YUV colors are colors represented using its coordinates in the
+`YUV color space`_.
+
+In thcolor, such a color is represented by the
+:py:class:`thcolor.colors.YUVColor` class, and other representations can be
+converted to this one using the :py:meth:`thcolor.colors.Color.asyuv`
+method.
+
+.. _natural-colors:
+
+Natural colors
+--------------
+
+Natural colors (NCol) are an initiative from W3Schools to make a color
+that is easily identifiable from reading its definition.
+
+In thcolor, no dedicated class exists for this representation since it is
+a light derivative from :ref:`HWB colors <hwb-colors>` with the angle
+expressed using a given format. It is, however, optionally supported
+in expressions behind the ``__ncol_support__`` option.
+
+.. _standard RGB color space: https://en.wikipedia.org/wiki/SRGB
+.. _CMYK color model: https://en.wikipedia.org/wiki/CMYK_color_model
+.. _HSL and HSV: https://en.wikipedia.org/wiki/HSL_and_HSV
+.. _HWB color model: https://en.wikipedia.org/wiki/HWB_color_model
+.. _CIELAB color space: https://en.wikipedia.org/wiki/CIELAB_color_space
+.. _CIE 1931 XYZ color space: https://en.wikipedia.org/wiki/CIE_1931_color_space
+.. _YIQ color space: https://en.wikipedia.org/wiki/YIQ
+.. _YUV color space: https://en.wikipedia.org/wiki/YUV
+.. _`natural colors`: https://www.w3schools.com/colors/colors_ncol.asp
diff --git a/docs/favicon.ico b/docs/favicon.ico
new file mode 100644
index 0000000..2946f11
--- /dev/null
+++ b/docs/favicon.ico
Binary files differ
diff --git a/docs/favicon.png b/docs/favicon.png
new file mode 100644
index 0000000..4ebff7a
--- /dev/null
+++ b/docs/favicon.png
Binary files differ
diff --git a/docs/guides.rst b/docs/guides.rst
new file mode 100644
index 0000000..8f5a931
--- /dev/null
+++ b/docs/guides.rst
@@ -0,0 +1,8 @@
+Guides
+======
+
+This section consists of multiple guides for solving specific problems.
+
+.. toctree::
+
+ guides/defining-decoders
diff --git a/docs/guides/defining-decoders.rst b/docs/guides/defining-decoders.rst
new file mode 100644
index 0000000..51bab99
--- /dev/null
+++ b/docs/guides/defining-decoders.rst
@@ -0,0 +1,217 @@
+.. _defining-decoders:
+
+Defining a decoder
+==================
+
+The goal of this guide is to bootstrap you into making your own color decoder
+using tools from thcolor. For clarity, you should first read :ref:`expr`,
+especially the :ref:`explain-decoders` section.
+
+For this guide, we will want to do the following:
+
+* Create our ``TutorialColorDecoder`` with extended hexadecimal color
+ support.
+* Create a ``sum`` function which can take 2 to 5 numbers and sum them.
+* Create a ``diff`` function which takes 2 numbers and return the first one
+ minus the second one.
+* Create a ``reverse_diff`` which takes 2 numbers and return the second one
+ minus the first one.
+* Create an ``transparent`` function which returns the alpha value
+ as a byte between 0 and 255, and returns the transparent color when
+ used as a value.
+* Create a ``awesome-color`` constant which evaluates as blue.
+
+Setting up the framework
+------------------------
+
+First of, the elements you will want to import are the following:
+
+* :py:class:`thcolor.decoders.MetaColorDecoder`, which will be the base
+ class your decoder will inherit from.
+* :py:class:`thcolor.decoders.alias`, which will be useful when you want to
+ define an alias for an existing function without doing it manually.
+* :py:class:`thcolor.decoders.fallback`, which will be useful when you want
+ to define a fallback value for a given function.
+* Colors we might want to use from :py:mod:`thcolor.colors`.
+* Angles we might want to use from :py:mod:`thcolor.angles`.
+
+For our exercise, we are going to use :py:class:`thcolor.colors.SRGBColor`
+and no angles.
+
+Our base code is the following:
+
+.. code-block:: python
+
+ from thcolor.decoders import MetaColorDecoder, alias, fallback
+ from thcolor.colors import Color, SRGBColor
+
+ __all__ = ['TutorialColorDecoder']
+
+ class TutorialColorDecoder(MetaColorDecoder):
+ pass
+
+As we want extended hexadecimal colors to be read as well, we need to define
+the corresponding option. As described in
+:py:class:`thcolor.decoders.ColorDecoder`, the option for doing this is
+``__extended_hex_support__``, which gives the following class definition:
+
+.. code-block::
+
+ class TutorialColorDecoder(MetaColorDecoder):
+ __extended_hex_support__ = True
+
+Defining the ``sum`` function
+-----------------------------
+
+As described in the constraints, the ``sum`` function will sum 2 to 5
+numbers; the type of these numbers is not given, so we have three options:
+
+* If the hint on these numbers is ``int``, only integers will be accepted
+ by the function, and floats with decimal parts will throw an error.
+* If the hint on these numbers is ``float``, integers will be converted
+ to ``float`` before being passed on to the function.
+* If the hint on these numbers is ``typing.Union[int, float]``, the
+ function will receive both depending on what the syntax was in the
+ original expression.
+
+Here, for simplicity, we choose to use ``float``. The resulting code is
+the following:
+
+.. code-block::
+
+ class TutorialColorDecoder(MetaColorDecoder):
+ # ...
+
+ def sum(
+ a: float, b: float, c: float = 0,
+ d: float = 0, e: float = 0,
+ ) -> float:
+ return a + b + c + d + e
+
+Defining the ``diff`` and ``reverse_diff`` functions
+----------------------------------------------------
+
+As described in the constraints, the ``diff`` function will compute the
+difference between two numbers. Based on what we've learned in the previous
+function, we can do the following:
+
+.. code-block::
+
+ class TutorialColorDecoder(MetaColorDecoder):
+ # ...
+
+ def diff(a: float, b: float) -> float:
+ return a - b
+
+Now for the ``reverse_diff`` function, we could define it independently,
+but in order to save time, we will use :py:class:`thcolor.decoders.alias`.
+This function takes the following arguments:
+
+* The name of the function to alias.
+* The new order of the arguments, by name.
+
+Based on this information, the :py:class:`thcolor.decoders.MetaColorDecoder`
+will create the function out of the previous function (by calling it) and
+take all related annotations and default values (if possible and available).
+
+For our current case, we can define our function the following way:
+
+.. code-block::
+
+ class TutorialColorDecoder(MetaColorDecoder):
+ # ...
+
+ reverse_diff = alias('diff', args=('b', 'a'))
+
+Note that aliases can be defined anywhere within the class, even before
+the aliased function.
+
+Defining the ``transparent`` function with a fallback value
+-----------------------------------------------------------
+
+For the ``transparent`` function, we will get the alpha value, multiply it
+by 255 and round it to the nearest integer. However, how do we add a fallback
+value for the function? :py:class:`thcolor.decoders.fallback` comes to
+our rescue!
+
+Once our function is defined, we use :py:class:`thcolor.decoders.fallback`
+as a decorator by giving it the value the function should fall back on when
+used as a constant.
+
+The resulting code is the following:
+
+.. code-block::
+
+ class TutorialColorDecoder(MetaColorDecoder):
+ # ...
+
+ @fallback(SRGBColor(0, 0, 0, 0.0))
+ def transparent(color: Color) -> int:
+ return int(round(color.alpha * 255))
+
+Defining the ``awesome-color`` constant
+---------------------------------------
+
+For defining a constant, we can use affectations, as for aliases.
+But how do we define names with carets when they are illegal in Python names?
+We can replace it with ``_``; the color decoders in thcolor are not only
+case-insensitive, they also treat carets and underscores the same.
+
+We can thus do the following:
+
+.. code-block::
+
+ class TutorialColorDecoder(MetaColorDecoder):
+ # ...
+
+ awesome_color = SRGBColor.frombytes(0, 0, 255)
+
+Testing the resulting class
+---------------------------
+
+Putting all of our efforts together, we should have the following code:
+
+.. code-block:: python
+
+ from thcolor.decoders import MetaColorDecoder, alias, fallback
+ from thcolor.colors import Color, SRGBColor
+
+ __all__ = ['TutorialColorDecoder']
+
+ class TutorialColorDecoder(MetaColorDecoder):
+ __extended_hex_support__ = True
+
+ def sum(
+ a: float, b: float, c: float = 0,
+ d: float = 0, e: float = 0,
+ ) -> float:
+ return a + b + c + d + e
+
+ def diff(a: float, b: float) -> float:
+ return a - b
+
+ reverse_diff = alias('diff', args=('b', 'a'))
+
+ @fallback(SRGBColor(0, 0, 0, 0.0))
+ def transparent(color: Color) -> int:
+ return int(round(color.alpha * 255))
+
+ awesome_color = SRGBColor.frombytes(0, 0, 255)
+
+Now that our class is defined, we can instanciate and test our decoder:
+
+.. code-block:: python
+
+ decoder = TutorialColorDecoder()
+ results = decoder.decode(
+ 'awesome-color '
+ 'sum(sum(1, 2, 3, 4), reverse_diff(transparent(transparent), 4))',
+ )
+
+ print(results)
+
+And the result we obtain are the following:
+
+::
+
+ (SRGBColor(red=0.0, green=0.0, blue=1.0, alpha=1.0), 14.0)
diff --git a/docs/index.rst b/docs/index.rst
index 50b5c57..a7089eb 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -1,22 +1,38 @@
Welcome to thcolor's documentation!
===================================
-This module is a color management module made by `Thomas Touhey`_ (``th``
-is for ``touhey``) for the `textoutpc`_ project, a BBCode to HTML translation
-module. It provides the following features:
+thcolor is a color management module made by `Thomas Touhey`_
+(``th`` is for ``touhey``).
- * Color management and conversions between formats (RGB, HSL, HWB, NCol, …).
- * Text-to-color using a format close to CSS.
+It was originally made for the `textoutpc`_ project, a BBCode to HTML
+translation module.
-For more information and links, consult `the official website`_.
+thcolor allows you to:
+
+* Represent colors using various colorspaces and coordinates.
+* Convert between these representations.
+* Parse colors and related elements using expressions inspired by (and
+ compatible with given the right options) CSS standards by the W3C.
+* Make CSS expressions out of given color representations.
+
+For more information, you can consult:
+
+* The project homepage at `thcolor.touhey.pro`_.
+* The PyPI project page at `pypi.org`_.
+* The source at `forge.touhey.org`_.
+
+The documentation contents is the following:
.. toctree::
:maxdepth: 2
onboarding
+ guides
discuss
api
.. _Thomas Touhey: https://thomas.touhey.fr/
.. _textoutpc: https://textout.touhey.pro/
-.. _the official website: https://thcolor.touhey.pro/
+.. _thcolor.touhey.pro: https://thcolor.touhey.pro/
+.. _pypi.org: https://pypi.org/project/thcolor/
+.. _forge.touhey.org: https://forge.touhey.org/thcolor.git/
diff --git a/docs/onboarding.rst b/docs/onboarding.rst
index 412df44..fb28fe0 100644
--- a/docs/onboarding.rst
+++ b/docs/onboarding.rst
@@ -8,5 +8,5 @@ thcolor to better suit your needs.
.. toctree::
- onboarding/installing
- onboarding/tweaking
+ onboarding/installing
+ onboarding/trying
diff --git a/docs/onboarding/installing.rst b/docs/onboarding/installing.rst
index 4fee3ca..3677dcf 100644
--- a/docs/onboarding/installing.rst
+++ b/docs/onboarding/installing.rst
@@ -4,14 +4,6 @@ Installing thcolor
In order to run and tweak thcolor, you must first install it; this section
will cover the need.
-Dependencies
-------------
-
-thcolor dependencies are pure Python dependencies, automatically installed
-when using a package manager such as pip:
-
- * regex_, used for parsing color expressions.
-
Installing thcolor using pip
----------------------------
@@ -32,4 +24,13 @@ Some notes on this command:
* On Microsoft Windows, the Python executable, when added to the PATH,
goes by the name ``py`` instead of ``python``.
+Installing thcolor from source
+------------------------------
+
+To install thcolor from source, you can use the following commands:
+
+.. code-block:: sh
+
+ python ./setup.py install --system # or --user
+
.. _regex: https://pypi.org/project/regex/
diff --git a/docs/onboarding/trying.rst b/docs/onboarding/trying.rst
new file mode 100644
index 0000000..85ac502
--- /dev/null
+++ b/docs/onboarding/trying.rst
@@ -0,0 +1,47 @@
+Trying out thcolor
+==================
+
+Once thcolor is installed, it is time to put it to the test!
+Here are a few use cases for the library.
+
+Converting an RGB color to HSL:
+
+.. code-block:: python
+
+ from thcolor.colors import SRGBColor
+
+ color = SRGBColor.frombytes(55, 23, 224)
+ print(color.ashsl())
+
+Converting a HSL color to RGB with an alpha value:
+
+.. code-block:: python
+
+ from thcolor.colors import HSLColor
+ from thcolor.angles import DegreesAngle
+
+ color = HSLColor(DegreesAngle(180), 0.5, 1.0, 0.75)
+ print(color.assrgb())
+
+Converting a textual representation to the RGBA color components:
+
+.. code-block:: python
+
+ from thcolor.colors import Color
+
+ color = Color.fromtext('darker(10%, hsl(0, 1, 50.0%))')
+ print(color.assrgb())
+
+Getting the CSS color representations (with compatibility for earlier CSS
+versions) from a textual representation:
+
+.. code-block:: python
+
+ from thcolor.colors import Color
+
+ color = Color.fromtext('gray(red( #123456 )/0.2/)')
+ for repres in color.css():
+ print(f'color: {repres}')
+
+For more information, please consult the guides, discussion topics and
+API reference on the current documentation.
diff --git a/docs/onboarding/tweaking.rst b/docs/onboarding/tweaking.rst
deleted file mode 100644
index 9ad9ab2..0000000
--- a/docs/onboarding/tweaking.rst
+++ /dev/null
@@ -1,16 +0,0 @@
-Tweaking thcolor
-================
-
-In order to start tweaking thcolor using Python instead of the CLI, you
-can import utilities from the module. The minimal code for running the
-server is the following:
-
-.. code-block:: python
-
- from thcolor import Color
-
- color = Color.from_text('darker(#123456 10%)')
- print(color)
-
-For more information, please consult the discussion topics and API reference
-on the current documentation.
diff --git a/docs/requirements.txt b/docs/requirements.txt
new file mode 100644
index 0000000..bf6bf6c
--- /dev/null
+++ b/docs/requirements.txt
@@ -0,0 +1,4 @@
+sphinx
+sphinx-autobuild
+sphinx_autodoc_typehints
+sphinx_rtd_theme
diff --git a/thcolor/builtin.py b/thcolor/builtin.py
index 5cf1646..e5191c7 100644
--- a/thcolor/builtin.py
+++ b/thcolor/builtin.py
@@ -36,7 +36,7 @@ _number = _Union[int, float]
class CSS1ColorDecoder(_MetaColorDecoder):
""" Named colors from CSS Level 1.
- See <https://www.w3.org/TR/CSS1/>_ for more information.
+ See `<https://www.w3.org/TR/CSS1/>`_ for more information.
"""
black = _rgb('#000000')
@@ -73,7 +73,7 @@ class CSS1ColorDecoder(_MetaColorDecoder):
class CSS2ColorDecoder(CSS1ColorDecoder):
""" Named colors from CSS Level 2 (Revision 1).
- See <https://www.w3.org/TR/CSS2/>_ for more information.
+ See `<https://www.w3.org/TR/CSS2/>`_ for more information.
"""
orange = _rgb('#ffa500')
@@ -82,7 +82,7 @@ class CSS2ColorDecoder(CSS1ColorDecoder):
class CSS3ColorDecoder(CSS2ColorDecoder):
""" Named colors and functions from CSS Color Module Level 3.
- See <https://drafts.csswg.org/css-color-3/>_ for more information.
+ See `<https://drafts.csswg.org/css-color-3/>`_ for more information.
"""
darkblue = _rgb('#00008B')
@@ -253,7 +253,7 @@ class CSS3ColorDecoder(CSS2ColorDecoder):
class CSS4ColorDecoder(CSS3ColorDecoder):
""" Named colors and functions from CSS Color Module Level 4.
- See <https://drafts.csswg.org/css-color/>_ for more information..
+ See `<https://drafts.csswg.org/css-color/>`_ for more information..
"""
__extended_hex_support__ = True
diff --git a/thcolor/colors.py b/thcolor/colors.py
index c0a59c4..e6c924e 100644
--- a/thcolor/colors.py
+++ b/thcolor/colors.py
@@ -36,6 +36,14 @@ class Color:
def __init__(self, alpha: float = 1.0):
super().__init__()
+ try:
+ alpha = float(alpha)
+ except (TypeError, ValueError):
+ raise ValueError(f'alpha should be a float, is {alpha!r}')
+ else:
+ if alpha < 0 or alpha > 1:
+ raise ValueError('alpha should be between 0.0 and 1.0')
+
self._alpha = alpha
def __repr__(self):
@@ -155,22 +163,22 @@ class 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.
+ """ Get the color with the given properties replaced.
For changing the alpha on an RGB color:
.. code-block:: python
- color = _RGBColor(1, 2, 3).replace(alpha=.5)
+ >>> SRGBColor(.1, .2, .3).replace(alpha=.5)
+ ... SRGBColor(red=0.1, green=0.2, blue=0.3, alpha=0.5)
For changing the lightness on an HSL color:
- .. code-block:: python
+ .. code-block:: pycon
- angle = _DegreesAngle(270)
- color = _HSLColor(angle, .5, 1).replace(lightness=.2)
+ >>> HSLColor(DegreesAngle(270), .5, 1).replace(lightness=.2)
+ ... HSLColor(hue=DegreesAngle(degrees=270.0), saturation=0.5,
+ ... lightness=0.2, alpha=1.0)
:param properties: Properties to change from the original
color.
@@ -238,7 +246,7 @@ class Color:
For example:
- >>> SRGBColor(18, 52, 86, 0.82).css()
+ >>> SRGBColor.frombytes(18, 52, 86, 0.82).css()
... ("#123456", "rgba(18, 52, 86, 82%)")
"""
diff --git a/thcolor/decoders.py b/thcolor/decoders.py
index 4092007..0e9d850 100644
--- a/thcolor/decoders.py
+++ b/thcolor/decoders.py
@@ -1005,6 +1005,17 @@ class ColorDecoder(_Mapping):
and isinstance(arg, (int, float))
):
arg = _DegreesAngle(arg)
+ elif (
+ _issubclass(float, argtype)
+ and isinstance(arg, int)
+ ):
+ arg = float(arg)
+ elif (
+ _issubclass(int, argtype)
+ and isinstance(arg, float)
+ and arg == int(arg)
+ ):
+ arg = int(arg)
else:
raise _ColorExpressionSyntaxError(
f'{arg!r} did not match expected type {argtype!r}'
@@ -1203,7 +1214,22 @@ class _MetaColorDecoderType(_ABCMeta):
if argdefvalue is _NO_DEFAULT_VALUE:
continue
- if not _isinstance(argdefvalue, argtype):
+ if (
+ not _isinstance(argdefvalue, argtype)
+ and not (
+ isinstance(argdefvalue, int)
+ and _issubclass(float, argtype)
+ )
+ and not (
+ isinstance(argdefvalue, float)
+ and int(argdefvalue) == argdefvalue
+ and _issubclass(int, argtype)
+ )
+ and not (
+ isinstance(argdefvalue, (int, float))
+ and _issubclass(_Angle, argtype)
+ )
+ ):
raise TypeError(
f'function {key!r}, argument {argname!r}: '
f'default value {argdefvalue!r} is not a valid '
@@ -1216,9 +1242,7 @@ class _MetaColorDecoderType(_ABCMeta):
class MetaColorDecoder(ColorDecoder, metaclass=_MetaColorDecoderType):
""" Base meta color decoder, which gets the function and things. """
- __ncol_support__ = False
- __extended_hex_support__ = False
- __defaults_to_netscape_color__ = True
+ pass
# End of file.
diff --git a/thcolor/errors.py b/thcolor/errors.py
index 3fa71c0..37bf337 100755
--- a/thcolor/errors.py
+++ b/thcolor/errors.py
@@ -11,7 +11,10 @@ __all__ = [
class ColorExpressionSyntaxError(Exception):
- """ A color decoding error has occurred on the text. """
+ """ An error has occurred while decoding a color expression.
+
+ Such an error can happen during parsing or evaluating.
+ """
def __init__(self, text, column=None, func=None):
self._column = column if column is not None and column >= 0 else None