# Armonia
> **ἁρμονία**
>
> _Ancient Greek; noun_
>
> The principle of order and beauty through balanced relationships.
>
> A joining, joint; harmony, agreement, concord.
A Python library for elegant color theme management with dynamic computed colors and powerful transformation functions.
[](https://www.python.org/downloads/)
[](LICENSE)
## Overview
**Armonia** provides a sophisticated yet simple system for managing color themes in Python applications.
Built on top of [polychromos](https://pypi.org/project/polychromos/), it offers:
- **Centralized Theme Management**: Define all your colors in one place
- **Dynamic Computed Colors**: Colors that automatically update when base colors change
- **Color Functions**: Comprehensive transformation library (lighter, darker, mix, contrast, etc.)
- **Palette System**: Organize colors into named collections
- **Serialization Support**: Save and load themes from JSON/YAML
- **Safety First**: Recursion protection and conflict detection
- **Type-Safe**: Full type hints and mypy compatibility
## Installation
```bash
pip install armonia
```
Or using `uv`:
```bash
uv add armonia
```
## Quick Start
```python
from armonia import Theme
from armonia import colorfunctions as cf
from polychromos.color import HSLColor
# Create a theme
theme = Theme()
# Set base colors
theme.set_color("primary", HSLColor.from_hex("#2563eb"))
theme.set_color("background", HSLColor.from_hex("#ffffff"))
theme.set_color("text", HSLColor.from_hex("#1f2937"))
# Create computed colors that automatically derive from base colors
theme.set_computed_color("primary_light", cf.lighter("primary", 0.2))
theme.set_computed_color("primary_dark", cf.darker("primary", 0.2))
theme.set_computed_color("text_muted", cf.mix("text", "background", 0.4))
theme.set_computed_color("on_primary", cf.contrast("primary"))
# Get colors - they resolve automatically
print(theme.get_color("primary_light").to_css_hex()) # #6b95f1
# Change the base color - computed colors update automatically!
theme.set_color("primary", HSLColor.from_hex("#7c3aed"))
print(theme.get_color("primary_light").to_css_hex()) # Now reflects new primary color
```
## Key Features
### 1. Dynamic Color Computation
Computed colors are functions that derive their values from other colors in the theme. When you change a base color, all computed colors update automatically:
```python
# Define once
theme.set_color("brand", HSLColor.from_hex("#ff6b6b"))
theme.set_computed_color("brand_hover", cf.darker("brand", 0.1))
theme.set_computed_color("brand_subtle", cf.alpha("brand", 0.3))
# Update anywhere - computed colors follow
theme.set_color("brand", HSLColor.from_hex("#4ecdc4"))
# brand_hover and brand_subtle automatically reflect the new brand color
```
### 2. Comprehensive Color Functions
Over 40 built-in transformation functions organized by purpose:
#### Lightness & Darkness
```python
cf.lighter("color", 0.2) # Increase lightness
cf.darker("color", 0.2) # Decrease lightness
cf.brighten("color", 0.3) # Significantly lighter
cf.dim("color", 0.3) # Significantly darker
```
#### Saturation
```python
cf.saturate("color", 0.2) # More vivid
cf.desaturate("color", 0.2) # More gray
cf.muted("color", 0.4) # Significantly less saturated
cf.grayscale("color") # Complete desaturation
```
#### Mixing & Blending
```python
cf.mix("color1", "color2", 0.5) # Blend two colors
cf.tint("color", 0.2) # Mix with white
cf.shade("color", 0.2) # Mix with black
cf.tone("color", 0.2) # Mix with gray
cf.softer("color", "background", 0.3) # Shift toward background
```
#### Opacity
```python
cf.alpha("color", 0.5) # Set opacity
cf.fade("color", 0.3) # Fade (alias for alpha)
```
#### Advanced Transformations
```python
cf.rotate_hue("color", 180) # Rotate hue by degrees
cf.complementary("color") # Opposite on color wheel
cf.invert("color") # Invert lightness
cf.contrast("color") # Choose black or white for contrast
cf.alias("color") # Reference another color
```
#### Scaling Functions
```python
# Multiply mode (direct multiplication)
cf.scale_lightness("color", 0.7) # new = old * 0.7
cf.scale_saturation("color", 0.5) # new = old * 0.5
# Screen mode (gentler, preserves more original color)
cf.screen_lightness("color", 0.6) # new = 1 - (1-old) * 0.6
cf.screen_saturation("color", 0.4) # new = 1 - (1-old) * 0.4
```
#### Multi-Step Transformations
```python
# Chain multiple transformations
theme.set_computed_color(
"accent_complex",
cf.multi(
"accent",
lambda c: c.delta(0, 0, 0.1), # Lighter
lambda c: c.delta(0, -0.2, 0), # Less saturated
)
)
```
### 3. Color Palettes
Organize related colors into named palettes:
```python
# Define a palette
theme.set_palette("primary_scale", [
"primary_dark",
"primary",
"primary_light",
"primary_bright"
])
# Get all colors in the palette
colors = theme.get_palette("primary_scale") # Returns List[HSLColor]
# Use for UI scales, gradients, etc.
theme.set_palette("grays", ["gray_900", "gray_700", "gray_500", "gray_300", "gray_100"])
```
### 4. Get All Colors
Retrieve and sort all theme colors:
```python
# Get all colors sorted by name (alphabetically)
colors = theme.get_all_colors(sort_by="name")
# Sort by hue (color wheel order)
colors = theme.get_all_colors(sort_by="hue")
# Sort by saturation (most vivid to most muted)
colors = theme.get_all_colors(sort_by="saturation", reverse=True)
# Sort by lightness (dark to light)
colors = theme.get_all_colors(sort_by="lightness")
# Each entry includes name, color, and source
for entry in colors:
print(f"{entry.name}: {entry.color.to_css_hex()} ({entry.source})")
# Example: "primary: #2563eb (manual)"
# Example: "primary_light: #6b95f1 (computed)"
```
### 5. Flexible Color Resolution
The `get_color()` method resolves colors with a smart fallback chain:
```python
# 1. Theme colors (highest priority)
theme.set_color("brand", HSLColor.from_hex("#ff6b6b"))
theme.get_color("brand")
# 2. Computed colors
theme.set_computed_color("brand_light", cf.lighter("brand"))
theme.get_color("brand_light")
# 3. Web colors (CSS/HTML standard colors)
theme.get_color("tomato") # Falls back to web color
theme.get_color("skyblue")
# 4. Hex colors (direct parsing)
theme.get_color("#3498db") # Parses as hex
```
### 6. Serialization Support
Save and load themes from dictionaries (compatible with JSON/YAML):
```python
# Export theme to dictionary
theme_dict = {
"colors": {
"primary": "#2563eb",
"secondary": "#7c3aed"
},
"computed_colors": {
"primary_light": {
"function": "lighter",
"args": ["primary", 0.15]
}
},
"palettes": {
"primary_scale": ["primary_dark", "primary", "primary_light"]
}
}
# Load from dictionary
theme = Theme.from_dict(theme_dict)
# Or load from JSON
import json
with open("theme.json", "r") as f:
theme = Theme.from_dict(json.load(f))
```
### 7. Safety & Validation
Armonia protects against common errors:
```python
# Prevents naming conflicts
theme.set_color("red", ...) # Error: 'red' is a web color
theme.set_color("primary", ...)
theme.set_computed_color("primary", ...) # Error: already exists as manual color
# Detects circular dependencies
theme.set_computed_color("a", cf.lighter("b"))
theme.set_computed_color("b", cf.darker("a"))
theme.get_color("a") # Raises ColorRecursionError
# Clear error messages
theme.get_color("nonexistent") # ColorNotFoundError with helpful message
```
## Complete Example
Here's a complete example of a modern design system:
```python
from armonia import Theme
from armonia import colorfunctions as cf
from polychromos.color import HSLColor
# Create theme
theme = Theme()
# Base colors
theme.set_color("primary", HSLColor.from_hex("#2563eb"))
theme.set_color("secondary", HSLColor.from_hex("#7c3aed"))
theme.set_color("accent", HSLColor.from_hex("#f59e0b"))
theme.set_color("background", HSLColor.from_hex("#ffffff"))
theme.set_color("surface", HSLColor.from_hex("#f3f4f6"))
theme.set_color("text", HSLColor.from_hex("#1f2937"))
# Primary variations
theme.set_computed_color("primary_light", cf.lighter("primary", 0.15))
theme.set_computed_color("primary_dark", cf.darker("primary", 0.15))
theme.set_computed_color("primary_muted", cf.muted("primary", 0.4))
theme.set_computed_color("primary_vivid", cf.saturate("primary", 0.2))
# Semantic colors
theme.set_computed_color("on_primary", cf.contrast("primary"))
theme.set_computed_color("on_secondary", cf.contrast("secondary"))
theme.set_computed_color("on_accent", cf.contrast("accent"))
# Surface variations
theme.set_computed_color("surface_light", cf.lighter("surface", 0.05))
theme.set_computed_color("surface_dark", cf.darker("surface", 0.05))
# Text hierarchy
theme.set_computed_color("text_muted", cf.mix("text", "background", 0.4))
theme.set_computed_color("text_subtle", cf.alpha("text", 0.6))
# Define palettes
theme.set_palette("primary_scale", [
"primary_dark",
"primary",
"primary_light",
"primary_vivid"
])
theme.set_palette("surfaces", [
"background",
"surface",
"surface_light",
"surface_dark"
])
theme.set_palette("text_hierarchy", [
"text",
"text_muted",
"text_subtle"
])
# Use colors
print(f"Primary: {theme.get_color('primary').to_css_hex()}")
print(f"Primary Light: {theme.get_color('primary_light').to_css_hex()}")
print(f"Text on Primary: {theme.get_color('on_primary').to_css_hex()}")
# Get a palette
primary_colors = theme.get_palette("primary_scale")
for i, color in enumerate(primary_colors):
print(f" {i}: {color.to_css_hex()}")
```
## Integration Examples
### Flask/Django (CSS Custom Properties)
```python
from armonia import Theme
from polychromos.color import HSLColor
theme = Theme()
# ... setup theme ...
def generate_css():
"""Generate CSS custom properties from theme."""
css_vars = [":root {"]
for entry in theme.get_all_colors():
css_name = entry.name.replace("_", "-")
css_value = entry.color.to_css_hex()
css_vars.append(f" --color-{css_name}: {css_value};")
css_vars.append("}")
return "\n".join(css_vars)
# In your Flask/Django view
@app.route('/theme.css')
def theme_css():
return generate_css(), 200, {'Content-Type': 'text/css'}
```
### TailwindCSS Integration
```python
import json
def generate_tailwind_colors(theme):
"""Generate Tailwind color configuration."""
colors = {}
for entry in theme.get_all_colors():
colors[entry.name] = entry.color.to_css_hex()
config = {
"theme": {
"extend": {
"colors": colors
}
}
}
with open("tailwind.theme.json", "w") as f:
json.dump(config, f, indent=2)
```
### Terminal/CLI Applications
```python
from armonia import Theme
from polychromos.color import HSLColor
theme = Theme()
# ... setup theme ...
# Get ANSI color codes for terminal output
def color_text(text, color_name):
color = theme.get_color(color_name)
r, g, b = color.rgb
return f"\033[38;2;{r};{g};{b}m{text}\033[0m"
print(color_text("Success!", "success"))
print(color_text("Warning!", "warning"))
```
## Live Example
Check out the interactive example in `examples/color-showcase.py`:
```bash
cd examples
uv run color-showcase.py
```
Then open http://localhost:5000 to see a live demonstration with:
- Interactive color pickers
- Real-time computed color updates
- Light/dark theme switching
- All colors panel with sorting options
## Development
This project uses `uv` for dependency management.
### Setup
```bash
# Clone the repository
git clone https://gitlab.com/Kencho1/armonia.git
cd armonia
# Install dependencies
uv sync
# Install with test dependencies
uv sync --extra test
```
### Testing
```bash
# Run tests
uv run pytest
# Run with coverage
uv run pytest --cov=armonia
# Type checking
uv run mypy armonia
# Linting
uv run ruff check armonia
```
## License
MIT License - see [LICENSE](LICENSE) file for details.
## Links
- **Repository**: https://gitlab.com/Kencho1/armonia
- **Issues**: https://gitlab.com/Kencho1/armonia/-/issues
- **Changelog**: [CHANGELOG.md](CHANGELOG.md)
Raw data
{
"_id": null,
"home_page": null,
"name": "armonia",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.11",
"maintainer_email": null,
"keywords": "color-management, colors, polychromos, theme, theming",
"author": "Jes\u00fas Alonso Abad",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/32/05/5a6ae8958a11965ed1c5e576d6d3278db3d786585c4e740550d6e1bd4bdb/armonia-1.0.1.tar.gz",
"platform": null,
"description": "# Armonia\n\n> **\u1f01\u03c1\u03bc\u03bf\u03bd\u03af\u03b1**\n>\n> _Ancient Greek; noun_\n>\n> The principle of order and beauty through balanced relationships.\n>\n> A joining, joint; harmony, agreement, concord.\n\nA Python library for elegant color theme management with dynamic computed colors and powerful transformation functions.\n\n[](https://www.python.org/downloads/)\n[](LICENSE)\n\n## Overview\n\n**Armonia** provides a sophisticated yet simple system for managing color themes in Python applications.\n\nBuilt on top of [polychromos](https://pypi.org/project/polychromos/), it offers:\n\n- **Centralized Theme Management**: Define all your colors in one place\n- **Dynamic Computed Colors**: Colors that automatically update when base colors change\n- **Color Functions**: Comprehensive transformation library (lighter, darker, mix, contrast, etc.)\n- **Palette System**: Organize colors into named collections\n- **Serialization Support**: Save and load themes from JSON/YAML\n- **Safety First**: Recursion protection and conflict detection\n- **Type-Safe**: Full type hints and mypy compatibility\n\n## Installation\n\n```bash\npip install armonia\n```\n\nOr using `uv`:\n\n```bash\nuv add armonia\n```\n\n## Quick Start\n\n```python\nfrom armonia import Theme\nfrom armonia import colorfunctions as cf\nfrom polychromos.color import HSLColor\n\n# Create a theme\ntheme = Theme()\n\n# Set base colors\ntheme.set_color(\"primary\", HSLColor.from_hex(\"#2563eb\"))\ntheme.set_color(\"background\", HSLColor.from_hex(\"#ffffff\"))\ntheme.set_color(\"text\", HSLColor.from_hex(\"#1f2937\"))\n\n# Create computed colors that automatically derive from base colors\ntheme.set_computed_color(\"primary_light\", cf.lighter(\"primary\", 0.2))\ntheme.set_computed_color(\"primary_dark\", cf.darker(\"primary\", 0.2))\ntheme.set_computed_color(\"text_muted\", cf.mix(\"text\", \"background\", 0.4))\ntheme.set_computed_color(\"on_primary\", cf.contrast(\"primary\"))\n\n# Get colors - they resolve automatically\nprint(theme.get_color(\"primary_light\").to_css_hex()) # #6b95f1\n\n# Change the base color - computed colors update automatically!\ntheme.set_color(\"primary\", HSLColor.from_hex(\"#7c3aed\"))\nprint(theme.get_color(\"primary_light\").to_css_hex()) # Now reflects new primary color\n```\n\n## Key Features\n\n### 1. Dynamic Color Computation\n\nComputed colors are functions that derive their values from other colors in the theme. When you change a base color, all computed colors update automatically:\n\n```python\n# Define once\ntheme.set_color(\"brand\", HSLColor.from_hex(\"#ff6b6b\"))\ntheme.set_computed_color(\"brand_hover\", cf.darker(\"brand\", 0.1))\ntheme.set_computed_color(\"brand_subtle\", cf.alpha(\"brand\", 0.3))\n\n# Update anywhere - computed colors follow\ntheme.set_color(\"brand\", HSLColor.from_hex(\"#4ecdc4\"))\n# brand_hover and brand_subtle automatically reflect the new brand color\n```\n\n### 2. Comprehensive Color Functions\n\nOver 40 built-in transformation functions organized by purpose:\n\n#### Lightness & Darkness\n```python\ncf.lighter(\"color\", 0.2) # Increase lightness\ncf.darker(\"color\", 0.2) # Decrease lightness\ncf.brighten(\"color\", 0.3) # Significantly lighter\ncf.dim(\"color\", 0.3) # Significantly darker\n```\n\n#### Saturation\n```python\ncf.saturate(\"color\", 0.2) # More vivid\ncf.desaturate(\"color\", 0.2) # More gray\ncf.muted(\"color\", 0.4) # Significantly less saturated\ncf.grayscale(\"color\") # Complete desaturation\n```\n\n#### Mixing & Blending\n```python\ncf.mix(\"color1\", \"color2\", 0.5) # Blend two colors\ncf.tint(\"color\", 0.2) # Mix with white\ncf.shade(\"color\", 0.2) # Mix with black\ncf.tone(\"color\", 0.2) # Mix with gray\ncf.softer(\"color\", \"background\", 0.3) # Shift toward background\n```\n\n#### Opacity\n```python\ncf.alpha(\"color\", 0.5) # Set opacity\ncf.fade(\"color\", 0.3) # Fade (alias for alpha)\n```\n\n#### Advanced Transformations\n```python\ncf.rotate_hue(\"color\", 180) # Rotate hue by degrees\ncf.complementary(\"color\") # Opposite on color wheel\ncf.invert(\"color\") # Invert lightness\ncf.contrast(\"color\") # Choose black or white for contrast\ncf.alias(\"color\") # Reference another color\n```\n\n#### Scaling Functions\n```python\n# Multiply mode (direct multiplication)\ncf.scale_lightness(\"color\", 0.7) # new = old * 0.7\ncf.scale_saturation(\"color\", 0.5) # new = old * 0.5\n\n# Screen mode (gentler, preserves more original color)\ncf.screen_lightness(\"color\", 0.6) # new = 1 - (1-old) * 0.6\ncf.screen_saturation(\"color\", 0.4) # new = 1 - (1-old) * 0.4\n```\n\n#### Multi-Step Transformations\n```python\n# Chain multiple transformations\ntheme.set_computed_color(\n \"accent_complex\",\n cf.multi(\n \"accent\",\n lambda c: c.delta(0, 0, 0.1), # Lighter\n lambda c: c.delta(0, -0.2, 0), # Less saturated\n )\n)\n```\n\n### 3. Color Palettes\n\nOrganize related colors into named palettes:\n\n```python\n# Define a palette\ntheme.set_palette(\"primary_scale\", [\n \"primary_dark\",\n \"primary\",\n \"primary_light\",\n \"primary_bright\"\n])\n\n# Get all colors in the palette\ncolors = theme.get_palette(\"primary_scale\") # Returns List[HSLColor]\n\n# Use for UI scales, gradients, etc.\ntheme.set_palette(\"grays\", [\"gray_900\", \"gray_700\", \"gray_500\", \"gray_300\", \"gray_100\"])\n```\n\n### 4. Get All Colors\n\nRetrieve and sort all theme colors:\n\n```python\n# Get all colors sorted by name (alphabetically)\ncolors = theme.get_all_colors(sort_by=\"name\")\n\n# Sort by hue (color wheel order)\ncolors = theme.get_all_colors(sort_by=\"hue\")\n\n# Sort by saturation (most vivid to most muted)\ncolors = theme.get_all_colors(sort_by=\"saturation\", reverse=True)\n\n# Sort by lightness (dark to light)\ncolors = theme.get_all_colors(sort_by=\"lightness\")\n\n# Each entry includes name, color, and source\nfor entry in colors:\n print(f\"{entry.name}: {entry.color.to_css_hex()} ({entry.source})\")\n # Example: \"primary: #2563eb (manual)\"\n # Example: \"primary_light: #6b95f1 (computed)\"\n```\n\n### 5. Flexible Color Resolution\n\nThe `get_color()` method resolves colors with a smart fallback chain:\n\n```python\n# 1. Theme colors (highest priority)\ntheme.set_color(\"brand\", HSLColor.from_hex(\"#ff6b6b\"))\ntheme.get_color(\"brand\")\n\n# 2. Computed colors\ntheme.set_computed_color(\"brand_light\", cf.lighter(\"brand\"))\ntheme.get_color(\"brand_light\")\n\n# 3. Web colors (CSS/HTML standard colors)\ntheme.get_color(\"tomato\") # Falls back to web color\ntheme.get_color(\"skyblue\")\n\n# 4. Hex colors (direct parsing)\ntheme.get_color(\"#3498db\") # Parses as hex\n```\n\n### 6. Serialization Support\n\nSave and load themes from dictionaries (compatible with JSON/YAML):\n\n```python\n# Export theme to dictionary\ntheme_dict = {\n \"colors\": {\n \"primary\": \"#2563eb\",\n \"secondary\": \"#7c3aed\"\n },\n \"computed_colors\": {\n \"primary_light\": {\n \"function\": \"lighter\",\n \"args\": [\"primary\", 0.15]\n }\n },\n \"palettes\": {\n \"primary_scale\": [\"primary_dark\", \"primary\", \"primary_light\"]\n }\n}\n\n# Load from dictionary\ntheme = Theme.from_dict(theme_dict)\n\n# Or load from JSON\nimport json\n\nwith open(\"theme.json\", \"r\") as f:\n theme = Theme.from_dict(json.load(f))\n```\n\n### 7. Safety & Validation\n\nArmonia protects against common errors:\n\n```python\n# Prevents naming conflicts\ntheme.set_color(\"red\", ...) # Error: 'red' is a web color\ntheme.set_color(\"primary\", ...)\ntheme.set_computed_color(\"primary\", ...) # Error: already exists as manual color\n\n# Detects circular dependencies\ntheme.set_computed_color(\"a\", cf.lighter(\"b\"))\ntheme.set_computed_color(\"b\", cf.darker(\"a\"))\ntheme.get_color(\"a\") # Raises ColorRecursionError\n\n# Clear error messages\ntheme.get_color(\"nonexistent\") # ColorNotFoundError with helpful message\n```\n\n## Complete Example\n\nHere's a complete example of a modern design system:\n\n```python\nfrom armonia import Theme\nfrom armonia import colorfunctions as cf\nfrom polychromos.color import HSLColor\n\n# Create theme\ntheme = Theme()\n\n# Base colors\ntheme.set_color(\"primary\", HSLColor.from_hex(\"#2563eb\"))\ntheme.set_color(\"secondary\", HSLColor.from_hex(\"#7c3aed\"))\ntheme.set_color(\"accent\", HSLColor.from_hex(\"#f59e0b\"))\ntheme.set_color(\"background\", HSLColor.from_hex(\"#ffffff\"))\ntheme.set_color(\"surface\", HSLColor.from_hex(\"#f3f4f6\"))\ntheme.set_color(\"text\", HSLColor.from_hex(\"#1f2937\"))\n\n# Primary variations\ntheme.set_computed_color(\"primary_light\", cf.lighter(\"primary\", 0.15))\ntheme.set_computed_color(\"primary_dark\", cf.darker(\"primary\", 0.15))\ntheme.set_computed_color(\"primary_muted\", cf.muted(\"primary\", 0.4))\ntheme.set_computed_color(\"primary_vivid\", cf.saturate(\"primary\", 0.2))\n\n# Semantic colors\ntheme.set_computed_color(\"on_primary\", cf.contrast(\"primary\"))\ntheme.set_computed_color(\"on_secondary\", cf.contrast(\"secondary\"))\ntheme.set_computed_color(\"on_accent\", cf.contrast(\"accent\"))\n\n# Surface variations\ntheme.set_computed_color(\"surface_light\", cf.lighter(\"surface\", 0.05))\ntheme.set_computed_color(\"surface_dark\", cf.darker(\"surface\", 0.05))\n\n# Text hierarchy\ntheme.set_computed_color(\"text_muted\", cf.mix(\"text\", \"background\", 0.4))\ntheme.set_computed_color(\"text_subtle\", cf.alpha(\"text\", 0.6))\n\n# Define palettes\ntheme.set_palette(\"primary_scale\", [\n \"primary_dark\",\n \"primary\",\n \"primary_light\",\n \"primary_vivid\"\n])\n\ntheme.set_palette(\"surfaces\", [\n \"background\",\n \"surface\",\n \"surface_light\",\n \"surface_dark\"\n])\n\ntheme.set_palette(\"text_hierarchy\", [\n \"text\",\n \"text_muted\",\n \"text_subtle\"\n])\n\n# Use colors\nprint(f\"Primary: {theme.get_color('primary').to_css_hex()}\")\nprint(f\"Primary Light: {theme.get_color('primary_light').to_css_hex()}\")\nprint(f\"Text on Primary: {theme.get_color('on_primary').to_css_hex()}\")\n\n# Get a palette\nprimary_colors = theme.get_palette(\"primary_scale\")\nfor i, color in enumerate(primary_colors):\n print(f\" {i}: {color.to_css_hex()}\")\n```\n\n## Integration Examples\n\n### Flask/Django (CSS Custom Properties)\n\n```python\nfrom armonia import Theme\nfrom polychromos.color import HSLColor\n\ntheme = Theme()\n# ... setup theme ...\n\ndef generate_css():\n \"\"\"Generate CSS custom properties from theme.\"\"\"\n css_vars = [\":root {\"]\n\n for entry in theme.get_all_colors():\n css_name = entry.name.replace(\"_\", \"-\")\n css_value = entry.color.to_css_hex()\n css_vars.append(f\" --color-{css_name}: {css_value};\")\n\n css_vars.append(\"}\")\n return \"\\n\".join(css_vars)\n\n# In your Flask/Django view\n@app.route('/theme.css')\ndef theme_css():\n return generate_css(), 200, {'Content-Type': 'text/css'}\n```\n\n### TailwindCSS Integration\n\n```python\nimport json\n\ndef generate_tailwind_colors(theme):\n \"\"\"Generate Tailwind color configuration.\"\"\"\n colors = {}\n for entry in theme.get_all_colors():\n colors[entry.name] = entry.color.to_css_hex()\n\n config = {\n \"theme\": {\n \"extend\": {\n \"colors\": colors\n }\n }\n }\n\n with open(\"tailwind.theme.json\", \"w\") as f:\n json.dump(config, f, indent=2)\n```\n\n### Terminal/CLI Applications\n\n```python\nfrom armonia import Theme\nfrom polychromos.color import HSLColor\n\ntheme = Theme()\n# ... setup theme ...\n\n# Get ANSI color codes for terminal output\ndef color_text(text, color_name):\n color = theme.get_color(color_name)\n r, g, b = color.rgb\n return f\"\\033[38;2;{r};{g};{b}m{text}\\033[0m\"\n\nprint(color_text(\"Success!\", \"success\"))\nprint(color_text(\"Warning!\", \"warning\"))\n```\n\n## Live Example\n\nCheck out the interactive example in `examples/color-showcase.py`:\n\n```bash\ncd examples\nuv run color-showcase.py\n```\n\nThen open http://localhost:5000 to see a live demonstration with:\n- Interactive color pickers\n- Real-time computed color updates\n- Light/dark theme switching\n- All colors panel with sorting options\n\n## Development\n\nThis project uses `uv` for dependency management.\n\n### Setup\n\n```bash\n# Clone the repository\ngit clone https://gitlab.com/Kencho1/armonia.git\ncd armonia\n\n# Install dependencies\nuv sync\n\n# Install with test dependencies\nuv sync --extra test\n```\n\n### Testing\n\n```bash\n# Run tests\nuv run pytest\n\n# Run with coverage\nuv run pytest --cov=armonia\n\n# Type checking\nuv run mypy armonia\n\n# Linting\nuv run ruff check armonia\n```\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n\n## Links\n\n- **Repository**: https://gitlab.com/Kencho1/armonia\n- **Issues**: https://gitlab.com/Kencho1/armonia/-/issues\n- **Changelog**: [CHANGELOG.md](CHANGELOG.md)\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A Python library for theming facilities",
"version": "1.0.1",
"project_urls": {
"Homepage": "https://gitlab.com/Kencho1/armonia",
"Issues": "https://gitlab.com/Kencho1/armonia/-/issues",
"Repository": "https://gitlab.com/Kencho1/armonia.git"
},
"split_keywords": [
"color-management",
" colors",
" polychromos",
" theme",
" theming"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "d5d6cf55e9486fa0c98f7386652b8ebc64c3a54bd1843527d56c3f243b6c8365",
"md5": "949ca11c9de5fca0aee725c8aab1db7f",
"sha256": "2e6cd932ae5805c7cc8a0a39fdea4e3b7f36fc8b57db7cc9c8917f4335063b70"
},
"downloads": -1,
"filename": "armonia-1.0.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "949ca11c9de5fca0aee725c8aab1db7f",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.11",
"size": 15611,
"upload_time": "2025-11-01T14:35:42",
"upload_time_iso_8601": "2025-11-01T14:35:42.161697Z",
"url": "https://files.pythonhosted.org/packages/d5/d6/cf55e9486fa0c98f7386652b8ebc64c3a54bd1843527d56c3f243b6c8365/armonia-1.0.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "32055a6ae8958a11965ed1c5e576d6d3278db3d786585c4e740550d6e1bd4bdb",
"md5": "2c64b60e6ec320e314d3b8d1046fcac8",
"sha256": "2c95a5be793c63e30d952abbbffbb33fe626d3539f41a137818b0083c9a8c820"
},
"downloads": -1,
"filename": "armonia-1.0.1.tar.gz",
"has_sig": false,
"md5_digest": "2c64b60e6ec320e314d3b8d1046fcac8",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.11",
"size": 13332,
"upload_time": "2025-11-01T14:35:43",
"upload_time_iso_8601": "2025-11-01T14:35:43.002894Z",
"url": "https://files.pythonhosted.org/packages/32/05/5a6ae8958a11965ed1c5e576d6d3278db3d786585c4e740550d6e1bd4bdb/armonia-1.0.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-11-01 14:35:43",
"github": false,
"gitlab": true,
"bitbucket": false,
"codeberg": false,
"gitlab_user": "Kencho1",
"gitlab_project": "armonia",
"lcname": "armonia"
}