diff --git a/buildroot-external/package/ovos-shell/ovos-shell.hash b/buildroot-external/package/ovos-shell/ovos-shell.hash
index 5587f1c8..05037141 100644
--- a/buildroot-external/package/ovos-shell/ovos-shell.hash
+++ b/buildroot-external/package/ovos-shell/ovos-shell.hash
@@ -1,2 +1,2 @@
# Locally computed
-sha256 1cbf2a9fab538a3fe2e01162bce7f8d30ba9d08cd345c9d40b14f326451625da ovos-shell-f05f5707b25bc860b69deb18055a55d5ef0b41ee.tar.gz
+sha256 323d768b33e09942ade8de3cb42b8c28a4c18abac15a49b3837d55b2c5650a99 ovos-shell-2813ad6c183a9cf8ffd0e9860dce5de0d0414258.tar.gz
diff --git a/buildroot-external/package/ovos-shell/ovos-shell.mk b/buildroot-external/package/ovos-shell/ovos-shell.mk
index 4839c758..88c1f8aa 100644
--- a/buildroot-external/package/ovos-shell/ovos-shell.mk
+++ b/buildroot-external/package/ovos-shell/ovos-shell.mk
@@ -4,7 +4,7 @@
#
################################################################################
-OVOS_SHELL_VERSION = f05f5707b25bc860b69deb18055a55d5ef0b41ee
+OVOS_SHELL_VERSION = 2813ad6c183a9cf8ffd0e9860dce5de0d0414258
OVOS_SHELL_SITE = $(call github,OpenVoiceOS,ovos-shell,$(OVOS_SHELL_VERSION))
OVOS_SHELL_LICENSE = Apache License 2.0
diff --git a/buildroot-external/package/python-ovos-core/0001-Loosen-some-requirements.patch b/buildroot-external/package/python-ovos-core/0001-Loosen-some-requirements.patch
deleted file mode 100644
index 61ad7308..00000000
--- a/buildroot-external/package/python-ovos-core/0001-Loosen-some-requirements.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From 984a029070c37436a30ab347a0bfafa67a960014 Mon Sep 17 00:00:00 2001
-From: j1nx
-Date: Sun, 5 Jun 2022 13:15:54 +0200
-Subject: [PATCH 1/1] Loosen some requirements
-
----
- requirements/requirements.txt | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/requirements/requirements.txt b/requirements/requirements.txt
-index ef51533514..563d0b1f6e 100644
---- a/requirements/requirements.txt
-+++ b/requirements/requirements.txt
-@@ -2,10 +2,10 @@ requests~=2.26
- PyAudio~=0.2
- SpeechRecognition~=3.8
- tornado~=6.0, >=6.0.3
--psutil~=5.6.6
-+psutil>=5.6.6
- python-dateutil~=2.6
- combo-lock~=0.2
--PyYAML~=5.4
-+PyYAML>=5.4
- watchdog
-
- ovos-utils~=0.0, >=0.0.22
---
-2.34.1
-
diff --git a/buildroot-external/package/python-ovos-core/python-ovos-core.hash b/buildroot-external/package/python-ovos-core/python-ovos-core.hash
index e2913aeb..bf395fb7 100644
--- a/buildroot-external/package/python-ovos-core/python-ovos-core.hash
+++ b/buildroot-external/package/python-ovos-core/python-ovos-core.hash
@@ -1 +1 @@
-sha256 d10ff97040eb91ee842952fd47e8c2648bdfba13c3080deedc714552e5329d02 python-ovos-core-dc960e7bf7afc33f53e5c918a08049b20745df47.tar.gz
+sha256 091f0b17f0a5cb905a65b60b67d9b1f21ea245a20606a338a6e806d9d9da254e python-ovos-core-bcca687c6f66368246303a75b9686e02feebfe68.tar.gz
diff --git a/buildroot-external/package/python-ovos-core/python-ovos-core.mk b/buildroot-external/package/python-ovos-core/python-ovos-core.mk
index de16e077..b5a0b105 100644
--- a/buildroot-external/package/python-ovos-core/python-ovos-core.mk
+++ b/buildroot-external/package/python-ovos-core/python-ovos-core.mk
@@ -4,9 +4,16 @@
#
################################################################################
-PYTHON_OVOS_CORE_VERSION = dc960e7bf7afc33f53e5c918a08049b20745df47
+PYTHON_OVOS_CORE_VERSION = bcca687c6f66368246303a75b9686e02feebfe68
PYTHON_OVOS_CORE_SITE = $(call github,OpenVoiceOS,ovos-core,$(PYTHON_OVOS_CORE_VERSION))
PYTHON_OVOS_CORE_SETUP_TYPE = setuptools
PYTHON_OVOS_CORE_LICENSE_FILES = LICENSE
+PYTHON_OVOS_CORE_ENV = MYCROFT_LOOSE_REQUIREMENTS=true
+
+PYTHON_OVOS_CORE_PRE_CONFIGURE_HOOKS = PYTHON_OVOS_CORE_REQUIREMENTS
+
+define PYTHON_OVOS_CORE_REQUIREMENTS
+ cp $(@D)/requirements/requirements.txt $(@D)/requirements/minimal.txt
+endef
$(eval $(python-package))
diff --git a/buildroot-external/package/python-ovos-lingua-franca/0001-Changes-to-setup.patch b/buildroot-external/package/python-ovos-lingua-franca/0001-Changes-to-setup.patch
new file mode 100644
index 00000000..59d74974
--- /dev/null
+++ b/buildroot-external/package/python-ovos-lingua-franca/0001-Changes-to-setup.patch
@@ -0,0 +1,61 @@
+From 0917fee8cef66042341bfdf569167e650ba3fe23 Mon Sep 17 00:00:00 2001
+From: j1nx
+Date: Sun, 1 Jan 2023 14:40:31 +0100
+Subject: [PATCH 1/1] Changes to setup
+
+---
+ setup.py | 19 ++++---------------
+ 1 file changed, 4 insertions(+), 15 deletions(-)
+
+diff --git a/setup.py b/setup.py
+index dc17012..cd7ca9d 100644
+--- a/setup.py
++++ b/setup.py
+@@ -1,22 +1,10 @@
+ import os
+-from distutils.command.install import install
+
+-import pip
+ from setuptools import setup
+
+ BASEDIR = os.path.abspath(os.path.dirname(__file__))
+
+
+-class CustomInstall(install):
+- """Custom handler for the 'install' command."""
+-
+- def run(self):
+- # uninstall lingua_franca
+- # the whole purpose of this package is to replace it
+- pip.main(["uninstall", "lingua_franca", "-y"])
+- super().run()
+-
+-
+ def package_files(directory):
+ paths = []
+ for (path, directories, filenames) in os.walk(directory):
+@@ -27,9 +15,11 @@ def package_files(directory):
+
+ def required(requirements_file):
+ """ Read requirements file and remove comments and empty lines. """
+- with open(os.path.join(os.path.dirname(__file__), requirements_file),
+- 'r') as f:
++ with open(os.path.join(BASEDIR, requirements_file), 'r') as f:
+ requirements = f.read().splitlines()
++ if 'MYCROFT_LOOSE_REQUIREMENTS' in os.environ:
++ print('USING LOOSE REQUIREMENTS!')
++ requirements = [r.replace('==', '>=').replace('~=', '>=') for r in requirements]
+ return [pkg for pkg in requirements
+ if pkg.strip() and not pkg.startswith("#")]
+
+@@ -68,7 +58,6 @@ setup(
+ name='ovos-lingua-franca',
+ version=get_version(),
+ packages=['lingua_franca', 'lingua_franca.lang', 'lingua_franca.util'],
+- cmdclass={'install': CustomInstall},
+ url='https://github.com/OpenVoiceOS/ovos-lingua-franca',
+ license='Apache2.0',
+ package_data={'': extra_files},
+--
+2.34.1
+
diff --git a/buildroot-external/package/python-ovos-lingua-franca/0001-Loosen-some-requirements.patch b/buildroot-external/package/python-ovos-lingua-franca/0001-Loosen-some-requirements.patch
deleted file mode 100644
index 297ed020..00000000
--- a/buildroot-external/package/python-ovos-lingua-franca/0001-Loosen-some-requirements.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-From 503f3301b063c22f9f92b884fdf157a28aa5251f Mon Sep 17 00:00:00 2001
-From: j1nx
-Date: Sat, 7 May 2022 18:32:10 +0200
-Subject: [PATCH 1/1] Loosen some requirements
-
----
- requirements/requirements.txt | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/requirements/requirements.txt b/requirements/requirements.txt
-index 5d943a5..54bcf40 100644
---- a/requirements/requirements.txt
-+++ b/requirements/requirements.txt
-@@ -1,2 +1,2 @@
--python-dateutil~=2.6
--rapidfuzz
-\ No newline at end of file
-+python-dateutil>=2.6
-+rapidfuzz
---
-2.34.1
-
diff --git a/buildroot-external/package/python-ovos-lingua-franca/0001-No-LF-uninstall.patch b/buildroot-external/package/python-ovos-lingua-franca/0001-No-LF-uninstall.patch
deleted file mode 100644
index d1585db1..00000000
--- a/buildroot-external/package/python-ovos-lingua-franca/0001-No-LF-uninstall.patch
+++ /dev/null
@@ -1,47 +0,0 @@
-From 6b6955e4ea7e0dd160a39f7a42fdf5cde78e0692 Mon Sep 17 00:00:00 2001
-From: j1nx
-Date: Tue, 8 Mar 2022 21:03:56 +0100
-Subject: [PATCH 1/1] No LF uninstall
-
----
- setup.py | 13 -------------
- 1 file changed, 13 deletions(-)
-
-diff --git a/setup.py b/setup.py
-index e8c5c76..2f6e142 100644
---- a/setup.py
-+++ b/setup.py
-@@ -1,22 +1,10 @@
- import os
--from distutils.command.install import install
-
--import pip
- from setuptools import setup
-
- BASEDIR = os.path.abspath(os.path.dirname(__file__))
-
-
--class CustomInstall(install):
-- """Custom handler for the 'install' command."""
--
-- def run(self):
-- # uninstall lingua_franca
-- # the whole purpose of this package is to replace it
-- pip.main(["uninstall", "lingua_franca", "-y"])
-- super().run()
--
--
- def package_files(directory):
- paths = []
- for (path, directories, filenames) in os.walk(directory):
-@@ -68,7 +56,6 @@ setup(
- name='ovos-lingua-franca',
- version=get_version(),
- packages=['lingua_franca', 'lingua_franca.lang'],
-- cmdclass={'install': CustomInstall},
- url='https://github.com/OpenVoiceOS/ovos-lingua-franca',
- license='Apache2.0',
- package_data={'': extra_files},
---
-2.20.1
-
diff --git a/buildroot-external/package/python-ovos-lingua-franca/python-ovos-lingua-franca.hash b/buildroot-external/package/python-ovos-lingua-franca/python-ovos-lingua-franca.hash
index e305435a..79e710de 100644
--- a/buildroot-external/package/python-ovos-lingua-franca/python-ovos-lingua-franca.hash
+++ b/buildroot-external/package/python-ovos-lingua-franca/python-ovos-lingua-franca.hash
@@ -1 +1 @@
-sha256 49fcfc2a8005d7f41e22904980e572b1e641dd2c1fbb82706a3be86102b1b6f2 python-ovos-lingua-franca-08ed3c6a7c5dcb94ac7ddf3ba7e8856019d15699.tar.gz
+sha256 5589cc5cca4336da0fe222b8c1279355aa43d86e6a3283991b2c93fa667eb7e6 python-ovos-lingua-franca-86a8f117ce7ca56a9ccf9cea27bcd5e63a7b54c8.tar.gz
diff --git a/buildroot-external/package/python-ovos-lingua-franca/python-ovos-lingua-franca.mk b/buildroot-external/package/python-ovos-lingua-franca/python-ovos-lingua-franca.mk
index 7e2e1ec3..110469f5 100644
--- a/buildroot-external/package/python-ovos-lingua-franca/python-ovos-lingua-franca.mk
+++ b/buildroot-external/package/python-ovos-lingua-franca/python-ovos-lingua-franca.mk
@@ -4,10 +4,11 @@
#
################################################################################
-PYTHON_OVOS_LINGUA_FRANCA_VERSION = 08ed3c6a7c5dcb94ac7ddf3ba7e8856019d15699
+PYTHON_OVOS_LINGUA_FRANCA_VERSION = 86a8f117ce7ca56a9ccf9cea27bcd5e63a7b54c8
PYTHON_OVOS_LINGUA_FRANCA_SITE = $(call github,OpenVoiceOS,ovos-lingua-franca,$(PYTHON_OVOS_LINGUA_FRANCA_VERSION))
PYTHON_OVOS_LINGUA_FRANCA_SETUP_TYPE = setuptools
PYTHON_OVOS_LINGUA_FRANCA_LICENSE = Apache-2.0
PYTHON_OVOS_LINGUA_FRANCA_LICENSE_FILES = LICENSE
+PYTHON_OVOS_LINGUA_FRANCA_ENV = MYCROFT_LOOSE_REQUIREMENTS=true
$(eval $(python-package))
diff --git a/buildroot-external/package/python-ovos-ocp-audio-plugin/python-ovos-ocp-audio-plugin.hash b/buildroot-external/package/python-ovos-ocp-audio-plugin/python-ovos-ocp-audio-plugin.hash
index 079224d4..d0fd2223 100644
--- a/buildroot-external/package/python-ovos-ocp-audio-plugin/python-ovos-ocp-audio-plugin.hash
+++ b/buildroot-external/package/python-ovos-ocp-audio-plugin/python-ovos-ocp-audio-plugin.hash
@@ -1 +1 @@
-sha256 6c7cb8630b07cbb891a9decd2379cec7b22049ff82ecac4445ef0aa0ade206df python-ovos-ocp-audio-plugin-de8ace8c9fe88c452c8ff2c11f149bc7d19275c5.tar.gz
+sha256 b2093a04d42b403d27e6b00e355b22bc2d83fd2694b735b372d2e37bb6ea0bee python-ovos-ocp-audio-plugin-a9a60bef7e45c7c6c2eb2ed8966cc8caab47d327.tar.gz
diff --git a/buildroot-external/package/python-ovos-ocp-audio-plugin/python-ovos-ocp-audio-plugin.mk b/buildroot-external/package/python-ovos-ocp-audio-plugin/python-ovos-ocp-audio-plugin.mk
index 51666f73..8aa16ea3 100644
--- a/buildroot-external/package/python-ovos-ocp-audio-plugin/python-ovos-ocp-audio-plugin.mk
+++ b/buildroot-external/package/python-ovos-ocp-audio-plugin/python-ovos-ocp-audio-plugin.mk
@@ -4,9 +4,10 @@
#
################################################################################
-PYTHON_OVOS_OCP_AUDIO_PLUGIN_VERSION = de8ace8c9fe88c452c8ff2c11f149bc7d19275c5
+PYTHON_OVOS_OCP_AUDIO_PLUGIN_VERSION = a9a60bef7e45c7c6c2eb2ed8966cc8caab47d327
PYTHON_OVOS_OCP_AUDIO_PLUGIN_SITE = $(call github,OpenVoiceOS,ovos-ocp-audio-plugin,$(PYTHON_OVOS_OCP_AUDIO_PLUGIN_VERSION))
PYTHON_OVOS_OCP_AUDIO_PLUGIN_SETUP_TYPE = setuptools
PYTHON_OVOS_OCP_AUDIO_PLUGIN_LICENSE_FILES = LICENSE
+PYTHON_OVOS_OCP_AUDIO_PLUGIN_ENV = MYCROFT_LOOSE_REQUIREMENTS=true
$(eval $(python-package))
diff --git a/buildroot-external/package/python-ovos-phal-plugin-gui-network-client/python-ovos-phal-plugin-gui-network-client.hash b/buildroot-external/package/python-ovos-phal-plugin-gui-network-client/python-ovos-phal-plugin-gui-network-client.hash
index 52024f4b..7a28e61d 100644
--- a/buildroot-external/package/python-ovos-phal-plugin-gui-network-client/python-ovos-phal-plugin-gui-network-client.hash
+++ b/buildroot-external/package/python-ovos-phal-plugin-gui-network-client/python-ovos-phal-plugin-gui-network-client.hash
@@ -1 +1 @@
-sha256 3aad49f90b4a4661e14a4380cfc53f0a799cbfa7f827f1c480e63694b3c40375 python-ovos-phal-plugin-gui-network-client-c44be4c09dda5c0bc73977d243165ebcf4dda59f.tar.gz
+sha256 8e181917ebe566fc1f12b32c6075452315edd125da0bcbd43de6af7081ca3319 python-ovos-phal-plugin-gui-network-client-3658f66461a5cd65ffed9e9bf4a45f887430fd85.tar.gz
diff --git a/buildroot-external/package/python-ovos-phal-plugin-gui-network-client/python-ovos-phal-plugin-gui-network-client.mk b/buildroot-external/package/python-ovos-phal-plugin-gui-network-client/python-ovos-phal-plugin-gui-network-client.mk
index 01aee3b7..e8decba9 100644
--- a/buildroot-external/package/python-ovos-phal-plugin-gui-network-client/python-ovos-phal-plugin-gui-network-client.mk
+++ b/buildroot-external/package/python-ovos-phal-plugin-gui-network-client/python-ovos-phal-plugin-gui-network-client.mk
@@ -4,9 +4,10 @@
#
################################################################################
-PYTHON_OVOS_PHAL_PLUGIN_GUI_NETWORK_CLIENT_VERSION = c44be4c09dda5c0bc73977d243165ebcf4dda59f
+PYTHON_OVOS_PHAL_PLUGIN_GUI_NETWORK_CLIENT_VERSION = 3658f66461a5cd65ffed9e9bf4a45f887430fd85
PYTHON_OVOS_PHAL_PLUGIN_GUI_NETWORK_CLIENT_SITE = $(call github,OpenVoiceOS,ovos-PHAL-plugin-gui-network-client,$(PYTHON_OVOS_PHAL_PLUGIN_GUI_NETWORK_CLIENT_VERSION))
PYTHON_OVOS_PHAL_PLUGIN_GUI_NETWORK_CLIENT_SETUP_TYPE = setuptools
PYTHON_OVOS_PHAL_PLUGIN_GUI_NETWORK_CLIENT_LICENSE_FILES = LICENSE
+PYTHON_OVOS_PHAL_PLUGIN_GUI_NETWORK_CLIENT_ENV = MYCROFT_LOOSE_REQUIREMENTS=true
$(eval $(python-package))
diff --git a/buildroot-external/package/python-ovos-phal-plugin-system/python-ovos-phal-plugin-system.hash b/buildroot-external/package/python-ovos-phal-plugin-system/python-ovos-phal-plugin-system.hash
index 6ef73c51..c4aa1a98 100644
--- a/buildroot-external/package/python-ovos-phal-plugin-system/python-ovos-phal-plugin-system.hash
+++ b/buildroot-external/package/python-ovos-phal-plugin-system/python-ovos-phal-plugin-system.hash
@@ -1 +1 @@
-sha256 5af6a5014cfc0ef741208bf5d43dd5d3532b8c0f3abfc64f69987f4dc461b777 python-ovos-phal-plugin-system-de5177a93a604deb9ff475e89990a2cb6684c6c4.tar.gz
+sha256 7a6c90a5e4e913c574c2bc81c10be1edf62896b4f3f01cde00d4513106e01ae2 python-ovos-phal-plugin-system-4792f16823f7949b863a21e3c12e2abf80b36203.tar.gz
diff --git a/buildroot-external/package/python-ovos-phal-plugin-system/python-ovos-phal-plugin-system.mk b/buildroot-external/package/python-ovos-phal-plugin-system/python-ovos-phal-plugin-system.mk
index 394dc788..0851c2e3 100644
--- a/buildroot-external/package/python-ovos-phal-plugin-system/python-ovos-phal-plugin-system.mk
+++ b/buildroot-external/package/python-ovos-phal-plugin-system/python-ovos-phal-plugin-system.mk
@@ -4,9 +4,10 @@
#
################################################################################
-PYTHON_OVOS_PHAL_PLUGIN_SYSTEM_VERSION = de5177a93a604deb9ff475e89990a2cb6684c6c4
+PYTHON_OVOS_PHAL_PLUGIN_SYSTEM_VERSION = 4792f16823f7949b863a21e3c12e2abf80b36203
PYTHON_OVOS_PHAL_PLUGIN_SYSTEM_SITE = $(call github,OpenVoiceOS,ovos-PHAL-plugin-system,$(PYTHON_OVOS_PHAL_PLUGIN_SYSTEM_VERSION))
PYTHON_OVOS_PHAL_PLUGIN_SYSTEM_SETUP_TYPE = setuptools
PYTHON_OVOS_PHAL_PLUGIN_SYSTEM_LICENSE_FILES = LICENSE
+PYTHON_OVOS_PHAL_PLUGIN_SYSTEM_ENV = MYCROFT_LOOSE_REQUIREMENTS=true
$(eval $(python-package))
diff --git a/buildroot-external/package/python-ovos-phal-plugin-wifi-setup/python-ovos-phal-plugin-wifi-setup.hash b/buildroot-external/package/python-ovos-phal-plugin-wifi-setup/python-ovos-phal-plugin-wifi-setup.hash
index 3f798cb5..9319b6a6 100644
--- a/buildroot-external/package/python-ovos-phal-plugin-wifi-setup/python-ovos-phal-plugin-wifi-setup.hash
+++ b/buildroot-external/package/python-ovos-phal-plugin-wifi-setup/python-ovos-phal-plugin-wifi-setup.hash
@@ -1 +1 @@
-sha256 35ffdee0841e6dddc418b8e2a66edc8bb28332a31e9d31e97d72896931c8c50b python-ovos-phal-plugin-wifi-setup-d4ea818d72f4ecb77e7602fcb0151ebee1760b4f.tar.gz
+sha256 67749f8e7b3f3e7ca4bfaf1082ac3e6d5859dbdaffe892913dfa8528e8402429 python-ovos-phal-plugin-wifi-setup-c5288b66850d55bdcf0932b0b059409b950cd88f.tar.gz
diff --git a/buildroot-external/package/python-ovos-phal-plugin-wifi-setup/python-ovos-phal-plugin-wifi-setup.mk b/buildroot-external/package/python-ovos-phal-plugin-wifi-setup/python-ovos-phal-plugin-wifi-setup.mk
index 0bf70148..de2dedb7 100644
--- a/buildroot-external/package/python-ovos-phal-plugin-wifi-setup/python-ovos-phal-plugin-wifi-setup.mk
+++ b/buildroot-external/package/python-ovos-phal-plugin-wifi-setup/python-ovos-phal-plugin-wifi-setup.mk
@@ -4,7 +4,7 @@
#
################################################################################
-PYTHON_OVOS_PHAL_PLUGIN_WIFI_SETUP_VERSION = d4ea818d72f4ecb77e7602fcb0151ebee1760b4f
+PYTHON_OVOS_PHAL_PLUGIN_WIFI_SETUP_VERSION = c5288b66850d55bdcf0932b0b059409b950cd88f
PYTHON_OVOS_PHAL_PLUGIN_WIFI_SETUP_SITE = $(call github,OpenVoiceOS,ovos-PHAL-plugin-wifi-setup,$(PYTHON_OVOS_PHAL_PLUGIN_WIFI_SETUP_VERSION))
PYTHON_OVOS_PHAL_PLUGIN_WIFI_SETUP_SETUP_TYPE = setuptools
PYTHON_OVOS_PHAL_PLUGIN_WIFI_SETUP_LICENSE_FILES = LICENSE
diff --git a/buildroot-external/package/python-ovos-plugin-manager/python-ovos-plugin-manager.hash b/buildroot-external/package/python-ovos-plugin-manager/python-ovos-plugin-manager.hash
index 3aafd283..1132a1b1 100644
--- a/buildroot-external/package/python-ovos-plugin-manager/python-ovos-plugin-manager.hash
+++ b/buildroot-external/package/python-ovos-plugin-manager/python-ovos-plugin-manager.hash
@@ -1 +1 @@
-sha256 52baca2b97fa6f961ae01f7c022f4f3ddc504da9dbbef5f58f3af5510f58d772 python-ovos-plugin-manager-d628bcae09a415188e432885647d8b6fc3072b43.tar.gz
+sha256 154bc420b874445f3725b07ce90857a800b6057c03e8dfd21bddb9fc9b9b2fe0 python-ovos-plugin-manager-1012f3fa2524513126b842bdb645409f5ed288be.tar.gz
diff --git a/buildroot-external/package/python-ovos-plugin-manager/python-ovos-plugin-manager.mk b/buildroot-external/package/python-ovos-plugin-manager/python-ovos-plugin-manager.mk
index 60af7de4..b8256854 100644
--- a/buildroot-external/package/python-ovos-plugin-manager/python-ovos-plugin-manager.mk
+++ b/buildroot-external/package/python-ovos-plugin-manager/python-ovos-plugin-manager.mk
@@ -4,7 +4,7 @@
#
################################################################################
-PYTHON_OVOS_PLUGIN_MANAGER_VERSION = d628bcae09a415188e432885647d8b6fc3072b43
+PYTHON_OVOS_PLUGIN_MANAGER_VERSION = 1012f3fa2524513126b842bdb645409f5ed288be
PYTHON_OVOS_PLUGIN_MANAGER_SITE = $(call github,OpenVoiceOS,OVOS-plugin-manager,$(PYTHON_OVOS_PLUGIN_MANAGER_VERSION))
PYTHON_OVOS_PLUGIN_MANAGER_SETUP_TYPE = setuptools
PYTHON_OVOS_PLUGIN_MANAGER_LICENSE_FILES = LICENSE
diff --git a/buildroot-external/package/python-ovos-skill-manager/python-ovos-skill-manager.hash b/buildroot-external/package/python-ovos-skill-manager/python-ovos-skill-manager.hash
index 6ff6c3a0..e51ed0ad 100644
--- a/buildroot-external/package/python-ovos-skill-manager/python-ovos-skill-manager.hash
+++ b/buildroot-external/package/python-ovos-skill-manager/python-ovos-skill-manager.hash
@@ -1 +1 @@
-sha256 9181142eb9d84eb523f210a0f9e26febf4536044b98f1adf69ab1a2fe14474f6 python-ovos-skill-manager-44103885ff80d3ed14bb96f6a3df3a17f854fd6e.tar.gz
+sha256 fb8d0ce497585504e0958343999ef605febfd6ff8fc6a32a5906f1b164f0defd python-ovos-skill-manager-1c3dc3929a6efff9ebf475e9be185b6bb8a965d9.tar.gz
diff --git a/buildroot-external/package/python-ovos-skill-manager/python-ovos-skill-manager.mk b/buildroot-external/package/python-ovos-skill-manager/python-ovos-skill-manager.mk
index 4a2ee38e..2e4edf11 100644
--- a/buildroot-external/package/python-ovos-skill-manager/python-ovos-skill-manager.mk
+++ b/buildroot-external/package/python-ovos-skill-manager/python-ovos-skill-manager.mk
@@ -4,7 +4,7 @@
#
################################################################################
-PYTHON_OVOS_SKILL_MANAGER_VERSION = 44103885ff80d3ed14bb96f6a3df3a17f854fd6e
+PYTHON_OVOS_SKILL_MANAGER_VERSION = 1c3dc3929a6efff9ebf475e9be185b6bb8a965d9
PYTHON_OVOS_SKILL_MANAGER_SITE = $(call github,OpenVoiceOS,ovos_skill_manager,$(PYTHON_OVOS_SKILL_MANAGER_VERSION))
PYTHON_OVOS_SKILL_MANAGER_SETUP_TYPE = setuptools
PYTHON_OVOS_SKILL_MANAGER_LICENSE_FILES = LICENSE
diff --git a/buildroot-external/package/python-ovos-utils/python-ovos-utils.hash b/buildroot-external/package/python-ovos-utils/python-ovos-utils.hash
index 31ba3354..c794b0be 100644
--- a/buildroot-external/package/python-ovos-utils/python-ovos-utils.hash
+++ b/buildroot-external/package/python-ovos-utils/python-ovos-utils.hash
@@ -1 +1 @@
-sha256 14783e19e3159df3d9fb12e65624cea9a03422bfd0abff18a1e574fdad3a468a python-ovos-utils-8e0c4b762bc5b44c9f96ed6397cb996d53a7d598.tar.gz
+sha256 300f95595963f893620cac755ee1fb0a1d126050bb04924825e0f45567f9d4e6 python-ovos-utils-d66d537679eea5732dcb0f9f69bc0524d470f13b.tar.gz
diff --git a/buildroot-external/package/python-ovos-utils/python-ovos-utils.mk b/buildroot-external/package/python-ovos-utils/python-ovos-utils.mk
index 8e884d02..ff274174 100644
--- a/buildroot-external/package/python-ovos-utils/python-ovos-utils.mk
+++ b/buildroot-external/package/python-ovos-utils/python-ovos-utils.mk
@@ -4,7 +4,7 @@
#
################################################################################
-PYTHON_OVOS_UTILS_VERSION = 8e0c4b762bc5b44c9f96ed6397cb996d53a7d598
+PYTHON_OVOS_UTILS_VERSION = d66d537679eea5732dcb0f9f69bc0524d470f13b
PYTHON_OVOS_UTILS_SITE = $(call github,OpenVoiceOS,ovos_utils,$(PYTHON_OVOS_UTILS_VERSION))
PYTHON_OVOS_UTILS_SETUP_TYPE = setuptools
PYTHON_OVOS_UTILS_LICENSE_FILES = LICENSE
diff --git a/buildroot-external/package/python-ovos-workshop/python-ovos-workshop.hash b/buildroot-external/package/python-ovos-workshop/python-ovos-workshop.hash
index 2fc70bd1..97ce4f74 100644
--- a/buildroot-external/package/python-ovos-workshop/python-ovos-workshop.hash
+++ b/buildroot-external/package/python-ovos-workshop/python-ovos-workshop.hash
@@ -1 +1 @@
-sha256 0022c7295d6286c7a5ec60d0bf02cb9d694810d20818c28bff7106b2df9b00d4 python-ovos-workshop-a0892345821183c78282a8c7e66abe4116e7893f.tar.gz
+sha256 1ebe5f278bf85e9ae48097d76de5f8a45c594a20757b1f9a70f074cdb1e14885 python-ovos-workshop-175e1eda39dc21627b1d8135cc98c838da99f5d7.tar.gz
diff --git a/buildroot-external/package/python-ovos-workshop/python-ovos-workshop.mk b/buildroot-external/package/python-ovos-workshop/python-ovos-workshop.mk
index e7589429..7e4d64ab 100644
--- a/buildroot-external/package/python-ovos-workshop/python-ovos-workshop.mk
+++ b/buildroot-external/package/python-ovos-workshop/python-ovos-workshop.mk
@@ -4,9 +4,10 @@
#
################################################################################
-PYTHON_OVOS_WORKSHOP_VERSION = a0892345821183c78282a8c7e66abe4116e7893f
+PYTHON_OVOS_WORKSHOP_VERSION = 175e1eda39dc21627b1d8135cc98c838da99f5d7
PYTHON_OVOS_WORKSHOP_SITE = $(call github,OpenVoiceOS,OVOS-workshop,$(PYTHON_OVOS_WORKSHOP_VERSION))
PYTHON_OVOS_WORKSHOP_SETUP_TYPE = setuptools
PYTHON_OVOS_WORKSHOP_LICENSE_FILES = LICENSE
+PYTHON_OVOS_WORKSHOP_ENV = MYCROFT_LOOSE_REQUIREMENTS=true
$(eval $(python-package))
diff --git a/buildroot-external/package/skill-ovos-fallback-unknown/skill-ovos-fallback-unknown.hash b/buildroot-external/package/skill-ovos-fallback-unknown/skill-ovos-fallback-unknown.hash
index 4b49d81c..43589f2f 100644
--- a/buildroot-external/package/skill-ovos-fallback-unknown/skill-ovos-fallback-unknown.hash
+++ b/buildroot-external/package/skill-ovos-fallback-unknown/skill-ovos-fallback-unknown.hash
@@ -1 +1 @@
-sha256 dd2571e17fa2604d031d3444e7e7665770dd2fb6f0176d63f0aacab6b02ec16c skill-ovos-fallback-unknown-2ce227adf319512ecd67897fb56f832d8656b981.tar.gz
+sha256 42ed1b020014615893c05524a15db73b6e1870c2a42fe1bae30d639a9b849fcb skill-ovos-fallback-unknown-185f029f7777d320fb713e04b11b295c4549e103.tar.gz
diff --git a/buildroot-external/package/skill-ovos-fallback-unknown/skill-ovos-fallback-unknown.mk b/buildroot-external/package/skill-ovos-fallback-unknown/skill-ovos-fallback-unknown.mk
index b716bcbe..5bbc2f31 100644
--- a/buildroot-external/package/skill-ovos-fallback-unknown/skill-ovos-fallback-unknown.mk
+++ b/buildroot-external/package/skill-ovos-fallback-unknown/skill-ovos-fallback-unknown.mk
@@ -4,7 +4,7 @@
#
################################################################################
-SKILL_OVOS_FALLBACK_UNKNOWN_VERSION = 2ce227adf319512ecd67897fb56f832d8656b981
+SKILL_OVOS_FALLBACK_UNKNOWN_VERSION = 185f029f7777d320fb713e04b11b295c4549e103
SKILL_OVOS_FALLBACK_UNKNOWN_SITE = $(call github,OpenVoiceOS,ovos-skill-fallback-unknown,$(SKILL_OVOS_FALLBACK_UNKNOWN_VERSION))
SKILL_OVOS_FALLBACK_UNKNOWN_SETUP_TYPE = setuptools
SKILL_OVOS_FALLBACK_UNKNOWN_LICENSE_FILES = LICENSE
diff --git a/buildroot-external/package/skill-ovos-homescreen/skill-ovos-homescreen.hash b/buildroot-external/package/skill-ovos-homescreen/skill-ovos-homescreen.hash
index c58746b2..63df4115 100644
--- a/buildroot-external/package/skill-ovos-homescreen/skill-ovos-homescreen.hash
+++ b/buildroot-external/package/skill-ovos-homescreen/skill-ovos-homescreen.hash
@@ -1 +1 @@
-sha256 4d37b79262533e2e1774c8d557b8f836a53b7f21fea3a77a8d252e28bc512cd9 skill-ovos-homescreen-a5373203b6266f309a3aee9f7c1528c5a25e8447.tar.gz
+sha256 a43a3d44d9161e079ee18523968f93ee844777f30047daff003f000c9445c460 skill-ovos-homescreen-590b9e62fbe77edbe9ea8bbc4112b0d690f53075.tar.gz
diff --git a/buildroot-external/package/skill-ovos-homescreen/skill-ovos-homescreen.mk b/buildroot-external/package/skill-ovos-homescreen/skill-ovos-homescreen.mk
index f255cc62..9f15efa6 100644
--- a/buildroot-external/package/skill-ovos-homescreen/skill-ovos-homescreen.mk
+++ b/buildroot-external/package/skill-ovos-homescreen/skill-ovos-homescreen.mk
@@ -4,7 +4,7 @@
#
################################################################################
-SKILL_OVOS_HOMESCREEN_VERSION = a5373203b6266f309a3aee9f7c1528c5a25e8447
+SKILL_OVOS_HOMESCREEN_VERSION = 590b9e62fbe77edbe9ea8bbc4112b0d690f53075
SKILL_OVOS_HOMESCREEN_SITE = $(call github,OpenVoiceOS,skill-ovos-homescreen,$(SKILL_OVOS_HOMESCREEN_VERSION))
SKILL_OVOS_HOMESCREEN_SETUP_TYPE = setuptools
SKILL_OVOS_HOMESCREEN_LICENSE_FILES = LICENSE
diff --git a/buildroot-external/package/skill-ovos-setup/0001-fix-text-overflow-in-list-delegates.patch b/buildroot-external/package/skill-ovos-setup/0001-fix-text-overflow-in-list-delegates.patch
new file mode 100644
index 00000000..32c80feb
--- /dev/null
+++ b/buildroot-external/package/skill-ovos-setup/0001-fix-text-overflow-in-list-delegates.patch
@@ -0,0 +1,50 @@
+From 29963eac8e3a5752d163f674c18b19bdd7775672 Mon Sep 17 00:00:00 2001
+From: Aditya Mehra
+Date: Fri, 16 Dec 2022 09:39:36 +1030
+Subject: [PATCH] fix text overflow in list delegates
+
+---
+ ui/STTListMenu.qml | 2 ++
+ ui/TTSListMenuNested.qml | 2 ++
+ ui/TTSListMenuSingle.qml | 2 ++
+ 3 files changed, 6 insertions(+)
+
+diff --git a/ui/STTListMenu.qml b/ui/STTListMenu.qml
+index 2fe5325..7b3e586 100644
+--- a/ui/STTListMenu.qml
++++ b/ui/STTListMenu.qml
+@@ -214,6 +214,8 @@ Item {
+ verticalAlignment: Text.AlignVCenter
+ color: Kirigami.Theme.textColor
+ font.capitalization: Font.AllUppercase
++ maximumLineCount: 2
++ elide: Text.ElideRight
+ text: model.plugin_name + " | " + model.display_name
+ }
+
+diff --git a/ui/TTSListMenuNested.qml b/ui/TTSListMenuNested.qml
+index e3edad7..4008397 100644
+--- a/ui/TTSListMenuNested.qml
++++ b/ui/TTSListMenuNested.qml
+@@ -230,6 +230,8 @@ Item {
+ verticalAlignment: Text.AlignVCenter
+ color: Kirigami.Theme.textColor
+ font.capitalization: Font.AllUppercase
++ maximumLineCount: 2
++ elide: Text.ElideRight
+ text: ttsListView.listmode == 1 ? modelData.plugin_name + " | " + modelData.display_name : model.plugin_name
+ }
+
+diff --git a/ui/TTSListMenuSingle.qml b/ui/TTSListMenuSingle.qml
+index 84d06a9..d3e3a84 100644
+--- a/ui/TTSListMenuSingle.qml
++++ b/ui/TTSListMenuSingle.qml
+@@ -214,6 +214,8 @@ Item {
+ verticalAlignment: Text.AlignVCenter
+ color: Kirigami.Theme.textColor
+ font.capitalization: Font.AllUppercase
++ maximumLineCount: 2
++ elide: Text.ElideRight
+ text: model.plugin_name + " | " + model.display_name
+ }
+
diff --git a/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour-0.1.5.dist-info/DESCRIPTION.rst b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour-0.1.5.dist-info/DESCRIPTION.rst
new file mode 100644
index 00000000..8b36b412
--- /dev/null
+++ b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour-0.1.5.dist-info/DESCRIPTION.rst
@@ -0,0 +1,606 @@
+======
+Colour
+======
+
+.. image:: http://img.shields.io/pypi/v/colour.svg?style=flat
+ :target: https://pypi.python.org/pypi/colour/
+ :alt: Latest PyPI version
+
+.. image:: https://img.shields.io/pypi/l/gitchangelog.svg?style=flat
+ :target: https://github.com/vaab/gitchangelog/blob/master/LICENSE
+ :alt: License
+
+.. image:: https://img.shields.io/pypi/pyversions/gitchangelog.svg?style=flat
+ :target: https://pypi.python.org/pypi/gitchangelog/
+ :alt: Compatible python versions
+
+.. image:: http://img.shields.io/pypi/dm/colour.svg?style=flat
+ :target: https://pypi.python.org/pypi/colour/
+ :alt: Number of PyPI downloads
+
+.. image:: http://img.shields.io/travis/vaab/colour/master.svg?style=flat
+ :target: https://travis-ci.org/vaab/colour/
+ :alt: Travis CI build status
+
+.. image:: https://img.shields.io/appveyor/ci/vaab/colour.svg
+ :target: https://ci.appveyor.com/project/vaab/colour/branch/master
+ :alt: Appveyor CI build status
+
+.. image:: http://img.shields.io/codecov/c/github/vaab/colour.svg?style=flat
+ :target: https://codecov.io/gh/vaab/colour/
+ :alt: Test coverage
+
+
+Converts and manipulates common color representation (RGB, HSL, web, ...)
+
+
+Feature
+=======
+
+- Damn simple and pythonic way to manipulate color representation (see
+ examples below)
+
+- Full conversion between RGB, HSL, 6-digit hex, 3-digit hex, human color
+
+- One object (``Color``) or bunch of single purpose function (``rgb2hex``,
+ ``hsl2rgb`` ...)
+
+- ``web`` format that use the smallest representation between
+ 6-digit (e.g. ``#fa3b2c``), 3-digit (e.g. ``#fbb``), fully spelled
+ color (e.g. ``white``), following `W3C color naming`_ for compatible
+ CSS or HTML color specifications.
+
+- smooth intuitive color scale generation choosing N color gradients.
+
+- can pick colors for you to identify objects of your application.
+
+
+.. _W3C color naming: http://www.w3.org/TR/css3-color/#svg-color
+
+
+Installation
+============
+
+You don't need to download the GIT version of the code as ``colour`` is
+available on the PyPI. So you should be able to run::
+
+ pip install colour
+
+If you have downloaded the GIT sources, then you could add the ``colour.py``
+directly to one of your ``site-packages`` (thanks to a symlink). Or install
+the current version via traditional::
+
+ python setup.py install
+
+And if you don't have the GIT sources but would like to get the latest
+master or branch from github, you could also::
+
+ pip install git+https://github.com/vaab/colour
+
+Or even select a specific revision (branch/tag/commit)::
+
+ pip install git+https://github.com/vaab/colour@master
+
+
+Usage
+=====
+
+To get complete demo of each function, please read the source code which is
+heavily documented and provide a lot of examples in doctest format.
+
+Here is a reduced sample of a common usage scenario:
+
+
+Instantiation
+-------------
+
+Let's create blue color::
+
+ >>> from colour import Color
+ >>> c = Color("blue")
+ >>> c
+
+
+Please note that all of these are equivalent examples to create the red color::
+
+ Color("red") ## human, web compatible representation
+ Color(red=1) ## default amount of blue and green is 0.0
+ Color("blue", hue=0) ## hue of blue is 0.66, hue of red is 0.0
+ Color("#f00") ## standard 3 hex digit web compatible representation
+ Color("#ff0000") ## standard 6 hex digit web compatible representation
+ Color(hue=0, saturation=1, luminance=0.5)
+ Color(hsl=(0, 1, 0.5)) ## full 3-uple HSL specification
+ Color(rgb=(1, 0, 0)) ## full 3-uple RGB specification
+ Color(Color("red")) ## recursion doesn't break object
+
+
+Reading values
+--------------
+
+Several representations are accessible::
+
+ >>> c.hex
+ '#00f'
+ >>> c.hsl # doctest: +ELLIPSIS
+ (0.66..., 1.0, 0.5)
+ >>> c.rgb
+ (0.0, 0.0, 1.0)
+
+And their different parts are also independently accessible, as the different
+amount of red, blue, green, in the RGB format::
+
+ >>> c.red
+ 0.0
+ >>> c.blue
+ 1.0
+ >>> c.green
+ 0.0
+
+Or the hue, saturation and luminance of the HSL representation::
+
+ >>> c.hue # doctest: +ELLIPSIS
+ 0.66...
+ >>> c.saturation
+ 1.0
+ >>> c.luminance
+ 0.5
+
+A note on the ``.hex`` property, it'll return the smallest valid value
+when possible. If you are only interested by the long value, use
+``.hex_l``::
+
+ >>> c.hex_l
+ '#0000ff'
+
+
+Modifying color objects
+-----------------------
+
+All of these properties are read/write, so let's add some red to this color::
+
+ >>> c.red = 1
+ >>> c
+
+
+We might want to de-saturate this color::
+
+ >>> c.saturation = 0.5
+ >>> c
+
+
+And of course, the string conversion will give the web representation which is
+human, or 3-digit, or 6-digit hex representation depending which is usable::
+
+ >>> "%s" % c
+ '#bf40bf'
+
+ >>> c.luminance = 1
+ >>> "%s" % c
+ 'white'
+
+
+Ranges of colors
+----------------
+
+You can get some color scale of variation between two ``Color`` objects quite
+easily. Here, is the color scale of the rainbow between red and blue::
+
+ >>> red = Color("red")
+ >>> blue = Color("blue")
+ >>> list(red.range_to(blue, 5))
+ [, , , , ]
+
+Or the different amount of gray between black and white::
+
+ >>> black = Color("black")
+ >>> white = Color("white")
+ >>> list(black.range_to(white, 6))
+ [, , , , , ]
+
+
+If you have to create graphical representation with color scale
+between red and green ('lime' color is full green)::
+
+ >>> lime = Color("lime")
+ >>> list(red.range_to(lime, 5))
+ [, , , , ]
+
+Notice how naturally, the yellow is displayed in human format and in
+the middle of the scale. And that the quite unusual (but compatible)
+'chartreuse' color specification has been used in place of the
+hexadecimal representation.
+
+
+Color comparison
+----------------
+
+Sane default
+~~~~~~~~~~~~
+
+Color comparison is a vast subject. However, it might seem quite straightforward for
+you. ``Colour`` uses a configurable default way of comparing color that might suit
+your needs::
+
+ >>> Color("red") == Color("#f00") == Color("blue", hue=0)
+ True
+
+The default comparison algorithm focuses only on the "web" representation which is
+equivalent to comparing the long hex representation (e.g. #FF0000) or to be more
+specific, it is equivalent to compare the amount of red, green, and blue composition
+of the RGB representation, each of these value being quantized to a 256 value scale.
+
+This default comparison is a practical and convenient way to measure the actual
+color equivalence on your screen, or in your video card memory.
+
+But this comparison wouldn't make the difference between a black red, and a
+black blue, which both are black::
+
+ >>> black_red = Color("red", luminance=0)
+ >>> black_blue = Color("blue", luminance=0)
+
+ >>> black_red == black_blue
+ True
+
+
+Customization
+~~~~~~~~~~~~~
+
+But, this is not the sole way to compare two colors. As I'm quite lazy, I'm providing
+you a way to customize it to your needs. Thus::
+
+ >>> from colour import RGB_equivalence, HSL_equivalence
+ >>> black_red = Color("red", luminance=0, equality=HSL_equivalence)
+ >>> black_blue = Color("blue", luminance=0, equality=HSL_equivalence)
+
+ >>> black_red == black_blue
+ False
+
+As you might have already guessed, the sane default is ``RGB_equivalence``, so::
+
+ >>> black_red = Color("red", luminance=0, equality=RGB_equivalence)
+ >>> black_blue = Color("blue", luminance=0, equality=RGB_equivalence)
+
+ >>> black_red == black_blue
+ True
+
+Here's how you could implement your unique comparison function::
+
+ >>> saturation_equivalence = lambda c1, c2: c1.saturation == c2.saturation
+ >>> red = Color("red", equality=saturation_equivalence)
+ >>> blue = Color("blue", equality=saturation_equivalence)
+ >>> white = Color("white", equality=saturation_equivalence)
+
+ >>> red == blue
+ True
+ >>> white == red
+ False
+
+Note: When comparing 2 colors, *only* the equality function *of the first
+color will be used*. Thus::
+
+ >>> black_red = Color("red", luminance=0, equality=RGB_equivalence)
+ >>> black_blue = Color("blue", luminance=0, equality=HSL_equivalence)
+
+ >>> black_red == black_blue
+ True
+
+But reverse operation is not equivalent !::
+
+ >>> black_blue == black_red
+ False
+
+
+Equality to non-Colour objects
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+As a side note, whatever your custom equality function is, it won't be
+used if you compare to anything else than a ``Colour`` instance::
+
+ >>> red = Color("red", equality=lambda c1, c2: True)
+ >>> blue = Color("blue", equality=lambda c1, c2: True)
+
+Note that these instances would compare as equal to any other color::
+
+ >>> red == blue
+ True
+
+But on another non-Colour object::
+
+ >>> red == None
+ False
+ >>> red != None
+ True
+
+Actually, ``Colour`` instances will, politely enough, leave
+the other side of the equality have a chance to decide of the output,
+(by executing its own ``__eq__``), so::
+
+ >>> class OtherColorImplem(object):
+ ... def __init__(self, color):
+ ... self.color = color
+ ... def __eq__(self, other):
+ ... return self.color == other.web
+
+ >>> alien_red = OtherColorImplem("red")
+ >>> red == alien_red
+ True
+ >>> blue == alien_red
+ False
+
+And inequality (using ``__ne__``) are also polite::
+
+ >>> class AnotherColorImplem(OtherColorImplem):
+ ... def __ne__(self, other):
+ ... return self.color != other.web
+
+ >>> new_alien_red = AnotherColorImplem("red")
+ >>> red != new_alien_red
+ False
+ >>> blue != new_alien_red
+ True
+
+
+Picking arbitrary color for a python object
+-------------------------------------------
+
+Basic Usage
+~~~~~~~~~~~
+
+Sometimes, you just want to pick a color for an object in your application
+often to visually identify this object. Thus, the picked color should be the
+same for same objects, and different for different object::
+
+ >>> foo = object()
+ >>> bar = object()
+
+ >>> Color(pick_for=foo) # doctest: +ELLIPSIS
+
+ >>> Color(pick_for=foo) == Color(pick_for=foo)
+ True
+ >>> Color(pick_for=foo) == Color(pick_for=bar)
+ False
+
+Of course, although there's a tiny probability that different strings yield the
+same color, most of the time, different inputs will produce different colors.
+
+Advanced Usage
+~~~~~~~~~~~~~~
+
+You can customize your color picking algorithm by providing a ``picker``. A
+``picker`` is a callable that takes an object, and returns something that can
+be instantiated as a color by ``Color``::
+
+ >>> my_picker = lambda obj: "red" if isinstance(obj, int) else "blue"
+ >>> Color(pick_for=3, picker=my_picker, pick_key=None)
+
+ >>> Color(pick_for="foo", picker=my_picker, pick_key=None)
+
+
+You might want to use a particular picker, but enforce how the picker will
+identify two object as the same (or not). So there's a ``pick_key`` attribute
+that is provided and defaults as equivalent of ``hash`` method and if hash is
+not supported by your object, it'll default to the ``str`` of your object salted
+with the class name.
+
+Thus::
+
+ >>> class MyObj(str): pass
+ >>> my_obj_color = Color(pick_for=MyObj("foo"))
+ >>> my_str_color = Color(pick_for="foo")
+ >>> my_obj_color == my_str_color
+ False
+
+Please make sure your object is hashable or "stringable" before using the
+``RGB_color_picker`` picking mechanism or provide another color picker. Nearly
+all python object are hashable by default so this shouldn't be an issue (e.g.
+instances of ``object`` and subclasses are hashable).
+
+Neither ``hash`` nor ``str`` are perfect solution. So feel free to use
+``pick_key`` at ``Color`` instantiation time to set your way to identify
+objects, for instance::
+
+ >>> a = object()
+ >>> b = object()
+ >>> Color(pick_for=a, pick_key=id) == Color(pick_for=b, pick_key=id)
+ False
+
+When choosing a pick key, you should closely consider if you want your color
+to be consistent between runs (this is NOT the case with the last example),
+or consistent with the content of your object if it is a mutable object.
+
+Default value of ``pick_key`` and ``picker`` ensures that the same color will
+be attributed to same object between different run on different computer for
+most python object.
+
+
+Color factory
+-------------
+
+As you might have noticed, there are few attributes that you might want to see
+attached to all of your colors as ``equality`` for equality comparison support,
+or ``picker``, ``pick_key`` to configure your object color picker.
+
+You can create a customized ``Color`` factory thanks to the ``make_color_factory``::
+
+ >>> from colour import make_color_factory, HSL_equivalence, RGB_color_picker
+
+ >>> get_color = make_color_factory(
+ ... equality=HSL_equivalence,
+ ... picker=RGB_color_picker,
+ ... pick_key=str,
+ ... )
+
+All color created thanks to ``CustomColor`` class instead of the default one
+would get the specified attributes by default::
+
+ >>> black_red = get_color("red", luminance=0)
+ >>> black_blue = get_color("blue", luminance=0)
+
+Of course, these are always instances of ``Color`` class::
+
+ >>> isinstance(black_red, Color)
+ True
+
+Equality was changed from normal defaults, so::
+
+ >>> black_red == black_blue
+ False
+
+This because the default equivalence of ``Color`` was set to
+``HSL_equivalence``.
+
+
+Contributing
+============
+
+Any suggestion or issue is welcome. Push request are very welcome,
+please check out the guidelines.
+
+
+Push Request Guidelines
+-----------------------
+
+You can send any code. I'll look at it and will integrate it myself in
+the code base and leave you as the author. This process can take time and
+it'll take less time if you follow the following guidelines:
+
+- check your code with PEP8 or pylint. Try to stick to 80 columns wide.
+- separate your commits per smallest concern.
+- each commit should pass the tests (to allow easy bisect)
+- each functionality/bugfix commit should contain the code, tests,
+ and doc.
+- prior minor commit with typographic or code cosmetic changes are
+ very welcome. These should be tagged in their commit summary with
+ ``!minor``.
+- the commit message should follow gitchangelog rules (check the git
+ log to get examples)
+- if the commit fixes an issue or finished the implementation of a
+ feature, please mention it in the summary.
+
+If you have some questions about guidelines which is not answered here,
+please check the current ``git log``, you might find previous commit that
+would show you how to deal with your issue.
+
+
+License
+=======
+
+Copyright (c) 2012-2017 Valentin Lab.
+
+Licensed under the `BSD License`_.
+
+.. _BSD License: http://raw.github.com/vaab/colour/master/LICENSE
+
+Changelog
+=========
+
+
+0.1.4 (2017-04-19)
+------------------
+
+Fix
+~~~
+- ``rgb2hsl`` would produce invalid hsl triplet when red, blue, green
+ component would be all very close to ``1.0``. (fixes #30) [Valentin
+ Lab]
+
+ Typically, saturation would shoot out of range 0.0..1.0. That could then
+ lead to exceptions being casts afterwards when trying to reconvert this
+ HSL triplet to RGB values.
+
+
+0.1.3 (2017-04-08)
+------------------
+
+Fix
+~~~
+- Unexpected behavior with ``!=`` operator. (fixes #26) [Valentin Lab]
+- Added mention of the ``hex_l`` property. (fixes #27) [Valentin Lab]
+
+
+0.1.2 (2015-09-15)
+------------------
+
+Fix
+~~~
+- Support for corner case 1-wide ``range_to`` color scale. (fixes #18)
+ [Valentin Lab]
+
+
+0.1.1 (2015-03-29)
+------------------
+
+Fix
+~~~
+- Avoid casting an exception when comparing to non-``Colour`` instances.
+ (fixes #14) [Riziq Sayegh]
+
+
+0.0.6 (2014-11-18)
+------------------
+
+New
+~~~
+- Provide all missing *2* function by combination with other existing
+ ones (fixes #13). [Valentin Lab]
+- Provide full access to any color name in HSL, RGB, HEX convenience
+ instances. [Valentin Lab]
+
+ Now you can call ``colour.HSL.cyan``, or ``colour.HEX.red`` for a direct encoding of
+ ``human`` colour labels to the 3 representations.
+
+
+0.0.5 (2013-09-16)
+------------------
+
+New
+~~~
+- Color names are case insensitive. [Chris Priest]
+
+ The color-name structure have their names capitalized. And color names
+ that are made of only one word will be displayed lowercased.
+
+Fix
+~~~
+- Now using W3C color recommandation. [Chris Priest]
+
+ Was using X11 color scheme before, which is slightly different from
+ W3C web color specifications.
+- Inconsistency in licence information (removed GPL mention). (fixes #8)
+ [Valentin Lab]
+- Removed ``gitchangelog`` from ``setup.py`` require list. (fixes #9)
+ [Valentin Lab]
+
+
+0.0.4 (2013-06-21)
+------------------
+
+New
+~~~
+- Added ``make_color_factory`` to customize some common color
+ attributes. [Valentin Lab]
+- Pick color to identify any python object (fixes #6) [Jonathan Ballet]
+- Equality support between colors, customizable if needed. (fixes #3)
+ [Valentin Lab]
+
+
+0.0.3 (2013-06-19)
+------------------
+
+New
+~~~
+- Colour is now compatible with python3. [Ryan Leckey]
+
+
+0.0.1 (2012-06-11)
+------------------
+- First import. [Valentin Lab]
+
+TODO
+====
+
+- ANSI 16-color and 256-color escape sequence generation
+- YUV, HSV, CMYK support
+
+
+
diff --git a/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour-0.1.5.dist-info/INSTALLER b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour-0.1.5.dist-info/INSTALLER
new file mode 100644
index 00000000..a1b589e3
--- /dev/null
+++ b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour-0.1.5.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour-0.1.5.dist-info/LICENSE.txt b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour-0.1.5.dist-info/LICENSE.txt
new file mode 100644
index 00000000..c4ed93bd
--- /dev/null
+++ b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour-0.1.5.dist-info/LICENSE.txt
@@ -0,0 +1,23 @@
+Copyright (c) 2012-2017, Valentin Lab
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+2. 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.
+
+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.
+
diff --git a/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour-0.1.5.dist-info/METADATA b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour-0.1.5.dist-info/METADATA
new file mode 100644
index 00000000..ce2ad8ad
--- /dev/null
+++ b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour-0.1.5.dist-info/METADATA
@@ -0,0 +1,630 @@
+Metadata-Version: 2.0
+Name: colour
+Version: 0.1.5
+Summary: converts and manipulates various color representation (HSL, RVB, web, X11, ...)
+Home-page: http://github.com/vaab/colour
+Author: Valentin LAB
+Author-email: valentin.lab@kalysto.org
+License: BSD 3-Clause License
+Platform: UNKNOWN
+Classifier: Programming Language :: Python
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Development Status :: 3 - Alpha
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Intended Audience :: Developers
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
+Provides-Extra: test
+Requires-Dist: nose; extra == 'test'
+
+======
+Colour
+======
+
+.. image:: http://img.shields.io/pypi/v/colour.svg?style=flat
+ :target: https://pypi.python.org/pypi/colour/
+ :alt: Latest PyPI version
+
+.. image:: https://img.shields.io/pypi/l/gitchangelog.svg?style=flat
+ :target: https://github.com/vaab/gitchangelog/blob/master/LICENSE
+ :alt: License
+
+.. image:: https://img.shields.io/pypi/pyversions/gitchangelog.svg?style=flat
+ :target: https://pypi.python.org/pypi/gitchangelog/
+ :alt: Compatible python versions
+
+.. image:: http://img.shields.io/pypi/dm/colour.svg?style=flat
+ :target: https://pypi.python.org/pypi/colour/
+ :alt: Number of PyPI downloads
+
+.. image:: http://img.shields.io/travis/vaab/colour/master.svg?style=flat
+ :target: https://travis-ci.org/vaab/colour/
+ :alt: Travis CI build status
+
+.. image:: https://img.shields.io/appveyor/ci/vaab/colour.svg
+ :target: https://ci.appveyor.com/project/vaab/colour/branch/master
+ :alt: Appveyor CI build status
+
+.. image:: http://img.shields.io/codecov/c/github/vaab/colour.svg?style=flat
+ :target: https://codecov.io/gh/vaab/colour/
+ :alt: Test coverage
+
+
+Converts and manipulates common color representation (RGB, HSL, web, ...)
+
+
+Feature
+=======
+
+- Damn simple and pythonic way to manipulate color representation (see
+ examples below)
+
+- Full conversion between RGB, HSL, 6-digit hex, 3-digit hex, human color
+
+- One object (``Color``) or bunch of single purpose function (``rgb2hex``,
+ ``hsl2rgb`` ...)
+
+- ``web`` format that use the smallest representation between
+ 6-digit (e.g. ``#fa3b2c``), 3-digit (e.g. ``#fbb``), fully spelled
+ color (e.g. ``white``), following `W3C color naming`_ for compatible
+ CSS or HTML color specifications.
+
+- smooth intuitive color scale generation choosing N color gradients.
+
+- can pick colors for you to identify objects of your application.
+
+
+.. _W3C color naming: http://www.w3.org/TR/css3-color/#svg-color
+
+
+Installation
+============
+
+You don't need to download the GIT version of the code as ``colour`` is
+available on the PyPI. So you should be able to run::
+
+ pip install colour
+
+If you have downloaded the GIT sources, then you could add the ``colour.py``
+directly to one of your ``site-packages`` (thanks to a symlink). Or install
+the current version via traditional::
+
+ python setup.py install
+
+And if you don't have the GIT sources but would like to get the latest
+master or branch from github, you could also::
+
+ pip install git+https://github.com/vaab/colour
+
+Or even select a specific revision (branch/tag/commit)::
+
+ pip install git+https://github.com/vaab/colour@master
+
+
+Usage
+=====
+
+To get complete demo of each function, please read the source code which is
+heavily documented and provide a lot of examples in doctest format.
+
+Here is a reduced sample of a common usage scenario:
+
+
+Instantiation
+-------------
+
+Let's create blue color::
+
+ >>> from colour import Color
+ >>> c = Color("blue")
+ >>> c
+
+
+Please note that all of these are equivalent examples to create the red color::
+
+ Color("red") ## human, web compatible representation
+ Color(red=1) ## default amount of blue and green is 0.0
+ Color("blue", hue=0) ## hue of blue is 0.66, hue of red is 0.0
+ Color("#f00") ## standard 3 hex digit web compatible representation
+ Color("#ff0000") ## standard 6 hex digit web compatible representation
+ Color(hue=0, saturation=1, luminance=0.5)
+ Color(hsl=(0, 1, 0.5)) ## full 3-uple HSL specification
+ Color(rgb=(1, 0, 0)) ## full 3-uple RGB specification
+ Color(Color("red")) ## recursion doesn't break object
+
+
+Reading values
+--------------
+
+Several representations are accessible::
+
+ >>> c.hex
+ '#00f'
+ >>> c.hsl # doctest: +ELLIPSIS
+ (0.66..., 1.0, 0.5)
+ >>> c.rgb
+ (0.0, 0.0, 1.0)
+
+And their different parts are also independently accessible, as the different
+amount of red, blue, green, in the RGB format::
+
+ >>> c.red
+ 0.0
+ >>> c.blue
+ 1.0
+ >>> c.green
+ 0.0
+
+Or the hue, saturation and luminance of the HSL representation::
+
+ >>> c.hue # doctest: +ELLIPSIS
+ 0.66...
+ >>> c.saturation
+ 1.0
+ >>> c.luminance
+ 0.5
+
+A note on the ``.hex`` property, it'll return the smallest valid value
+when possible. If you are only interested by the long value, use
+``.hex_l``::
+
+ >>> c.hex_l
+ '#0000ff'
+
+
+Modifying color objects
+-----------------------
+
+All of these properties are read/write, so let's add some red to this color::
+
+ >>> c.red = 1
+ >>> c
+
+
+We might want to de-saturate this color::
+
+ >>> c.saturation = 0.5
+ >>> c
+
+
+And of course, the string conversion will give the web representation which is
+human, or 3-digit, or 6-digit hex representation depending which is usable::
+
+ >>> "%s" % c
+ '#bf40bf'
+
+ >>> c.luminance = 1
+ >>> "%s" % c
+ 'white'
+
+
+Ranges of colors
+----------------
+
+You can get some color scale of variation between two ``Color`` objects quite
+easily. Here, is the color scale of the rainbow between red and blue::
+
+ >>> red = Color("red")
+ >>> blue = Color("blue")
+ >>> list(red.range_to(blue, 5))
+ [, , , , ]
+
+Or the different amount of gray between black and white::
+
+ >>> black = Color("black")
+ >>> white = Color("white")
+ >>> list(black.range_to(white, 6))
+ [, , , , , ]
+
+
+If you have to create graphical representation with color scale
+between red and green ('lime' color is full green)::
+
+ >>> lime = Color("lime")
+ >>> list(red.range_to(lime, 5))
+ [, , , , ]
+
+Notice how naturally, the yellow is displayed in human format and in
+the middle of the scale. And that the quite unusual (but compatible)
+'chartreuse' color specification has been used in place of the
+hexadecimal representation.
+
+
+Color comparison
+----------------
+
+Sane default
+~~~~~~~~~~~~
+
+Color comparison is a vast subject. However, it might seem quite straightforward for
+you. ``Colour`` uses a configurable default way of comparing color that might suit
+your needs::
+
+ >>> Color("red") == Color("#f00") == Color("blue", hue=0)
+ True
+
+The default comparison algorithm focuses only on the "web" representation which is
+equivalent to comparing the long hex representation (e.g. #FF0000) or to be more
+specific, it is equivalent to compare the amount of red, green, and blue composition
+of the RGB representation, each of these value being quantized to a 256 value scale.
+
+This default comparison is a practical and convenient way to measure the actual
+color equivalence on your screen, or in your video card memory.
+
+But this comparison wouldn't make the difference between a black red, and a
+black blue, which both are black::
+
+ >>> black_red = Color("red", luminance=0)
+ >>> black_blue = Color("blue", luminance=0)
+
+ >>> black_red == black_blue
+ True
+
+
+Customization
+~~~~~~~~~~~~~
+
+But, this is not the sole way to compare two colors. As I'm quite lazy, I'm providing
+you a way to customize it to your needs. Thus::
+
+ >>> from colour import RGB_equivalence, HSL_equivalence
+ >>> black_red = Color("red", luminance=0, equality=HSL_equivalence)
+ >>> black_blue = Color("blue", luminance=0, equality=HSL_equivalence)
+
+ >>> black_red == black_blue
+ False
+
+As you might have already guessed, the sane default is ``RGB_equivalence``, so::
+
+ >>> black_red = Color("red", luminance=0, equality=RGB_equivalence)
+ >>> black_blue = Color("blue", luminance=0, equality=RGB_equivalence)
+
+ >>> black_red == black_blue
+ True
+
+Here's how you could implement your unique comparison function::
+
+ >>> saturation_equivalence = lambda c1, c2: c1.saturation == c2.saturation
+ >>> red = Color("red", equality=saturation_equivalence)
+ >>> blue = Color("blue", equality=saturation_equivalence)
+ >>> white = Color("white", equality=saturation_equivalence)
+
+ >>> red == blue
+ True
+ >>> white == red
+ False
+
+Note: When comparing 2 colors, *only* the equality function *of the first
+color will be used*. Thus::
+
+ >>> black_red = Color("red", luminance=0, equality=RGB_equivalence)
+ >>> black_blue = Color("blue", luminance=0, equality=HSL_equivalence)
+
+ >>> black_red == black_blue
+ True
+
+But reverse operation is not equivalent !::
+
+ >>> black_blue == black_red
+ False
+
+
+Equality to non-Colour objects
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+As a side note, whatever your custom equality function is, it won't be
+used if you compare to anything else than a ``Colour`` instance::
+
+ >>> red = Color("red", equality=lambda c1, c2: True)
+ >>> blue = Color("blue", equality=lambda c1, c2: True)
+
+Note that these instances would compare as equal to any other color::
+
+ >>> red == blue
+ True
+
+But on another non-Colour object::
+
+ >>> red == None
+ False
+ >>> red != None
+ True
+
+Actually, ``Colour`` instances will, politely enough, leave
+the other side of the equality have a chance to decide of the output,
+(by executing its own ``__eq__``), so::
+
+ >>> class OtherColorImplem(object):
+ ... def __init__(self, color):
+ ... self.color = color
+ ... def __eq__(self, other):
+ ... return self.color == other.web
+
+ >>> alien_red = OtherColorImplem("red")
+ >>> red == alien_red
+ True
+ >>> blue == alien_red
+ False
+
+And inequality (using ``__ne__``) are also polite::
+
+ >>> class AnotherColorImplem(OtherColorImplem):
+ ... def __ne__(self, other):
+ ... return self.color != other.web
+
+ >>> new_alien_red = AnotherColorImplem("red")
+ >>> red != new_alien_red
+ False
+ >>> blue != new_alien_red
+ True
+
+
+Picking arbitrary color for a python object
+-------------------------------------------
+
+Basic Usage
+~~~~~~~~~~~
+
+Sometimes, you just want to pick a color for an object in your application
+often to visually identify this object. Thus, the picked color should be the
+same for same objects, and different for different object::
+
+ >>> foo = object()
+ >>> bar = object()
+
+ >>> Color(pick_for=foo) # doctest: +ELLIPSIS
+
+ >>> Color(pick_for=foo) == Color(pick_for=foo)
+ True
+ >>> Color(pick_for=foo) == Color(pick_for=bar)
+ False
+
+Of course, although there's a tiny probability that different strings yield the
+same color, most of the time, different inputs will produce different colors.
+
+Advanced Usage
+~~~~~~~~~~~~~~
+
+You can customize your color picking algorithm by providing a ``picker``. A
+``picker`` is a callable that takes an object, and returns something that can
+be instantiated as a color by ``Color``::
+
+ >>> my_picker = lambda obj: "red" if isinstance(obj, int) else "blue"
+ >>> Color(pick_for=3, picker=my_picker, pick_key=None)
+
+ >>> Color(pick_for="foo", picker=my_picker, pick_key=None)
+
+
+You might want to use a particular picker, but enforce how the picker will
+identify two object as the same (or not). So there's a ``pick_key`` attribute
+that is provided and defaults as equivalent of ``hash`` method and if hash is
+not supported by your object, it'll default to the ``str`` of your object salted
+with the class name.
+
+Thus::
+
+ >>> class MyObj(str): pass
+ >>> my_obj_color = Color(pick_for=MyObj("foo"))
+ >>> my_str_color = Color(pick_for="foo")
+ >>> my_obj_color == my_str_color
+ False
+
+Please make sure your object is hashable or "stringable" before using the
+``RGB_color_picker`` picking mechanism or provide another color picker. Nearly
+all python object are hashable by default so this shouldn't be an issue (e.g.
+instances of ``object`` and subclasses are hashable).
+
+Neither ``hash`` nor ``str`` are perfect solution. So feel free to use
+``pick_key`` at ``Color`` instantiation time to set your way to identify
+objects, for instance::
+
+ >>> a = object()
+ >>> b = object()
+ >>> Color(pick_for=a, pick_key=id) == Color(pick_for=b, pick_key=id)
+ False
+
+When choosing a pick key, you should closely consider if you want your color
+to be consistent between runs (this is NOT the case with the last example),
+or consistent with the content of your object if it is a mutable object.
+
+Default value of ``pick_key`` and ``picker`` ensures that the same color will
+be attributed to same object between different run on different computer for
+most python object.
+
+
+Color factory
+-------------
+
+As you might have noticed, there are few attributes that you might want to see
+attached to all of your colors as ``equality`` for equality comparison support,
+or ``picker``, ``pick_key`` to configure your object color picker.
+
+You can create a customized ``Color`` factory thanks to the ``make_color_factory``::
+
+ >>> from colour import make_color_factory, HSL_equivalence, RGB_color_picker
+
+ >>> get_color = make_color_factory(
+ ... equality=HSL_equivalence,
+ ... picker=RGB_color_picker,
+ ... pick_key=str,
+ ... )
+
+All color created thanks to ``CustomColor`` class instead of the default one
+would get the specified attributes by default::
+
+ >>> black_red = get_color("red", luminance=0)
+ >>> black_blue = get_color("blue", luminance=0)
+
+Of course, these are always instances of ``Color`` class::
+
+ >>> isinstance(black_red, Color)
+ True
+
+Equality was changed from normal defaults, so::
+
+ >>> black_red == black_blue
+ False
+
+This because the default equivalence of ``Color`` was set to
+``HSL_equivalence``.
+
+
+Contributing
+============
+
+Any suggestion or issue is welcome. Push request are very welcome,
+please check out the guidelines.
+
+
+Push Request Guidelines
+-----------------------
+
+You can send any code. I'll look at it and will integrate it myself in
+the code base and leave you as the author. This process can take time and
+it'll take less time if you follow the following guidelines:
+
+- check your code with PEP8 or pylint. Try to stick to 80 columns wide.
+- separate your commits per smallest concern.
+- each commit should pass the tests (to allow easy bisect)
+- each functionality/bugfix commit should contain the code, tests,
+ and doc.
+- prior minor commit with typographic or code cosmetic changes are
+ very welcome. These should be tagged in their commit summary with
+ ``!minor``.
+- the commit message should follow gitchangelog rules (check the git
+ log to get examples)
+- if the commit fixes an issue or finished the implementation of a
+ feature, please mention it in the summary.
+
+If you have some questions about guidelines which is not answered here,
+please check the current ``git log``, you might find previous commit that
+would show you how to deal with your issue.
+
+
+License
+=======
+
+Copyright (c) 2012-2017 Valentin Lab.
+
+Licensed under the `BSD License`_.
+
+.. _BSD License: http://raw.github.com/vaab/colour/master/LICENSE
+
+Changelog
+=========
+
+
+0.1.4 (2017-04-19)
+------------------
+
+Fix
+~~~
+- ``rgb2hsl`` would produce invalid hsl triplet when red, blue, green
+ component would be all very close to ``1.0``. (fixes #30) [Valentin
+ Lab]
+
+ Typically, saturation would shoot out of range 0.0..1.0. That could then
+ lead to exceptions being casts afterwards when trying to reconvert this
+ HSL triplet to RGB values.
+
+
+0.1.3 (2017-04-08)
+------------------
+
+Fix
+~~~
+- Unexpected behavior with ``!=`` operator. (fixes #26) [Valentin Lab]
+- Added mention of the ``hex_l`` property. (fixes #27) [Valentin Lab]
+
+
+0.1.2 (2015-09-15)
+------------------
+
+Fix
+~~~
+- Support for corner case 1-wide ``range_to`` color scale. (fixes #18)
+ [Valentin Lab]
+
+
+0.1.1 (2015-03-29)
+------------------
+
+Fix
+~~~
+- Avoid casting an exception when comparing to non-``Colour`` instances.
+ (fixes #14) [Riziq Sayegh]
+
+
+0.0.6 (2014-11-18)
+------------------
+
+New
+~~~
+- Provide all missing *2* function by combination with other existing
+ ones (fixes #13). [Valentin Lab]
+- Provide full access to any color name in HSL, RGB, HEX convenience
+ instances. [Valentin Lab]
+
+ Now you can call ``colour.HSL.cyan``, or ``colour.HEX.red`` for a direct encoding of
+ ``human`` colour labels to the 3 representations.
+
+
+0.0.5 (2013-09-16)
+------------------
+
+New
+~~~
+- Color names are case insensitive. [Chris Priest]
+
+ The color-name structure have their names capitalized. And color names
+ that are made of only one word will be displayed lowercased.
+
+Fix
+~~~
+- Now using W3C color recommandation. [Chris Priest]
+
+ Was using X11 color scheme before, which is slightly different from
+ W3C web color specifications.
+- Inconsistency in licence information (removed GPL mention). (fixes #8)
+ [Valentin Lab]
+- Removed ``gitchangelog`` from ``setup.py`` require list. (fixes #9)
+ [Valentin Lab]
+
+
+0.0.4 (2013-06-21)
+------------------
+
+New
+~~~
+- Added ``make_color_factory`` to customize some common color
+ attributes. [Valentin Lab]
+- Pick color to identify any python object (fixes #6) [Jonathan Ballet]
+- Equality support between colors, customizable if needed. (fixes #3)
+ [Valentin Lab]
+
+
+0.0.3 (2013-06-19)
+------------------
+
+New
+~~~
+- Colour is now compatible with python3. [Ryan Leckey]
+
+
+0.0.1 (2012-06-11)
+------------------
+- First import. [Valentin Lab]
+
+TODO
+====
+
+- ANSI 16-color and 256-color escape sequence generation
+- YUV, HSV, CMYK support
+
+
+
diff --git a/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour-0.1.5.dist-info/RECORD b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour-0.1.5.dist-info/RECORD
new file mode 100644
index 00000000..351a0ed4
--- /dev/null
+++ b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour-0.1.5.dist-info/RECORD
@@ -0,0 +1,11 @@
+colour-0.1.5.dist-info/DESCRIPTION.rst,sha256=hPBkXALLft1zfCftLr--oylXrhnxFIXvRVk3ga--bK8,17325
+colour-0.1.5.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+colour-0.1.5.dist-info/LICENSE.txt,sha256=jwhqMkd7-dP7p3VMptM6CpLlsx0DZfmEdg3GigdOQng,1304
+colour-0.1.5.dist-info/METADATA,sha256=1dIO3yNuvoAan1hBE9_y766TbXs9cKRjEuIUI92nUhE,18273
+colour-0.1.5.dist-info/RECORD,,
+colour-0.1.5.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+colour-0.1.5.dist-info/WHEEL,sha256=o2k-Qa-RMNIJmUdIc7KU6VWR_ErNRbWNlxDIpl7lm34,110
+colour-0.1.5.dist-info/metadata.json,sha256=OviC7TmmKwtRUjauJE5IrjD9kyga_JzrCUZQri6L1xo,1090
+colour-0.1.5.dist-info/top_level.txt,sha256=XKC-SRGJZMW4pzXxl1NWLlZYzRFz7JuWiOJSkQfrWOE,7
+colour.py,sha256=GNhLVa29gX2sIT4h79BbnyEJeZDa7uSRt49Cz1zJL_U,28693
+colour.pyc,,
diff --git a/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/.empty b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour-0.1.5.dist-info/REQUESTED
similarity index 100%
rename from buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/.empty
rename to buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour-0.1.5.dist-info/REQUESTED
diff --git a/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour-0.1.5.dist-info/WHEEL b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour-0.1.5.dist-info/WHEEL
new file mode 100644
index 00000000..8b6dd1b5
--- /dev/null
+++ b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour-0.1.5.dist-info/WHEEL
@@ -0,0 +1,6 @@
+Wheel-Version: 1.0
+Generator: bdist_wheel (0.29.0)
+Root-Is-Purelib: true
+Tag: py2-none-any
+Tag: py3-none-any
+
diff --git a/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour-0.1.5.dist-info/metadata.json b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour-0.1.5.dist-info/metadata.json
new file mode 100644
index 00000000..dde02cd3
--- /dev/null
+++ b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour-0.1.5.dist-info/metadata.json
@@ -0,0 +1 @@
+{"classifiers": ["Programming Language :: Python", "Topic :: Software Development :: Libraries :: Python Modules", "Development Status :: 3 - Alpha", "License :: OSI Approved :: BSD License", "Intended Audience :: Developers", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6"], "extensions": {"python.details": {"contacts": [{"email": "valentin.lab@kalysto.org", "name": "Valentin LAB", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst", "license": "LICENSE.txt"}, "project_urls": {"Home": "http://github.com/vaab/colour"}}}, "extras": ["test"], "generator": "bdist_wheel (0.29.0)", "license": "BSD 3-Clause License", "metadata_version": "2.0", "name": "colour", "run_requires": [{"extra": "test", "requires": ["nose"]}], "summary": "converts and manipulates various color representation (HSL, RVB, web, X11, ...)", "version": "0.1.5"}
\ No newline at end of file
diff --git a/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour-0.1.5.dist-info/top_level.txt b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour-0.1.5.dist-info/top_level.txt
new file mode 100644
index 00000000..b0d95faa
--- /dev/null
+++ b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour-0.1.5.dist-info/top_level.txt
@@ -0,0 +1 @@
+colour
diff --git a/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour.py b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour.py
new file mode 100644
index 00000000..1bd48e82
--- /dev/null
+++ b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/colour.py
@@ -0,0 +1,1124 @@
+# -*- coding: utf-8 -*-
+"""Color Library
+
+.. :doctest:
+
+This module defines several color formats that can be converted to one or
+another.
+
+Formats
+-------
+
+HSL:
+ 3-uple of Hue, Saturation, Lightness all between 0.0 and 1.0
+
+RGB:
+ 3-uple of Red, Green, Blue all between 0.0 and 1.0
+
+HEX:
+ string object beginning with '#' and with red, green, blue value.
+ This format accept color in 3 or 6 value ex: '#fff' or '#ffffff'
+
+WEB:
+ string object that defaults to HEX representation or human if possible
+
+Usage
+-----
+
+Several function exists to convert from one format to another. But all
+function are not written. So the best way is to use the object Color.
+
+Please see the documentation of this object for more information.
+
+.. note:: Some constants are defined for convenience in HSL, RGB, HEX
+
+"""
+
+from __future__ import with_statement, print_function
+
+import hashlib
+import re
+import sys
+
+
+##
+## Some Constants
+##
+
+## Soften inequalities and some rounding issue based on float
+FLOAT_ERROR = 0.0000005
+
+
+RGB_TO_COLOR_NAMES = {
+ (0, 0, 0): ['Black'],
+ (0, 0, 128): ['Navy', 'NavyBlue'],
+ (0, 0, 139): ['DarkBlue'],
+ (0, 0, 205): ['MediumBlue'],
+ (0, 0, 255): ['Blue'],
+ (0, 100, 0): ['DarkGreen'],
+ (0, 128, 0): ['Green'],
+ (0, 139, 139): ['DarkCyan'],
+ (0, 191, 255): ['DeepSkyBlue'],
+ (0, 206, 209): ['DarkTurquoise'],
+ (0, 250, 154): ['MediumSpringGreen'],
+ (0, 255, 0): ['Lime'],
+ (0, 255, 127): ['SpringGreen'],
+ (0, 255, 255): ['Cyan', 'Aqua'],
+ (25, 25, 112): ['MidnightBlue'],
+ (30, 144, 255): ['DodgerBlue'],
+ (32, 178, 170): ['LightSeaGreen'],
+ (34, 139, 34): ['ForestGreen'],
+ (46, 139, 87): ['SeaGreen'],
+ (47, 79, 79): ['DarkSlateGray', 'DarkSlateGrey'],
+ (50, 205, 50): ['LimeGreen'],
+ (60, 179, 113): ['MediumSeaGreen'],
+ (64, 224, 208): ['Turquoise'],
+ (65, 105, 225): ['RoyalBlue'],
+ (70, 130, 180): ['SteelBlue'],
+ (72, 61, 139): ['DarkSlateBlue'],
+ (72, 209, 204): ['MediumTurquoise'],
+ (75, 0, 130): ['Indigo'],
+ (85, 107, 47): ['DarkOliveGreen'],
+ (95, 158, 160): ['CadetBlue'],
+ (100, 149, 237): ['CornflowerBlue'],
+ (102, 205, 170): ['MediumAquamarine'],
+ (105, 105, 105): ['DimGray', 'DimGrey'],
+ (106, 90, 205): ['SlateBlue'],
+ (107, 142, 35): ['OliveDrab'],
+ (112, 128, 144): ['SlateGray', 'SlateGrey'],
+ (119, 136, 153): ['LightSlateGray', 'LightSlateGrey'],
+ (123, 104, 238): ['MediumSlateBlue'],
+ (124, 252, 0): ['LawnGreen'],
+ (127, 255, 0): ['Chartreuse'],
+ (127, 255, 212): ['Aquamarine'],
+ (128, 0, 0): ['Maroon'],
+ (128, 0, 128): ['Purple'],
+ (128, 128, 0): ['Olive'],
+ (128, 128, 128): ['Gray', 'Grey'],
+ (132, 112, 255): ['LightSlateBlue'],
+ (135, 206, 235): ['SkyBlue'],
+ (135, 206, 250): ['LightSkyBlue'],
+ (138, 43, 226): ['BlueViolet'],
+ (139, 0, 0): ['DarkRed'],
+ (139, 0, 139): ['DarkMagenta'],
+ (139, 69, 19): ['SaddleBrown'],
+ (143, 188, 143): ['DarkSeaGreen'],
+ (144, 238, 144): ['LightGreen'],
+ (147, 112, 219): ['MediumPurple'],
+ (148, 0, 211): ['DarkViolet'],
+ (152, 251, 152): ['PaleGreen'],
+ (153, 50, 204): ['DarkOrchid'],
+ (154, 205, 50): ['YellowGreen'],
+ (160, 82, 45): ['Sienna'],
+ (165, 42, 42): ['Brown'],
+ (169, 169, 169): ['DarkGray', 'DarkGrey'],
+ (173, 216, 230): ['LightBlue'],
+ (173, 255, 47): ['GreenYellow'],
+ (175, 238, 238): ['PaleTurquoise'],
+ (176, 196, 222): ['LightSteelBlue'],
+ (176, 224, 230): ['PowderBlue'],
+ (178, 34, 34): ['Firebrick'],
+ (184, 134, 11): ['DarkGoldenrod'],
+ (186, 85, 211): ['MediumOrchid'],
+ (188, 143, 143): ['RosyBrown'],
+ (189, 183, 107): ['DarkKhaki'],
+ (192, 192, 192): ['Silver'],
+ (199, 21, 133): ['MediumVioletRed'],
+ (205, 92, 92): ['IndianRed'],
+ (205, 133, 63): ['Peru'],
+ (208, 32, 144): ['VioletRed'],
+ (210, 105, 30): ['Chocolate'],
+ (210, 180, 140): ['Tan'],
+ (211, 211, 211): ['LightGray', 'LightGrey'],
+ (216, 191, 216): ['Thistle'],
+ (218, 112, 214): ['Orchid'],
+ (218, 165, 32): ['Goldenrod'],
+ (219, 112, 147): ['PaleVioletRed'],
+ (220, 20, 60): ['Crimson'],
+ (220, 220, 220): ['Gainsboro'],
+ (221, 160, 221): ['Plum'],
+ (222, 184, 135): ['Burlywood'],
+ (224, 255, 255): ['LightCyan'],
+ (230, 230, 250): ['Lavender'],
+ (233, 150, 122): ['DarkSalmon'],
+ (238, 130, 238): ['Violet'],
+ (238, 221, 130): ['LightGoldenrod'],
+ (238, 232, 170): ['PaleGoldenrod'],
+ (240, 128, 128): ['LightCoral'],
+ (240, 230, 140): ['Khaki'],
+ (240, 248, 255): ['AliceBlue'],
+ (240, 255, 240): ['Honeydew'],
+ (240, 255, 255): ['Azure'],
+ (244, 164, 96): ['SandyBrown'],
+ (245, 222, 179): ['Wheat'],
+ (245, 245, 220): ['Beige'],
+ (245, 245, 245): ['WhiteSmoke'],
+ (245, 255, 250): ['MintCream'],
+ (248, 248, 255): ['GhostWhite'],
+ (250, 128, 114): ['Salmon'],
+ (250, 235, 215): ['AntiqueWhite'],
+ (250, 240, 230): ['Linen'],
+ (250, 250, 210): ['LightGoldenrodYellow'],
+ (253, 245, 230): ['OldLace'],
+ (255, 0, 0): ['Red'],
+ (255, 0, 255): ['Magenta', 'Fuchsia'],
+ (255, 20, 147): ['DeepPink'],
+ (255, 69, 0): ['OrangeRed'],
+ (255, 99, 71): ['Tomato'],
+ (255, 105, 180): ['HotPink'],
+ (255, 127, 80): ['Coral'],
+ (255, 140, 0): ['DarkOrange'],
+ (255, 160, 122): ['LightSalmon'],
+ (255, 165, 0): ['Orange'],
+ (255, 182, 193): ['LightPink'],
+ (255, 192, 203): ['Pink'],
+ (255, 215, 0): ['Gold'],
+ (255, 218, 185): ['PeachPuff'],
+ (255, 222, 173): ['NavajoWhite'],
+ (255, 228, 181): ['Moccasin'],
+ (255, 228, 196): ['Bisque'],
+ (255, 228, 225): ['MistyRose'],
+ (255, 235, 205): ['BlanchedAlmond'],
+ (255, 239, 213): ['PapayaWhip'],
+ (255, 240, 245): ['LavenderBlush'],
+ (255, 245, 238): ['Seashell'],
+ (255, 248, 220): ['Cornsilk'],
+ (255, 250, 205): ['LemonChiffon'],
+ (255, 250, 240): ['FloralWhite'],
+ (255, 250, 250): ['Snow'],
+ (255, 255, 0): ['Yellow'],
+ (255, 255, 224): ['LightYellow'],
+ (255, 255, 240): ['Ivory'],
+ (255, 255, 255): ['White']
+}
+
+## Building inverse relation
+COLOR_NAME_TO_RGB = dict(
+ (name.lower(), rgb)
+ for rgb, names in RGB_TO_COLOR_NAMES.items()
+ for name in names)
+
+
+LONG_HEX_COLOR = re.compile(r'^#[0-9a-fA-F]{6}$')
+SHORT_HEX_COLOR = re.compile(r'^#[0-9a-fA-F]{3}$')
+
+
+class C_HSL:
+
+ def __getattr__(self, value):
+ label = value.lower()
+ if label in COLOR_NAME_TO_RGB:
+ return rgb2hsl(tuple(v / 255. for v in COLOR_NAME_TO_RGB[label]))
+ raise AttributeError("%s instance has no attribute %r"
+ % (self.__class__, value))
+
+
+HSL = C_HSL()
+
+
+class C_RGB:
+ """RGB colors container
+
+ Provides a quick color access.
+
+ >>> from colour import RGB
+
+ >>> RGB.WHITE
+ (1.0, 1.0, 1.0)
+ >>> RGB.BLUE
+ (0.0, 0.0, 1.0)
+
+ >>> RGB.DONOTEXISTS # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ AttributeError: ... has no attribute 'DONOTEXISTS'
+
+ """
+
+ def __getattr__(self, value):
+ return hsl2rgb(getattr(HSL, value))
+
+
+class C_HEX:
+ """RGB colors container
+
+ Provides a quick color access.
+
+ >>> from colour import HEX
+
+ >>> HEX.WHITE
+ '#fff'
+ >>> HEX.BLUE
+ '#00f'
+
+ >>> HEX.DONOTEXISTS # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ AttributeError: ... has no attribute 'DONOTEXISTS'
+
+ """
+
+ def __getattr__(self, value):
+ return rgb2hex(getattr(RGB, value))
+
+RGB = C_RGB()
+HEX = C_HEX()
+
+
+##
+## Conversion function
+##
+
+def hsl2rgb(hsl):
+ """Convert HSL representation towards RGB
+
+ :param h: Hue, position around the chromatic circle (h=1 equiv h=0)
+ :param s: Saturation, color saturation (0=full gray, 1=full color)
+ :param l: Ligthness, Overhaul lightness (0=full black, 1=full white)
+ :rtype: 3-uple for RGB values in float between 0 and 1
+
+ Hue, Saturation, Range from Lightness is a float between 0 and 1
+
+ Note that Hue can be set to any value but as it is a rotation
+ around the chromatic circle, any value above 1 or below 0 can
+ be expressed by a value between 0 and 1 (Note that h=0 is equiv
+ to h=1).
+
+ This algorithm came from:
+ http://www.easyrgb.com/index.php?X=MATH&H=19#text19
+
+ Here are some quick notion of HSL to RGB conversion:
+
+ >>> from colour import hsl2rgb
+
+ With a lightness put at 0, RGB is always rgbblack
+
+ >>> hsl2rgb((0.0, 0.0, 0.0))
+ (0.0, 0.0, 0.0)
+ >>> hsl2rgb((0.5, 0.0, 0.0))
+ (0.0, 0.0, 0.0)
+ >>> hsl2rgb((0.5, 0.5, 0.0))
+ (0.0, 0.0, 0.0)
+
+ Same for lightness put at 1, RGB is always rgbwhite
+
+ >>> hsl2rgb((0.0, 0.0, 1.0))
+ (1.0, 1.0, 1.0)
+ >>> hsl2rgb((0.5, 0.0, 1.0))
+ (1.0, 1.0, 1.0)
+ >>> hsl2rgb((0.5, 0.5, 1.0))
+ (1.0, 1.0, 1.0)
+
+ With saturation put at 0, the RGB should be equal to Lightness:
+
+ >>> hsl2rgb((0.0, 0.0, 0.25))
+ (0.25, 0.25, 0.25)
+ >>> hsl2rgb((0.5, 0.0, 0.5))
+ (0.5, 0.5, 0.5)
+ >>> hsl2rgb((0.5, 0.0, 0.75))
+ (0.75, 0.75, 0.75)
+
+ With saturation put at 1, and lightness put to 0.5, we can find
+ normal full red, green, blue colors:
+
+ >>> hsl2rgb((0 , 1.0, 0.5))
+ (1.0, 0.0, 0.0)
+ >>> hsl2rgb((1 , 1.0, 0.5))
+ (1.0, 0.0, 0.0)
+ >>> hsl2rgb((1.0/3 , 1.0, 0.5))
+ (0.0, 1.0, 0.0)
+ >>> hsl2rgb((2.0/3 , 1.0, 0.5))
+ (0.0, 0.0, 1.0)
+
+ Of course:
+ >>> hsl2rgb((0.0, 2.0, 0.5)) # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ ValueError: Saturation must be between 0 and 1.
+
+ And:
+ >>> hsl2rgb((0.0, 0.0, 1.5)) # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ ValueError: Lightness must be between 0 and 1.
+
+ """
+ h, s, l = [float(v) for v in hsl]
+
+ if not (0.0 - FLOAT_ERROR <= s <= 1.0 + FLOAT_ERROR):
+ raise ValueError("Saturation must be between 0 and 1.")
+ if not (0.0 - FLOAT_ERROR <= l <= 1.0 + FLOAT_ERROR):
+ raise ValueError("Lightness must be between 0 and 1.")
+
+ if s == 0:
+ return l, l, l
+
+ if l < 0.5:
+ v2 = l * (1.0 + s)
+ else:
+ v2 = (l + s) - (s * l)
+
+ v1 = 2.0 * l - v2
+
+ r = _hue2rgb(v1, v2, h + (1.0 / 3))
+ g = _hue2rgb(v1, v2, h)
+ b = _hue2rgb(v1, v2, h - (1.0 / 3))
+
+ return r, g, b
+
+
+def rgb2hsl(rgb):
+ """Convert RGB representation towards HSL
+
+ :param r: Red amount (float between 0 and 1)
+ :param g: Green amount (float between 0 and 1)
+ :param b: Blue amount (float between 0 and 1)
+ :rtype: 3-uple for HSL values in float between 0 and 1
+
+ This algorithm came from:
+ http://www.easyrgb.com/index.php?X=MATH&H=19#text19
+
+ Here are some quick notion of RGB to HSL conversion:
+
+ >>> from colour import rgb2hsl
+
+ Note that if red amount is equal to green and blue, then you
+ should have a gray value (from black to white).
+
+
+ >>> rgb2hsl((1.0, 1.0, 1.0)) # doctest: +ELLIPSIS
+ (..., 0.0, 1.0)
+ >>> rgb2hsl((0.5, 0.5, 0.5)) # doctest: +ELLIPSIS
+ (..., 0.0, 0.5)
+ >>> rgb2hsl((0.0, 0.0, 0.0)) # doctest: +ELLIPSIS
+ (..., 0.0, 0.0)
+
+ If only one color is different from the others, it defines the
+ direct Hue:
+
+ >>> rgb2hsl((0.5, 0.5, 1.0)) # doctest: +ELLIPSIS
+ (0.66..., 1.0, 0.75)
+ >>> rgb2hsl((0.2, 0.1, 0.1)) # doctest: +ELLIPSIS
+ (0.0, 0.33..., 0.15...)
+
+ Having only one value set, you can check that:
+
+ >>> rgb2hsl((1.0, 0.0, 0.0))
+ (0.0, 1.0, 0.5)
+ >>> rgb2hsl((0.0, 1.0, 0.0)) # doctest: +ELLIPSIS
+ (0.33..., 1.0, 0.5)
+ >>> rgb2hsl((0.0, 0.0, 1.0)) # doctest: +ELLIPSIS
+ (0.66..., 1.0, 0.5)
+
+ Regression check upon very close values in every component of
+ red, green and blue:
+
+ >>> rgb2hsl((0.9999999999999999, 1.0, 0.9999999999999994))
+ (0.0, 0.0, 0.999...)
+
+ Of course:
+
+ >>> rgb2hsl((0.0, 2.0, 0.5)) # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ ValueError: Green must be between 0 and 1. You provided 2.0.
+
+ And:
+ >>> rgb2hsl((0.0, 0.0, 1.5)) # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ ValueError: Blue must be between 0 and 1. You provided 1.5.
+
+ """
+ r, g, b = [float(v) for v in rgb]
+
+ for name, v in {'Red': r, 'Green': g, 'Blue': b}.items():
+ if not (0 - FLOAT_ERROR <= v <= 1 + FLOAT_ERROR):
+ raise ValueError("%s must be between 0 and 1. You provided %r."
+ % (name, v))
+
+ vmin = min(r, g, b) ## Min. value of RGB
+ vmax = max(r, g, b) ## Max. value of RGB
+ diff = vmax - vmin ## Delta RGB value
+
+ vsum = vmin + vmax
+
+ l = vsum / 2
+
+ if diff < FLOAT_ERROR: ## This is a gray, no chroma...
+ return (0.0, 0.0, l)
+
+ ##
+ ## Chromatic data...
+ ##
+
+ ## Saturation
+ if l < 0.5:
+ s = diff / vsum
+ else:
+ s = diff / (2.0 - vsum)
+
+ dr = (((vmax - r) / 6) + (diff / 2)) / diff
+ dg = (((vmax - g) / 6) + (diff / 2)) / diff
+ db = (((vmax - b) / 6) + (diff / 2)) / diff
+
+ if r == vmax:
+ h = db - dg
+ elif g == vmax:
+ h = (1.0 / 3) + dr - db
+ elif b == vmax:
+ h = (2.0 / 3) + dg - dr
+
+ if h < 0: h += 1
+ if h > 1: h -= 1
+
+ return (h, s, l)
+
+
+def _hue2rgb(v1, v2, vH):
+ """Private helper function (Do not call directly)
+
+ :param vH: rotation around the chromatic circle (between 0..1)
+
+ """
+
+ while vH < 0: vH += 1
+ while vH > 1: vH -= 1
+
+ if 6 * vH < 1: return v1 + (v2 - v1) * 6 * vH
+ if 2 * vH < 1: return v2
+ if 3 * vH < 2: return v1 + (v2 - v1) * ((2.0 / 3) - vH) * 6
+
+ return v1
+
+
+def rgb2hex(rgb, force_long=False):
+ """Transform RGB tuple to hex RGB representation
+
+ :param rgb: RGB 3-uple of float between 0 and 1
+ :rtype: 3 hex char or 6 hex char string representation
+
+ Usage
+ -----
+
+ >>> from colour import rgb2hex
+
+ >>> rgb2hex((0.0,1.0,0.0))
+ '#0f0'
+
+ Rounding try to be as natural as possible:
+
+ >>> rgb2hex((0.0,0.999999,1.0))
+ '#0ff'
+
+ And if not possible, the 6 hex char representation is used:
+
+ >>> rgb2hex((0.23,1.0,1.0))
+ '#3bffff'
+
+ >>> rgb2hex((0.0,0.999999,1.0), force_long=True)
+ '#00ffff'
+
+ """
+
+ hx = ''.join(["%02x" % int(c * 255 + 0.5 - FLOAT_ERROR)
+ for c in rgb])
+
+ if not force_long and hx[0::2] == hx[1::2]:
+ hx = ''.join(hx[0::2])
+
+ return "#%s" % hx
+
+
+def hex2rgb(str_rgb):
+ """Transform hex RGB representation to RGB tuple
+
+ :param str_rgb: 3 hex char or 6 hex char string representation
+ :rtype: RGB 3-uple of float between 0 and 1
+
+ >>> from colour import hex2rgb
+
+ >>> hex2rgb('#00ff00')
+ (0.0, 1.0, 0.0)
+
+ >>> hex2rgb('#0f0')
+ (0.0, 1.0, 0.0)
+
+ >>> hex2rgb('#aaa') # doctest: +ELLIPSIS
+ (0.66..., 0.66..., 0.66...)
+
+ >>> hex2rgb('#aa') # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ ValueError: Invalid value '#aa' provided for rgb color.
+
+ """
+
+ try:
+ rgb = str_rgb[1:]
+
+ if len(rgb) == 6:
+ r, g, b = rgb[0:2], rgb[2:4], rgb[4:6]
+ elif len(rgb) == 3:
+ r, g, b = rgb[0] * 2, rgb[1] * 2, rgb[2] * 2
+ else:
+ raise ValueError()
+ except:
+ raise ValueError("Invalid value %r provided for rgb color."
+ % str_rgb)
+
+ return tuple([float(int(v, 16)) / 255 for v in (r, g, b)])
+
+
+def hex2web(hex):
+ """Converts HEX representation to WEB
+
+ :param rgb: 3 hex char or 6 hex char string representation
+ :rtype: web string representation (human readable if possible)
+
+ WEB representation uses X11 rgb.txt to define conversion
+ between RGB and english color names.
+
+ Usage
+ =====
+
+ >>> from colour import hex2web
+
+ >>> hex2web('#ff0000')
+ 'red'
+
+ >>> hex2web('#aaaaaa')
+ '#aaa'
+
+ >>> hex2web('#abc')
+ '#abc'
+
+ >>> hex2web('#acacac')
+ '#acacac'
+
+ """
+ dec_rgb = tuple(int(v * 255) for v in hex2rgb(hex))
+ if dec_rgb in RGB_TO_COLOR_NAMES:
+ ## take the first one
+ color_name = RGB_TO_COLOR_NAMES[dec_rgb][0]
+ ## Enforce full lowercase for single worded color name.
+ return color_name if len(re.sub(r"[^A-Z]", "", color_name)) > 1 \
+ else color_name.lower()
+
+ # Hex format is verified by hex2rgb function. And should be 3 or 6 digit
+ if len(hex) == 7:
+ if hex[1] == hex[2] and \
+ hex[3] == hex[4] and \
+ hex[5] == hex[6]:
+ return '#' + hex[1] + hex[3] + hex[5]
+ return hex
+
+
+def web2hex(web, force_long=False):
+ """Converts WEB representation to HEX
+
+ :param rgb: web string representation (human readable if possible)
+ :rtype: 3 hex char or 6 hex char string representation
+
+ WEB representation uses X11 rgb.txt to define conversion
+ between RGB and english color names.
+
+ Usage
+ =====
+
+ >>> from colour import web2hex
+
+ >>> web2hex('red')
+ '#f00'
+
+ >>> web2hex('#aaa')
+ '#aaa'
+
+ >>> web2hex('#foo') # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ AttributeError: '#foo' is not in web format. Need 3 or 6 hex digit.
+
+ >>> web2hex('#aaa', force_long=True)
+ '#aaaaaa'
+
+ >>> web2hex('#aaaaaa')
+ '#aaaaaa'
+
+ >>> web2hex('#aaaa') # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ AttributeError: '#aaaa' is not in web format. Need 3 or 6 hex digit.
+
+ >>> web2hex('pinky') # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ ValueError: 'pinky' is not a recognized color.
+
+ And color names are case insensitive:
+
+ >>> Color('RED')
+
+
+ """
+ if web.startswith('#'):
+ if (LONG_HEX_COLOR.match(web) or
+ (not force_long and SHORT_HEX_COLOR.match(web))):
+ return web.lower()
+ elif SHORT_HEX_COLOR.match(web) and force_long:
+ return '#' + ''.join([("%s" % (t, )) * 2 for t in web[1:]])
+ raise AttributeError(
+ "%r is not in web format. Need 3 or 6 hex digit." % web)
+
+ web = web.lower()
+ if web not in COLOR_NAME_TO_RGB:
+ raise ValueError("%r is not a recognized color." % web)
+
+ ## convert dec to hex:
+
+ return rgb2hex([float(int(v)) / 255 for v in COLOR_NAME_TO_RGB[web]],
+ force_long)
+
+
+## Missing functions conversion
+
+hsl2hex = lambda x: rgb2hex(hsl2rgb(x))
+hex2hsl = lambda x: rgb2hsl(hex2rgb(x))
+rgb2web = lambda x: hex2web(rgb2hex(x))
+web2rgb = lambda x: hex2rgb(web2hex(x))
+web2hsl = lambda x: rgb2hsl(web2rgb(x))
+hsl2web = lambda x: rgb2web(hsl2rgb(x))
+
+
+def color_scale(begin_hsl, end_hsl, nb):
+ """Returns a list of nb color HSL tuples between begin_hsl and end_hsl
+
+ >>> from colour import color_scale
+
+ >>> [rgb2hex(hsl2rgb(hsl)) for hsl in color_scale((0, 1, 0.5),
+ ... (1, 1, 0.5), 3)]
+ ['#f00', '#0f0', '#00f', '#f00']
+
+ >>> [rgb2hex(hsl2rgb(hsl))
+ ... for hsl in color_scale((0, 0, 0),
+ ... (0, 0, 1),
+ ... 15)] # doctest: +ELLIPSIS
+ ['#000', '#111', '#222', ..., '#ccc', '#ddd', '#eee', '#fff']
+
+ Of course, asking for negative values is not supported:
+
+ >>> color_scale((0, 1, 0.5), (1, 1, 0.5), -2)
+ Traceback (most recent call last):
+ ...
+ ValueError: Unsupported negative number of colors (nb=-2).
+
+ """
+
+ if nb < 0:
+ raise ValueError(
+ "Unsupported negative number of colors (nb=%r)." % nb)
+
+ step = tuple([float(end_hsl[i] - begin_hsl[i]) / nb for i in range(0, 3)]) \
+ if nb > 0 else (0, 0, 0)
+
+ def mul(step, value):
+ return tuple([v * value for v in step])
+
+ def add_v(step, step2):
+ return tuple([v + step2[i] for i, v in enumerate(step)])
+
+ return [add_v(begin_hsl, mul(step, r)) for r in range(0, nb + 1)]
+
+
+##
+## Color Pickers
+##
+
+def RGB_color_picker(obj):
+ """Build a color representation from the string representation of an object
+
+ This allows to quickly get a color from some data, with the
+ additional benefit that the color will be the same as long as the
+ (string representation of the) data is the same::
+
+ >>> from colour import RGB_color_picker, Color
+
+ Same inputs produce the same result::
+
+ >>> RGB_color_picker("Something") == RGB_color_picker("Something")
+ True
+
+ ... but different inputs produce different colors::
+
+ >>> RGB_color_picker("Something") != RGB_color_picker("Something else")
+ True
+
+ In any case, we still get a ``Color`` object::
+
+ >>> isinstance(RGB_color_picker("Something"), Color)
+ True
+
+ """
+
+ ## Turn the input into a by 3-dividable string. SHA-384 is good because it
+ ## divides into 3 components of the same size, which will be used to
+ ## represent the RGB values of the color.
+ digest = hashlib.sha384(str(obj).encode('utf-8')).hexdigest()
+
+ ## Split the digest into 3 sub-strings of equivalent size.
+ subsize = int(len(digest) / 3)
+ splitted_digest = [digest[i * subsize: (i + 1) * subsize]
+ for i in range(3)]
+
+ ## Convert those hexadecimal sub-strings into integer and scale them down
+ ## to the 0..1 range.
+ max_value = float(int("f" * subsize, 16))
+ components = (
+ int(d, 16) ## Make a number from a list with hex digits
+ / max_value ## Scale it down to [0.0, 1.0]
+ for d in splitted_digest)
+
+ return Color(rgb2hex(components)) ## Profit!
+
+
+def hash_or_str(obj):
+ try:
+ return hash((type(obj).__name__, obj))
+ except TypeError:
+ ## Adds the type name to make sure two object of different type but
+ ## identical string representation get distinguished.
+ return type(obj).__name__ + str(obj)
+
+
+##
+## All purpose object
+##
+
+class Color(object):
+ """Abstraction of a color object
+
+ Color object keeps information of a color. It can input/output to different
+ format (HSL, RGB, HEX, WEB) and their partial representation.
+
+ >>> from colour import Color, HSL
+
+ >>> b = Color()
+ >>> b.hsl = HSL.BLUE
+
+ Access values
+ -------------
+
+ >>> b.hue # doctest: +ELLIPSIS
+ 0.66...
+ >>> b.saturation
+ 1.0
+ >>> b.luminance
+ 0.5
+
+ >>> b.red
+ 0.0
+ >>> b.blue
+ 1.0
+ >>> b.green
+ 0.0
+
+ >>> b.rgb
+ (0.0, 0.0, 1.0)
+ >>> b.hsl # doctest: +ELLIPSIS
+ (0.66..., 1.0, 0.5)
+ >>> b.hex
+ '#00f'
+
+ Change values
+ -------------
+
+ Let's change Hue toward red tint:
+
+ >>> b.hue = 0.0
+ >>> b.hex
+ '#f00'
+
+ >>> b.hue = 2.0/3
+ >>> b.hex
+ '#00f'
+
+ In the other way round:
+
+ >>> b.hex = '#f00'
+ >>> b.hsl
+ (0.0, 1.0, 0.5)
+
+ Long hex can be accessed directly:
+
+ >>> b.hex_l = '#123456'
+ >>> b.hex_l
+ '#123456'
+ >>> b.hex
+ '#123456'
+
+ >>> b.hex_l = '#ff0000'
+ >>> b.hex_l
+ '#ff0000'
+ >>> b.hex
+ '#f00'
+
+ Convenience
+ -----------
+
+ >>> c = Color('blue')
+ >>> c
+
+ >>> c.hue = 0
+ >>> c
+
+
+ >>> c.saturation = 0.0
+ >>> c.hsl # doctest: +ELLIPSIS
+ (..., 0.0, 0.5)
+ >>> c.rgb
+ (0.5, 0.5, 0.5)
+ >>> c.hex
+ '#7f7f7f'
+ >>> c
+
+
+ >>> c.luminance = 0.0
+ >>> c
+
+
+ >>> c.hex
+ '#000'
+
+ >>> c.green = 1.0
+ >>> c.blue = 1.0
+ >>> c.hex
+ '#0ff'
+ >>> c
+
+
+ >>> c = Color('blue', luminance=0.75)
+ >>> c
+
+
+ >>> c = Color('red', red=0.5)
+ >>> c
+
+
+ >>> print(c)
+ #7f0000
+
+ You can try to query unexisting attributes:
+
+ >>> c.lightness # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ ...
+ AttributeError: 'lightness' not found
+
+ TODO: could add HSV, CMYK, YUV conversion.
+
+# >>> b.hsv
+# >>> b.value
+# >>> b.cyan
+# >>> b.magenta
+# >>> b.yellow
+# >>> b.key
+# >>> b.cmyk
+
+
+ Recursive init
+ --------------
+
+ To support blind conversion of web strings (or already converted object),
+ the Color object supports instantiation with another Color object.
+
+ >>> Color(Color(Color('red')))
+
+
+ Equality support
+ ----------------
+
+ Default equality is RGB hex comparison:
+
+ >>> Color('red') == Color('blue')
+ False
+ >>> Color('red') == Color('red')
+ True
+ >>> Color('red') != Color('blue')
+ True
+ >>> Color('red') != Color('red')
+ False
+
+ But this can be changed:
+
+ >>> saturation_equality = lambda c1, c2: c1.luminance == c2.luminance
+ >>> Color('red', equality=saturation_equality) == Color('blue')
+ True
+
+
+ Subclassing support
+ -------------------
+
+ You should be able to subclass ``Color`` object without any issues::
+
+ >>> class Tint(Color):
+ ... pass
+
+ And keep the internal API working::
+
+ >>> Tint("red").hsl
+ (0.0, 1.0, 0.5)
+
+ """
+
+ _hsl = None ## internal representation
+
+ def __init__(self, color=None,
+ pick_for=None, picker=RGB_color_picker, pick_key=hash_or_str,
+ **kwargs):
+
+ if pick_key is None:
+ pick_key = lambda x: x
+
+ if pick_for is not None:
+ color = picker(pick_key(pick_for))
+
+ if isinstance(color, Color):
+ self.web = color.web
+ else:
+ self.web = color if color else 'black'
+
+ self.equality = RGB_equivalence
+
+ for k, v in kwargs.items():
+ setattr(self, k, v)
+
+ def __getattr__(self, label):
+ if label.startswith("get_"):
+ raise AttributeError("'%s' not found" % label)
+ try:
+ return getattr(self, 'get_' + label)()
+ except AttributeError:
+ raise AttributeError("'%s' not found" % label)
+
+ def __setattr__(self, label, value):
+ if label not in ["_hsl", "equality"]:
+ fc = getattr(self, 'set_' + label)
+ fc(value)
+ else:
+ self.__dict__[label] = value
+
+ ##
+ ## Get
+ ##
+
+ def get_hsl(self):
+ return tuple(self._hsl)
+
+ def get_hex(self):
+ return rgb2hex(self.rgb)
+
+ def get_hex_l(self):
+ return rgb2hex(self.rgb, force_long=True)
+
+ def get_rgb(self):
+ return hsl2rgb(self.hsl)
+
+ def get_hue(self):
+ return self.hsl[0]
+
+ def get_saturation(self):
+ return self.hsl[1]
+
+ def get_luminance(self):
+ return self.hsl[2]
+
+ def get_red(self):
+ return self.rgb[0]
+
+ def get_green(self):
+ return self.rgb[1]
+
+ def get_blue(self):
+ return self.rgb[2]
+
+ def get_web(self):
+ return hex2web(self.hex)
+
+ ##
+ ## Set
+ ##
+
+ def set_hsl(self, value):
+ self._hsl = list(value)
+
+ def set_rgb(self, value):
+ self.hsl = rgb2hsl(value)
+
+ def set_hue(self, value):
+ self._hsl[0] = value
+
+ def set_saturation(self, value):
+ self._hsl[1] = value
+
+ def set_luminance(self, value):
+ self._hsl[2] = value
+
+ def set_red(self, value):
+ _, g, b = self.rgb
+ self.rgb = (value, g, b)
+
+ def set_green(self, value):
+ r, _, b = self.rgb
+ self.rgb = (r, value, b)
+
+ def set_blue(self, value):
+ r, g, _ = self.rgb
+ self.rgb = (r, g, value)
+
+ def set_hex(self, value):
+ self.rgb = hex2rgb(value)
+
+ set_hex_l = set_hex
+
+ def set_web(self, value):
+ self.hex = web2hex(value)
+
+ ## range of color generation
+
+ def range_to(self, value, steps):
+ for hsl in color_scale(self._hsl, Color(value).hsl, steps - 1):
+ yield Color(hsl=hsl)
+
+ ##
+ ## Convenience
+ ##
+
+ def __str__(self):
+ return "%s" % self.web
+
+ def __repr__(self):
+ return "" % self.web
+
+ def __eq__(self, other):
+ if isinstance(other, Color):
+ return self.equality(self, other)
+ return NotImplemented
+
+ if sys.version_info[0] == 2:
+ ## Note: intended to be a backport of python 3 behavior
+ def __ne__(self, other):
+ equal = self.__eq__(other)
+ return equal if equal is NotImplemented else not equal
+
+
+RGB_equivalence = lambda c1, c2: c1.hex_l == c2.hex_l
+HSL_equivalence = lambda c1, c2: c1._hsl == c2._hsl
+
+
+def make_color_factory(**kwargs_defaults):
+
+ def ColorFactory(*args, **kwargs):
+ new_kwargs = kwargs_defaults.copy()
+ new_kwargs.update(kwargs)
+ return Color(*args, **new_kwargs)
+ return ColorFactory
diff --git a/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/webcolors-1.12.dist-info/INSTALLER b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/webcolors-1.12.dist-info/INSTALLER
new file mode 100644
index 00000000..a1b589e3
--- /dev/null
+++ b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/webcolors-1.12.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/webcolors-1.12.dist-info/LICENSE b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/webcolors-1.12.dist-info/LICENSE
new file mode 100644
index 00000000..e4190ba6
--- /dev/null
+++ b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/webcolors-1.12.dist-info/LICENSE
@@ -0,0 +1,28 @@
+Copyright (c) 2008-2022, 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.
diff --git a/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/webcolors-1.12.dist-info/METADATA b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/webcolors-1.12.dist-info/METADATA
new file mode 100644
index 00000000..71d37fb8
--- /dev/null
+++ b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/webcolors-1.12.dist-info/METADATA
@@ -0,0 +1,64 @@
+Metadata-Version: 2.1
+Name: webcolors
+Version: 1.12
+Summary: A library for working with color names and color values formats defined by HTML and CSS.
+Home-page: https://github.com/ubernostrum/webcolors
+Author: James Bennett
+Author-email: james@b-list.org
+License: BSD 3-Clause
+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 :: 3
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
+Classifier: Topic :: Utilities
+Requires-Python: >=3.7
+License-File: LICENSE
+
+.. -*-restructuredtext-*-
+
+.. image:: https://github.com/ubernostrum/webcolors/workflows/CI/badge.svg
+ :alt: CI status image
+ :target: https://github.com/ubernostrum/webcolors/actions?query=workflow%3ACI
+
+``webcolors`` is a 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:
+
+.. code-block:: python
+
+ >>> 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:
+
+.. code-block:: python
+
+ >>> import webcolors
+ >>> webcolors.html5_parse_legacy_color(u'chucknorris')
+ HTML5SimpleColor(red=192, green=0, blue=0)
+
+Full documentation is `available online `_.
diff --git a/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/webcolors-1.12.dist-info/RECORD b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/webcolors-1.12.dist-info/RECORD
new file mode 100644
index 00000000..74f4296c
--- /dev/null
+++ b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/webcolors-1.12.dist-info/RECORD
@@ -0,0 +1,9 @@
+webcolors-1.12.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+webcolors-1.12.dist-info/LICENSE,sha256=ii0_r1bvLUKXO599sXarGslRtQGkmhx7s0ACbx5NxIk,1523
+webcolors-1.12.dist-info/METADATA,sha256=56Xnd_OybLPtSNbCG8SixpiFKH0lqki7ihJWET3Ea_o,2049
+webcolors-1.12.dist-info/RECORD,,
+webcolors-1.12.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+webcolors-1.12.dist-info/WHEEL,sha256=_NOXIqFgOaYmlm9RJLPQZ13BJuEIrp5jx5ptRD5uh3Y,92
+webcolors-1.12.dist-info/top_level.txt,sha256=HUENGOTrUyEUebL1YSZy2ROMReykfiyMzSB-mSi72_4,10
+webcolors.py,sha256=OFDSm2rv4D0Jh1qhIOCLTy3g_8SpKfWNByWbnPmPYbk,25487
+webcolors.pyc,,
diff --git a/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/webcolors-1.12.dist-info/REQUESTED b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/webcolors-1.12.dist-info/REQUESTED
new file mode 100644
index 00000000..e69de29b
diff --git a/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/webcolors-1.12.dist-info/WHEEL b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/webcolors-1.12.dist-info/WHEEL
new file mode 100644
index 00000000..4eeaea1f
--- /dev/null
+++ b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/webcolors-1.12.dist-info/WHEEL
@@ -0,0 +1,5 @@
+Wheel-Version: 1.0
+Generator: bdist_wheel (0.32.3)
+Root-Is-Purelib: true
+Tag: py3-none-any
+
diff --git a/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/webcolors-1.12.dist-info/top_level.txt b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/webcolors-1.12.dist-info/top_level.txt
new file mode 100644
index 00000000..2ff3d436
--- /dev/null
+++ b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/webcolors-1.12.dist-info/top_level.txt
@@ -0,0 +1 @@
+webcolors
diff --git a/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/webcolors.py b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/webcolors.py
new file mode 100644
index 00000000..7738ebdc
--- /dev/null
+++ b/buildroot-external/rootfs-overlay/home/mycroft/.local/lib/python3.10/site-packages/webcolors.py
@@ -0,0 +1,781 @@
+"""
+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, conventions and conversions.
+
+"""
+
+import re
+import string
+from typing import NamedTuple, Tuple, Union
+
+__version__ = "1.11.1"
+
+
+def _reversedict(d: dict) -> dict:
+ """
+ Internal helper for generating reverse mappings; given a
+ dictionary, returns a new dictionary with keys and values swapped.
+
+ """
+ return {value: key for key, value in d.items()}
+
+
+HEX_COLOR_RE = re.compile(r"^#([a-fA-F0-9]{3}|[a-fA-F0-9]{6})$")
+
+HTML4 = "html4"
+CSS2 = "css2"
+CSS21 = "css21"
+CSS3 = "css3"
+
+SUPPORTED_SPECIFICATIONS = (HTML4, CSS2, CSS21, CSS3)
+
+SPECIFICATION_ERROR_TEMPLATE = "{{spec}} is not a supported specification for color name lookups; \
+supported specifications are: {supported}.".format(
+ supported=",".join(SUPPORTED_SPECIFICATIONS)
+)
+
+IntegerRGB = NamedTuple("IntegerRGB", [("red", int), ("green", int), ("blue", int)])
+PercentRGB = NamedTuple("PercentRGB", [("red", str), ("green", str), ("blue", str)])
+HTML5SimpleColor = NamedTuple(
+ "HTML5SimpleColor", [("red", int), ("green", int), ("blue", int)]
+)
+
+IntTuple = Union[IntegerRGB, HTML5SimpleColor, Tuple[int, int, int]]
+PercentTuple = Union[PercentRGB, Tuple[str, str, str]]
+
+
+# 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 = {
+ "aqua": "#00ffff",
+ "black": "#000000",
+ "blue": "#0000ff",
+ "fuchsia": "#ff00ff",
+ "green": "#008000",
+ "gray": "#808080",
+ "lime": "#00ff00",
+ "maroon": "#800000",
+ "navy": "#000080",
+ "olive": "#808000",
+ "purple": "#800080",
+ "red": "#ff0000",
+ "silver": "#c0c0c0",
+ "teal": "#008080",
+ "white": "#ffffff",
+ "yellow": "#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 = {"orange": "#ffa500", **HTML4_NAMES_TO_HEX}
+
+# 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 = {
+ "aliceblue": "#f0f8ff",
+ "antiquewhite": "#faebd7",
+ "aqua": "#00ffff",
+ "aquamarine": "#7fffd4",
+ "azure": "#f0ffff",
+ "beige": "#f5f5dc",
+ "bisque": "#ffe4c4",
+ "black": "#000000",
+ "blanchedalmond": "#ffebcd",
+ "blue": "#0000ff",
+ "blueviolet": "#8a2be2",
+ "brown": "#a52a2a",
+ "burlywood": "#deb887",
+ "cadetblue": "#5f9ea0",
+ "chartreuse": "#7fff00",
+ "chocolate": "#d2691e",
+ "coral": "#ff7f50",
+ "cornflowerblue": "#6495ed",
+ "cornsilk": "#fff8dc",
+ "crimson": "#dc143c",
+ "cyan": "#00ffff",
+ "darkblue": "#00008b",
+ "darkcyan": "#008b8b",
+ "darkgoldenrod": "#b8860b",
+ "darkgray": "#a9a9a9",
+ "darkgrey": "#a9a9a9",
+ "darkgreen": "#006400",
+ "darkkhaki": "#bdb76b",
+ "darkmagenta": "#8b008b",
+ "darkolivegreen": "#556b2f",
+ "darkorange": "#ff8c00",
+ "darkorchid": "#9932cc",
+ "darkred": "#8b0000",
+ "darksalmon": "#e9967a",
+ "darkseagreen": "#8fbc8f",
+ "darkslateblue": "#483d8b",
+ "darkslategray": "#2f4f4f",
+ "darkslategrey": "#2f4f4f",
+ "darkturquoise": "#00ced1",
+ "darkviolet": "#9400d3",
+ "deeppink": "#ff1493",
+ "deepskyblue": "#00bfff",
+ "dimgray": "#696969",
+ "dimgrey": "#696969",
+ "dodgerblue": "#1e90ff",
+ "firebrick": "#b22222",
+ "floralwhite": "#fffaf0",
+ "forestgreen": "#228b22",
+ "fuchsia": "#ff00ff",
+ "gainsboro": "#dcdcdc",
+ "ghostwhite": "#f8f8ff",
+ "gold": "#ffd700",
+ "goldenrod": "#daa520",
+ "gray": "#808080",
+ "grey": "#808080",
+ "green": "#008000",
+ "greenyellow": "#adff2f",
+ "honeydew": "#f0fff0",
+ "hotpink": "#ff69b4",
+ "indianred": "#cd5c5c",
+ "indigo": "#4b0082",
+ "ivory": "#fffff0",
+ "khaki": "#f0e68c",
+ "lavender": "#e6e6fa",
+ "lavenderblush": "#fff0f5",
+ "lawngreen": "#7cfc00",
+ "lemonchiffon": "#fffacd",
+ "lightblue": "#add8e6",
+ "lightcoral": "#f08080",
+ "lightcyan": "#e0ffff",
+ "lightgoldenrodyellow": "#fafad2",
+ "lightgray": "#d3d3d3",
+ "lightgrey": "#d3d3d3",
+ "lightgreen": "#90ee90",
+ "lightpink": "#ffb6c1",
+ "lightsalmon": "#ffa07a",
+ "lightseagreen": "#20b2aa",
+ "lightskyblue": "#87cefa",
+ "lightslategray": "#778899",
+ "lightslategrey": "#778899",
+ "lightsteelblue": "#b0c4de",
+ "lightyellow": "#ffffe0",
+ "lime": "#00ff00",
+ "limegreen": "#32cd32",
+ "linen": "#faf0e6",
+ "magenta": "#ff00ff",
+ "maroon": "#800000",
+ "mediumaquamarine": "#66cdaa",
+ "mediumblue": "#0000cd",
+ "mediumorchid": "#ba55d3",
+ "mediumpurple": "#9370db",
+ "mediumseagreen": "#3cb371",
+ "mediumslateblue": "#7b68ee",
+ "mediumspringgreen": "#00fa9a",
+ "mediumturquoise": "#48d1cc",
+ "mediumvioletred": "#c71585",
+ "midnightblue": "#191970",
+ "mintcream": "#f5fffa",
+ "mistyrose": "#ffe4e1",
+ "moccasin": "#ffe4b5",
+ "navajowhite": "#ffdead",
+ "navy": "#000080",
+ "oldlace": "#fdf5e6",
+ "olive": "#808000",
+ "olivedrab": "#6b8e23",
+ "orange": "#ffa500",
+ "orangered": "#ff4500",
+ "orchid": "#da70d6",
+ "palegoldenrod": "#eee8aa",
+ "palegreen": "#98fb98",
+ "paleturquoise": "#afeeee",
+ "palevioletred": "#db7093",
+ "papayawhip": "#ffefd5",
+ "peachpuff": "#ffdab9",
+ "peru": "#cd853f",
+ "pink": "#ffc0cb",
+ "plum": "#dda0dd",
+ "powderblue": "#b0e0e6",
+ "purple": "#800080",
+ "red": "#ff0000",
+ "rosybrown": "#bc8f8f",
+ "royalblue": "#4169e1",
+ "saddlebrown": "#8b4513",
+ "salmon": "#fa8072",
+ "sandybrown": "#f4a460",
+ "seagreen": "#2e8b57",
+ "seashell": "#fff5ee",
+ "sienna": "#a0522d",
+ "silver": "#c0c0c0",
+ "skyblue": "#87ceeb",
+ "slateblue": "#6a5acd",
+ "slategray": "#708090",
+ "slategrey": "#708090",
+ "snow": "#fffafa",
+ "springgreen": "#00ff7f",
+ "steelblue": "#4682b4",
+ "tan": "#d2b48c",
+ "teal": "#008080",
+ "thistle": "#d8bfd8",
+ "tomato": "#ff6347",
+ "turquoise": "#40e0d0",
+ "violet": "#ee82ee",
+ "wheat": "#f5deb3",
+ "white": "#ffffff",
+ "whitesmoke": "#f5f5f5",
+ "yellow": "#ffff00",
+ "yellowgreen": "#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)
+
+# CSS3 defines both 'gray' and 'grey', as well as defining either
+# variant for other related colors like 'darkgray'/'darkgrey'. For a
+# 'forward' lookup from name to hex, this is straightforward, but a
+# 'reverse' lookup from hex to name requires picking one spelling.
+#
+# The way in which _reversedict() generates the reverse mappings will
+# pick a spelling based on the ordering of dictionary keys, which
+# varies according to the version and implementation of Python in use,
+# and in some Python versions is explicitly not to be relied on for
+# consistency. So here we manually pick a single spelling that will
+# consistently be returned. Since 'gray' was the only spelling
+# supported in HTML 4, CSS1, and CSS2, 'gray' and its varients are
+# chosen.
+CSS3_HEX_TO_NAMES["#a9a9a9"] = "darkgray"
+CSS3_HEX_TO_NAMES["#2f4f4f"] = "darkslategray"
+CSS3_HEX_TO_NAMES["#696969"] = "dimgray"
+CSS3_HEX_TO_NAMES["#808080"] = "gray"
+CSS3_HEX_TO_NAMES["#d3d3d3"] = "lightgray"
+CSS3_HEX_TO_NAMES["#778899"] = "lightslategray"
+CSS3_HEX_TO_NAMES["#708090"] = "slategray"
+
+
+# Normalization functions.
+#################################################################
+
+
+def normalize_hex(hex_value: str) -> str:
+ """
+ Normalize a hexadecimal color value to 6 digits, lowercase.
+
+ """
+ match = HEX_COLOR_RE.match(hex_value)
+ if match is None:
+ raise ValueError(
+ "'{}' is not a valid hexadecimal color value.".format(hex_value)
+ )
+ hex_digits = match.group(1)
+ if len(hex_digits) == 3:
+ hex_digits = "".join(2 * s for s in hex_digits)
+ return "#{}".format(hex_digits.lower())
+
+
+def _normalize_integer_rgb(value: int) -> int:
+ """
+ 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: IntTuple) -> IntegerRGB:
+ """
+ Normalize an integer ``rgb()`` triplet so that all values are
+ within the range 0-255 inclusive.
+
+ """
+ return IntegerRGB._make(_normalize_integer_rgb(value) for value in rgb_triplet)
+
+
+def _normalize_percent_rgb(value: str) -> str:
+ """
+ Internal normalization function for clipping percent values into
+ the permitted range (0%-100%, inclusive).
+
+ """
+ value = value.split("%")[0]
+ percent = float(value) if "." in value else int(value)
+
+ return "0%" if percent < 0 else "100%" if percent > 100 else "{}%".format(percent)
+
+
+def normalize_percent_triplet(rgb_triplet: PercentTuple) -> PercentRGB:
+ """
+ Normalize a percentage ``rgb()`` triplet so that all values are
+ within the range 0%-100% inclusive.
+
+ """
+ return PercentRGB._make(_normalize_percent_rgb(value) for value in rgb_triplet)
+
+
+# Conversions from color names to various formats.
+#################################################################
+
+
+def name_to_hex(name: str, spec: str = CSS3) -> str:
+ """
+ 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. 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.format(spec=spec))
+ normalized = name.lower()
+ hex_value = {
+ CSS2: CSS2_NAMES_TO_HEX,
+ CSS21: CSS21_NAMES_TO_HEX,
+ CSS3: CSS3_NAMES_TO_HEX,
+ HTML4: HTML4_NAMES_TO_HEX,
+ }[spec].get(normalized)
+ if hex_value is None:
+ raise ValueError(
+ "'{name}' is not defined as a named color in {spec}".format(
+ name=name, spec=spec
+ )
+ )
+ return hex_value
+
+
+def name_to_rgb(name: str, spec: str = CSS3) -> IntegerRGB:
+ """
+ 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: str, spec: str = CSS3) -> PercentRGB:
+ """
+ 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: str, spec: str = CSS3) -> str:
+ """
+ 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. 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.format(spec=spec))
+ normalized = normalize_hex(hex_value)
+ name = {
+ CSS2: CSS2_HEX_TO_NAMES,
+ CSS21: CSS21_HEX_TO_NAMES,
+ CSS3: CSS3_HEX_TO_NAMES,
+ HTML4: HTML4_HEX_TO_NAMES,
+ }[spec].get(normalized)
+ if name is None:
+ raise ValueError("'{}' has no defined color name in {}".format(hex_value, spec))
+ return name
+
+
+def hex_to_rgb(hex_value: str) -> IntegerRGB:
+ """
+ Convert a hexadecimal color value to a 3-tuple of integers
+ suitable for use in an ``rgb()`` triplet specifying that color.
+
+ """
+ int_value = int(normalize_hex(hex_value)[1:], 16)
+ return IntegerRGB(int_value >> 16, int_value >> 8 & 0xFF, int_value & 0xFF)
+
+
+def hex_to_rgb_percent(hex_value: str) -> PercentRGB:
+ """
+ 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: IntTuple, spec: str = CSS3) -> str:
+ """
+ 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. 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: IntTuple) -> str:
+ """
+ Convert a 3-tuple of integers, suitable for use in an ``rgb()``
+ color triplet, to a normalized hexadecimal value for that color.
+
+ """
+ return "#{:02x}{:02x}{:02x}".format(*normalize_integer_triplet(rgb_triplet))
+
+
+def rgb_to_rgb_percent(rgb_triplet: IntTuple) -> PercentRGB:
+ """
+ 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: "100%",
+ 128: "50%",
+ 64: "25%",
+ 32: "12.5%",
+ 16: "6.25%",
+ 0: "0%",
+ }
+ return PercentRGB._make(
+ specials.get(d, "{:.02f}%".format(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: PercentTuple, spec: str = CSS3) -> str:
+ """
+ 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. 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: PercentTuple) -> str:
+ """
+ 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: str) -> int:
+ """
+ Internal helper for converting a percentage value to an integer
+ between 0 and 255 inclusive.
+
+ """
+ return int(round(float(percent.split("%")[0]) / 100 * 255))
+
+
+def rgb_percent_to_rgb(rgb_percent_triplet: PercentTuple) -> IntegerRGB:
+ """
+ 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 IntegerRGB._make(
+ 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: str) -> HTML5SimpleColor:
+ """
+ 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, str) or len(input) != 7:
+ raise ValueError(
+ "An HTML5 simple color must be a Unicode string "
+ "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(
+ "An HTML5 simple color must begin with the " "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(
+ "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.
+ return HTML5SimpleColor(
+ int(input[1:3], 16), int(input[3:5], 16), int(input[5:7], 16)
+ )
+
+
+def html5_serialize_simple_color(simple_color: IntTuple) -> str:
+ """
+ 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 = "#"
+
+ # 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.
+ format_string = "{:02x}"
+ result += format_string.format(red)
+ result += format_string.format(green)
+ result += format_string.format(blue)
+
+ # 3. Return result, which will be a valid lowercase simple color.
+ return result
+
+
+def html5_parse_legacy_color(input: str) -> HTML5SimpleColor:
+ """
+ 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, str):
+ raise ValueError(
+ "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("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() == "transparent":
+ raise ValueError('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("#")
+ 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 = HTML5SimpleColor(
+ 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".
+ input = "".join("00" if ord(c) > 0xFFFF else c for c in input)
+
+ # 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("#"):
+ input = input[1:]
+
+ # 10. Replace any character in input that is not an ASCII hex
+ # digit with the character "0" (U+0030).
+ input = "".join(c if c in string.hexdigits else "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 += "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] == "0" and green[0] == "0" and blue[0] == "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.
+ #
+ # 20. Return result.
+ return HTML5SimpleColor(int(red, 16), int(green, 16), int(blue, 16))