heinzel-theme 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- heinzel_theme-0.1.0/.gitignore +15 -0
- heinzel_theme-0.1.0/LICENSE +21 -0
- heinzel_theme-0.1.0/PKG-INFO +29 -0
- heinzel_theme-0.1.0/README.md +17 -0
- heinzel_theme-0.1.0/plugin-lock.json +40 -0
- heinzel_theme-0.1.0/pyproject.toml +129 -0
- heinzel_theme-0.1.0/requirements.lock +1158 -0
- heinzel_theme-0.1.0/src/heinzel_theme/__init__.py +9 -0
- heinzel_theme-0.1.0/src/heinzel_theme/py.typed +0 -0
- heinzel_theme-0.1.0/src/heinzel_theme/soundscapes/claude-fm.toml +9 -0
- heinzel_theme-0.1.0/src/heinzel_theme/soundscapes/focus.toml +10 -0
- heinzel_theme-0.1.0/src/heinzel_theme/soundscapes/hyper-focus.toml +9 -0
- heinzel_theme-0.1.0/src/heinzel_theme/themes/heinzelmaennchen.toml +63 -0
- heinzel_theme-0.1.0/src/heinzel_theme/themes/logo/mark.svg +183 -0
- heinzel_theme-0.1.0/src/heinzel_theme/themes/logo/wordmark-dark.svg +186 -0
- heinzel_theme-0.1.0/src/heinzel_theme/themes/logo/wordmark-light.svg +186 -0
- heinzel_theme-0.1.0/tests/acceptance/install_test.py +95 -0
- heinzel_theme-0.1.0/tests/conftest.py +21 -0
- heinzel_theme-0.1.0/tests/unit/content_test.py +30 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Helmut Hoffer von Ankershoffen
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: heinzel-theme
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: The Heinzelmännchen theme and its soundscapes.
|
|
5
|
+
Project-URL: Source, https://github.com/helmut-hoffer-von-ankershoffen/heinzel-plugins/tree/main/plugins/heinzel-theme
|
|
6
|
+
Project-URL: Issues, https://github.com/helmut-hoffer-von-ankershoffen/heinzel-plugins/issues
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Python: >=3.12
|
|
10
|
+
Requires-Dist: heinzel<0.10,>=0.9.1
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
|
|
13
|
+
# Heinzelmännchen theme
|
|
14
|
+
|
|
15
|
+
The standard Heinzelmännchen appearance and its three soundscapes: Claude FM, Die Heinzelmännchen and Hyper Focus.
|
|
16
|
+
The standard app installs and enables this plugin automatically. Installation leaves the current theme choice and
|
|
17
|
+
playback state alone; sound starts only after the person presses Play.
|
|
18
|
+
|
|
19
|
+
Select **Heinzelmännchen** in Settings → Appearance, or run `hz system theme use heinzelmaennchen`. With **Follow my
|
|
20
|
+
theme** enabled, its paired soundscape is Die Heinzelmännchen (`focus`). Choose any of its soundscapes manually with
|
|
21
|
+
`hz system sound use claude-fm`, `hz system sound use focus` or `hz system sound use hyper-focus`.
|
|
22
|
+
|
|
23
|
+
All theme values, logos, soundscape definitions, pairing and tests belong to this directory. The plugin uses public
|
|
24
|
+
`module.theme` and `module.soundscape` declarations. It imports no other plugin or core implementation. Disabling
|
|
25
|
+
or removing it restores core's fallback appearance and leaves unavailable sound choices silent.
|
|
26
|
+
|
|
27
|
+
From the repository root, run `make lock`, `make check`, `make build` and `make acceptance` with `NAME=heinzel-theme`
|
|
28
|
+
and `CORE=<compatible-core-wheel>`. Only this plugin's environment and tests are used. New content requires no core
|
|
29
|
+
or parent registry change.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Heinzelmännchen theme
|
|
2
|
+
|
|
3
|
+
The standard Heinzelmännchen appearance and its three soundscapes: Claude FM, Die Heinzelmännchen and Hyper Focus.
|
|
4
|
+
The standard app installs and enables this plugin automatically. Installation leaves the current theme choice and
|
|
5
|
+
playback state alone; sound starts only after the person presses Play.
|
|
6
|
+
|
|
7
|
+
Select **Heinzelmännchen** in Settings → Appearance, or run `hz system theme use heinzelmaennchen`. With **Follow my
|
|
8
|
+
theme** enabled, its paired soundscape is Die Heinzelmännchen (`focus`). Choose any of its soundscapes manually with
|
|
9
|
+
`hz system sound use claude-fm`, `hz system sound use focus` or `hz system sound use hyper-focus`.
|
|
10
|
+
|
|
11
|
+
All theme values, logos, soundscape definitions, pairing and tests belong to this directory. The plugin uses public
|
|
12
|
+
`module.theme` and `module.soundscape` declarations. It imports no other plugin or core implementation. Disabling
|
|
13
|
+
or removing it restores core's fallback appearance and leaves unavailable sound choices silent.
|
|
14
|
+
|
|
15
|
+
From the repository root, run `make lock`, `make check`, `make build` and `make acceptance` with `NAME=heinzel-theme`
|
|
16
|
+
and `CORE=<compatible-core-wheel>`. Only this plugin's environment and tests are used. New content requires no core
|
|
17
|
+
or parent registry change.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"format": 1,
|
|
3
|
+
"sdk": 1,
|
|
4
|
+
"inputs": [
|
|
5
|
+
"coverage>=7.12",
|
|
6
|
+
"editables>=0.5",
|
|
7
|
+
"hatchling>=1.29.0",
|
|
8
|
+
"heinzel>=0.9.1,<0.10",
|
|
9
|
+
"mypy>=1.19.0,<3",
|
|
10
|
+
"pyright[nodejs]==1.1.414",
|
|
11
|
+
"pytest-timeout>=2.4.0,<3",
|
|
12
|
+
"pytest-xdist>=3.8",
|
|
13
|
+
"pytest>=9.0.3,<10",
|
|
14
|
+
"ruff==0.17.2"
|
|
15
|
+
],
|
|
16
|
+
"core": {
|
|
17
|
+
"version": "0.9.1",
|
|
18
|
+
"dependencies": [
|
|
19
|
+
"croniter>=6.2.4",
|
|
20
|
+
"fastapi>=0.161",
|
|
21
|
+
"keyring>=25.6",
|
|
22
|
+
"mcp>=2.3",
|
|
23
|
+
"packaging>=25.0",
|
|
24
|
+
"platformdirs>=4.5",
|
|
25
|
+
"pluggy<2,>=1.6.0",
|
|
26
|
+
"psutil==7.2.2",
|
|
27
|
+
"pydantic-ai-slim==2.61.0",
|
|
28
|
+
"pydantic-ai-slim[anthropic]==2.61.0; extra == \"anthropic\"",
|
|
29
|
+
"pydantic-ai-slim[openai]==2.61.0; extra == \"openai\"",
|
|
30
|
+
"pydantic-settings<3,>=2.11.0",
|
|
31
|
+
"pydantic<3,>=2.12.0",
|
|
32
|
+
"pyyaml<7,>=6.0.2",
|
|
33
|
+
"rich>=14.2.0",
|
|
34
|
+
"tomlkit>=0.13",
|
|
35
|
+
"typer>=0.23.0",
|
|
36
|
+
"uvicorn>=0.54",
|
|
37
|
+
"wsproto>=1.3"
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "heinzel-theme"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "The Heinzelmännchen theme and its soundscapes."
|
|
5
|
+
license = "MIT"
|
|
6
|
+
license-files = ["LICENSE"]
|
|
7
|
+
readme = "README.md"
|
|
8
|
+
requires-python = ">=3.12"
|
|
9
|
+
dependencies = ["heinzel>=0.9.1,<0.10"]
|
|
10
|
+
|
|
11
|
+
[project.entry-points."heinzel.modules"]
|
|
12
|
+
theme = "heinzel_theme"
|
|
13
|
+
|
|
14
|
+
[project.urls]
|
|
15
|
+
Source = "https://github.com/helmut-hoffer-von-ankershoffen/heinzel-plugins/tree/main/plugins/heinzel-theme"
|
|
16
|
+
Issues = "https://github.com/helmut-hoffer-von-ankershoffen/heinzel-plugins/issues"
|
|
17
|
+
|
|
18
|
+
[tool.heinzel.plugin]
|
|
19
|
+
profiles = ["standard"]
|
|
20
|
+
requires = ["core:plugin-api@1"]
|
|
21
|
+
provides = []
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
[tool.ruff]
|
|
25
|
+
line-length = 120
|
|
26
|
+
fix = true
|
|
27
|
+
extend-exclude = ["template"] # rendered and checked by `make template-test`
|
|
28
|
+
|
|
29
|
+
[tool.ruff.lint]
|
|
30
|
+
select = ["ALL"]
|
|
31
|
+
# pydoclint (DOC): docstring sections must match what the code raises, returns and yields. Preview rules, opted into
|
|
32
|
+
# one by one so no other preview rule sneaks in.
|
|
33
|
+
preview = true
|
|
34
|
+
explicit-preview-rules = true
|
|
35
|
+
extend-select = ["DOC201", "DOC202", "DOC402", "DOC403", "DOC501", "DOC502"]
|
|
36
|
+
ignore = [
|
|
37
|
+
"COM812", # conflicts with the ruff formatter
|
|
38
|
+
"CPY001", # no copyright header in OSS files
|
|
39
|
+
"D203", # incompatible with D211
|
|
40
|
+
"DOC201", # a return value is documented by the type and the summary line; Returns: only when it adds meaning
|
|
41
|
+
"DOC502", # documenting exceptions raised by callees is useful for callers
|
|
42
|
+
"D213", # incompatible with D212
|
|
43
|
+
"FBT001", # boolean positional arguments are idiomatic for Typer options
|
|
44
|
+
"FBT002", # same as FBT001
|
|
45
|
+
"ISC001", # conflicts with the ruff formatter
|
|
46
|
+
"TD003", # todos don't need an issue link
|
|
47
|
+
"FIX002", # todos are allowed
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
[tool.ruff.lint.per-file-ignores]
|
|
51
|
+
".claude/hooks/*.py" = [
|
|
52
|
+
"D103", # hook entry points are documented by the module docstring
|
|
53
|
+
"INP001", # hooks are scripts, not a package
|
|
54
|
+
"S603", # subprocess calls with fixed argument lists
|
|
55
|
+
"S607", # tools (uv, git, make) are resolved from PATH on purpose
|
|
56
|
+
"T201", # hooks talk to the agent through stdout/stderr
|
|
57
|
+
]
|
|
58
|
+
"fuzz/*.py" = [
|
|
59
|
+
"INP001", # fuzz targets are scripts, not a package
|
|
60
|
+
]
|
|
61
|
+
"hatch_build.py" = [
|
|
62
|
+
"INP001", # the build hook hatch loads by path, not a package
|
|
63
|
+
]
|
|
64
|
+
"scripts/*.py" = [
|
|
65
|
+
"INP001", # scripts are not a package
|
|
66
|
+
"T201", # scripts report on stdout/stderr
|
|
67
|
+
]
|
|
68
|
+
"**/tests/**/*.py" = [
|
|
69
|
+
"ANN", # fixtures and tests don't need full annotations
|
|
70
|
+
"DOC", # test docstrings describe behaviour, not interfaces
|
|
71
|
+
"ARG", # fixtures are used for their side effects
|
|
72
|
+
"D", # test names are the documentation
|
|
73
|
+
"INP001", # tests are not a package
|
|
74
|
+
"PLC0415", # local imports keep fixtures isolated
|
|
75
|
+
"PLR2004", # magic values are fine in assertions
|
|
76
|
+
"S101", # asserts are what tests do
|
|
77
|
+
"S105", # fake tokens and passwords are test data (credentials, adapters for tracker and document services)
|
|
78
|
+
"S106", # same as S105, passed as arguments
|
|
79
|
+
"S603", # subprocess calls with trusted input
|
|
80
|
+
"S607", # partial executable paths (uv, hz) are resolved from PATH on purpose
|
|
81
|
+
"SLF001", # private access is needed for solitary unit tests
|
|
82
|
+
]
|
|
83
|
+
|
|
84
|
+
[tool.ruff.lint.pydocstyle]
|
|
85
|
+
convention = "google"
|
|
86
|
+
|
|
87
|
+
[tool.ruff.format]
|
|
88
|
+
docstring-code-format = true
|
|
89
|
+
|
|
90
|
+
[tool.mypy]
|
|
91
|
+
strict = true
|
|
92
|
+
mypy_path = ["src"]
|
|
93
|
+
files = ["src"]
|
|
94
|
+
plugins = ["pydantic.mypy"]
|
|
95
|
+
|
|
96
|
+
[tool.pydantic-mypy]
|
|
97
|
+
init_forbid_extra = true
|
|
98
|
+
init_typed = true
|
|
99
|
+
warn_required_dynamic_aliases = true
|
|
100
|
+
|
|
101
|
+
[tool.pytest]
|
|
102
|
+
minversion = "9.0"
|
|
103
|
+
strict = true
|
|
104
|
+
testpaths = ["tests"]
|
|
105
|
+
addopts = ["-ra", "--import-mode=importlib"]
|
|
106
|
+
filterwarnings = ["error"]
|
|
107
|
+
markers = ["unit: Offline isolated behavior.", "integration: Offline public-contract integration.", "e2e: Installed artifacts or real external services.", "perf: Explicit timing tests.", "long_running: Extended end-to-end budget."]
|
|
108
|
+
|
|
109
|
+
[tool.coverage.run]
|
|
110
|
+
source = ["heinzel_theme"]
|
|
111
|
+
branch = true
|
|
112
|
+
|
|
113
|
+
[tool.coverage.report]
|
|
114
|
+
fail_under = 90
|
|
115
|
+
show_missing = true
|
|
116
|
+
[build-system]
|
|
117
|
+
requires = ["hatchling>=1.29.0"]
|
|
118
|
+
build-backend = "hatchling.build"
|
|
119
|
+
|
|
120
|
+
[dependency-groups]
|
|
121
|
+
test = ["editables>=0.5", "pytest>=9.0.3,<10", "pytest-timeout>=2.4.0,<3", "pytest-xdist>=3.8", "ruff==0.17.2", "mypy>=1.19.0,<3", "coverage>=7.12", "pyright[nodejs]==1.1.414"]
|
|
122
|
+
|
|
123
|
+
[tool.pyright]
|
|
124
|
+
typeCheckingMode = "strict"
|
|
125
|
+
include = ["src"]
|
|
126
|
+
pythonVersion = "3.12"
|
|
127
|
+
|
|
128
|
+
[tool.hatch.build.targets.sdist]
|
|
129
|
+
exclude = [".venv", ".acceptance", ".preview", "dist", "web/node_modules", "**/__pycache__", ".pytest_cache", ".mypy_cache", ".coverage*"]
|