Skip to content

Commit b8a58fb

Browse files
authored
Merge pull request #3 from PyDevices/cursor/api-docstrings-a2a7
Add Google-style docstrings for RTD API reference
2 parents 916bbe5 + 818ac95 commit b8a58fb

4 files changed

Lines changed: 219 additions & 92 deletions

File tree

src/palettes/__init__.py

Lines changed: 138 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
11
# SPDX-FileCopyrightText: 2024 Brad Barnett
22
#
33
# SPDX-License-Identifier: MIT
4-
"""
5-
`palettes`
6-
====================================================
4+
"""Color palette toolkit for pydisplay.
5+
6+
Provides named color sets, RGB/HSV wheels, RGB cubes, and Material Design
7+
swatches. Palettes map integer indices to display-ready color values at
8+
several bit depths (4, 8, 16, or 24).
9+
10+
Example:
11+
>>> from palettes import get_palette
12+
>>> palette = get_palette(name="wheel", length=256, saturation=1.0)
13+
>>> palette[0]
14+
>>> palette.color_name(0)
15+
16+
Attributes:
17+
WIN16: Mapping of ``0xRRGGBB`` values to Windows 16-color names. Used as
18+
the default name table for :class:`Palette` and
19+
:class:`~palettes.wheel.WheelPalette`.
720
"""
821

9-
# The 16 colors of the standard Windows 16-color palette
1022
WIN16 = {
1123
0x000000: "Black",
1224
0x000080: "Navy",
@@ -28,6 +40,21 @@
2840

2941

3042
def get_palette(name="default", **kwargs):
43+
"""Construct a palette by logical name.
44+
45+
Args:
46+
name: Palette type. One of ``"default"`` (Windows 16-color),
47+
``"wheel"``, ``"cube"``, or ``"material_design"``. Unknown names
48+
fall back to :class:`Palette`.
49+
**kwargs: Forwarded to the palette constructor (for example
50+
``color_depth``, ``length``, ``size``, ``saturation``).
51+
52+
Returns:
53+
A :class:`Palette` subclass instance.
54+
55+
Example:
56+
>>> get_palette(name="cube", size=3, color_depth=16)
57+
"""
3158
if name == "wheel":
3259
from .wheel import WheelPalette as MyPalette
3360
elif name == "material_design":
@@ -40,8 +67,21 @@ def get_palette(name="default", **kwargs):
4067

4168

4269
class Palette:
43-
"""
44-
A class to represent a color palette.
70+
"""Indexed color palette with optional named color attributes.
71+
72+
Subclasses override :meth:`_get_rgb` to define how each index maps to
73+
red, green, and blue components. :meth:`__getitem__` converts those
74+
components to the configured ``color_depth``.
75+
76+
Named colors from the palette's name table (for example ``palette.RED``)
77+
are attached as attributes during initialization.
78+
79+
Args:
80+
name: Optional label stored in :attr:`name`.
81+
color_depth: Output format for :meth:`__getitem__`: ``4`` (24-bit
82+
index), ``8`` (RGB332), ``16`` (RGB565), or ``24`` (``0xRRGGBB``).
83+
swapped: If ``True``, byte-swap 16-bit colors (little-endian displays).
84+
cached: If ``True``, memoize computed index colors in an internal dict.
4585
"""
4686

4787
def __init__(self, name="", color_depth=16, swapped=False, cached=False):
@@ -69,16 +109,32 @@ def _define_named_colors(self):
69109

70110
@property
71111
def name(self):
112+
"""Human-readable palette label."""
72113
return self._name
73114

74115
def __iter__(self):
116+
"""Yield each palette entry in index order."""
75117
for i in range(len(self)):
76118
yield self[i]
77119

78120
def __len__(self):
121+
"""Number of colors in the palette."""
79122
return self._length
80123

81124
def __getitem__(self, index):
125+
"""Return the color at ``index`` in the configured bit depth.
126+
127+
Negative indices and indices beyond the palette length wrap around.
128+
129+
Args:
130+
index: Color index (supports negative and out-of-range values).
131+
132+
Returns:
133+
Color value as an integer (format depends on ``color_depth``).
134+
135+
Raises:
136+
ValueError: If ``color_depth`` is not 4, 8, 16, or 24.
137+
"""
82138
index = self._normalize(index)
83139

84140
if self._cache is not None and index in self._cache:
@@ -101,6 +157,17 @@ def _normalize(self, index):
101157
return index
102158

