webcolors-1.5/ 0000755 0000767 0000767 00000000000 12502171014 012565 5 ustar james 0000000 0000000 webcolors-1.5/docs/ 0000755 0000767 0000767 00000000000 12502171014 013515 5 ustar james 0000000 0000000 webcolors-1.5/docs/colors.rst 0000644 0000767 0000767 00000016574 12427605447 015607 0 ustar james 0000000 0000000 .. _colors:
An overview of colors on the Web
================================
Colors on the Web are typically specified in `the sRGB color space`_,
where each color is made up of a red component, a green component and
a blue component. This maps to the red, green and blue components of
the pixels on a computer display, and to the three sets of cone cells
in the human eye, which respond to (roughly) the wavelengths of light
associated with red, green and blue.
On the Web, sRGB colors are specified in formats which describe the
color as a 24-bit integer, where the first 8 bits provide the red
value, the second 8 bits the green value and the final 8 bits the blue
value. This gives a total space of 256 * 256 * 256 or 16,777,216
unique colors, though due to differences in display technology not all
of these colors may be clearly distinguishable on any given physical
display.
HTML 4
------
HTML 4 defined `two ways to specify sRGB colors`_:
* The character ``#`` followed by three pairs of hexdecimal digits,
specifying values for red, green and blue components in that order;
for example, ``#0099cc``.
* A set of predefined color names which correspond to specific
hexadecimal values; for example, ``blue``. HTML 4 defines sixteen
such colors.
CSS 1
-----
In `its description of color units`_, CSS 1 added
three new ways to specify sRGB colors:
* The character ``#`` followed by three hexadecimal digits, which is
expanded into three hexadecimal pairs by repeating each digit; thus
``#09c`` is equivalent to ``#0099cc``.
* The string ``rgb``, followed by parentheses, between which are three
base-10 integers in the range 0..255, which are taken
to be the values of the red, green and blue components in that
order; for example, ``rgb(0, 153, 204)``.
* The same as above, except using percentages instead of numeric
values; for example, ``rgb(0%, 60%, 80%)``.
CSS 1 also suggested a set of sixteen color names. These names were
identical to the set defined in HTML 4, but CSS 1 did not provide
definitions of their values and stated that they were taken from "the
Windows VGA palette".
CSS 2
-----
In its `section on colors`_, CSS 2 allowed the same methods of
specifying colors as CSS 1, and defined and provided values for
sixteen named colors, identical to the set found in HTML 4.
CSS 2 also specified `a list of names of system colors`_. These had no
fixed color values, but would take on values from the operating system
or other user interface, and allowed elements to be styled using the
same colors as the surrounding user interface. These names are
deprecated as of CSS 3.
The CSS 2.1 revision did not add any new methods of specifying sRGB
colors, but did define `one additional named color`_: ``orange``.
CSS 3
-----
`The CSS 3 color module`_ adds one new way to specify colors:
* A hue-saturation-lightness triplet (HSL), using the construct
``hsl()``.
CSS 3 also adds support for variable opacity of colors, by allowing
the specification of alpha-channel information through the ``rgba()``
and ``hsla()`` constructs. These are used similarly to the ``rgb()``
and ``hsl()`` constructs, except a fourth value is supplied indicating
the level of opacity from ``0.0`` (completely transparent) to ``1.0``
(completely opaque). Though not technically a color, the keyword
``transparent`` is also made available in lieu of a color value, and
corresponds to ``rgba(0,0,0,0)``.
CSS 3 also defines a new set of 147 color names. This set is taken
directly from `the named colors defined for SVG (Scalable Vector
Graphics)`_ markup, and is a superset of the named colors defined in
CSS 2.1.
HTML5
-----
HTML5 exists in two forms: a living document maintained by WHATWG, and
a W3C Recommendation. The two HTML5 documents, as of this writing,
share a common definition of color values and parsing, and formalize
the parsing and serialization of colors according to prior standards
and real-world implementations in Web browsers.
HTML5 does not introduce any new methods of specifying colors, but
does simplify the description of colors and introduce useful
terminology.
* A set of three 8-bit numbers representing the red, blue and green
components of an sRGB color is termed a "simple color".
* A seven-character string which begins with the character ``#``,
followed by six ASCII hex digits (i.e., ``A-Fa-f0-9``), representing
the red, green and blue components of an sRGB color, is a "valid
simple color".
* A valid simple color expressed with only lowercase ASCII hex digits
(i.e., ``a-f0-9``) is a "valid lowercase simple color".
HTML5 provides three algorithms related to colors:
1. An algorithm for parsing simple color values, which works on any
string that is a valid simple color as defined above.
2. An algorithm for serializing simple color values, which will always
produce a valid lowercase simple color.
3. A legacy color-parsing algorithm, which will yield a valid simple
color from a variety of inputs, including inputs which are valid
simple colors, inputs which are valid for formats from other
standards, and certain types of "junk" inputs which were common in
real-world documents.
The HTML5 legacy parsing algorithm does not support the non-color
keyword ``transparent`` from CSS 3 and will produce an error for that
input. It also does not recognize the CSS 2 "system color" keywords;
it will convert each such keyword to simple color, consistently, but
in a way which does not follow CSS 2's definitions of these keywords
(which itself was system- and configuration-dependent).
The implementations in this module are based on the definitions and
algorithms of `the W3C HTML5 Recommendation's section on colors`_.
.. _the sRGB color space: http://www.w3.org/Graphics/Color/sRGB
.. _two ways to specify sRGB colors: http://www.w3.org/TR/html401/types.html#h-6.5
.. _its description of color units: http://www.w3.org/TR/CSS1/#color-units
.. _section on colors: http://www.w3.org/TR/CSS2/syndata.html#color-units
.. _a list of names of system colors: http://www.w3.org/TR/CSS2/ui.html#system-colors
.. _one additional named color: http://www.w3.org/TR/CSS21/changes.html#q2
.. _The CSS 3 color module: http://www.w3.org/TR/css3-color/
.. _the named colors defined for SVG (Scalable Vector Graphics): http://www.w3.org/TR/SVG11/types.html#ColorKeywords
.. _the W3C HTML5 Recommendation's section on colors: http://www.w3.org/TR/html5/infrastructure.html#colors
.. _support:
What this module supports
-------------------------
The ``webcolors`` module supports the following methods of specifying
sRGB colors, and conversions between them:
* Six-digit hexadecimal.
* Three-digit hexadecimal.
* Integer ``rgb()`` triplet.
* Percentage ``rgb()`` triplet.
* Varying selections of predefined color names.
The ``webcolors`` module **does not support**:
* The CSS 1 named colors, which did not have defined values.
* The CSS 2 system colors, which did not have fixed values.
* The ``transparent`` keyword, which denotes an effective lack of
color.
* Opacity/alpha-channel information specified via ``rgba()`` triplets.
* Colors specified in the HSL color space, via ``hsl()`` or ``hsla()``
triplets.
If you need to convert between sRGB-specified colors and HSL-specified
colors, or colors specified via other means, consult `the colorsys
module`_ in the Python standard library, which can perform conversions
amongst several common color systems.
.. _the colorsys module: http://docs.python.org/library/colorsys.html
webcolors-1.5/docs/conf.py 0000644 0000767 0000767 00000001163 12332137070 015022 0 ustar james 0000000 0000000 import os
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
extensions = []
templates_path = ['_templates']
source_suffix = '.rst'
master_doc = 'index'
project = u'webcolors'
copyright = u'2009-2014, James Bennett'
version = '1.5'
release = '1.5'
exclude_trees = ['_build']
pygments_style = 'sphinx'
html_static_path = ['_static']
htmlhelp_basename = 'webcolorsdoc'
latex_documents = [
('index', 'webcolors.tex', u'webcolors Documentation',
u'James Bennett', 'manual'),
]
if not on_rtd:
import sphinx_rtd_theme
html_theme = 'sphinx_rtd_theme'
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
webcolors-1.5/docs/conformance.rst 0000644 0000767 0000767 00000014034 12332145233 016550 0 ustar james 0000000 0000000 .. _conformance:
Conformance and testing
=======================
Much of the behavior of ``webcolors`` is dictated by the relevant Web
standards, which define the acceptable color formats, how to determine
valid values for each format and the values corresponding to defined
color names. Maintaining correct conversions and conformance to those
standards is crucial.
The normal test suite
---------------------
The normal test suite for ``webcolors`` -- that is, the set of unit
tests which will execute using standard Python test runners -- aims
for 100% code coverage, but does *not* aim for 100% coverage of
possible color value inputs and outputs. Instead, it uses a small
number of test values to routinely exercise various functions.
The test values used in most test functions are chosen to provide,
where applicable, at least one of each of the following types of
values:
* An endpoint of the acceptable range of values (i.e., ``#ffffff``
and/or ``#000000`` for hexadecimal).
* A value beyond the high end of the acceptable range (i.e., greater
than 255 in an integer triplet, or greater than 100% for a
percentage triplet).
* A value beyond the low end of the acceptable range (i.e., less than
0 in an integer triplet, or less than 0% for a percentage triplet).
* A "negative zero" value (-0 in an integer triplet, or -0% in
a percentage triplet).
* An arbitrary value not from an endpoint of the acceptable range
(usually ``#000080``, chosen because the author likes navy blue).
* A value which corresponds to a named color in CSS 3/SVG but not in
earlier standards (usually ``#daa520``, which is ``goldenrod`` in
CSS 3/SVG).
Since this covers the cases most likely to produce problems, it
provides good basic confidence in the correctness of the tested
functions.
However, the normal test suite cannot guarantee that the color
definitions included in ``webcolors`` correspond to those in the
relevant standards, and cannot provide guarantees of correct
conversions for all possible values. For that, additional tests are
required.
Those tests are contained in two files in the source distribution,
which are not executed during normal test runs:
``tests/definitions.py`` and ``tests/full_colors.py``.
Verifying color definitions
---------------------------
The ``definitions`` test file verifies that the color definitions in
``webcolors`` are correct. It does this by retrieving the relevant
standards documents as HTML, parsing out the color definitions in
them, and comparing them to the definitions in ``webcolors``. That
consists of:
* Parsing out the names and hexadecimal values of the 16 named colors
in the HTML 4 standard, and checking that the names and values in
:data:`~webcolors.HTML4_NAMES_TO_HEX` match.
* Parsing out the names and hexadecimal values of the 17 named colors
in the CSS 2.1 standard, and checking that the names and values in
:data:`~webcolors.CSS21_NAMES_TO_HEX` match.
* Parsing out the names and hexadecimal and integer values of the 147
named colors in the CSS 3 color module (although the color set is
taken from SVG, CSS 3 provides both hexadecimal and integer values
for them, while the SVG standard provides only integer values), and
checking that the names and values in
:data:`~webcolors.CSS3_NAMES_TO_HEX` match, and that
:func:`~webcolors.name_to_rgb` returns the correct integer values.
The ``definitions`` file can be run standalone (i.e., ``python
tests/definitions.py``) to execute these tests, but it does require an
internet connection (to retrieve the standards documents) and requires
`the BeautifulSoup library
`_ for HTML parsing.
Fully verifying correctness of conversions
------------------------------------------
The ``full_colors`` test file exercises :func:`~webcolors.hex_to_rgb`,
:func:`~webcolors.rgb_to_hex`, :func:`~webcolors.rgb_to_rgb_percent`
and :func:`~webcolors.rgb_percent_to_rgb` as fully as is practical.
For conversions between hexadecimal and integer ``rgb()``, that file
generates all 16,777,216 possible color values for each format in
order (starting at ``#000000`` and ``(0, 0, 0)`` and incrementing),
and verifies that each one converts to the corresponding value in the
other format. Thus, it is possible to be confident that ``webcolors``
provides correct conversions between all possible color values in
those formats.
Testing the correctness of conversion to and from percentage
``rgb()``, however, is more difficult, and a full test is not
provided, for two reasons:
1. Because percentage ``rgb()`` values can make use of floating-point
values, and because standard floating-point types in most common
programming languages (Python included) are inherently imprecise,
exact verification is not possible.
2. The only rigorous definition of the format of a percentage value is
in CSS 2, `which declares a percentage to be
`_ "a
```` immediately followed by '%'". `The CSS 2 definition of
a number
`_ places
no limit on the length past the decimal point, and appears to be
declaring any real number as a valid value. As the subset of reals
in the range 0.0 to 100.0 is uncountably infinite, testing all
legal values is not possible on current hardware in any reasonable
amount of time.
Since precise correctness and completeness are not achievable,
``webcolors`` instead aims to achieve *consistency* in
conversions. Specifically, the ``full_colors`` test generates all
16,777,216 integer ``rgb()`` triplets, and for each such triplet ``t``
verifies that the following assertion holds::
t == rgb_percent_to_rgb(rgb_to_rgb_percent(t))
The ``full_colors`` test has no external dependencies other than
Python, and does not require an internet connection. It is written to
be run standalone (``python tests/full_colors.py``). However, due to
the fact that it must generate all 16,777,216 color values multiple
times, and perform checks on each one, it does take some time to run
even on fast hardware.
webcolors-1.5/docs/contents.rst 0000644 0000767 0000767 00000042732 12501443212 016115 0 ustar james 0000000 0000000 .. module:: webcolors
.. _contents:
Module contents
===============
The contents of the ``webcolors`` module fall into four categories:
1. Constants which provide mappings between color names and values.
2. Normalization functions which sanitize input in various formats
prior to conversion or output.
3. Conversion functions between each method of specifying colors.
4. Implementations of the color parsing and serialization algorithms
in HTML5.
See :ref:`the documentation regarding conventions ` for
information regarding the types and representation of various color
formats in ``webcolors``.
All conversion functions which involve color names take an optional
argument to determine which specification to draw color names
from. See :ref:`the list of specification identifiers
` for a list of valid values.
All conversion functions, when faced with identifiably invalid
hexadecimal color values, or with a request to name a color which has
no name in the requested specification, or with an invalid
specification identifier, will raise ``ValueError``.
In the documentation below, "Unicode string" means the Unicode string
type of the Python version being used; on Python 3 this is ``str`` and
on Python 2 it is ``unicode``. See :ref:`the documentation on use of
Python string types ` for details.
Constants
---------
The following constants are available for direct use in mapping from
color names to values, although it is strongly recommended to use one
of the normalizing conversion functions instead.
Mappings from names to hexadecimal values
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. data:: HTML4_NAMES_TO_HEX
A dictionary whose keys are the normalized names of the sixteen
named HTML 4 colors, and whose values are the normalized
hexadecimal values of those colors.
.. data:: CSS2_NAMES_TO_HEX
An alias for :data:`~webcolors.HTML4_NAMES_TO_HEX`, as CSS 2
defined the same set of colors.
.. data:: CSS21_NAMES_TO_HEX
A dictionary whose keys are the normalized names of the seventeen
named CSS 2.1 colors, and whose values are the normalized
hexadecimal values of those colors (sixteen of these are identical
to HTML 4 and CSS 2; the seventeenth color is ``orange``, added in
CSS 2.1).
.. data:: CSS3_NAMES_TO_HEX
A dictionary whose keys are the normalized names of the 147 named
CSS 3 colors, and whose values are the normalized hexadecimal
values of those colors. These colors are also identical to the 147
named colors of SVG.
Mappings from hexadecimal values to names
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. data:: HTML4_HEX_TO_NAMES
A dictionary whose keys are the normalized hexadecimal values of
the sixteen named HTML 4 colors, and whose values are the
corresponding normalized names.
.. data:: CSS2_HEX_TO_NAMES
An alias for :data:`~webcolors.HTML4_HEX_TO_NAMES`.
.. data:: CSS21_HEX_TO_NAMES
A dictionary whose keys are the normalized hexadecimal values of
the seventeen named CSS 2.1 colors, and whose values are the
corresponding normalized names.
.. data:: CSS3_HEX_TO_NAMES
A dictionary whose keys are the normalized hexadecimal values of
the 147 names CSS 3 colors, and whose values are the corresponding
normalized names.
The canonical names of these constants are as listed above, entirely
in uppercase. For backwards compatibility with older versions of
``webcolors``, aliases are provided whose names are entirely lowercase
(for example, ``html4_names_to_hex``).
Normalization functions
-----------------------
.. function:: normalize_hex(hex_value)
Normalize a hexadecimal color value to a string consisting of the
character ``#`` followed by six lowercase hexadecimal digits (what
HTML5 terms a "valid lowercase simple color").
If the supplied value cannot be interpreted as a hexadecimal color
value, ``ValueError`` is raised. See :ref:`the conventions used by
this module ` for information on acceptable formats
for hexadecimal values.
Examples::
>>> normalize_hex(u'#0099cc')
'#0099cc'
>>> normalize_hex(u'#0099CC')
'#0099cc'
>>> normalize_hex(u'#09c')
'#0099cc'
>>> normalize_hex(u'#09C')
'#0099cc'
>>> normalize_hex(u'#0099gg')
Traceback (most recent call last):
...
ValueError: '#0099gg' is not a valid hexadecimal color value.
>>> normalize_hex(u'0099cc')
Traceback (most recent call last):
...
ValueError: '0099cc' is not a valid hexadecimal color value.
:param hex_value: The hexadecimal color value to normalize.
:type hex_value: ``str``
:rtype: Unicode string
.. function:: normalize_integer_triplet(rgb_triplet)
Normalize an integer ``rgb()`` triplet so that all values are
within the range 0..255.
Examples::
>>> normalize_integer_triplet((128, 128, 128))
(128, 128, 128)
>>> normalize_integer_triplet((0, 0, 0))
(0, 0, 0)
>>> normalize_integer_triplet((255, 255, 255))
(255, 255, 255)
>>> normalize_integer_triplet((270, -20, -0))
(255, 0, 0)
:param rgb_triplet: The integer ``rgb()`` triplet to normalize.
:type rgb_triplet: 3-tuple of ``int``
:rtype: 3-tuple of ``int``
.. function:: normalize_percent_triplet(rgb_triplet)
Normalize a percentage ``rgb()`` triplet to that all values are
within the range 0%..100%.
Examples::
>>> normalize_percent_triplet((u'50%', u'50%', u'50%'))
(u'50%', u'50%', u'50%')
>>> normalize_percent_triplet((u'0%', u'100%', u'0%'))
(u'0%', u'100%', u'0%')
>>> normalize_percent_triplet((u'-10%', u'-0%', u'500%'))
(u'0%', u'0%', u'100%')
:param rgb_triplet: The percentage ``rgb()`` triplet to normalize.
:type rgb_triplet: 3-tuple of ``str``
:rtype: 3-tuple of Unicode string
Conversions from color names to other formats
---------------------------------------------
.. function:: name_to_hex(name, spec=u'css3')
Convert a color name to a normalized hexadecimal color value.
The color name will be normalized to lower-case before being looked
up.
Examples::
>>> name_to_hex(u'white')
u'#ffffff'
>>> name_to_hex(u'navy')
u'#000080'
>>> name_to_hex(u'goldenrod')
u'#daa520'
>>> name_to_hex(u'goldenrod', spec=u'html4')
Traceback (most recent call last):
...
ValueError: 'goldenrod' is not defined as a named color in html4.
:param name: The color name to convert.
:type name: ``str``
:param spec: The specification from which to draw the list of color
names; valid values are ``'html4'``, ``'css2'``, ``'css21'`` and
``'css3'``. Default is ``'css3'``.
:type spec: ``str``
:rtype: Unicode string
.. function:: name_to_rgb(name, spec=u'css3')
Convert a color name to a 3-tuple of integers suitable for use in
an ``rgb()`` triplet specifying that color.
The color name will be normalized to lower-case before being looked
up.
Examples::
>>> name_to_rgb(u'white')
(255, 255, 255)
>>> name_to_rgb(u'navy')
(0, 0, 128)
>>> name_to_rgb(u'goldenrod')
(218, 165, 32)
:param name: The color name to convert.
:type name: ``str``
:param spec: The specification from which to draw the list of color
names; valid values are ``'html4'``, ``'css2'``, ``'css21'`` and
``'css3'``. Default is ``'css3'``.
:type spec: ``str``
:rtype: 3-tuple of ``int``
.. function:: name_to_rgb_percent(name, spec=u'css3')
Convert a color name to a 3-tuple of percentages suitable for use
in an ``rgb()`` triplet specifying that color.
The color name will be normalized to lower-case before being looked
up.
Examples::
>>> name_to_rgb_percent(u'white')
(u'100%', u'100%', u'100%')
>>> name_to_rgb_percent(u'navy')
(u'0%', u'0%', u'50%')
>>> name_to_rgb_percent(u'goldenrod')
(u'85.49%', u'64.71%', u'12.5%')
:param name: The color name to convert.
:type name: ``str``
:param spec: The specification from which to draw the list of color
names; valid values are ``'html4'``, ``'css2'``, ``'css21'`` and
``'css3'``. Default is ``'css3'``.
:type spec: ``str``
:rtype: 3-tuple of Unicode string
Conversion from hexadecimal color values to other formats
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. function:: hex_to_name(hex_value, spec=u'css3')
Convert a hexadecimal color value to its corresponding normalized
color name, if any such name exists.
The hexadecimal value will be normalized before being looked up.
Examples::
>>> hex_to_name(u'#ffffff')
u'white'
>>> hex_to_name(u'#fff')
u'white'
>>> hex_to_name(u'#000080')
u'navy'
>>> hex_to_name(u'#daa520')
u'goldenrod'
>>> hex_to_name(u'#daa520', spec=u'html4')
Traceback (most recent call last):
...
ValueError: '#daa520' has no defined color name in html4.
:param hex_value: The hexadecimal color value to convert.
:type hex_value: str
:param spec: The specification from which to draw the list of color
names; valid values are ``'html4'``, ``'css2'``, ``'css21'`` and
``'css3'``. Default is ``'css3'``.
:type spec: ``str``
:rtype: Unicode string
.. function:: hex_to_rgb(hex_value)
Convert a hexadecimal color value to a 3-tuple of integers suitable
for use in an ``rgb()`` triplet specifying that color.
The hexadecimal value will be normalized before being converted.
Examples::
>>> hex_to_rgb(u'#fff')
(255, 255, 255)
>>> hex_to_rgb(u'#000080')
(0, 0, 128)
:param hex_value: The hexadecimal color value to convert.
:type hex_value: ``str``
:rtype: 3-tuple of ``int``
.. function:: hex_to_rgb_percent(hex_value)
Convert a hexadecimal color value to a 3-tuple of percentages
suitable for use in an ``rgb()`` triplet representing that color.
The hexadecimal value will be normalized before being converted.
Examples::
>>> hex_to_rgb_percent(u'#ffffff')
(u'100%', u'100%', u'100%')
>>> hex_to_rgb_percent(u'#000080')
(u'0%', u'0%', u'50%')
:param hex_value: The hexadecimal color value to convert.
:type hex_value: ``str``
:rtype: 3-tuple of Unicode string
Conversions from integer ``rgb()`` triplets to other formats
------------------------------------------------------------
.. function:: rgb_to_name(rgb_triplet, spec=u'css3')
Convert a 3-tuple of integers, suitable for use in an ``rgb()``
color triplet, to its corresponding normalized color name, if any
such name exists.
To determine the name, the triplet will be converted to a
normalized hexadecimal value.
Examples::
>>> rgb_to_name((255, 255, 255))
u'white'
>>> rgb_to_name((0, 0, 128))
u'navy'
:param rgb_triplet: The ``rgb()`` triplet
:type rgb_triplet: 3-tuple of ``int``
:param spec: The specification from which to draw the list of color
names; valid values are ``'html4'``, ``'css2'``, ``'css21'`` and
``'css3'``. Default is ``'css3'``.
:type spec: ``str``
:rtype: Unicode string
.. function:: rgb_to_hex(rgb_triplet)
Convert a 3-tuple of integers, suitable for use in an ``rgb()``
color triplet, to a normalized hexadecimal value for that color.
Examples::
>>> rgb_to_hex((255, 255, 255))
u'#ffffff'
>>> rgb_to_hex((0, 0, 128))
u'#000080'
:param rgb_triplet: The ``rgb()`` triplet.
:type rgb_triplet: 3-tuple of ``int``
:rtype: Unicode string
.. function:: rgb_to_rgb_percent(rgb_triplet)
Convert a 3-tuple of integers, suitable for use in an ``rgb()``
color triplet, to a 3-tuple of percentages suitable for use in
representing that color.
This function makes some trade-offs in terms of the accuracy of the
final representation; for some common integer values, special-case
logic is used to ensure a precise result (e.g., integer 128 will
always convert to '50%', integer 32 will always convert to
'12.5%'), but for all other values a standard Python ``float`` is
used and rounded to two decimal places, which may result in a loss
of precision for some values.
Examples::
>>> rgb_to_rgb_percent((255, 255, 255))
(u'100%', u'100%', u'100%')
>>> rgb_to_rgb_percent((0, 0, 128))
(u'0%', u'0%', u'50%')
>>> rgb_to_rgb_percent((218, 165, 32))
(u'85.49%', u'64.71%', u'12.5%')
:param rgb_triplet: The ``rgb()`` triplet.
:type rgb_triplet: 3-tuple of ``int``
:rtype: 3-tuple of Unicode string
Conversions from percentage ``rgb()`` triplets to other formats
---------------------------------------------------------------
.. function:: rgb_percent_to_name(rgb_percent_triplet, spec=u'css3')
Convert a 3-tuple of percentages, suitable for use in an ``rgb()``
color triplet, to its corresponding normalized color name, if any
such name exists.
To determine the name, the triplet will be converted to a
normalized hexadecimal value.
Examples::
>>> rgb_percent_to_name((u'100%', u'100%', u'100%'))
u'white'
>>> rgb_percent_to_name((u'0%', u'0%', u'50%'))
u'navy'
>>> rgb_percent_to_name((u'85.49%', u'64.71%', u'12.5%'))
u'goldenrod'
:param rgb_percent_triplet: The ``rgb()`` triplet.
:type rgb_percent_triplet: 3-tuple of ``str``
:param spec: The specification from which to draw the list of color
names; valid values are ``'html4'``, ``'css2'``, ``'css21'``
and ``'css3'``. Default is ``'css3'``.
:type spec: ``str``
:rtype: Unicode string
.. function:: rgb_percent_to_hex(rgb_percent_triplet)
Convert a 3-tuple of percentages, suitable for use in an ``rgb()``
color triplet, to a normalized hexadecimal color value for that
color.
Examples::
>>> rgb_percent_to_hex((u'100%', u'100%', u'0%'))
u'#ffff00'
>>> rgb_percent_to_hex((u'0%', u'0%', u'50%'))
u'#000080'
>>> rgb_percent_to_hex((u'85.49%', u'64.71%', u'12.5%'))
u'#daa520'
:param rgb_percent_triplet: The ``rgb()`` triplet.
:type rgb_percent_triplet: 3-tuple of ``str``
:rtype: ``str``
.. function:: rgb_percent_to_rgb(rgb_percent_triplet)
Convert a 3-tuple of percentages, suitable for use in an ``rgb()``
color triplet, to a 3-tuple of integers suitable for use in
representing that color.
Some precision may be lost in this conversion. See the note
regarding precision for :func:`~webcolors.rgb_to_rgb_percent` for
details.
Examples::
>>> rgb_percent_to_rgb((u'100%', u'100%', u'100%'))
(255, 255, 255)
>>> rgb_percent_to_rgb((u'0%', u'0%', u'50%'))
(0, 0, 128)
>>> rgb_percent_to_rgb((u'85.49%', u'64.71%', u'12.5%'))
(218, 165, 32)
:param rgb_percent_triplet: The ``rgb()`` triplet.
:type rgb_percent_triplet: 3-tuple of ``str``
:rtype: 3-tuple of ``int``
HTML5 color algorithms
----------------------
.. warning:: There are two versions of the HTML5 standard. Although
they have common origins and are extremely similar, one is a living
document (maintained by WHATWG) and the other is a W3C
Recommendation. The functions documented below implement the HTML5
color algorithms as given in `section 2.4.6 of the W3C HTML5
Recommendation
`_.
.. function:: html5_parse_simple_color(input)
Apply the HTML5 simple color parsing algorithm.
Note that ``input`` *must* be a Unicode string -- on Python 2,
bytestrings will not be accepted.
Examples::
>>> html5_parse_simple_color(u'#ffffff')
(255, 255, 255)
>>> html5_parse_simple_color(u'#fff')
Traceback (most recent call last):
...
ValueError: An HTML5 simple color must be a string exactly seven characters long.
:param input: The color to parse.
:type input: seven-character ``str`` on Python 3, ``unicode`` on
Python 2, which must consist of exactly the character ``#``
followed by six hexadecimal digits
:rtype: 3-tuple of ``int``, each in the range 0..255.
.. function:: html5_serialize_simple_color(simple_color)
Apply the HTML5 simple color serialization algorithm.
Examples::
>>> html5_serialize_simple_color((0, 0, 0))
u'#000000'
>>> html5_serialize_simple_color((255, 255, 255))
u'#ffffff'
:param simple_color: The color to serialize.
:type simple_color: 3-tuple of ``int``, each in the range 0..255
:rtype: A valid lowercase simple color, which is a Unicode string
exactly seven characters long, beginning with ``#`` and followed
by six lowercase hexadecimal digits.
.. function:: html5_parse_legacy_color(input)
Apply the HTML5 legacy color parsing algorithm.
Note that, since this algorithm is intended to handle many types of
malformed color values present in real-world Web documents, it is
*extremely* forgiving of input, but the results of parsing inputs
with high levels of "junk" (i.e., text other than a color value)
may be surprising.
Note also that ``input`` *must* be a Unicode string -- on Python 2,
bytestrings will not be accepted.
Examples::
>>> html5_parse_legacy_color(u'black')
(0, 0, 0)
>>> html5_parse_legacy_color(u'chucknorris')
(192, 0, 0)
>>> html5_parse_legacy_color(u'Window')
(0, 13, 0)
:param input: The color to parse.
:type input: ``str`` on Python 3, ``unicode`` on Python 2
:rtype: 3-tuple of ``int``, each in the range 0..255 webcolors-1.5/docs/conventions.rst 0000644 0000767 0000767 00000015031 12501505544 016624 0 ustar james 0000000 0000000 .. _conventions:
Normalization and conventions
=============================
Since the various formats used to specify colors in Web documents do
not always map cleanly to Python data types, and some variation is
permitted in how to use each format in a Web document, ``webcolors``
applies a set of conventions for representing color names and values,
and for normalizing them.
.. _string-types:
Python string types
-------------------
The ``webcolors`` module is written to be compatible with both Python
2 and Python 3, which have different approaches to strings:
* On Python 2, a sequence of bytes in a particular encoding (a "byte
string") is represented by the type ``str`` , and Unicode strings
are represented by the type ``unicode``. Promiscuous mixing of
``str`` and ``unicode`` is possible in Python 2, but not recommended
as it is a frequent source of bugs.
* On Python 3, a sequence of bytes in a particular encoding is
represented by the type ``bytes``, and Unicode strings are
represented by the type ``str``. Promiscuous mixing of ``str`` and
``bytes`` is not permitted in Python 3, and will usually raise
exceptions.
The approach to string types in ``webcolors`` is as follows:
* On Python 3, use of Unicode strings -- ``str`` -- is mandatory for
all string arguments to functions in ``webcolors``. Use of ``bytes``
values is forbidden.
* All mappings from color names to hexadecimal values (and vice versa)
are dictionaries whose keys and values are Unicode strings (``str``
on Python 3 and ``unicode`` on Python 2). This permits promiscuous
use of byte strings on Python 2, but ensures that results will be
Unicode strings.
* All functions whose return values include strings will use Unicode
strings (``unicode`` on Python 2 and ``str`` on Python 3).
* All functions whose arguments include string values, *except* for
the HTML5 color algorithms (see below), will accept a sequence of
bytes (``str``) on Python 2, but will convert to Unicode strings
(``unicode``) for output.
Because the HTML5 Recommendation specifies its color algorithms in
terms of Unicode strings only (and in some cases, requires exact
identification of Unicode code points to determine behavior), the
following constraint applies to the functions implementing these
algorithms:
* Any string arguments *must* be Unicode strings (``unicode`` on
Python 2 or ``str`` on Python 3). Use of ``str`` on Python 2 or
``bytes`` on Python 3 will raise a ``ValueError``.
Use of Unicode strings whenever possible is strongly preferred. To
encourage this, all documentation for ``webcolors`` uses the ``u``
prefix for string literals. Use of the ``u`` prefix is required on
Python 2 to mark a string literal as Unicode; on Pyhon 3.3 and later,
use is permitted but not necessary (as all un-prefixed string literals
on Python 3 are Unicode strings).
Hexadecimal color values
------------------------
For colors specified via hexadecimal values, ``webcolors`` will accept
strings in the following formats:
* The character ``#`` followed by three hexadecimal digits, where
digits A-F may be upper- or lowercase.
* The character ``#`` followed by six hexadecimal digits, where
digits A-F may be upper- or lowercase (i.e., what HTML5 designates a
"valid simple color" when all digits are uppercase, and a "valid
lowercase simple color" when all digits are lowercase).
For output which consists of a color specified via hexadecimal values,
and for functions which perform intermediate conversion to hexadecimal
before returning a result in another format, ``webcolors`` always
normalizes such values to a string in the following format:
* The character ``#`` followed by six hexadecimal digits, with digits
A-F forced to lowercase (what HTML5 designates a "valid lowercase
simple color").
The function :func:`~webcolors.normalize_hex` can be used to perform
this normalization manually if desired.
Integer and percentage ``rgb()`` triplets
-----------------------------------------
Functions which work with integer ``rgb()`` triplets accept and return
them as a 3-tuple of Python ``int``. Functions which work with
percentage ``rgb()`` triplets accept them as 3-tuple of Python strings
(either ``str`` or ``unicode`` is permitted on Python 2; only ``str``
is permitted on Python 3) and return them as a 3-tuple of Python
Unicode strings (``unicode`` or ``str`` depending on Python version).
Internally, Python ``float`` is used in some conversions to and from
the triplet representations; for each function which may have the
precision of its results affected by this, a note is provided in the
documentation.
For colors specified via ``rgb()`` triplets, values contained in the
triplets will be normalized via clipping in accordance with CSS:
* Integer values less than 0 will be normalized to 0, and percentage
values less than 0% will be normalized to 0%.
* Integer values greater than 255 will be normalized to 255, and
percentage values greater than 100% will be normalized to 100%.
* The "negative zero" values -0 and -0% will be normalized to 0 and
0%, respectively.
The functions :func:`~webcolors.normalize_integer_triplet` and
:func:`~webcolors.normalize_percent_triplet` can be used to
perform this normalization manually if desired.
Color names
-----------
For colors specified via predefined names, ``webcolors`` will accept
strings containing names case-insensitively, so long as they contain
no spaces or non-alphabetic characters. Thus, for example,
``u'AliceBlue'`` and ``u'aliceblue'`` are both accepted, and both will
refer to the same color (namely, ``rgb(240, 248, 255)``).
For output which consists of a color name, and for functions which
perform intermediate conversion to a predefined name before returning
a result in another format, ``webcolors`` always normalizes such
values to be entirely lowercase.
.. _spec-identifiers:
Identifying sets of named colors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For purposes of identifying the specification from which to draw the
selection of defined color names, ``webcolors`` recognizes the
following strings as identifiers:
``'html4'``
The HTML 4 named colors.
``'css2'``
The CSS 2 named colors.
``'css21'``
The CSS 2.1 named colors.
``'css3'``
The CSS 3/SVG named colors. For all functions for which the set of
color names is relevant, this is the default set used.
The CSS 1 named colors are not represented here, as CSS 1 merely
"suggested" a set of color names, and declined to provide values for
them. The CSS 2 "system colors" are also not represented here, as they
had no fixed defined values and are now deprecated.
webcolors-1.5/docs/faq.rst 0000644 0000767 0000767 00000011103 12364747655 015044 0 ustar james 0000000 0000000 .. _faq:
Frequently asked questions
==========================
The following notes answer common questions, and may be useful to you
when using ``webcolors``.
What versions of Python are supported?
--------------------------------------
On Python 2, ``webcolors`` supports and is tested on Python 2.6 and
2.7. Although ``webcolors`` may work on Python 2.5 or older versions,
this is unintentional and unsupported.
On Python 3, ``webcolors`` supports and is tested on Python 3.3 and
3.4. Python 3.0, 3.1 and 3.2 are explicitly unsupported, and the
``webcolors`` test suite will not execute on those versions. The
minimum-3.3 version requirement is because Python 3.3 was both the
first generally-adopted Python 3 release, and because Python 3.3
greatly simplified the process of consistently handling both Python 2
and Python 3 strings in the same codebase.
How closely does this module follow the standards?
--------------------------------------------------
As closely as is practical (see below regarding floating-point
values), within :ref:`the supported formats `; the
``webcolors`` module was written with the relevant standards documents
close at hand. See :ref:`the conformance documentation `
for details.
Why aren't ``rgb_to_rgb_percent()`` and ``rgb_percent_to_rgb()`` precise?
-------------------------------------------------------------------------
This is due to limitations in the representation of floating-point
numbers in programming languages. Python, like many programming
languages, uses `IEEE floating-point
`_, which is
inherently imprecise for some values.
This imprecision only appears when converting between integer and
percentage ``rgb()`` triplets.
To work around this, some common values (255, 128, 64, 32, 16 and 0)
are handled as special cases, with hard-coded precise results. For all
other values, conversion to percentage ``rgb()`` triplet uses a
standard Python ``float``, rounding the result to two decimal places.
See :ref:`the conformance documentation ` for details on
how this affects testing.
Why aren't HSL values supported?
--------------------------------
In the author's experience, actual use of HSL values on the Web is
extremely rare; the overwhelming majority of all colors used on the
Web are specified using sRGB, through hexadecimal color values or
through integer or percentage ``rgb()`` triplets. This decreases the
importance of supporting the ``hsl()`` construct.
Additionally, Python already has `the colorsys module`_ in the
standard library, which offers functions for converting between RGB,
HSL, HSV and YIQ color systems. If you need conversion to/from HSL or
another color system, use ``colorsys``.
.. _the colorsys module: http://docs.python.org/library/colorsys.html
Why not use a more object-oriented design with classes for the colors?
----------------------------------------------------------------------
Representing color values with Python classes would introduce overhead
for no real gain. Real-world use cases tend to simply involve working
with the actual values, so settling on conventions for how to
represent them as Python types, and then offering a function-based
interface, accomplishes everything needed without the addtional
indirection layer of having to instantiate and serialize a
color-wrapping object.
Keeping a simple function-based interface also maintains consistency
with `Python's built-in colorsys module
`_, which has the same
style of interface for converting amongst color spaces.
Note that if an object-oriented interface is desired, `the third-party
colormath module `_ does have
a class-based interface (and rightly so, as it offers a wider range of
color representation and manipulation options than ``webcolors``).
How am I allowed to use this module?
------------------------------------
The ``webcolors`` module is distributed under a `three-clause BSD
license `_. This is an
open-source license which grants you broad freedom to use,
redistribute, modify and distribute modified versions of
``webcolors``. For details, see the file ``LICENSE`` in the source
distribution of ``webcolors``.
.. _three-clause BSD license: http://opensource.org/licenses/BSD-3-Clause
I found a bug or want to make an improvement!
---------------------------------------------
The canonical development repository for ``webcolors`` is online at
. Issues and pull requests
can both be filed there.
webcolors-1.5/docs/index.rst 0000644 0000767 0000767 00000002732 12502163531 015367 0 ustar james 0000000 0000000 webcolors
=========
This module provides utility functions for working with the color
names and color value formats defined by the HTML and CSS
specifications for use in documents on the Web.
Support is included for normalizing and converting between the
following formats (RGB colorspace only; conversion to/from HSL can be
handled by the ``colorsys`` module in the Python standard library):
* Specification-defined color names
* Six-digit hexadecimal
* Three-digit hexadecimal
* Integer ``rgb()`` triplet
* Percentage ``rgb()`` triplet
For example::
>>> import webcolors
>>> webcolors.hex_to_name(u'#daa520')
u'goldenrod'
Implementations are also provided for the HTML5 color parsing and
serialization algorithms. For example, parsing the infamous
"chucknorris" string into an rgb() triplet::
>>> import webcolors
>>> webcolors.html5_parse_legacy_color(u'chucknorris')
(192, 0, 0)
Documentation contents
----------------------
.. toctree::
:maxdepth: 1
install
colors
conventions
contents
conformance
faq
.. seealso::
* `The sRGB color space `_
* `HTML 4: Colors `_
* `CSS 1: Color units `_
* `CSS 2: Colors `_
* `CSS 3 color module `_
* `HTML5: Colors `_ webcolors-1.5/docs/install.rst 0000644 0000767 0000767 00000003420 12501376456 015734 0 ustar james 0000000 0000000 .. _install:
Installation guide
==================
The ``webcolors`` module has no external dependencies other than
Python itself. It's officially tested and supported on the following
versions of Python:
* Python 2.6
* Python 2.7
* Python 3.3
* Python 3.4
Normal installation
-------------------
The preferred method of installing ``webcolors`` is via ``pip``, the
standard Python package-installation tool. If you don't have ``pip``,
instructions are available for `how to obtain and install it
`_.
Once you have ``pip``, simply type::
pip install webcolors
Manual installation
-------------------
It's also possible to install ``webcolors`` manually. To do so, obtain
the latest packaged version from `the listing on the Python Package
Index `_. Unpack the
``.tar.gz`` file, and run::
python setup.py install
Once you've installed ``webcolors``, you can verify successful
installation by opening a Python interpreter and typing ``import
webcolors``.
If the installation was successful, you'll simply get a fresh Python
prompt. If you instead see an ``ImportError``, check the configuration
of your install tools and your Python import path to ensure
``webcolors`` installed into a location Python can import from.
Installing from a source checkout
---------------------------------
The development repository for ``webcolors`` is at
. Presuming you have `git
`_ installed, you can obtain a copy of the
repository by typing::
git clone https://github.com/ubernostrum/webcolors.git
From there, you can use normal git commands to check out the specific
revision you want, and install it using ``python setup.py install``.
webcolors-1.5/docs/make.bat 0000644 0000767 0000767 00000005625 12214057665 015151 0 ustar james 0000000 0000000 @ECHO OFF
REM Command file for Sphinx documentation
set SPHINXBUILD=sphinx-build
set ALLSPHINXOPTS=-d _build/doctrees %SPHINXOPTS% .
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^` where ^ is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. changes to make an overview over all changed/added/deprecated items
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (_build\*) do rmdir /q /s %%i
del /q /s _build\*
goto end
)
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% _build/html
echo.
echo.Build finished. The HTML pages are in _build/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% _build/dirhtml
echo.
echo.Build finished. The HTML pages are in _build/dirhtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% _build/pickle
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% _build/json
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% _build/htmlhelp
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in _build/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% _build/qthelp
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in _build/qthelp, like this:
echo.^> qcollectiongenerator _build\qthelp\webcolors.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile _build\qthelp\webcolors.ghc
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% _build/latex
echo.
echo.Build finished; the LaTeX files are in _build/latex.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% _build/changes
echo.
echo.The overview file is in _build/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% _build/linkcheck
echo.
echo.Link check complete; look for any errors in the above output ^
or in _build/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% _build/doctest
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in _build/doctest/output.txt.
goto end
)
:end
webcolors-1.5/docs/Makefile 0000644 0000767 0000767 00000005667 12214057665 015212 0 ustar james 0000000 0000000 # Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest
help:
@echo "Please use \`make ' where is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
-rm -rf _build/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html
@echo
@echo "Build finished. The HTML pages are in _build/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) _build/dirhtml
@echo
@echo "Build finished. The HTML pages are in _build/dirhtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) _build/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in _build/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) _build/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in _build/qthelp, like this:"
@echo "# qcollectiongenerator _build/qthelp/webcolors.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile _build/qthelp/webcolors.qhc"
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex
@echo
@echo "Build finished; the LaTeX files are in _build/latex."
@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
"run these through (pdf)latex."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) _build/changes
@echo
@echo "The overview file is in _build/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) _build/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in _build/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) _build/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in _build/doctest/output.txt."
webcolors-1.5/LICENSE 0000644 0000767 0000767 00000002763 12327544612 013617 0 ustar james 0000000 0000000 Copyright (c) 2008-2014, James Bennett
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of the author nor the names of other
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
webcolors-1.5/MANIFEST.in 0000644 0000767 0000767 00000000151 12442306163 014330 0 ustar james 0000000 0000000 include LICENSE
include MANIFEST.in
include README.rst
recursive-include docs *
recursive-include tests * webcolors-1.5/PKG-INFO 0000644 0000767 0000767 00000004140 12502171014 013661 0 ustar james 0000000 0000000 Metadata-Version: 1.1
Name: webcolors
Version: 1.5
Summary: A library for working with color names and color value formats defined by the HTML and CSS specifications for use in documents on the Web.
Home-page: https://github.com/ubernostrum/webcolors
Author: James Bennett
Author-email: james@b-list.org
License: UNKNOWN
Description: .. -*-restructuredtext-*-
``webcolors`` is a simple Python module for working with HTML/CSS
color definitions.
Support is included for normalizing and converting between the
following formats (RGB colorspace only; conversion to/from HSL can be
handled by the ``colorsys`` module in the Python standard library):
* Specification-defined color names
* Six-digit hexadecimal
* Three-digit hexadecimal
* Integer ``rgb()`` triplet
* Percentage ``rgb()`` triplet
For example::
>>> import webcolors
>>> webcolors.hex_to_name(u'#daa520')
u'goldenrod'
Implementations are also provided for the HTML5 color parsing and
serialization algorithms. For example, parsing the infamous
"chucknorris" string into an rgb() triplet::
>>> import webcolors
>>> webcolors.html5_parse_legacy_color(u'chucknorris')
(192, 0, 0)
Full documentation is `available online `_.
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 2.6
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
Classifier: Topic :: Utilities
webcolors-1.5/README.rst 0000644 0000767 0000767 00000001624 12502163541 014265 0 ustar james 0000000 0000000 .. -*-restructuredtext-*-
``webcolors`` is a simple Python module for working with HTML/CSS
color definitions.
Support is included for normalizing and converting between the
following formats (RGB colorspace only; conversion to/from HSL can be
handled by the ``colorsys`` module in the Python standard library):
* Specification-defined color names
* Six-digit hexadecimal
* Three-digit hexadecimal
* Integer ``rgb()`` triplet
* Percentage ``rgb()`` triplet
For example::
>>> import webcolors
>>> webcolors.hex_to_name(u'#daa520')
u'goldenrod'
Implementations are also provided for the HTML5 color parsing and
serialization algorithms. For example, parsing the infamous
"chucknorris" string into an rgb() triplet::
>>> import webcolors
>>> webcolors.html5_parse_legacy_color(u'chucknorris')
(192, 0, 0)
Full documentation is `available online `_. webcolors-1.5/setup.py 0000644 0000767 0000767 00000002336 12442305773 014321 0 ustar james 0000000 0000000 import os
from distutils.core import setup
setup(name='webcolors',
version='1.5',
description='A library for working with color names and color value formats defined by the HTML and CSS specifications for use in documents on the Web.',
long_description=open(os.path.join(os.path.dirname(__file__), 'README.rst')).read(),
author='James Bennett',
author_email='james@b-list.org',
url='https://github.com/ubernostrum/webcolors',
py_modules=['webcolors'],
classifiers=['Development Status :: 5 - Production/Stable',
'Environment :: Web Environment',
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License',
'Operating System :: OS Independent',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Topic :: Utilities'],
)
webcolors-1.5/tests/ 0000755 0000767 0000767 00000000000 12502171014 013727 5 ustar james 0000000 0000000 webcolors-1.5/tests/__init__.py 0000644 0000767 0000767 00000000000 12331140746 016036 0 ustar james 0000000 0000000 webcolors-1.5/tests/definitions.py 0000644 0000767 0000767 00000010400 12455160367 016627 0 ustar james 0000000 0000000 """
Test accuracy of the mappings of color names and values, by extracting
the definitions of the colors from the relevant standards documents.
"""
import re
import unittest
try:
import urllib2
except ImportError:
import urllib.request as urllib2
from BeautifulSoup import BeautifulSoup
import webcolors
class HTML4DefinitionTests(unittest.TestCase):
"""
Extract the names and values of the 16 defined HTML 4 colors from
the online version of the standard, and check them against this
module's definitions of them.
"""
def setUp(self):
self.html4_colors = {}
soup = BeautifulSoup(
urllib2.urlopen('http://www.w3.org/TR/html401/types.html'))
color_table = soup.find(
'table',
attrs={
'summary': 'Table of color names and their sRGB values'})
for td in color_table.findAll('td'):
if (u'width', u'16') not in td.attrs:
color_name, color_value = td.text.split(' = ')
self.html4_colors[color_name] = color_value.replace('"', '')
def test_color_definitions(self):
for color_name, color_value in self.html4_colors.items():
self.assertEqual(color_value.lower(),
webcolors.HTML4_NAMES_TO_HEX[color_name.lower()])
class CSS21DefinitionTests(unittest.TestCase):
"""
Extract the names and values of the 17 defined CSS 2.1 colors from
the online version of the standard, and check them against this
module's definitions of them.
"""
def setUp(self):
self.color_matching_re = re.compile(r'^([a-z]+)(#[a-fA-F0-9]{6})$')
self.css21_colors = {}
soup = BeautifulSoup(
urllib2.urlopen('http://www.w3.org/TR/CSS2/syndata.html'))
color_table = soup.find('div',
attrs={'id': 'TanteksColorDiagram20020613'})
for color_square in color_table.findAll('span',
attrs={
'class': 'colorsquare'}):
color_name, color_value = self.color_matching_re.match(
color_square.text
).groups()
self.css21_colors[color_name] = color_value
def test_color_definitions(self):
for color_name, color_value in self.css21_colors.items():
self.assertEqual(color_value.lower(),
webcolors.CSS21_NAMES_TO_HEX[color_name.lower()])
class CSS3DefinitionTests(unittest.TestCase):
"""
Extract the names and values of the 147 defined CSS 3 colors from
the online version of the standard, and check them against this
module's definitions of them.
"""
def setUp(self):
self.css3_colors = {}
soup = BeautifulSoup(urllib2.urlopen(
'http://www.w3.org/TR/css3-color/'))
color_table = soup.findAll('table',
attrs={'class': 'colortable'})[1]
color_names = [dfn.text for dfn in color_table.findAll('dfn')]
hex_values = [td.text for
td in
color_table.findAll('td',
attrs={'class': 'c',
'style': 'background:silver'})
if td.text.startswith('#')]
rgb_values = [td.text for
td in
color_table.findAll('td',
attrs={'class': 'c',
'style': 'background:silver'})
if not td.text.startswith('#') and
not td.text.startswith('&')]
for i, color_name in enumerate(color_names):
self.css3_colors[color_name] = {
'hex': hex_values[i],
'rgb': tuple(map(int, rgb_values[i].split(',')))}
def test_color_definitions(self):
for color_name, color_values in self.css3_colors.items():
self.assertEqual(color_values['hex'].lower(),
webcolors.CSS3_NAMES_TO_HEX[color_name.lower()])
self.assertEqual(color_values['rgb'],
webcolors.name_to_rgb(color_name))
if __name__ == '__main__':
unittest.main()
webcolors-1.5/tests/full_colors.py 0000644 0000767 0000767 00000005132 12501405276 016636 0 ustar james 0000000 0000000 """
Test case which exercises webcolors' conversion functions across all
16,777,216 possible hexadecimal values and all 16,777,216 possible
integer rgb() triplet values.
You should not ever need to run this test; it is not part of the
normal unit-test suite, and is used only as a final check when
preparing a new release of webcolors.
Because it generates each of the nearly 17 million color values
multiple times, this test case takes some time to run and consumes
most or all available CPU while running. As a consolation, it is
somewhat efficient with respect to memory.
Due to the inherent imprecision of floating-point percentage values,
and the fact that the legal (with respect to the CSS standards) set of
percentage rgb() triplets is uncountably infinite, percentage rgb()
triplets are not exhaustively tested here, and the normal test suite
is used to ensure correctness of the conversion functions for those
values.
The only test performed here for percentage rgb() triplets is to
ensure that converting an integer rgb() triplet to percentage and back
returns the original integer values, for consistency.
"""
import unittest
import webcolors
try:
# On Python 3, the built-in zip() is identical to the Python 2
# itertools.izip(), and Python 3's itertools does not define an
# izip() as a result.
from itertools import izip as zip
except ImportError:
pass
try:
# Similarly, Python 3's range() does what Python 2's xrange() did,
# and so Python 3 does not have xrange()
xrange(1)
except NameError:
xrange = range
def hex_colors():
HEX_TEMPLATE = u"#%06x"
for i in xrange(16777217):
yield HEX_TEMPLATE % i
def int_colors():
red_counter = tuple(range(256))
green_counter = tuple(range(256))
blue_counter = tuple(range(256))
for red_value in red_counter:
for green_value in green_counter:
for blue_value in blue_counter:
yield (red_value, green_value, blue_value)
class FullColorTest(unittest.TestCase):
def test_full_colors(self):
for hex_color, int_triplet in zip(hex_colors(), int_colors()):
self.assertEqual(int_triplet,
webcolors.hex_to_rgb(hex_color))
self.assertEqual(hex_color,
webcolors.rgb_to_hex(int_triplet))
def test_triplet_conversion(self):
for int_triplet in int_colors():
self.assertEqual(int_triplet,
webcolors.rgb_percent_to_rgb(
webcolors.rgb_to_rgb_percent(int_triplet)))
if __name__ == '__main__':
unittest.main()
webcolors-1.5/tests/test_conformance.py 0000644 0000767 0000767 00000016312 12332402762 017645 0 ustar james 0000000 0000000 """
Conformance tests which do not require an internet connection or HTML
parsing libraries, and so can be run as part of the normal test suite
of webcolors.
For tests which extract the relevant values, during the test run, from
the online standards documents (and so require both an internet
connection and an HTML parsing library), see the file
``definitions.py`` in this directory.
"""
import unittest
import webcolors
# The mappings of color names to values below are used for conformance
# testing; while the main webcolors module makes use of alphabetized,
# normalized mappings to hex values, the mappings below are the
# definitions in precisely the form they take in the relevant
# standards documents (they were produced via automated extraction
# from the HTML of those documents, to avoid the possibility of human
# copy/paste error).
#
# Sources are:
#
# HTML 4 colors: http://www.w3.org/TR/html401/types.html#h-6.5
#
# SVG colors (which CSS 3 adopted): http://www.w3.org/TR/SVG/types.html#ColorKeywords
#
# Conformance of this module with the relevant standards is proven by
# comparing its output to these mappings.
HTML4_COLOR_DEFINITIONS = {
'Black': '#000000',
'Silver': '#C0C0C0',
'Gray': '#808080',
'White': '#FFFFFF',
'Maroon': '#800000',
'Red': '#FF0000',
'Purple': '#800080',
'Fuchsia': '#FF00FF',
'Green': '#008000',
'Lime': '#00FF00',
'Olive': '#808000',
'Yellow': '#FFFF00',
'Navy': '#000080',
'Blue': '#0000FF',
'Teal': '#008080',
'Aqua': '#00FFFF',
}
SVG_COLOR_DEFINITIONS = {
'aliceblue': (240, 248, 255),
'antiquewhite': (250, 235, 215),
'aqua': (0, 255, 255),
'aquamarine': (127, 255, 212),
'azure': (240, 255, 255),
'beige': (245, 245, 220),
'bisque': (255, 228, 196),
'black': (0, 0, 0),
'blanchedalmond': (255, 235, 205),
'blue': (0, 0, 255),
'blueviolet': (138, 43, 226),
'brown': (165, 42, 42),
'burlywood': (222, 184, 135),
'cadetblue': (95, 158, 160),
'chartreuse': (127, 255, 0),
'chocolate': (210, 105, 30),
'coral': (255, 127, 80),
'cornflowerblue': (100, 149, 237),
'cornsilk': (255, 248, 220),
'crimson': (220, 20, 60),
'cyan': (0, 255, 255),
'darkblue': (0, 0, 139),
'darkcyan': (0, 139, 139),
'darkgoldenrod': (184, 134, 11),
'darkgray': (169, 169, 169),
'darkgreen': (0, 100, 0),
'darkgrey': (169, 169, 169),
'darkkhaki': (189, 183, 107),
'darkmagenta': (139, 0, 139),
'darkolivegreen': (85, 107, 47),
'darkorange': (255, 140, 0),
'darkorchid': (153, 50, 204),
'darkred': (139, 0, 0),
'darksalmon': (233, 150, 122),
'darkseagreen': (143, 188, 143),
'darkslateblue': (72, 61, 139),
'darkslategray': (47, 79, 79),
'darkslategrey': (47, 79, 79),
'darkturquoise': (0, 206, 209),
'darkviolet': (148, 0, 211),
'deeppink': (255, 20, 147),
'deepskyblue': (0, 191, 255),
'dimgray': (105, 105, 105),
'dimgrey': (105, 105, 105),
'dodgerblue': (30, 144, 255),
'firebrick': (178, 34, 34),
'floralwhite': (255, 250, 240),
'forestgreen': (34, 139, 34),
'fuchsia': (255, 0, 255),
'gainsboro': (220, 220, 220),
'ghostwhite': (248, 248, 255),
'gold': (255, 215, 0),
'goldenrod': (218, 165, 32),
'gray': (128, 128, 128),
'grey': (128, 128, 128),
'green': (0, 128, 0),
'greenyellow': (173, 255, 47),
'honeydew': (240, 255, 240),
'hotpink': (255, 105, 180),
'indianred': (205, 92, 92),
'indigo': (75, 0, 130),
'ivory': (255, 255, 240),
'khaki': (240, 230, 140),
'lavender': (230, 230, 250),
'lavenderblush': (255, 240, 245),
'lawngreen': (124, 252, 0),
'lemonchiffon': (255, 250, 205),
'lightblue': (173, 216, 230),
'lightcoral': (240, 128, 128),
'lightcyan': (224, 255, 255),
'lightgoldenrodyellow': (250, 250, 210),
'lightgray': (211, 211, 211),
'lightgreen': (144, 238, 144),
'lightgrey': (211, 211, 211),
'lightpink': (255, 182, 193),
'lightsalmon': (255, 160, 122),
'lightseagreen': (32, 178, 170),
'lightskyblue': (135, 206, 250),
'lightslategray': (119, 136, 153),
'lightslategrey': (119, 136, 153),
'lightsteelblue': (176, 196, 222),
'lightyellow': (255, 255, 224),
'lime': (0, 255, 0),
'limegreen': (50, 205, 50),
'linen': (250, 240, 230),
'magenta': (255, 0, 255),
'maroon': (128, 0, 0),
'mediumaquamarine': (102, 205, 170),
'mediumblue': (0, 0, 205),
'mediumorchid': (186, 85, 211),
'mediumpurple': (147, 112, 219),
'mediumseagreen': (60, 179, 113),
'mediumslateblue': (123, 104, 238),
'mediumspringgreen': (0, 250, 154),
'mediumturquoise': (72, 209, 204),
'mediumvioletred': (199, 21, 133),
'midnightblue': (25, 25, 112),
'mintcream': (245, 255, 250),
'mistyrose': (255, 228, 225),
'moccasin': (255, 228, 181),
'navajowhite': (255, 222, 173),
'navy': (0, 0, 128),
'oldlace': (253, 245, 230),
'olive': (128, 128, 0),
'olivedrab': (107, 142, 35),
'orange': (255, 165, 0),
'orangered': (255, 69, 0),
'orchid': (218, 112, 214),
'palegoldenrod': (238, 232, 170),
'palegreen': (152, 251, 152),
'paleturquoise': (175, 238, 238),
'palevioletred': (219, 112, 147),
'papayawhip': (255, 239, 213),
'peachpuff': (255, 218, 185),
'peru': (205, 133, 63),
'pink': (255, 192, 203),
'plum': (221, 160, 221),
'powderblue': (176, 224, 230),
'purple': (128, 0, 128),
'red': (255, 0, 0),
'rosybrown': (188, 143, 143),
'royalblue': (65, 105, 225),
'saddlebrown': (139, 69, 19),
'salmon': (250, 128, 114),
'sandybrown': (244, 164, 96),
'seagreen': (46, 139, 87),
'seashell': (255, 245, 238),
'sienna': (160, 82, 45),
'silver': (192, 192, 192),
'skyblue': (135, 206, 235),
'slateblue': (106, 90, 205),
'slategray': (112, 128, 144),
'slategrey': (112, 128, 144),
'snow': (255, 250, 250),
'springgreen': (0, 255, 127),
'steelblue': (70, 130, 180),
'tan': (210, 180, 140),
'teal': (0, 128, 128),
'thistle': (216, 191, 216),
'tomato': (255, 99, 71),
'turquoise': (64, 224, 208),
'violet': (238, 130, 238),
'wheat': (245, 222, 179),
'white': (255, 255, 255),
'whitesmoke': (245, 245, 245),
'yellow': (255, 255, 0),
'yellowgreen': (154, 205, 50),
}
class ConformanceTests(unittest.TestCase):
"""
Demonstrate that this module conforms to the relevant standards
documents governing colors on the Web.
"""
def test_html_definition_conformance(self):
"""
Compare the results of name-to-hex conversion to the canonical
hex values provided in the HTML 4 specification.
"""
for color, hex_value in HTML4_COLOR_DEFINITIONS.items():
self.assertEqual(webcolors.normalize_hex(hex_value),
webcolors.name_to_hex(color))
def test_svg_definition_conformance(self):
"""
Compare the results of name-to-rgb-triplet conversion to the
canonical triplet values provided in the SVG specification.
"""
for color, triplet in SVG_COLOR_DEFINITIONS.items():
self.assertEqual(triplet,
webcolors.name_to_rgb(color))
webcolors-1.5/tests/test_hexadecimal.py 0000644 0000767 0000767 00000005166 12501405530 017616 0 ustar james 0000000 0000000 import unittest
import webcolors
class HexConversionTests(unittest.TestCase):
"""
Test functions which convert from hex color codes to other
formats.
"""
def test_hex_to_name(self):
"""
Test conversion from hex to color name.
"""
test_pairs = ((u'#ffffff', u'white'),
(u'#fff', u'white'),
(u'#000080', u'navy'),
(u'#daa520', u'goldenrod'))
for pair in test_pairs:
self.assertEqual(pair[1],
webcolors.hex_to_name(pair[0]))
def test_hex_to_name_unnamed(self):
"""
A hex code which does not correspond to a named color, or does
not correspond to a named color in the given specification,
raises ValueError.
"""
# No name in any spec.
self.assertRaises(ValueError,
webcolors.hex_to_name,
'#123456')
# This is 'goldenrod' in CSS 3 list, unnamed in HTML 4.
self.assertRaises(ValueError,
webcolors.hex_to_name,
'#daa520', spec=u'html4')
def test_hex_to_name_specs(self):
"""
Using one of the supported specifications succeeds; using an
unsupported specification raises ValueError.
"""
for supported_spec in (u'html4', u'css2', u'css21', u'css3'):
self.assertEqual(u'white',
webcolors.hex_to_name(u'#ffffff',
spec=supported_spec))
for unsupported_spec in (u'css1', u'css4', u'html5'):
self.assertRaises(ValueError,
webcolors.hex_to_name,
'#ffffff', spec=unsupported_spec)
def test_hex_to_rgb(self):
"""
Test conversion from hex to integer RGB triplet.
"""
test_pairs = ((u'#fff', (255, 255, 255)),
(u'#ffffff', (255, 255, 255)),
(u'#000080', (0, 0, 128)))
for pair in test_pairs:
self.assertEqual(pair[1],
webcolors.hex_to_rgb(pair[0]))
def test_hex_to_rgb_percent(self):
"""
Test conversion from hex to percent RGB triplet.
"""
test_pairs = ((u'#fff', (u'100%', u'100%', u'100%')),
(u'#ffffff', (u'100%', u'100%', u'100%')),
(u'#000080', (u'0%', u'0%', u'50%')))
for pair in test_pairs:
self.assertEqual(pair[1],
webcolors.hex_to_rgb_percent(pair[0]))
webcolors-1.5/tests/test_html5.py 0000644 0000767 0000767 00000007013 12501405436 016401 0 ustar james 0000000 0000000 import unittest
import webcolors
class HTML5Tests(unittest.TestCase):
"""
Test functions which implement the HTML5 color algorithms.
"""
def test_parse_simple_color(self):
"""
Test implementation of the HTML5 simple color parsing
algorithm.
"""
test_pairs = ((u'#ffffff', (255, 255, 255)),
(u'#000080', (0, 0, 128)),
(u'#daa520', (218, 165, 32)))
for pair in test_pairs:
self.assertEqual(pair[1],
webcolors.html5_parse_simple_color(pair[0]))
def test_parse_simple_color_error(self):
"""
Test error conditions of the HTML5 simple color parsing
algorithm.
"""
test_values = (u'0099cc',
u'#09c',
u'#0000',
u'#0000000',
u'#0000gg',
u'#000000'.encode('ascii'))
for value in test_values:
self.assertRaises(ValueError,
webcolors.html5_parse_simple_color,
value)
def test_serialize_simple_color(self):
"""
Test implementation of the HTML5 simple color serialization
algorithm.
"""
test_pairs = (((0, 0, 0), u'#000000'),
((0, 0, 128), u'#000080'),
((218, 165, 32), u'#daa520'))
for pair in test_pairs:
self.assertEqual(pair[1],
webcolors.html5_serialize_simple_color(pair[0]))
def test_parse_legacy_color(self):
"""
Test implementation of the HTML5 legacy color parsing
algorithm.
"""
# One of these is the famous "chucknorris" value. Another is a
# CSS 2 system color. The final two are randomly-generated but
# believable junk strings. Correct output values obtained
# manually.
test_pairs = ((u'chucknorris', (192, 0, 0)),
(u'Window', (0, 13, 0)),
(u'RE|SXLuAse', (224, 0, 224)),
(u'+=@FnnWL!Yb}5Dk', (0, 0, 176)))
for pair in test_pairs:
self.assertEqual(pair[1],
webcolors.html5_parse_legacy_color(pair[0]))
def test_parse_legacy_color_names(self):
"""
Test the HTML5 legacy color parsing of SVG/CSS3 color names.
"""
for name in webcolors.CSS3_NAMES_TO_HEX.keys():
self.assertEqual(webcolors.name_to_rgb(name),
webcolors.html5_parse_legacy_color(name))
def test_parse_legacy_color_hex(self):
"""
Test the HTML5 legacy color parsing of three- and six-digit
hexadecimal color values.
"""
test_values = (u'#000',
u'#000000',
u'#fff',
u'#ffffff',
u'#000080')
for value in test_values:
self.assertEqual(webcolors.hex_to_rgb(value),
webcolors.html5_parse_legacy_color(value))
def test_parse_legacy_color_error(self):
"""
Test error conditions of the HTML5 legacy color parsing algorithm.
"""
test_values = (u'#000000'.encode('ascii'),
u"transparent",
u'')
for value in test_values:
self.assertRaises(ValueError,
webcolors.html5_parse_legacy_color,
value)
webcolors-1.5/tests/test_integer.py 0000644 0000767 0000767 00000005266 12501405512 017010 0 ustar james 0000000 0000000 import unittest
import webcolors
class IntegerRGBConversionTests(unittest.TestCase):
"""
Test functions which convert from integer RGB triplets to other
formats.
"""
def test_rgb_to_name(self):
"""
Test conversion from integer RGB triplet to color name.
"""
test_pairs = (((255, 255, 255), u'white'),
((0, 0, 128), u'navy'),
((218, 165, 32), u'goldenrod'))
for pair in test_pairs:
self.assertEqual(pair[1],
webcolors.rgb_to_name(pair[0]))
def test_rgb_to_name_unnamed(self):
"""
An integer RGB triplet which does not correspond to a named
color, or does not correspond to a named color in the given
specification, raises ValueError.
"""
# No name in any spec.
self.assertRaises(ValueError,
webcolors.rgb_to_name,
(18, 52, 86))
# This is 'goldenrod' in CSS 3 list, unnamed in HTML 4.
self.assertRaises(ValueError,
webcolors.rgb_to_name,
(218, 165, 32), spec=u'html4')
def test_rgb_to_name_specs(self):
"""
Using one of the supported specifications succeeds; an
unsupported specification raises ValueError.
"""
for supported_spec in (u'html4', u'css2', u'css21', u'css3'):
self.assertEqual(u'white',
webcolors.rgb_to_name((255, 255, 255),
spec=supported_spec))
for unsupported_spec in (u'css1', u'css4', u'html5'):
self.assertRaises(ValueError,
webcolors.rgb_to_name,
(255, 255, 255), spec=unsupported_spec)
def test_rgb_to_hex(self):
"""
Test conversion from integer RGB triplet to hex.
"""
test_pairs = (((255, 255, 255), u'#ffffff'),
((0, 0, 128), u'#000080'),
((218, 165, 32), u'#daa520'))
for pair in test_pairs:
self.assertEqual(pair[1],
webcolors.rgb_to_hex(pair[0]))
def test_rgb_to_rgb_percent(self):
"""
Test conversion from integer RGB triplet to percent RGB
triplet.
"""
test_pairs = (((255, 255, 255), (u'100%', u'100%', u'100%')),
((0, 0, 128), (u'0%', u'0%', u'50%')),
((218, 165, 32), (u'85.49%', u'64.71%', u'12.5%')))
for pair in test_pairs:
self.assertEqual(pair[1],
webcolors.rgb_to_rgb_percent(pair[0]))
webcolors-1.5/tests/test_name.py 0000644 0000767 0000767 00000005032 12501405620 016262 0 ustar james 0000000 0000000 import unittest
import webcolors
class NameConversionTests(unittest.TestCase):
"""
Test functions which convert from color names to other formats.
"""
def test_name_to_hex(self):
"""
Test correct conversion of color names to hex.
"""
test_pairs = ((u'white', u'#ffffff'),
(u'navy', u'#000080'),
(u'goldenrod', u'#daa520'))
for pair in test_pairs:
self.assertEqual(pair[1],
webcolors.name_to_hex(pair[0]))
def test_name_to_hex_bad_name(self):
"""
A name which does not correspond to a color, or does not
correspond to a color in the given specification, raises
ValueError.
"""
test_values = ((u'goldenrod', u'html4'),
(u'glue', u'css21'),
(u'breen', u'css3'))
for value in test_values:
self.assertRaises(ValueError,
webcolors.name_to_hex,
*value)
def test_name_to_hex_specs(self):
"""
Using one of the supported specifications succeeds; using an
unsupported specification raises ValueError.
"""
for supported_spec in (u'html4', u'css2', u'css21', u'css3'):
self.assertEqual(u'#ffffff',
webcolors.name_to_hex(u'white',
spec=supported_spec))
for unsupported_spec in (u'css1', u'css4', u'html5'):
self.assertRaises(ValueError,
webcolors.name_to_hex,
'white', spec=unsupported_spec)
def test_name_to_rgb(self):
"""
Test conversion from color name to integer RGB triplet.
"""
test_pairs = ((u'white', (255, 255, 255)),
(u'navy', (0, 0, 128)),
(u'goldenrod', (218, 165, 32)))
for pair in test_pairs:
self.assertEqual(pair[1],
webcolors.name_to_rgb(pair[0]))
def test_name_to_rgb_percent(self):
"""
Test conversion from color name to percent RGB triplet.
"""
test_pairs = ((u'white', (u'100%', u'100%', u'100%')),
(u'navy', (u'0%', u'0%', u'50%')),
(u'goldenrod', (u'85.49%', u'64.71%', u'12.5%')))
for pair in test_pairs:
self.assertEqual(pair[1],
webcolors.name_to_rgb_percent(pair[0]))
webcolors-1.5/tests/test_normalization.py 0000644 0000767 0000767 00000006227 12501405672 020246 0 ustar james 0000000 0000000 import unittest
import webcolors
class NormalizationTests(unittest.TestCase):
"""
Test both the publicly-exposed and internal normalization
functions.
"""
def test_normalize_hex(self):
"""
Hexadecimal normalization normalizes valid hex color codes to
6 digits, lowercase.
"""
test_pairs = ((u'#0099cc', u'#0099cc'),
(u'#0099CC', u'#0099cc'),
(u'#09c', u'#0099cc'),
(u'#09C', u'#0099cc'))
for pair in test_pairs:
self.assertEqual(pair[1],
webcolors.normalize_hex(pair[0]))
def test_normalize_hex_format(self):
"""
Hex normalization raises ValueError on invalid hex color code.
"""
test_values = (u'0099cc',
'#0000gg',
'#0000',
'#00000000')
for value in test_values:
self.assertRaises(ValueError,
webcolors.normalize_hex,
value)
def test_normalize_integer_rgb(self):
"""
Integer normalization clips to 0-255.
"""
test_pairs = ((255, 255),
(0, 0),
(128, 128),
(-20, 0),
(270, 255),
(-0, 0))
for pair in test_pairs:
self.assertEqual(pair[1],
webcolors._normalize_integer_rgb(pair[0]))
def test_normalize_integer_triplet(self):
"""
Integer triplet normalization clips all values to 0-255.
"""
test_pairs = (((128, 128, 128), (128, 128, 128)),
((0, 0, 0), (0, 0, 0)),
((255, 255, 255), (255, 255, 255)),
((270, -20, 128), (255, 0, 128)),
((-0, -0, -0), (0, 0, 0)))
for pair in test_pairs:
self.assertEqual(pair[1],
webcolors.normalize_integer_triplet(pair[0]))
def test_normalize_percent_rgb(self):
"""
Percent normalization clips to 0%-100%.
"""
test_pairs = ((u'0%', u'0%'),
(u'100%', u'100%'),
(u'62%', u'62%'),
(u'-5%', u'0%'),
(u'250%', u'100%'),
(u'85.49%', u'85.49%'),
(u'-0%', u'0%'))
for pair in test_pairs:
self.assertEqual(pair[1],
webcolors._normalize_percent_rgb(pair[0]))
def test_normalize_percent_triplet(self):
"""
Percent triplet normalization clips all values to 0%-100%.
"""
test_pairs = (((u'50%', u'50%', u'50%'), (u'50%', u'50%', u'50%')),
((u'0%', u'100%', u'0%'), (u'0%', u'100%', u'0%')),
((u'-10%', u'250%', u'500%'), (u'0%', u'100%', u'100%')),
((u'-0%', u'-0%', u'-0%'), (u'0%', u'0%', u'0%')))
for pair in test_pairs:
self.assertEqual(pair[1],
webcolors.normalize_percent_triplet(pair[0]))
webcolors-1.5/tests/test_percent.py 0000644 0000767 0000767 00000005675 12501405746 017030 0 ustar james 0000000 0000000 import unittest
import webcolors
class PercentRGBConversionTests(unittest.TestCase):
"""
Test functions which convert from percent RGB triplets to other
formats.
"""
def test_rgb_percent_to_name(self):
"""
Test conversion from percent RGB triplet to color name.
"""
test_pairs = (((u'100%', u'100%', u'100%'), u'white'),
((u'0%', u'0%', u'50%'), u'navy'),
((u'85.49%', u'64.71%', u'12.5%'), u'goldenrod'))
for pair in test_pairs:
self.assertEqual(pair[1],
webcolors.rgb_percent_to_name(pair[0]))
def test_rgb_percent_to_name_unnamed(self):
"""
A percent RGB triplet which does not correspond to a named
color, or does not correspond to a named color in the given
specification, raises ValueError.
"""
# No name in any spec.
self.assertRaises(ValueError,
webcolors.rgb_percent_to_name,
(u'7.06%', u'20.39%', u'33.73%'))
# This is 'goldenrod' in CSS 3 list, unnamed in HTML 4.
self.assertRaises(ValueError,
webcolors.rgb_percent_to_name,
(u'85.49%', u'64.71%', u'12.5%'), spec=u'html4')
def test_rgb_percent_to_name_specs(self):
"""
Using one of the supported specifications succeeds; an
unsupported specification raises ValueError.
"""
for supported_spec in (u'html4', u'css2', u'css21', u'css3'):
self.assertEqual(u'white',
webcolors.rgb_percent_to_name(
(u'100%', u'100%', u'100%'),
spec=supported_spec))
for unsupported_spec in (u'css1', u'css4', u'html5'):
self.assertRaises(ValueError,
webcolors.rgb_percent_to_name,
(u'100%', u'100%', u'100%'),
spec=unsupported_spec)
def test_rgb_percent_to_hex(self):
"""
Test conversion from percent RGB triplet to hex.
"""
test_pairs = (((u'100%', u'100%', u'0%'), u'#ffff00'),
((u'0%', u'0%', u'50%'), u'#000080'),
((u'85.49%', u'64.71%', u'12.5%'), u'#daa520'))
for pair in test_pairs:
self.assertEqual(pair[1],
webcolors.rgb_percent_to_hex(pair[0]))
def test_rgb_percent_to_rgb(self):
"""
Test conversion from percent RGB triplet to integer RGB
triplet.
"""
test_pairs = (((u'100%', u'100%', u'0%'), (255, 255, 0)),
((u'0%', u'0%', u'50%'), (0, 0, 128)),
((u'85.49%', u'64.71%', u'12.5%'), (218, 165, 32)))
for pair in test_pairs:
self.assertEqual(pair[1],
webcolors.rgb_percent_to_rgb(pair[0]))
webcolors-1.5/webcolors.py 0000644 0000767 0000767 00000064627 12501404154 015160 0 ustar james 0000000 0000000 """
Utility functions for working with the color names and color value
formats defined by the HTML and CSS specifications for use in
documents on the Web.
See documentation (in docs/ directory of source distribution) for
details of the supported formats and conversions.
"""
import math
import re
import string
import struct
# Python 2's unichr() is Python 3's chr().
try:
unichr
except NameError:
unichr = chr
# Python 2's unicode is Python 3's str.
try:
unicode
except NameError:
unicode = str
def _reversedict(d):
"""
Internal helper for generating reverse mappings; given a
dictionary, returns a new dictionary with keys and values swapped.
"""
return dict(zip(d.values(), d.keys()))
HEX_COLOR_RE = re.compile(r'^#([a-fA-F0-9]{3}|[a-fA-F0-9]{6})$')
SUPPORTED_SPECIFICATIONS = (u'html4', u'css2', u'css21', u'css3')
SPECIFICATION_ERROR_TEMPLATE = u"'%%s' is not a supported specification for color name lookups; \
supported specifications are: %s." % (u', '.join(SUPPORTED_SPECIFICATIONS))
# Mappings of color names to normalized hexadecimal color values.
#################################################################
# The HTML 4 named colors.
#
# The canonical source for these color definitions is the HTML 4
# specification:
#
# http://www.w3.org/TR/html401/types.html#h-6.5
#
# The file tests/definitions.py in the source distribution of this
# module downloads a copy of the HTML 4 standard and parses out the
# color names to ensure the values below are correct.
HTML4_NAMES_TO_HEX = {
u'aqua': u'#00ffff',
u'black': u'#000000',
u'blue': u'#0000ff',
u'fuchsia': u'#ff00ff',
u'green': u'#008000',
u'gray': u'#808080',
u'lime': u'#00ff00',
u'maroon': u'#800000',
u'navy': u'#000080',
u'olive': u'#808000',
u'purple': u'#800080',
u'red': u'#ff0000',
u'silver': u'#c0c0c0',
u'teal': u'#008080',
u'white': u'#ffffff',
u'yellow': u'#ffff00',
}
# CSS 2 used the same list as HTML 4.
CSS2_NAMES_TO_HEX = HTML4_NAMES_TO_HEX
# CSS 2.1 added orange.
CSS21_NAMES_TO_HEX = dict(HTML4_NAMES_TO_HEX, orange=u'#ffa500')
# The CSS 3/SVG named colors.
#
# The canonical source for these color definitions is the SVG
# specification's color list (which was adopted as CSS 3's color
# definition):
#
# http://www.w3.org/TR/SVG11/types.html#ColorKeywords
#
# CSS 3 also provides definitions of these colors:
#
# http://www.w3.org/TR/css3-color/#svg-color
#
# SVG provides the definitions as RGB triplets. CSS 3 provides them
# both as RGB triplets and as hexadecimal. Since hex values are more
# common in real-world HTML and CSS, the mapping below is to hex
# values instead. The file tests/definitions.py in the source
# distribution of this module downloads a copy of the CSS 3 color
# module and parses out the color names to ensure the values below are
# correct.
CSS3_NAMES_TO_HEX = {
u'aliceblue': u'#f0f8ff',
u'antiquewhite': u'#faebd7',
u'aqua': u'#00ffff',
u'aquamarine': u'#7fffd4',
u'azure': u'#f0ffff',
u'beige': u'#f5f5dc',
u'bisque': u'#ffe4c4',
u'black': u'#000000',
u'blanchedalmond': u'#ffebcd',
u'blue': u'#0000ff',
u'blueviolet': u'#8a2be2',
u'brown': u'#a52a2a',
u'burlywood': u'#deb887',
u'cadetblue': u'#5f9ea0',
u'chartreuse': u'#7fff00',
u'chocolate': u'#d2691e',
u'coral': u'#ff7f50',
u'cornflowerblue': u'#6495ed',
u'cornsilk': u'#fff8dc',
u'crimson': u'#dc143c',
u'cyan': u'#00ffff',
u'darkblue': u'#00008b',
u'darkcyan': u'#008b8b',
u'darkgoldenrod': u'#b8860b',
u'darkgray': u'#a9a9a9',
u'darkgrey': u'#a9a9a9',
u'darkgreen': u'#006400',
u'darkkhaki': u'#bdb76b',
u'darkmagenta': u'#8b008b',
u'darkolivegreen': u'#556b2f',
u'darkorange': u'#ff8c00',
u'darkorchid': u'#9932cc',
u'darkred': u'#8b0000',
u'darksalmon': u'#e9967a',
u'darkseagreen': u'#8fbc8f',
u'darkslateblue': u'#483d8b',
u'darkslategray': u'#2f4f4f',
u'darkslategrey': u'#2f4f4f',
u'darkturquoise': u'#00ced1',
u'darkviolet': u'#9400d3',
u'deeppink': u'#ff1493',
u'deepskyblue': u'#00bfff',
u'dimgray': u'#696969',
u'dimgrey': u'#696969',
u'dodgerblue': u'#1e90ff',
u'firebrick': u'#b22222',
u'floralwhite': u'#fffaf0',
u'forestgreen': u'#228b22',
u'fuchsia': u'#ff00ff',
u'gainsboro': u'#dcdcdc',
u'ghostwhite': u'#f8f8ff',
u'gold': u'#ffd700',
u'goldenrod': u'#daa520',
u'gray': u'#808080',
u'grey': u'#808080',
u'green': u'#008000',
u'greenyellow': u'#adff2f',
u'honeydew': u'#f0fff0',
u'hotpink': u'#ff69b4',
u'indianred': u'#cd5c5c',
u'indigo': u'#4b0082',
u'ivory': u'#fffff0',
u'khaki': u'#f0e68c',
u'lavender': u'#e6e6fa',
u'lavenderblush': u'#fff0f5',
u'lawngreen': u'#7cfc00',
u'lemonchiffon': u'#fffacd',
u'lightblue': u'#add8e6',
u'lightcoral': u'#f08080',
u'lightcyan': u'#e0ffff',
u'lightgoldenrodyellow': u'#fafad2',
u'lightgray': u'#d3d3d3',
u'lightgrey': u'#d3d3d3',
u'lightgreen': u'#90ee90',
u'lightpink': u'#ffb6c1',
u'lightsalmon': u'#ffa07a',
u'lightseagreen': u'#20b2aa',
u'lightskyblue': u'#87cefa',
u'lightslategray': u'#778899',
u'lightslategrey': u'#778899',
u'lightsteelblue': u'#b0c4de',
u'lightyellow': u'#ffffe0',
u'lime': u'#00ff00',
u'limegreen': u'#32cd32',
u'linen': u'#faf0e6',
u'magenta': u'#ff00ff',
u'maroon': u'#800000',
u'mediumaquamarine': u'#66cdaa',
u'mediumblue': u'#0000cd',
u'mediumorchid': u'#ba55d3',
u'mediumpurple': u'#9370db',
u'mediumseagreen': u'#3cb371',
u'mediumslateblue': u'#7b68ee',
u'mediumspringgreen': u'#00fa9a',
u'mediumturquoise': u'#48d1cc',
u'mediumvioletred': u'#c71585',
u'midnightblue': u'#191970',
u'mintcream': u'#f5fffa',
u'mistyrose': u'#ffe4e1',
u'moccasin': u'#ffe4b5',
u'navajowhite': u'#ffdead',
u'navy': u'#000080',
u'oldlace': u'#fdf5e6',
u'olive': u'#808000',
u'olivedrab': u'#6b8e23',
u'orange': u'#ffa500',
u'orangered': u'#ff4500',
u'orchid': u'#da70d6',
u'palegoldenrod': u'#eee8aa',
u'palegreen': u'#98fb98',
u'paleturquoise': u'#afeeee',
u'palevioletred': u'#db7093',
u'papayawhip': u'#ffefd5',
u'peachpuff': u'#ffdab9',
u'peru': u'#cd853f',
u'pink': u'#ffc0cb',
u'plum': u'#dda0dd',
u'powderblue': u'#b0e0e6',
u'purple': u'#800080',
u'red': u'#ff0000',
u'rosybrown': u'#bc8f8f',
u'royalblue': u'#4169e1',
u'saddlebrown': u'#8b4513',
u'salmon': u'#fa8072',
u'sandybrown': u'#f4a460',
u'seagreen': u'#2e8b57',
u'seashell': u'#fff5ee',
u'sienna': u'#a0522d',
u'silver': u'#c0c0c0',
u'skyblue': u'#87ceeb',
u'slateblue': u'#6a5acd',
u'slategray': u'#708090',
u'slategrey': u'#708090',
u'snow': u'#fffafa',
u'springgreen': u'#00ff7f',
u'steelblue': u'#4682b4',
u'tan': u'#d2b48c',
u'teal': u'#008080',
u'thistle': u'#d8bfd8',
u'tomato': u'#ff6347',
u'turquoise': u'#40e0d0',
u'violet': u'#ee82ee',
u'wheat': u'#f5deb3',
u'white': u'#ffffff',
u'whitesmoke': u'#f5f5f5',
u'yellow': u'#ffff00',
u'yellowgreen': u'#9acd32',
}
# Mappings of normalized hexadecimal color values to color names.
#################################################################
HTML4_HEX_TO_NAMES = _reversedict(HTML4_NAMES_TO_HEX)
CSS2_HEX_TO_NAMES = HTML4_HEX_TO_NAMES
CSS21_HEX_TO_NAMES = _reversedict(CSS21_NAMES_TO_HEX)
CSS3_HEX_TO_NAMES = _reversedict(CSS3_NAMES_TO_HEX)
# Aliases of the above mappings, for backwards compatibility.
#################################################################
(html4_names_to_hex,
css2_names_to_hex,
css21_names_to_hex,
css3_names_to_hex) = (HTML4_NAMES_TO_HEX,
CSS2_NAMES_TO_HEX,
CSS21_NAMES_TO_HEX,
CSS3_NAMES_TO_HEX)
(html4_hex_to_names,
css2_hex_to_names,
css21_hex_to_names,
css3_hex_to_names) = (HTML4_HEX_TO_NAMES,
CSS2_HEX_TO_NAMES,
CSS21_HEX_TO_NAMES,
CSS3_HEX_TO_NAMES)
# Normalization functions.
#################################################################
def normalize_hex(hex_value):
"""
Normalize a hexadecimal color value to 6 digits, lowercase.
"""
match = HEX_COLOR_RE.match(hex_value)
if match is None:
raise ValueError(
u"'%s' is not a valid hexadecimal color value." % hex_value
)
hex_digits = match.group(1)
if len(hex_digits) == 3:
hex_digits = u''.join(2 * s for s in hex_digits)
return u'#%s' % hex_digits.lower()
def _normalize_integer_rgb(value):
"""
Internal normalization function for clipping integer values into
the permitted range (0-255, inclusive).
"""
return 0 if value < 0 \
else 255 if value > 255 \
else value
def normalize_integer_triplet(rgb_triplet):
"""
Normalize an integer ``rgb()`` triplet so that all values are
within the range 0-255 inclusive.
"""
return tuple(_normalize_integer_rgb(value) for value in rgb_triplet)
def _normalize_percent_rgb(value):
"""
Internal normalization function for clipping percent values into
the permitted range (0%-100%, inclusive).
"""
percent = value.split(u'%')[0]
percent = float(percent) if u'.' in percent else int(percent)
return u'0%' if percent < 0 \
else u'100%' if percent > 100 \
else u'%s%%' % percent
def normalize_percent_triplet(rgb_triplet):
"""
Normalize a percentage ``rgb()`` triplet so that all values are
within the range 0%-100% inclusive.
"""
return tuple(_normalize_percent_rgb(value) for value in rgb_triplet)
# Conversions from color names to various formats.
#################################################################
def name_to_hex(name, spec=u'css3'):
"""
Convert a color name to a normalized hexadecimal color value.
The optional keyword argument ``spec`` determines which
specification's list of color names will be used; valid values are
``html4``, ``css2``, ``css21`` and ``css3``, and the default is
``css3``.
When no color of that name exists in the given specification,
``ValueError`` is raised.
"""
if spec not in SUPPORTED_SPECIFICATIONS:
raise ValueError(SPECIFICATION_ERROR_TEMPLATE % spec)
normalized = name.lower()
hex_value = {u'css2': CSS2_NAMES_TO_HEX,
u'css21': CSS21_NAMES_TO_HEX,
u'css3': CSS3_NAMES_TO_HEX,
u'html4': HTML4_NAMES_TO_HEX}[spec].get(normalized)
if hex_value is None:
raise ValueError(
u"'%s' is not defined as a named color in %s." % (name, spec)
)
return hex_value
def name_to_rgb(name, spec=u'css3'):
"""
Convert a color name to a 3-tuple of integers suitable for use in
an ``rgb()`` triplet specifying that color.
"""
return hex_to_rgb(name_to_hex(name, spec=spec))
def name_to_rgb_percent(name, spec=u'css3'):
"""
Convert a color name to a 3-tuple of percentages suitable for use
in an ``rgb()`` triplet specifying that color.
"""
return rgb_to_rgb_percent(name_to_rgb(name, spec=spec))
# Conversions from hexadecimal color values to various formats.
#################################################################
def hex_to_name(hex_value, spec=u'css3'):
"""
Convert a hexadecimal color value to its corresponding normalized
color name, if any such name exists.
The optional keyword argument ``spec`` determines which
specification's list of color names will be used; valid values are
``html4``, ``css2``, ``css21`` and ``css3``, and the default is
``css3``.
When no color name for the value is found in the given
specification, ``ValueError`` is raised.
"""
if spec not in SUPPORTED_SPECIFICATIONS:
raise ValueError(SPECIFICATION_ERROR_TEMPLATE % spec)
normalized = normalize_hex(hex_value)
name = {u'css2': CSS2_HEX_TO_NAMES,
u'css21': CSS21_HEX_TO_NAMES,
u'css3': CSS3_HEX_TO_NAMES,
u'html4': HTML4_HEX_TO_NAMES}[spec].get(normalized)
if name is None:
raise ValueError(
u"'%s' has no defined color name in %s." % (hex_value, spec)
)
return name
def hex_to_rgb(hex_value):
"""
Convert a hexadecimal color value to a 3-tuple of integers
suitable for use in an ``rgb()`` triplet specifying that color.
"""
hex_value = normalize_hex(hex_value)
hex_value = int(hex_value[1:], 16)
return (hex_value >> 16,
hex_value >> 8 & 0xff,
hex_value & 0xff)
def hex_to_rgb_percent(hex_value):
"""
Convert a hexadecimal color value to a 3-tuple of percentages
suitable for use in an ``rgb()`` triplet representing that color.
"""
return rgb_to_rgb_percent(hex_to_rgb(hex_value))
# Conversions from integer rgb() triplets to various formats.
#################################################################
def rgb_to_name(rgb_triplet, spec=u'css3'):
"""
Convert a 3-tuple of integers, suitable for use in an ``rgb()``
color triplet, to its corresponding normalized color name, if any
such name exists.
The optional keyword argument ``spec`` determines which
specification's list of color names will be used; valid values are
``html4``, ``css2``, ``css21`` and ``css3``, and the default is
``css3``.
If there is no matching name, ``ValueError`` is raised.
"""
return hex_to_name(
rgb_to_hex(
normalize_integer_triplet(rgb_triplet)),
spec=spec)
def rgb_to_hex(rgb_triplet):
"""
Convert a 3-tuple of integers, suitable for use in an ``rgb()``
color triplet, to a normalized hexadecimal value for that color.
"""
return u'#%02x%02x%02x' % normalize_integer_triplet(rgb_triplet)
def rgb_to_rgb_percent(rgb_triplet):
"""
Convert a 3-tuple of integers, suitable for use in an ``rgb()``
color triplet, to a 3-tuple of percentages suitable for use in
representing that color.
This function makes some trade-offs in terms of the accuracy of
the final representation; for some common integer values,
special-case logic is used to ensure a precise result (e.g.,
integer 128 will always convert to '50%', integer 32 will always
convert to '12.5%'), but for all other values a standard Python
``float`` is used and rounded to two decimal places, which may
result in a loss of precision for some values.
"""
# In order to maintain precision for common values,
# special-case them.
specials = {255: u'100%', 128: u'50%', 64: u'25%',
32: u'12.5%', 16: u'6.25%', 0: u'0%'}
return tuple(specials.get(d, u'%.02f%%' % (d / 255.0 * 100))
for d in normalize_integer_triplet(rgb_triplet))
# Conversions from percentage rgb() triplets to various formats.
#################################################################
def rgb_percent_to_name(rgb_percent_triplet, spec=u'css3'):
"""
Convert a 3-tuple of percentages, suitable for use in an ``rgb()``
color triplet, to its corresponding normalized color name, if any
such name exists.
The optional keyword argument ``spec`` determines which
specification's list of color names will be used; valid values are
``html4``, ``css2``, ``css21`` and ``css3``, and the default is
``css3``.
If there is no matching name, ``ValueError`` is raised.
"""
return rgb_to_name(
rgb_percent_to_rgb(
normalize_percent_triplet(
rgb_percent_triplet)),
spec=spec)
def rgb_percent_to_hex(rgb_percent_triplet):
"""
Convert a 3-tuple of percentages, suitable for use in an ``rgb()``
color triplet, to a normalized hexadecimal color value for that
color.
"""
return rgb_to_hex(
rgb_percent_to_rgb(
normalize_percent_triplet(rgb_percent_triplet)))
def _percent_to_integer(percent):
"""
Internal helper for converting a percentage value to an integer
between 0 and 255 inclusive.
"""
num = float(percent.split(u'%')[0]) / 100 * 255
e = num - math.floor(num)
return e < 0.5 and int(math.floor(num)) or int(math.ceil(num))
def rgb_percent_to_rgb(rgb_percent_triplet):
"""
Convert a 3-tuple of percentages, suitable for use in an ``rgb()``
color triplet, to a 3-tuple of integers suitable for use in
representing that color.
Some precision may be lost in this conversion. See the note
regarding precision for ``rgb_to_rgb_percent()`` for details.
"""
return tuple(map(_percent_to_integer,
normalize_percent_triplet(rgb_percent_triplet)))
# HTML5 color algorithms.
#################################################################
# These functions are written in a way that may seem strange to
# developers familiar with Python, because they do not use the most
# efficient or idiomatic way of accomplishing their tasks. This is
# because, for compliance, these functions are written as literal
# translations into Python of the algorithms in HTML5.
#
# For ease of understanding, the relevant steps of the algorithm from
# the standard are included as comments interspersed in the
# implementation.
def html5_parse_simple_color(input):
"""
Apply the simple color parsing algorithm from section 2.4.6 of
HTML5.
"""
# 1. Let input be the string being parsed.
#
# 2. If input is not exactly seven characters long, then return an
# error.
if not isinstance(input, unicode) or len(input) != 7:
raise ValueError(
u"An HTML5 simple color must be a Unicode string "
u"exactly seven characters long."
)
# 3. If the first character in input is not a U+0023 NUMBER SIGN
# character (#), then return an error.
if not input.startswith('#'):
raise ValueError(
u"An HTML5 simple color must begin with the "
u"character '#' (U+0023)."
)
# 4. If the last six characters of input are not all ASCII hex
# digits, then return an error.
if not all(c in string.hexdigits for c in input[1:]):
raise ValueError(
u"An HTML5 simple color must contain exactly six ASCII hex digits."
)
# 5. Let result be a simple color.
#
# 6. Interpret the second and third characters as a hexadecimal
# number and let the result be the red component of result.
#
# 7. Interpret the fourth and fifth characters as a hexadecimal
# number and let the result be the green component of result.
#
# 8. Interpret the sixth and seventh characters as a hexadecimal
# number and let the result be the blue component of result.
#
# 9. Return result.
result = (int(input[1:3], 16),
int(input[3:5], 16),
int(input[5:7], 16))
return result
def html5_serialize_simple_color(simple_color):
"""
Apply the serialization algorithm for a simple color from section
2.4.6 of HTML5.
"""
red, green, blue = simple_color
# 1. Let result be a string consisting of a single "#" (U+0023)
# character.
result = u'#'
# 2. Convert the red, green, and blue components in turn to
# two-digit hexadecimal numbers using lowercase ASCII hex
# digits, zero-padding if necessary, and append these numbers
# to result, in the order red, green, blue.
result += (u"%02x" % red).lower()
result += (u"%02x" % green).lower()
result += (u"%02x" % blue).lower()
# 3. Return result, which will be a valid lowercase simple color.
return result
def html5_parse_legacy_color(input):
"""
Apply the legacy color parsing algorithm from section 2.4.6 of
HTML5.
"""
# 1. Let input be the string being parsed.
if not isinstance(input, unicode):
raise ValueError(
u"HTML5 legacy color parsing requires a Unicode string as input."
)
# 2. If input is the empty string, then return an error.
if input == "":
raise ValueError(
u"HTML5 legacy color parsing forbids empty string as a value."
)
# 3. Strip leading and trailing whitespace from input.
input = input.strip()
# 4. If input is an ASCII case-insensitive match for the string
# "transparent", then return an error.
if input.lower() == u"transparent":
raise ValueError(
u'HTML5 legacy color parsing forbids "transparent" as a value.'
)
# 5. If input is an ASCII case-insensitive match for one of the
# keywords listed in the SVG color keywords section of the CSS3
# Color specification, then return the simple color
# corresponding to that keyword.
keyword_hex = CSS3_NAMES_TO_HEX.get(input.lower())
if keyword_hex is not None:
return html5_parse_simple_color(keyword_hex)
# 6. If input is four characters long, and the first character in
# input is a "#" (U+0023) character, and the last three
# characters of input are all ASCII hex digits, then run these
# substeps:
if len(input) == 4 and \
input.startswith(u'#') and \
all(c in string.hexdigits for c in input[1:]):
# 1. Let result be a simple color.
#
# 2. Interpret the second character of input as a hexadecimal
# digit; let the red component of result be the resulting
# number multiplied by 17.
#
# 3. Interpret the third character of input as a hexadecimal
# digit; let the green component of result be the resulting
# number multiplied by 17.
#
# 4. Interpret the fourth character of input as a hexadecimal
# digit; let the blue component of result be the resulting
# number multiplied by 17.
result = (int(input[1], 16) * 17,
int(input[2], 16) * 17,
int(input[3], 16) * 17)
# 5. Return result.
return result
# 7. Replace any characters in input that have a Unicode code
# point greater than U+FFFF (i.e. any characters that are not
# in the basic multilingual plane) with the two-character
# string "00".
# This one's a bit weird due to the existence of multiple internal
# Unicode string representations in different versions and builds
# of Python.
#
# From Python 2.2 through 3.2, Python could be compiled with
# "narrow" or "wide" Unicode strings (see PEP 261). Narrow builds
# handled Unicode strings with two-byte characters and surrogate
# pairs for non-BMP code points. Wide builds handled Unicode
# strings with four-byte characters and no surrogates. This means
# ord() is only sufficient to identify a non-BMP character on a
# wide build.
#
# Starting with Python 3.3, the internal string representation
# (see PEP 393) is now dynamic, and Python chooses an encoding --
# either latin-1, UCS-2 or UCS-4 -- wide enough to handle the
# highest code point in the string.
#
# The code below bypasses all of that for a consistently effective
# method: encode the string to little-endian UTF-32, then perform
# a binary unpack of it as four-byte integers. Those integers will
# be the Unicode code points, and from there filtering out non-BMP
# code points is easy.
encoded_input = input.encode('utf_32_le')
# Format string is '<' (for little-endian byte order), then a
# sequence of 'L' characters (for 4-byte unsigned long integer)
# equal to the length of the original string, which is also
# one-fourth the encoded length. For example, for a six-character
# input the generated format string will be ' 0xffff
else unichr(c)
for c in codepoints)
# 8. If input is longer than 128 characters, truncate input,
# leaving only the first 128 characters.
if len(input) > 128:
input = input[:128]
# 9. If the first character in input is a "#" (U+0023) character,
# remove it.
if input.startswith(u'#'):
input = input[1:]
# 10. Replace any character in input that is not an ASCII hex
# digit with the character "0" (U+0030).
if any(c for c in input if c not in string.hexdigits):
input = ''.join(c if c in string.hexdigits else u'0' for c in input)
# 11. While input's length is zero or not a multiple of three,
# append a "0" (U+0030) character to input.
while (len(input) == 0) or (len(input) % 3 != 0):
input += u'0'
# 12. Split input into three strings of equal length, to obtain
# three components. Let length be the length of those
# components (one third the length of input).
length = int(len(input) / 3)
red = input[:length]
green = input[length:length*2]
blue = input[length*2:]
# 13. If length is greater than 8, then remove the leading
# length-8 characters in each component, and let length be 8.
if length > 8:
red, green, blue = (red[length-8:],
green[length-8:],
blue[length-8:])
length = 8
# 14. While length is greater than two and the first character in
# each component is a "0" (U+0030) character, remove that
# character and reduce length by one.
while (length > 2) and (red[0] == u'0' and
green[0] == u'0' and
blue[0] == u'0'):
red, green, blue = (red[1:],
green[1:],
blue[1:])
length -= 1
# 15. If length is still greater than two, truncate each
# component, leaving only the first two characters in each.
if length > 2:
red, green, blue = (red[:2],
green[:2],
blue[:2])
# 16. Let result be a simple color.
#
# 17. Interpret the first component as a hexadecimal number; let
# the red component of result be the resulting number.
#
# 18. Interpret the second component as a hexadecimal number; let
# the green component of result be the resulting number.
#
# 19. Interpret the third component as a hexadecimal number; let
# the blue component of result be the resulting number.
result = (int(red, 16),
int(green, 16),
int(blue, 16))
# 20. Return result.
return result