Skip to content

Commit

Permalink
Add first draft of names() function (refs #20).
Browse files Browse the repository at this point in the history
  • Loading branch information
ubernostrum committed Aug 7, 2024
1 parent bb87686 commit dee9d46
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 4 deletions.
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ repos:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/psf/black
rev: 24.4.2
rev: 24.8.0
hooks:
- id: black
language_version: python3.8
name: black (Python formatter)
- repo: https://github.com/pycqa/flake8
rev: 7.0.0
rev: 7.1.1
hooks:
- id: flake8
name: flake8 (Python linter)
Expand Down
11 changes: 11 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,17 @@ The API stability/deprecation policy for this library is as follows:
Releases under CalVer
---------------------

Version 24.8.0
~~~~~~~~~~~~~~

*Under development*

* Added the :func:`~webcolors.names` function to allow retrieving lists of
color names. The underlying mappings of color names/values still are not
supported API; to obtain the color value corresponding to a name, use the
appropriate conversion function.


Version 24.6.0
~~~~~~~~~~~~~~

Expand Down
7 changes: 7 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"""

import doctest
import sys
from importlib.metadata import version as get_version

Expand Down Expand Up @@ -50,6 +51,12 @@

# Doctest configuration.
doctest_global_setup = "from webcolors import *"
doctest_default_flags = (
doctest.DONT_ACCEPT_TRUE_FOR_1
| doctest.ELLIPSIS
| doctest.IGNORE_EXCEPTION_DETAIL
| doctest.NORMALIZE_WHITESPACE
)

# OGP metadata configuration.
ogp_enable_meta_description = True
Expand Down
6 changes: 6 additions & 0 deletions docs/contents.rst
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ specifications.
Represents the HTML 4 specification. Value is ``"html4"``.


Informative functions
---------------------

.. autofunction:: names


Normalization functions
-----------------------

Expand Down
23 changes: 23 additions & 0 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,29 @@ def docs_spellcheck(session: nox.Session) -> None:
clean()


@nox.session(python=["3.11"], tags=["docs", "tests"])
def docs_test(session: nox.Session) -> None:
"""
Run the code samples in the documentation with doctest, to ensure they are
correct.
"""
session.install(".[docs]")
session.run(
f"python{session.python}",
"-Im",
"sphinx",
"-c",
"docs/",
"-b",
"doctest",
"-d",
"docs/_build/doctrees/html",
"docs/",
"docs/_build/html",
)


# Code formatting checks.
#
# These checks do *not* reformat code -- that happens in pre-commit hooks -- but will
Expand Down
5 changes: 3 additions & 2 deletions src/webcolors/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
rgb_to_name,
rgb_to_rgb_percent,
)
from ._definitions import CSS2, CSS3, CSS21, HTML4
from ._definitions import CSS2, CSS3, CSS21, HTML4, names
from ._html5 import (
html5_parse_legacy_color,
html5_parse_simple_color,
Expand All @@ -36,7 +36,7 @@
)
from ._types import HTML5SimpleColor, IntegerRGB, IntTuple, PercentRGB, PercentTuple

__version__ = "24.6.0"
__version__ = "24.8.0a1"

__all__ = [
"HTML4",
Expand All @@ -49,6 +49,7 @@
"hex_to_name",
"hex_to_rgb",
"hex_to_rgb_percent",
"names",
"rgb_to_hex",
"rgb_to_name",
"rgb_to_rgb_percent",
Expand Down
41 changes: 41 additions & 0 deletions src/webcolors/_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
# SPDX-License-Identifier: BSD-3-Clause

import re
from typing import List


def _reversedict(dict_to_reverse: dict) -> dict:
Expand Down Expand Up @@ -299,3 +300,43 @@ def _get_hex_to_name_map(spec: str):
if spec not in _SUPPORTED_SPECIFICATIONS:
raise ValueError(_SPECIFICATION_ERROR_TEMPLATE.format(spec=spec))
return _hex_to_names[spec]


def names(spec: str = CSS3) -> List[str]:
"""
Return the list of valid color names for the given specification.
The color names will be normalized to all-lowercase, and will be returned in
alphabetical order.
.. note:: **Spelling variants**
Some values representing named gray colors can map to either of two names in
CSS3, because it supports both ``"gray"`` and ``"grey"`` spelling variants for
those colors. Functions which produce a name from a color value in other formats
all normalize to the ``"gray"`` spelling for consistency with earlier CSS and
HTML specifications which only supported ``"gray"``. Here, however, *all* valid
names are returned, including -- for CSS3 -- both variant spellings for each of
the affected ``"gray"``/``"grey"`` colors.
Examples:
.. doctest::
>>> names(spec=HTML4)
['aqua', 'black', 'blue', 'fuchsia', 'gray', 'green',
'lime', 'maroon', 'navy', 'olive', 'purple', 'red',
'silver', 'teal', 'white', 'yellow']
>>> names(spec="CSS1")
Traceback (most recent call last):
...
ValueError: "CSS1" is not a supported specification ...
:raises ValueError: when the given spec is not supported.
"""
if spec not in _SUPPORTED_SPECIFICATIONS:
raise ValueError(_SPECIFICATION_ERROR_TEMPLATE.format(spec=spec))
mapping = _names_to_hex[spec]
return list(sorted(mapping.keys()))
24 changes: 24 additions & 0 deletions tests/test_conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -411,3 +411,27 @@ def test_spelling_variants(self):
(webcolors.rgb_percent_to_name, percent_tuple),
):
assert name == converter(value, spec=webcolors.CSS3)

def test_names_valid(self):
"""
names() correctly returns the set of names for a given spec.
"""
for spec, mapping in (
(webcolors.HTML4, webcolors._definitions._HTML4_NAMES_TO_HEX),
(webcolors.CSS2, webcolors._definitions._CSS2_NAMES_TO_HEX),
(webcolors.CSS21, webcolors._definitions._CSS21_NAMES_TO_HEX),
(webcolors.CSS3, webcolors._definitions._CSS3_NAMES_TO_HEX),
):
with self.subTest(spec=spec):
assert webcolors.names(spec) == list(sorted(mapping.keys()))

def test_names_invalid(self):
"""
names() raises ValueError when asked for an unsupported spec.
"""
for spec in ("CSS0", "HTML12", "random"):
with self.subTest(spec=spec):
with self.assertRaises(ValueError):
webcolors.names(spec)

0 comments on commit dee9d46

Please sign in to comment.