cheerlights-api 0.1.2__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2 @@
1
+ # Auto detect text files and perform LF normalization
2
+ * text=auto
@@ -0,0 +1,27 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ test:
13
+ runs-on: ubuntu-latest
14
+ strategy:
15
+ fail-fast: false
16
+ matrix:
17
+ python: ["3.10", "3.11", "3.12", "3.13", "3.14"]
18
+ steps:
19
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
20
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
21
+ with:
22
+ python-version: ${{ matrix.python }}
23
+ - run: uv sync --locked
24
+ - run: uv run pytest
25
+ - run: uv run ruff check .
26
+ - run: uv run ruff format --check .
27
+ - run: uv run mypy src
@@ -0,0 +1,57 @@
1
+ # Publishes to PyPI when a GitHub release is published, using PyPI Trusted Publishing:
2
+ # PyPI trusts this workflow directly, so no API token is stored anywhere.
3
+ # One-time setup on pypi.org: a trusted publisher for owner cheerlights, repository cheerlights-python-package,
4
+ # workflow publish.yml, environment pypi.
5
+ name: Publish to PyPI
6
+
7
+ on:
8
+ release:
9
+ types: [published]
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ jobs:
15
+ test:
16
+ runs-on: ubuntu-latest
17
+ strategy:
18
+ matrix:
19
+ python: ["3.10", "3.11", "3.12", "3.13", "3.14"]
20
+ steps:
21
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
22
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
23
+ with:
24
+ python-version: ${{ matrix.python }}
25
+ - run: uv sync --locked
26
+ - run: uv run pytest
27
+
28
+ build:
29
+ needs: test
30
+ runs-on: ubuntu-latest
31
+ steps:
32
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
33
+ - uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
34
+ - name: Check the release tag matches the package version
35
+ run: |
36
+ version=$(uv version --short)
37
+ test "v$version" = "$GITHUB_REF_NAME" || { echo "tag $GITHUB_REF_NAME does not match version $version"; exit 1; }
38
+ - run: uv build
39
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
40
+ with:
41
+ name: dist
42
+ path: dist/
43
+
44
+ publish:
45
+ needs: build
46
+ runs-on: ubuntu-latest
47
+ environment:
48
+ name: pypi
49
+ url: https://pypi.org/project/cheerlights-api/
50
+ permissions:
51
+ id-token: write
52
+ steps:
53
+ - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
54
+ with:
55
+ name: dist
56
+ path: dist/
57
+ - uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
@@ -0,0 +1,185 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py,cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # poetry
98
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
102
+ #poetry.lock
103
+
104
+ # pdm
105
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
106
+ #pdm.lock
107
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
108
+ # in version control.
109
+ # https://pdm.fming.dev/#use-with-ide
110
+ .pdm.toml
111
+
112
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
113
+ __pypackages__/
114
+
115
+ # Celery stuff
116
+ celerybeat-schedule
117
+ celerybeat.pid
118
+
119
+ # SageMath parsed files
120
+ *.sage.py
121
+
122
+ # Environments
123
+ .env
124
+ .venv
125
+ env/
126
+ venv/
127
+ ENV/
128
+ env.bak/
129
+ venv.bak/
130
+
131
+ # Spyder project settings
132
+ .spyderproject
133
+ .spyproject
134
+
135
+ # Rope project settings
136
+ .ropeproject
137
+
138
+ # mkdocs documentation
139
+ /site
140
+
141
+ # mypy
142
+ .mypy_cache/
143
+ .dmypy.json
144
+ dmypy.json
145
+
146
+ # Pyre type checker
147
+ .pyre/
148
+
149
+ # pytype static type analyzer
150
+ .pytype/
151
+
152
+ # Cython debug symbols
153
+ cython_debug/
154
+
155
+ # PyCharm
156
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
157
+ # be added to the global gitignore or merged into this project gitignore. For a PyCharm
158
+ # project, it is recommended to exclude the entire .idea directory.
159
+ .idea/
160
+
161
+ # VS Code
162
+ .vscode/
163
+
164
+ # macOS
165
+ .DS_Store
166
+
167
+ # Windows
168
+ Thumbs.db
169
+ ehthumbs.db
170
+ Desktop.ini
171
+
172
+ # Linux
173
+ *~
174
+
175
+ # Temporary files
176
+ *.tmp
177
+ *.temp
178
+ *.swp
179
+ *.swo
180
+
181
+ # uv
182
+ .python-version
183
+
184
+ # MCP specific
185
+ *.mcp
@@ -0,0 +1,112 @@
1
+ Metadata-Version: 2.5
2
+ Name: cheerlights-api
3
+ Version: 0.2.0
4
+ Summary: Read the live CheerLights color, its history, and the CheerLights palette
5
+ Project-URL: Homepage, https://cheerlights.com
6
+ Project-URL: Repository, https://github.com/cheerlights/cheerlights-python-package
7
+ Project-URL: Issues, https://github.com/cheerlights/cheerlights-python-package/issues
8
+ Author-email: CheerLights Community <info@cheerlights.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: cheerlights,color,iot,led,thingspeak
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: Education
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Topic :: Home Automation
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.10
24
+ Requires-Dist: requests>=2.32
25
+ Description-Content-Type: text/markdown
26
+
27
+ # CheerLights API for Python
28
+
29
+ A small Python package that reads the live CheerLights color, its recent history, and the CheerLights palette.
30
+
31
+ [![PyPI](https://img.shields.io/pypi/v/cheerlights-api)](https://pypi.org/project/cheerlights-api/) [![Python](https://img.shields.io/pypi/pyversions/cheerlights-api)](https://pypi.org/project/cheerlights-api/) [![CI](https://github.com/cheerlights/cheerlights-python-package/actions/workflows/ci.yml/badge.svg)](https://github.com/cheerlights/cheerlights-python-package/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/license-MIT-yellow)](https://github.com/cheerlights/cheerlights-python-package/blob/main/LICENSE)
32
+
33
+ [CheerLights](https://cheerlights.com) is a global network of lights that all show the same color, set by anyone on the [CheerLights Discord](https://cheerlights.com/discord).
34
+ This package reads the public CheerLights feed (ThingSpeak channel 1417), so a Python script on a laptop or a Raspberry Pi can follow the color.
35
+ It needs no API key and depends only on `requests`.
36
+
37
+ ## Quick start
38
+
39
+ Install it from [PyPI](https://pypi.org/project/cheerlights-api/) (Python 3.10 or later):
40
+
41
+ ```bash
42
+ pip install cheerlights-api
43
+ ```
44
+
45
+ Then read the current color:
46
+
47
+ ```python
48
+ import cheerlights_api
49
+
50
+ print(cheerlights_api.get_current_color())
51
+ ```
52
+
53
+ ## Example
54
+
55
+ ```python
56
+ import cheerlights_api
57
+
58
+ current = cheerlights_api.get_current_color()
59
+ print(current)
60
+ print(cheerlights_api.hex_to_rgb(current["hex"]))
61
+
62
+ for change in cheerlights_api.get_color_history(3):
63
+ print(change)
64
+ ```
65
+
66
+ Output from version 0.2.0 on 2026-10-29:
67
+
68
+ ```text
69
+ {'color': 'red', 'hex': '#ff0000'}
70
+ (255, 0, 0)
71
+ {'color': 'cyan', 'hex': '#00ffff', 'timestamp': '2026-10-29T17:01:36Z'}
72
+ {'color': 'purple', 'hex': '#800080', 'timestamp': '2026-10-29T17:20:53Z'}
73
+ {'color': 'red', 'hex': '#ff0000', 'timestamp': '2026-10-29T18:00:53Z'}
74
+ ```
75
+
76
+ The `(255, 0, 0)` tuple is what an RGB LED or a NeoPixel library takes.
77
+
78
+ ## Features
79
+
80
+ - The current color as a name and a HEX value: `get_current_color()`, `get_current_color_name()`, `get_current_hex()`.
81
+ - The last 1 to 8000 color changes with the time each was set, oldest first: `get_color_history(count)`.
82
+ - The 11 official CheerLights colors with their HEX values, as the feed publishes them: `COLORS`.
83
+ - Name and HEX helpers: `color_name_to_hex("Old Lace")` gives `#fdf5e6`, `hex_to_rgb("#ffa500")` gives `(255, 165, 0)`, `is_valid_color("pink")` gives `True`.
84
+ - Type hints throughout, checked with mypy in strict mode.
85
+ - A 10 second timeout on every request, and clear errors: `requests` exceptions when the feed cannot be reached, `LookupError` when it returns no color, `ValueError` for bad input.
86
+
87
+ ## Limits
88
+
89
+ - It reads the color; it cannot set it. Anyone sets the color with the `/cheerlights` command on the [CheerLights Discord](https://cheerlights.com/discord).
90
+ - It polls the feed. For a light that changes the moment the color does, subscribe to MQTT instead: broker `mqtt.cheerlights.com`, port 1883, topic `cheerlights` for the name or `hex` for the HEX value.
91
+ - History comes back oldest first, the order the feed returns it.
92
+
93
+ ## Documentation
94
+
95
+ - [Reference](https://github.com/cheerlights/cheerlights-python-package/blob/main/docs/reference.md): every function, its return value, and its errors.
96
+ - [Changes in 0.2.0](https://github.com/cheerlights/cheerlights-python-package/blob/main/docs/reference.md#changes-in-020): what changed from 0.1.2, including the fixed green and lowercase HEX values.
97
+ - [CheerLights](https://cheerlights.com): the project, the feeds, and how to build your first light.
98
+
99
+ ## Development
100
+
101
+ ```bash
102
+ git clone https://github.com/cheerlights/cheerlights-python-package
103
+ cd cheerlights-python-package
104
+ uv sync
105
+ uv run pytest # offline, against a fake feed
106
+ uv run pytest -m live # one check against the real feed
107
+ uv run ruff check . && uv run mypy src
108
+ ```
109
+
110
+ ## License
111
+
112
+ MIT. See [LICENSE](https://github.com/cheerlights/cheerlights-python-package/blob/main/LICENSE).
@@ -0,0 +1,86 @@
1
+ # CheerLights API for Python
2
+
3
+ A small Python package that reads the live CheerLights color, its recent history, and the CheerLights palette.
4
+
5
+ [![PyPI](https://img.shields.io/pypi/v/cheerlights-api)](https://pypi.org/project/cheerlights-api/) [![Python](https://img.shields.io/pypi/pyversions/cheerlights-api)](https://pypi.org/project/cheerlights-api/) [![CI](https://github.com/cheerlights/cheerlights-python-package/actions/workflows/ci.yml/badge.svg)](https://github.com/cheerlights/cheerlights-python-package/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/license-MIT-yellow)](https://github.com/cheerlights/cheerlights-python-package/blob/main/LICENSE)
6
+
7
+ [CheerLights](https://cheerlights.com) is a global network of lights that all show the same color, set by anyone on the [CheerLights Discord](https://cheerlights.com/discord).
8
+ This package reads the public CheerLights feed (ThingSpeak channel 1417), so a Python script on a laptop or a Raspberry Pi can follow the color.
9
+ It needs no API key and depends only on `requests`.
10
+
11
+ ## Quick start
12
+
13
+ Install it from [PyPI](https://pypi.org/project/cheerlights-api/) (Python 3.10 or later):
14
+
15
+ ```bash
16
+ pip install cheerlights-api
17
+ ```
18
+
19
+ Then read the current color:
20
+
21
+ ```python
22
+ import cheerlights_api
23
+
24
+ print(cheerlights_api.get_current_color())
25
+ ```
26
+
27
+ ## Example
28
+
29
+ ```python
30
+ import cheerlights_api
31
+
32
+ current = cheerlights_api.get_current_color()
33
+ print(current)
34
+ print(cheerlights_api.hex_to_rgb(current["hex"]))
35
+
36
+ for change in cheerlights_api.get_color_history(3):
37
+ print(change)
38
+ ```
39
+
40
+ Output from version 0.2.0 on 2026-10-29:
41
+
42
+ ```text
43
+ {'color': 'red', 'hex': '#ff0000'}
44
+ (255, 0, 0)
45
+ {'color': 'cyan', 'hex': '#00ffff', 'timestamp': '2026-10-29T17:01:36Z'}
46
+ {'color': 'purple', 'hex': '#800080', 'timestamp': '2026-10-29T17:20:53Z'}
47
+ {'color': 'red', 'hex': '#ff0000', 'timestamp': '2026-10-29T18:00:53Z'}
48
+ ```
49
+
50
+ The `(255, 0, 0)` tuple is what an RGB LED or a NeoPixel library takes.
51
+
52
+ ## Features
53
+
54
+ - The current color as a name and a HEX value: `get_current_color()`, `get_current_color_name()`, `get_current_hex()`.
55
+ - The last 1 to 8000 color changes with the time each was set, oldest first: `get_color_history(count)`.
56
+ - The 11 official CheerLights colors with their HEX values, as the feed publishes them: `COLORS`.
57
+ - Name and HEX helpers: `color_name_to_hex("Old Lace")` gives `#fdf5e6`, `hex_to_rgb("#ffa500")` gives `(255, 165, 0)`, `is_valid_color("pink")` gives `True`.
58
+ - Type hints throughout, checked with mypy in strict mode.
59
+ - A 10 second timeout on every request, and clear errors: `requests` exceptions when the feed cannot be reached, `LookupError` when it returns no color, `ValueError` for bad input.
60
+
61
+ ## Limits
62
+
63
+ - It reads the color; it cannot set it. Anyone sets the color with the `/cheerlights` command on the [CheerLights Discord](https://cheerlights.com/discord).
64
+ - It polls the feed. For a light that changes the moment the color does, subscribe to MQTT instead: broker `mqtt.cheerlights.com`, port 1883, topic `cheerlights` for the name or `hex` for the HEX value.
65
+ - History comes back oldest first, the order the feed returns it.
66
+
67
+ ## Documentation
68
+
69
+ - [Reference](https://github.com/cheerlights/cheerlights-python-package/blob/main/docs/reference.md): every function, its return value, and its errors.
70
+ - [Changes in 0.2.0](https://github.com/cheerlights/cheerlights-python-package/blob/main/docs/reference.md#changes-in-020): what changed from 0.1.2, including the fixed green and lowercase HEX values.
71
+ - [CheerLights](https://cheerlights.com): the project, the feeds, and how to build your first light.
72
+
73
+ ## Development
74
+
75
+ ```bash
76
+ git clone https://github.com/cheerlights/cheerlights-python-package
77
+ cd cheerlights-python-package
78
+ uv sync
79
+ uv run pytest # offline, against a fake feed
80
+ uv run pytest -m live # one check against the real feed
81
+ uv run ruff check . && uv run mypy src
82
+ ```
83
+
84
+ ## License
85
+
86
+ MIT. See [LICENSE](https://github.com/cheerlights/cheerlights-python-package/blob/main/LICENSE).
@@ -0,0 +1,90 @@
1
+ # Reference
2
+
3
+ Everything `cheerlights_api` exports, as of version 0.2.0.
4
+ Every function that reads the feed makes one HTTPS request to `https://api.thingspeak.com/channels/1417/feed.json` with a 10 second timeout.
5
+
6
+ ## Reading the feed
7
+
8
+ ### `get_current_color() -> Color`
9
+
10
+ The current color as `{"color": "red", "hex": "#ff0000"}`.
11
+ The name is lowercase; the HEX value is the one the feed publishes, lowercase with a leading `#`.
12
+
13
+ Raises `requests.RequestException` (for example `requests.HTTPError` or `requests.Timeout`) when the feed cannot be reached or answers with an error, and `LookupError` when it returns no color.
14
+
15
+ ### `get_current_color_name() -> str`
16
+
17
+ The name of the current color, for example `"red"`.
18
+ Same errors as `get_current_color()`.
19
+
20
+ ### `get_current_hex() -> str`
21
+
22
+ The HEX value of the current color, for example `"#ff0000"`.
23
+ Same errors as `get_current_color()`.
24
+
25
+ ### `get_color_history(count: int = 10) -> list[ColorChange]`
26
+
27
+ The last `count` color changes, oldest first, each as `{"color": "cyan", "hex": "#00ffff", "timestamp": "2026-10-29T17:01:36Z"}`.
28
+ The timestamp is the time the color was set, in UTC, ISO 8601.
29
+
30
+ `count` must be a whole number from 1 to 8000 (`MAX_HISTORY`, the most the feed returns at once); anything else raises `ValueError` before any request is made.
31
+ Network errors are the same as for `get_current_color()`.
32
+
33
+ Very old entries in the feed have no HEX value; for those the HEX value comes from the palette.
34
+
35
+ ## The palette
36
+
37
+ ### `COLORS: dict[str, str]`
38
+
39
+ The 11 official CheerLights colors and their HEX values:
40
+
41
+ | Name | HEX |
42
+ |---|---|
43
+ | red | `#ff0000` |
44
+ | green | `#008000` |
45
+ | blue | `#0000ff` |
46
+ | cyan | `#00ffff` |
47
+ | white | `#ffffff` |
48
+ | oldlace | `#fdf5e6` |
49
+ | purple | `#800080` |
50
+ | magenta | `#ff00ff` |
51
+ | yellow | `#ffff00` |
52
+ | orange | `#ffa500` |
53
+ | pink | `#ffc0cb` |
54
+
55
+ ### `ALIASES: dict[str, str]`
56
+
57
+ Older names that still mean a CheerLights color: `warmwhite` is `oldlace`.
58
+
59
+ ### `color_name_to_hex(color_name: str) -> str | None`
60
+
61
+ The HEX value of a color name, or `None` when the name is not a CheerLights color.
62
+ Case and spaces do not matter, and aliases count: `"Old Lace"` and `"warmwhite"` both give `"#fdf5e6"`.
63
+
64
+ ### `is_valid_color(color_name: str) -> bool`
65
+
66
+ Whether a name is a CheerLights color, with the same rules as `color_name_to_hex()`.
67
+
68
+ ### `hex_to_rgb(hex_code: str) -> tuple[int, int, int]`
69
+
70
+ A HEX value as a `(red, green, blue)` tuple of 0 to 255: `hex_to_rgb("#ffa500")` gives `(255, 165, 0)`.
71
+ The `#` is optional; anything other than six hexadecimal digits raises `ValueError`.
72
+
73
+ ## Types and constants
74
+
75
+ - `Color`: a `TypedDict` with `color` and `hex`.
76
+ - `ColorChange`: a `TypedDict` with `color`, `hex`, and `timestamp`.
77
+ - `CHEERLIGHTS_FEED_URL`, `TIMEOUT` (10.0 seconds), `MAX_HISTORY` (8000).
78
+ - `__version__`: the installed version.
79
+
80
+ The functions can also be imported from `cheerlights_api.cheerlights_api`, the path versions before 0.2.0 used.
81
+
82
+ ## Changes in 0.2.0
83
+
84
+ These change what 0.1.2 returned:
85
+
86
+ - `green` is `#008000`, the CheerLights green; 0.1.2 gave `#00ff00`.
87
+ - HEX values are lowercase everywhere, matching the feed, so `color_name_to_hex(get_current_color_name()) == get_current_hex()` holds; 0.1.2 returned uppercase from `color_name_to_hex()`.
88
+ - `get_color_history()` checks `count` and raises `ValueError` outside 1 to 8000; 0.1.2 passed any value to the feed.
89
+ - `hex_to_rgb()` raises `ValueError` for anything but six hexadecimal digits.
90
+ - An empty feed raises `LookupError` with a message; 0.1.2 raised a bare `IndexError` (also a `LookupError`).
@@ -0,0 +1,60 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.27"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "cheerlights-api"
7
+ version = "0.2.0"
8
+ description = "Read the live CheerLights color, its history, and the CheerLights palette"
9
+ authors = [{ name = "CheerLights Community", email = "info@cheerlights.com" }]
10
+ readme = "README.md"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ requires-python = ">=3.10"
14
+ keywords = ["cheerlights", "iot", "thingspeak", "led", "color"]
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Intended Audience :: Developers",
18
+ "Intended Audience :: Education",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.10",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Programming Language :: Python :: 3.13",
24
+ "Programming Language :: Python :: 3.14",
25
+ "Topic :: Home Automation",
26
+ "Typing :: Typed",
27
+ ]
28
+ dependencies = ["requests>=2.32"]
29
+
30
+ [project.urls]
31
+ Homepage = "https://cheerlights.com"
32
+ Repository = "https://github.com/cheerlights/cheerlights-python-package"
33
+ Issues = "https://github.com/cheerlights/cheerlights-python-package/issues"
34
+
35
+ [dependency-groups]
36
+ dev = [
37
+ "pytest>=9.0",
38
+ "ruff>=0.17",
39
+ "mypy>=2.0",
40
+ "types-requests",
41
+ ]
42
+
43
+ [tool.hatch.build.targets.wheel]
44
+ packages = ["src/cheerlights_api"]
45
+
46
+ [tool.ruff]
47
+ target-version = "py310"
48
+ line-length = 110
49
+
50
+ [tool.ruff.lint]
51
+ select = ["E", "W", "F", "I", "B", "C4", "UP"]
52
+
53
+ [tool.mypy]
54
+ python_version = "3.10"
55
+ strict = true
56
+
57
+ [tool.pytest.ini_options]
58
+ addopts = "-ra -q -m 'not live'"
59
+ testpaths = ["tests"]
60
+ markers = ["live: calls the real CheerLights feed (run with -m live)"]
@@ -0,0 +1,39 @@
1
+ """Read the live CheerLights color, its history, and the CheerLights palette."""
2
+
3
+ from importlib.metadata import PackageNotFoundError, version
4
+
5
+ from .cheerlights_api import (
6
+ ALIASES,
7
+ CHEERLIGHTS_FEED_URL,
8
+ COLORS,
9
+ Color,
10
+ ColorChange,
11
+ color_name_to_hex,
12
+ get_color_history,
13
+ get_current_color,
14
+ get_current_color_name,
15
+ get_current_hex,
16
+ hex_to_rgb,
17
+ is_valid_color,
18
+ )
19
+
20
+ try:
21
+ __version__ = version("cheerlights-api")
22
+ except PackageNotFoundError: # running from a source tree that is not installed
23
+ __version__ = "0.0.0"
24
+
25
+ __all__ = [
26
+ "ALIASES",
27
+ "CHEERLIGHTS_FEED_URL",
28
+ "COLORS",
29
+ "Color",
30
+ "ColorChange",
31
+ "__version__",
32
+ "color_name_to_hex",
33
+ "get_color_history",
34
+ "get_current_color",
35
+ "get_current_color_name",
36
+ "get_current_hex",
37
+ "hex_to_rgb",
38
+ "is_valid_color",
39
+ ]