103159
def color565(self, r, g=None, b=None):
160+
"""Convert RGB to a 16-bit RGB565 value.
161+
162+
Args:
163+
r: Red component (0–255), a 24-bit ``0xRRGGBB`` integer, or an
164+
``(r, g, b)`` sequence.
165+
g: Green component when ``r`` is passed separately.
166+
b: Blue component when ``r`` is passed separately.
167+
168+
Returns:
169+
16-bit color, optionally byte-swapped when ``swapped`` is ``True``.
170+
"""
104171
if isinstance(r, (tuple, list)):
105172
# r is a tuple or list
106173
r, g, b = r
@@ -115,6 +182,17 @@ def color565(self, r, g=None, b=None):
115182
return color
116183

117184
def color332(self, r, g=None, b=None):
185+
"""Convert RGB to an 8-bit RGB332 value.
186+
187+
Args:
188+
r: Red component (0–255), a 24-bit ``0xRRGGBB`` integer, or an
189+
``(r, g, b)`` sequence.
190+
g: Green component when ``r`` is passed separately.
191+
b: Blue component when ``r`` is passed separately.
192+
193+
Returns:
194+
8-bit RGB332 color.
195+
"""
118196
# Convert r, g, b to 8-bit
119197
if isinstance(r, (tuple, list)):
120198
# r is a tuple or list
@@ -127,8 +205,14 @@ def color332(self, r, g=None, b=None):
127205
return color
128206

129207
def color_rgb(self, color):
130-
"""
131-
color can be an 16-bit integer or a tuple, list or bytearray of length 2 or 3.
208+
"""Expand a packed color to an ``(r, g, b)`` tuple.
209+
210+
Args:
211+
color: A 16-bit integer, or a 2- or 3-byte sequence in display
212+
byte order.
213+
214+
Returns:
215+
``(red, green, blue)`` with each component in ``0``–``255``.
132216
"""
133217
if isinstance(color, int):
134218
# convert 16-bit int color to 2 bytes
@@ -142,18 +226,53 @@ def color_rgb(self, color):
142226
return (r, g, b)
143227

144228
def color_name(self, index):
229+
"""Return the name of the color at ``index``.
230+
231+
Args:
232+
index: Palette index (supports wrapping).
233+
234+
Returns:
235+
A name from the palette name table, or a ``"#RRGGBB"`` hex string
236+
when no name matches.
237+
"""
145238
return self.rgb_name(self._get_rgb(self._normalize(index)))
146239

147240
def rgb_name(self, r, g=None, b=None):
241+
"""Look up a color name from RGB components.
242+
243+
Args:
244+
r: Red (0–255), a 24-bit integer, or an ``(r, g, b)`` sequence.
245+
g: Green when ``r`` is passed separately.
246+
b: Blue when ``r`` is passed separately.
247+
248+
Returns:
249+
Matching name from :attr:`_names`, or ``"#RRGGBB"`` if unknown.
250+
"""
148251
if isinstance(r, (tuple, list)):
149252
r, g, b = r
150253
return self._names.get(r << 16 | g << 8 | b, f"#{r:02X}{g:02X}{b:02X}")
151254

152255
def luminance(self, index):
256+
"""Perceived brightness of the color at ``index`` (ITU-R BT.601).
257+
258+
Args:
259+
index: Palette index.
260+
261+
Returns:
262+
Luminance in ``0.0``–``255.0``.
263+
"""
153264
r, g, b = self._get_rgb(index)
154265
return 0.299 * r + 0.587 * g + 0.114 * b
155266

156267
def brightness(self, index):
268+
"""Average channel brightness of the color at ``index``.
269+
270+
Args:
271+
index: Palette index.
272+
273+
Returns:
274+
Normalized brightness in ``0.0``–``1.0``.
275+
"""
157276
r, g, b = self._get_rgb(index)
158277
return (r + g + b) / 3 / 255
159278

@@ -163,8 +282,17 @@ def _get_rgb(self, index):
163282

164283

165284
class MappedPalette(Palette):
166-
"""
167-
A class to represent a color palette with a color map.
285+
"""Palette backed by a flat RGB byte map.
286+
287+
Each color occupies three consecutive bytes ``(r, g, b)`` in
288+
``color_map``. Subclasses such as :class:`~palettes.material_design.MDPalette`
289+
supply a pre-built map and named-color attributes.
290+
291+
Args:
292+
name: Optional label stored in :attr:`name`.
293+
color_depth: Output format for :meth:`Palette.__getitem__`.
294+
swapped: Byte-swap 16-bit colors when ``True``.
295+
color_map: ``bytes`` or buffer of RGB triplets, length ``3 * n_colors``.
168296
"""
169297

170298
def __init__(self, name, color_depth, swapped, color_map):

src/palettes/cube.py

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,34 @@
1-
# SPDIX:# SPDX-FileCopyrightText: 2024 Brad Barnett
1+
# SPDX-FileCopyrightText: 2024 Brad Barnett
22
#
33
# SPDX-License-Identifier: MIT
4-
"""
5-
`palettes.cube`
6-
====================================================
7-
Makes a color cube palette.
8-
9-
Usage:
10-
from palettes import get_palette
11-
palette = get_palette(name="cube", size=5, color_depth=16, swapped=False)
12-
# OR
13-
palette = get_palette(name="cube")
14-
15-
# OR
16-
from palettes.cube import CubePalette
17-
palette = CubePalette(size=5, color_depth=24)
18-
19-
print(f"Palette: {palette.name}, Length: {len(palette)}")
20-
for i, color in enumerate(palette):
21-
for i, color in enumerate(palette): print(f"{i}. {color:#06X} {palette.color_name(i)}")
4+
"""RGB color-cube palettes.
5+
6+
Samples the RGB cube at evenly spaced points. Supported cube sizes are
7+
2, 3, 4, and 5 (8, 27, 64, or 125 colors). Each size uses a built-in
8+
name table for :meth:`~palettes.Palette.color_name`.
9+
10+
Example:
11+
>>> from palettes import get_palette
12+
>>> palette = get_palette(name="cube", size=5, color_depth=16)
13+
>>> len(palette)
14+
125
2215
"""
2316

2417
from . import Palette as _Palette
2518

2619

2720
class CubePalette(_Palette):
28-
"""
29-
A color cube palette. The size of the cube is determined by the size parameter.
21+
"""Evenly spaced RGB cube palette.
22+
23+
Indices traverse the cube in ``x``, then ``y``, then ``z`` order. Channel
24+
values are spaced from ``0`` to ``255`` inclusive.
25+
26+
Args:
27+
name: Prefix for :attr:`~palettes.Palette.name` (length suffix is added).
28+
color_depth: Output format; see :class:`~palettes.Palette`.
29+
swapped: Byte-swap 16-bit colors when ``True``.
30+
cached: Memoize index lookups when ``True`` (default).
31+
size: Cube edge length. Must be ``2``, ``3``, ``4``, or ``5``.
3032
"""
3133

3234
def __init__(self, name="", color_depth=16, swapped=False, cached=True, size=5):

src/palettes/material_design.py

Lines changed: 24 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,39 @@
11
# SPDX-FileCopyrightText: 2024 Brad Barnett
22
#
33
# SPDX-License-Identifier: MIT
4-
"""
5-
`palettes.material_design`
6-
====================================================
7-
This module contains the Material Design color palette as a class object.
8-
9-
10-
Usage:
11-
from palettes import get_palette
12-
palette = get_palette(name="material_design", color_depth=16, swapped=False)
13-
# OR
14-
palette = get_palette("material_design")
15-
16-
# OR
17-
from palettes.material_design import MDPalette
18-
palette = MDPalette(size=5, color_depth=24)
19-
20-
# to access the primary variant of a color family by name:
21-
x = palette.RED
22-
x = palette.BLACK
4+
"""Material Design color palette.
235
24-
# to access all 256 colors directly:
25-
x = palette[127] # color at index 127
6+
256 swatches from the Material Design spec, exposed as indexed colors and
7+
named attributes. Each hue family includes shades ``S50``–``S900``; most
8+
families also provide accent colors ``A100``, ``A200``, ``A400``, and
9+
``A700``.
2610
27-
# to access a shade by name:
28-
x = palette.RED_S500 # shade 500
29-
x = palette.RED_S900 # shade 900
30-
x = palette.RED_S50 # shade 50
31-
32-
# to access an accent of a color family by name:
33-
x = palette.RED_A100
34-
x = palette.RED_A700
35-
36-
# to iterate over all 256 colors:
37-
for x in palette:
38-
pass
11+
Example:
12+
>>> from palettes import get_palette
13+
>>> palette = get_palette(name="material_design", color_depth=16)
14+
>>> palette.RED
15+
>>> palette.RED_S900
16+
>>> palette[127]
3917
"""
4018

4119
from . import MappedPalette
4220
from ._material_design import COLORS, FAMILIES, LENGTHS
4321

4422

4523
class MDPalette(MappedPalette):
46-
"""
47-
A class to represent the Material Design color palette.
24+
"""Material Design swatch palette.
25+
26+
Colors are stored in a flat RGB map. During initialization, named
27+
attributes are created for each family and shade (for example
28+
``RED``, ``RED_S500``, ``RED_A700``). The unsuffixed name always
29+
refers to the ``S500`` primary shade.
30+
31+
Args:
32+
name: Label for :attr:`~palettes.Palette.name`; defaults to
33+
``"MaterialDesign"`` when empty.
34+
color_depth: Output format; see :class:`~palettes.Palette`.
35+
swapped: Byte-swap 16-bit colors when ``True``.
36+
color_map: RGB byte map; defaults to the built-in Material Design table.
4837
"""
4938

5039
_shades = [

0 commit comments

Comments
 (0)