Compare commits

...

40 commits
v0.4.2 ... main

Author SHA1 Message Date
bronsen
e5bb663ee8 main,database: add debug log stanzas
All checks were successful
ci/woodpecker/push/workflow Pipeline was successful
closes: #7
2026-02-22 20:59:45 +01:00
bronsen
d8101d7c55 models: log incoming and outgoing data with debug logger 2026-02-22 20:42:42 +01:00
bronsen
336eeb7af2 codestyle: add docstrings to helper functions 2026-02-22 20:41:40 +01:00
bronsen
600b211d3c Release version 0.5.3
All checks were successful
ci/woodpecker/push/workflow Pipeline was successful
ci/woodpecker/tag/workflow Pipeline was successful
2026-02-22 20:24:50 +01:00
bronsen
8894a4d321 just: export requirements when building a release
So others do not have to use "uv"
2026-02-22 20:24:37 +01:00
bronsen
ab355ddc06 just: require release notes when releasing
All checks were successful
ci/woodpecker/push/workflow Pipeline was successful
2026-02-22 19:35:22 +01:00
bronsen
2229bc7b05 git: ignore all our releasenotes 2026-02-22 19:30:47 +01:00
bronsen
0bd7080948 Release version 0.5.2
All checks were successful
ci/woodpecker/push/workflow Pipeline was successful
ci/woodpecker/tag/workflow Pipeline was successful
2026-02-22 19:26:27 +01:00
bronsen
278bd4a8ed release: bump version since we have more tests now
All checks were successful
ci/woodpecker/tag/workflow Pipeline was successful
ci/woodpecker/push/workflow Pipeline was successful
re: #14
2026-02-22 19:06:31 +01:00
bronsen
4832a0d69b codestyle: move "statement" out of with block 2026-02-22 19:05:37 +01:00
bronsen
1fdf5cb1d3 codestyle: remove unhelpful type hints 2026-02-22 19:04:46 +01:00
bronsen
aecd10115e tests: ensure helper function actually updates database schema 2026-02-22 18:58:05 +01:00
bronsen
aba919adca tests: separate "engine" from "db with tables" 2026-02-22 18:57:16 +01:00
bronsen
a4df79cda3 tests: ensure we actually commit given data to the database 2026-02-22 18:57:16 +01:00
bronsen
d205f4909e test: ensure we read expected data from database 2026-02-22 18:57:16 +01:00
bronsen
d712c7eead just: exclude snapshot test from coverage
All checks were successful
ci/woodpecker/push/workflow Pipeline was successful
2026-02-22 17:05:45 +01:00
bronsen
98ebb69fa4 release: bump version to 0.5.0
All checks were successful
ci/woodpecker/push/workflow Pipeline was successful
ci/woodpecker/tag/workflow Pipeline was successful
2026-02-22 16:48:31 +01:00
bronsen
f4f2e98c94 tests: update snapshot after changing placeholder text for input field 2026-02-22 16:45:27 +01:00
bronsen
5d10f25c39 main: absorb former tui module's responsibilities 2026-02-22 16:43:07 +01:00
bronsen
db47501cd0 models: we can now store TeilchenCreate data in the database thus creating a new Teilchen
closes #3
2026-02-22 16:41:42 +01:00
bronsen
1b565e5a4e delete tui module
Its code is in main now
2026-02-22 13:04:20 +01:00
bronsen
dd42e6119c just: congregate releated recipes; reuse recipes in "release" 2026-02-22 12:17:34 +01:00
bronsen
84f488f06a prek: we don't have yamls to check 2026-02-22 12:17:12 +01:00
bronsen
3e898d1771 doc: update notes about releasing since the script now works for the most part 2026-02-22 12:09:53 +01:00
bronsen
13239d6f73 prek: never use colors
Otherwise some parts become unreadable on dark backgrounded terminals
2026-02-22 12:09:06 +01:00
bronsen
90388ed48c prek: clean up config file 2026-02-22 12:08:17 +01:00
bronsen
387a6f4e34 just: assign arguments to local fish var, so we don't mix interpolation from just and fish 2026-02-22 11:34:00 +01:00
bronsen
dd79123d7b Release version 0.4.9
Some checks failed
ci/woodpecker/push/workflow Pipeline failed
ci/woodpecker/tag/workflow Pipeline failed
2026-02-22 11:29:10 +01:00
bronsen
eeb3fe8720 Release version 0.4.8
Some checks failed
ci/woodpecker/push/workflow Pipeline failed
ci/woodpecker/tag/workflow Pipeline failed
2026-02-22 11:18:58 +01:00
bronsen
986c7e3544 just: fix paramter for "fj release create" 2026-02-22 11:18:42 +01:00
bronsen
81202c8388 Release version 0.4.7
Some checks failed
ci/woodpecker/push/workflow Pipeline failed
ci/woodpecker/tag/workflow Pipeline failed
2026-02-22 11:16:07 +01:00
bronsen
82978c516c just: rewrite release recipe in fish
closes #13
2026-02-22 11:15:25 +01:00
bronsen
0f18820f46 git: keep releasenotes.md off of version control
It is a transient file
2026-02-22 11:14:09 +01:00
bronsen
60705c87d7 Release version 0.4.6
Some checks failed
ci/woodpecker/push/workflow Pipeline failed
ci/woodpecker/tag/workflow Pipeline failed
2026-02-22 11:06:09 +01:00
bronsen
c7a4c7a411 codestyle: explain why we instantiate the app at module level 2026-02-22 11:04:05 +01:00
bronsen
2de1b3ce0e tui: reword placeholder and tooltip to give hints about expected input format 2026-02-22 11:03:20 +01:00
bronsen
5f26fbc18f Release version 0.4.5
All checks were successful
ci/woodpecker/push/workflow Pipeline was successful
ci/woodpecker/tag/workflow Pipeline was successful
2026-02-21 13:32:01 +01:00
bronsen
2ebf30bec1 just: refine release script
I want to make it a fish script though...
2026-02-21 13:30:02 +01:00
bronsen
6476938f06 Release version 0.4.4
All checks were successful
ci/woodpecker/push/workflow Pipeline was successful
ci/woodpecker/tag/workflow Pipeline was successful
2026-02-21 08:54:45 +01:00
bronsen
005c5c4cb9 Release version 0.4.3
All checks were successful
ci/woodpecker/push/workflow Pipeline was successful
2026-02-21 01:35:14 +01:00
15 changed files with 999 additions and 757 deletions

3
.gitignore vendored
View file

@ -1,3 +1,6 @@
# we create this for the release message
releasenotes.md*
# Created by https://www.toptal.com/developers/gitignore/api/python,vim # Created by https://www.toptal.com/developers/gitignore/api/python,vim
# Edit at https://www.toptal.com/developers/gitignore?templates=python,vim # Edit at https://www.toptal.com/developers/gitignore?templates=python,vim

View file

@ -108,10 +108,8 @@ Please don't: this is my little human-created thing.
Where `segment` is one of: major, minor, patch, stable, alpha, beta, rc, Where `segment` is one of: major, minor, patch, stable, alpha, beta, rc,
post, dev post, dev
* commit * commit
* push commits * When we really really want to release:
* use lazygit to create the new version tag * `just release {Release Name can be several words}`
* remember to prefix it with "v"
* push the tags, using lazygit
---- ----

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Before After
Before After

View file

@ -1,5 +1,9 @@
the_app := "teilchensammler_cli.main" the_app := "teilchensammler_cli.main"
uv_export_options := "--frozen --format requirements.txt --quiet --no-install-project" uv_export_options := "--frozen --format requirements.txt --quiet --no-install-project"
releasenotes := "releasenotes.md"
requirements_file := "requirements.txt"
dev_requirements_file := "requirements.dev.txt"
pyproject := "pyproject.toml"
[private] [private]
default: default:
@ -9,14 +13,6 @@ default:
setup: setup:
uv sync uv sync
# builds a package
build:
uv build --wheel --clear
# upload to Package Registry
upload: build
uv run twine upload --repository code.cbo --config-file ~/.config/pypirc dist/*.whl
# console to observe log messages # console to observe log messages
console: console:
uv run textual console uv run textual console
@ -29,16 +25,16 @@ run-console:
run: run:
uv run python -m {{ the_app }} uv run python -m {{ the_app }}
# export dependencies into requirements files
exports-deps:
uv export {{ uv_export_options }} --output-file requirements.txt
uv export {{ uv_export_options }} --output-file requirements.dev.txt --only-dev
# Update dependencies to new versions # Update dependencies to new versions
update-deps: update-deps:
uv lock --upgrade uv lock --upgrade
uv sync uv sync
# export dependencies into requirements files
exports-deps:
uv export {{ uv_export_options }} --output-file {{ requirements_file }}
uv export {{ uv_export_options }} --output-file {{ dev_requirements_file }} --only-dev
# Run tests, ARGS are passed-through to pytest # Run tests, ARGS are passed-through to pytest
test *ARGS: test *ARGS:
uv run pytest tests.py -m "not final" {{ ARGS }} uv run pytest tests.py -m "not final" {{ ARGS }}
@ -48,33 +44,38 @@ alltests *ARGS:
# run tests and create coverage reports # run tests and create coverage reports
coverage: coverage:
uv run pytest tests.py --cov=src/ --cov-report term --cov-report xml --cov-report html --cov-config pyproject.toml uv run pytest tests.py -m "not final" --cov=src/ --cov-report term --cov-report xml --cov-report html --cov-config {{ pyproject }}
# run python and markdown # lint python, markdown, wheel file names, prek config
lint: lint:
uv run ruff check . uv run ruff check .
markdownlint-cli2 . markdownlint-cli2 .
uv run twine check --strict dist/* uv run twine check --strict dist/*
prek validate-config prek.toml
# pretend we are CI release *release_name:
ci: lint #!/usr/bin/env fish
prek run --all-files test -f {{ releasenotes }}; and set -l body "$(cat {{ releasenotes }})"; or begin echo Release notes are missing!; exit 2; end
# woodpecker-cli exec "whatever" set -l tag (uv version --short --output-format text)
[private] just exports-deps
bump segment: git add {{ pyproject }} uv.lock {{ requirements_file }} {{ dev_requirements_file }}
uv version --bump {{ segment }}
[private]
release segment:
#!/usr/bin/bash
export tag=$(uv version --short --output-format text --frozen --bump {{ segment }})
git add pyproject.toml uv.lock
git commit -m "Release version $tag" git commit -m "Release version $tag"
git tag "v$tag"
git push git push
git tag v$tag git push origin tag "v$tag"
git push origin tag v$tag
just build
fj release create "v$tag: {{ release_name }}" --tag "v$tag" --attach dist/*.whl --body "$body"
just upload
mv {{ releasenotes }} {{ releasenotes }}.$tag
# builds a package
build:
uv build --wheel --clear uv build --wheel --clear
export body=$(cat changelog.md)
fj release create "v$tag" --tag "v$tag" --attach dist/*.whl --body "$body" # upload to Package Registry
uv run twine upload --config-file ~/.config/pypirc --repository code.cbo dist/*.whl upload:
uv run twine upload --repository code.cbo --config-file ~/.config/pypirc dist/*.whl

View file

@ -1,6 +1,7 @@
[env] [env]
'_'.python.venv = { path = ".venv", create = true } '_'.python.venv = { path = ".venv", create = true }
DATABASE_URL = "sqlite:///database.db" DATABASE_URL = "sqlite:///database.db"
PREK_COLOR = "never"
[tools] [tools]
difftastic = "latest" difftastic = "latest"

View file

@ -1,5 +1,7 @@
#:tombi schema.strict = false #:tombi schema.strict = false
# see also: https://prek.j178.dev/builtin/
exclude = { glob = ["__snapshots__/**", "__pycache__", "dist/**"] } exclude = { glob = ["__snapshots__/**", "__pycache__", "dist/**"] }
[[repos]] [[repos]]
@ -7,19 +9,10 @@ repo = "builtin"
hooks = [ hooks = [
{ id = "check-case-conflict" }, { id = "check-case-conflict" },
{ id = "check-merge-conflict" }, { id = "check-merge-conflict" },
{ id = "check-json" },
{ id = "check-symlinks" },
{ id = "check-toml" }, { id = "check-toml" },
{ id = "check-yaml", args = [
# "--allow-multiple-documents", #https://prek.j178.dev/builtin/#check-yaml
] },
{ id = "end-of-file-fixer" }, { id = "end-of-file-fixer" },
{ id = "mixed-line-ending", args = [ { id = "mixed-line-ending", args = [ "--fix=lf" ] },
"--fix=lf", # https://prek.j178.dev/builtin/#mixed-line-ending { id = "trailing-whitespace", args = [ "--markdown-linebreak-ext=md" ] },
] },
{ id = "trailing-whitespace", args = [
"--markdown-linebreak-ext=md", # https://prek.j178.dev/builtin/#trailing-whitespace
] },
] ]
[[repos]] [[repos]]

View file

@ -1,6 +1,6 @@
[project] [project]
name = "teilchensammler-cli" name = "teilchensammler-cli"
version = "0.4.2" version = "0.5.3"
description = "Build up and maintain an inventory of electronics parts and tools." description = "Build up and maintain an inventory of electronics parts and tools."
readme = "README.md" readme = "README.md"
requires-python = ">=3.14,<4.0" requires-python = ">=3.14,<4.0"

View file

@ -1,102 +1,235 @@
# This file was autogenerated by uv via the following command: # This file was autogenerated by uv via the following command:
# uv export --frozen --format requirements.txt --no-install-project --output-file requirements.dev.txt --only-dev # uv export --frozen --format requirements.txt --no-install-project --output-file requirements.dev.txt --only-dev
aiohappyeyeballs==2.6.1 \
--hash=sha256:c3f9d0113123803ccadfdf3f0faa505bc78e6a72d1cc4806cbd719826e943558 \
--hash=sha256:f349ba8f4b75cb25c99c5c2d84e997e485204d2902a9597802b0371f09331fb8
# via aiohttp
aiohttp==3.13.3 \
--hash=sha256:042e9e0bcb5fba81886c8b4fbb9a09d6b8a00245fd8d88e4d989c1f96c74164c \
--hash=sha256:05861afbbec40650d8a07ea324367cb93e9e8cc7762e04dd4405df99fa65159c \
--hash=sha256:0add0900ff220d1d5c5ebbf99ed88b0c1bbf87aa7e4262300ed1376a6b13414f \
--hash=sha256:10b47b7ba335d2e9b1239fa571131a87e2d8ec96b333e68b2a305e7a98b0bae2 \
--hash=sha256:2e41b18a58da1e474a057b3d35248d8320029f61d70a37629535b16a0c8f3767 \
--hash=sha256:2eb752b102b12a76ca02dff751a801f028b4ffbbc478840b473597fc91a9ed43 \
--hash=sha256:2fc82186fadc4a8316768d61f3722c230e2c1dcab4200d52d2ebdf2482e47592 \
--hash=sha256:2fff83cfc93f18f215896e3a190e8e5cb413ce01553901aca925176e7568963a \
--hash=sha256:34749271508078b261c4abb1767d42b8d0c0cc9449c73a4df494777dc55f0687 \
--hash=sha256:34bac00a67a812570d4a460447e1e9e06fae622946955f939051e7cc895cfab8 \
--hash=sha256:3dd4dce1c718e38081c8f35f323209d4c1df7d4db4bab1b5c88a6b4d12b74587 \
--hash=sha256:44531a36aa2264a1860089ffd4dce7baf875ee5a6079d5fb42e261c704ef7344 \
--hash=sha256:48e377758516d262bde50c2584fc6c578af272559c409eecbdd2bae1601184d6 \
--hash=sha256:568f416a4072fbfae453dcf9a99194bbb8bdeab718e08ee13dfa2ba0e4bebf29 \
--hash=sha256:5e1d8c8b8f1d91cd08d8f4a3c2b067bfca6ec043d3ff36de0f3a715feeedf926 \
--hash=sha256:5f8ca7f2bb6ba8348a3614c7918cc4bb73268c5ac2a207576b7afea19d3d9f64 \
--hash=sha256:6fc0e2337d1a4c3e6acafda6a78a39d4c14caea625124817420abceed36e2415 \
--hash=sha256:7b5e8fe4de30df199155baaf64f2fcd604f4c678ed20910db8e2c66dc4b11603 \
--hash=sha256:82611aeec80eb144416956ec85b6ca45a64d76429c1ed46ae1b5f86c6e0c9a26 \
--hash=sha256:8542f41a62bcc58fc7f11cf7c90e0ec324ce44950003feb70640fc2a9092c32a \
--hash=sha256:90455115e5da1c3c51ab619ac57f877da8fd6d73c05aacd125c5ae9819582aba \
--hash=sha256:90751b8eed69435bac9ff4e3d2f6b3af1f57e37ecb0fbeee59c0174c9e2d41df \
--hash=sha256:9bf9f7a65e7aa20dd764151fb3d616c81088f91f8df39c3893a536e279b4b984 \
--hash=sha256:a19884d2ee70b06d9204b2727a7b9f983d0c684c650254679e716b0b77920632 \
--hash=sha256:a1e53262fd202e4b40b70c3aff944a8155059beedc8a89bba9dc1f9ef06a1b56 \
--hash=sha256:a949eee43d3782f2daae4f4a2819b2cb9b0c5d3b7f7a927067cc84dafdbb9f88 \
--hash=sha256:add1da70de90a2569c5e15249ff76a631ccacfe198375eead4aadf3b8dc849dc \
--hash=sha256:b0d95340658b9d2f11d9697f59b3814a9d3bb4b7a7c20b131df4bcef464037c0 \
--hash=sha256:b556c85915d8efaed322bf1bdae9486aa0f3f764195a0fb6ee962e5c71ef5ce1 \
--hash=sha256:b928f30fe49574253644b1ca44b1b8adbd903aa0da4b9054a6c20fc7f4092a25 \
--hash=sha256:bbe7d4cecacb439e2e2a8a1a7b935c25b812af7a5fd26503a66dadf428e79ec1 \
--hash=sha256:c685f2d80bb67ca8c3837823ad76196b3694b0159d232206d1e461d3d434666f \
--hash=sha256:d60ac9663f44168038586cab2157e122e46bdef09e9368b37f2d82d354c23f72 \
--hash=sha256:ea37047c6b367fd4bd632bff8077449b8fa034b69e812a18e0132a00fae6e808 \
--hash=sha256:fc353029f176fd2b3ec6cfc71be166aba1936fe5d73dd1992ce289ca6647a9aa
# via
# aiohttp-jinja2
# textual-dev
# textual-serve
aiohttp-jinja2==1.6 \
--hash=sha256:0df405ee6ad1b58e5a068a105407dc7dcc1704544c559f1938babde954f945c7 \
--hash=sha256:a3a7ff5264e5bca52e8ae547bbfd0761b72495230d438d05b6c0915be619b0e2
# via textual-serve
aiosignal==1.4.0 \
--hash=sha256:053243f8b92b990551949e63930a839ff0cf0b0ebbe0597b0f3fb19e1a0fe82e \
--hash=sha256:f47eecd9468083c2029cc99945502cb7708b082c232f9aca65da147157b251c7
# via aiohttp
asttokens==3.0.1 \ asttokens==3.0.1 \
--hash=sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a \ --hash=sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a \
--hash=sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7 --hash=sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7
# via stack-data # via stack-data
attrs==25.4.0 \
--hash=sha256:16d5969b87f0859ef33a48b35d55ac1be6e42ae49d5e853b597db70c35c57e11 \
--hash=sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373
# via aiohttp
certifi==2026.1.4 \
--hash=sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c \
--hash=sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120
# via requests
cffi==2.0.0 ; platform_machine != 'ppc64le' and platform_machine != 's390x' and platform_python_implementation != 'PyPy' and sys_platform == 'linux' \
--hash=sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b \
--hash=sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592 \
--hash=sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1 \
--hash=sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529 \
--hash=sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4 \
--hash=sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205 \
--hash=sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512 \
--hash=sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c \
--hash=sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775
# via cryptography
charset-normalizer==3.4.4 \
--hash=sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152 \
--hash=sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c \
--hash=sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e \
--hash=sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14 \
--hash=sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828 \
--hash=sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f \
--hash=sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090 \
--hash=sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c \
--hash=sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb \
--hash=sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a \
--hash=sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec \
--hash=sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e \
--hash=sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6 \
--hash=sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191 \
--hash=sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd \
--hash=sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2 \
--hash=sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838 \
--hash=sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9
# via requests
click==8.3.1 \
--hash=sha256:12ff4785d337a1bb490bb7e9c2b1ee5da3112e94a8622f26a6c77f5d2fc6842a \
--hash=sha256:981153a64e25f12d547d3426c367a4857371575ee7ad18df2a6183ab0545b2a6
# via textual-dev
colorama==0.4.6 ; sys_platform == 'win32' \ colorama==0.4.6 ; sys_platform == 'win32' \
--hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \
--hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6
# via # via
# click
# ipython # ipython
# pytest # pytest
coverage==7.13.4 \ coverage==7.13.4 \
--hash=sha256:01d4cbc3c283a17fc1e42d614a119f7f438eabb593391283adca8dc86eff1246 \
--hash=sha256:02231499b08dabbe2b96612993e5fc34217cdae907a51b906ac7fca8027a4459 \
--hash=sha256:0dd7ab8278f0d58a0128ba2fca25824321f05d059c1441800e934ff2efa52129 \ --hash=sha256:0dd7ab8278f0d58a0128ba2fca25824321f05d059c1441800e934ff2efa52129 \
--hash=sha256:0e086334e8537ddd17e5f16a344777c1ab8194986ec533711cbe6c41cde841b6 \ --hash=sha256:0e086334e8537ddd17e5f16a344777c1ab8194986ec533711cbe6c41cde841b6 \
--hash=sha256:14375934243ee05f56c45393fe2ce81fe5cc503c07cee2bdf1725fb8bef3ffaf \ --hash=sha256:14375934243ee05f56c45393fe2ce81fe5cc503c07cee2bdf1725fb8bef3ffaf \
--hash=sha256:1731dc33dc276dafc410a885cbf5992f1ff171393e48a21453b78727d090de80 \
--hash=sha256:1af1641e57cf7ba1bd67d677c9abdbcd6cc2ab7da3bca7fa1e2b7e50e65f2ad0 \ --hash=sha256:1af1641e57cf7ba1bd67d677c9abdbcd6cc2ab7da3bca7fa1e2b7e50e65f2ad0 \
--hash=sha256:1d4be36a5114c499f9f1f9195e95ebf979460dbe2d88e6816ea202010ba1c34b \
--hash=sha256:200dea7d1e8095cc6e98cdabe3fd1d21ab17d3cee6dab00cadbb2fe35d9c15b9 \
--hash=sha256:23e3f687cf945070d1c90f85db66d11e3025665d8dafa831301a0e0038f3db9b \ --hash=sha256:23e3f687cf945070d1c90f85db66d11e3025665d8dafa831301a0e0038f3db9b \
--hash=sha256:245e37f664d89861cf2329c9afa2c1fe9e6d4e1a09d872c947e70718aeeac505 \ --hash=sha256:245e37f664d89861cf2329c9afa2c1fe9e6d4e1a09d872c947e70718aeeac505 \
--hash=sha256:25381386e80ae727608e662474db537d4df1ecd42379b5ba33c84633a2b36d47 \
--hash=sha256:25a41c3104d08edb094d9db0d905ca54d0cd41c928bb6be3c4c799a54753af55 \ --hash=sha256:25a41c3104d08edb094d9db0d905ca54d0cd41c928bb6be3c4c799a54753af55 \
--hash=sha256:29e3220258d682b6226a9b0925bc563ed9a1ebcff3cad30f043eceea7eaf2689 \ --hash=sha256:29e3220258d682b6226a9b0925bc563ed9a1ebcff3cad30f043eceea7eaf2689 \
--hash=sha256:2b0f6ccf3dbe577170bebfce1318707d0e8c3650003cb4b3a9dd744575daa8b5 \ --hash=sha256:2b0f6ccf3dbe577170bebfce1318707d0e8c3650003cb4b3a9dd744575daa8b5 \
--hash=sha256:2c048ea43875fbf8b45d476ad79f179809c590ec7b79e2035c662e7afa3192e3 \
--hash=sha256:2fa8d5f8de70688a28240de9e139fa16b153cc3cbb01c5f16d88d6505ebdadf9 \
--hash=sha256:300deaee342f90696ed186e3a00c71b5b3d27bffe9e827677954f4ee56969601 \ --hash=sha256:300deaee342f90696ed186e3a00c71b5b3d27bffe9e827677954f4ee56969601 \
--hash=sha256:30b8d0512f2dc8c8747557e8fb459d6176a2c9e5731e2b74d311c03b78451997 \
--hash=sha256:3599eb3992d814d23b35c536c28df1a882caa950f8f507cef23d1cbf334995ac \
--hash=sha256:391ee8f19bef69210978363ca930f7328081c6a0152f1166c91f0b5fdd2a773c \ --hash=sha256:391ee8f19bef69210978363ca930f7328081c6a0152f1166c91f0b5fdd2a773c \
--hash=sha256:3c06f0f1337c667b971ca2f975523347e63ec5e500b9aa5882d91931cd3ef750 \ --hash=sha256:3c06f0f1337c667b971ca2f975523347e63ec5e500b9aa5882d91931cd3ef750 \
--hash=sha256:40aa8808140e55dc022b15d8aa7f651b6b3d68b365ea0398f1441e0b04d859c3 \
--hash=sha256:40d74da8e6c4b9ac18b15331c4b5ebc35a17069410cad462ad4f40dcd2d50c0d \
--hash=sha256:4223b4230a376138939a9173f1bdd6521994f2aff8047fae100d6d94d50c5a12 \
--hash=sha256:48685fee12c2eb3b27c62f2658e7ea21e9c3239cba5a8a242801a0a3f6a8c62a \ --hash=sha256:48685fee12c2eb3b27c62f2658e7ea21e9c3239cba5a8a242801a0a3f6a8c62a \
--hash=sha256:4c7d3cc01e7350f2f0f6f7036caaf5673fb56b6998889ccfe9e1c1fe75a9c932 \ --hash=sha256:4c7d3cc01e7350f2f0f6f7036caaf5673fb56b6998889ccfe9e1c1fe75a9c932 \
--hash=sha256:4e83efc079eb39480e6346a15a1bcb3e9b04759c5202d157e1dd4303cd619356 \ --hash=sha256:4e83efc079eb39480e6346a15a1bcb3e9b04759c5202d157e1dd4303cd619356 \
--hash=sha256:53d133df809c743eb8bce33b24bcababb371f4441340578cd406e084d94a6148 \
--hash=sha256:590c0ed4bf8e85f745e6b805b2e1c457b2e33d5255dd9729743165253bc9ad39 \ --hash=sha256:590c0ed4bf8e85f745e6b805b2e1c457b2e33d5255dd9729743165253bc9ad39 \
--hash=sha256:5b856a8ccf749480024ff3bd7310adaef57bf31fd17e1bfc404b7940b6986634 \
--hash=sha256:6f01afcff62bf9a08fb32b2c1d6e924236c0383c02c790732b6537269e466a72 \ --hash=sha256:6f01afcff62bf9a08fb32b2c1d6e924236c0383c02c790732b6537269e466a72 \
--hash=sha256:6fdef321fdfbb30a197efa02d48fcd9981f0d8ad2ae8903ac318adc653f5df98 \ --hash=sha256:6fdef321fdfbb30a197efa02d48fcd9981f0d8ad2ae8903ac318adc653f5df98 \
--hash=sha256:725d985c5ab621268b2edb8e50dfe57633dc69bda071abc470fed55a14935fd3 \ --hash=sha256:725d985c5ab621268b2edb8e50dfe57633dc69bda071abc470fed55a14935fd3 \
--hash=sha256:75eab1ebe4f2f64d9509b984f9314d4aa788540368218b858dad56dc8f3e5eb9 \
--hash=sha256:75fcd519f2a5765db3f0e391eb3b7d150cce1a771bf4c9f861aeab86c767a3c0 \ --hash=sha256:75fcd519f2a5765db3f0e391eb3b7d150cce1a771bf4c9f861aeab86c767a3c0 \
--hash=sha256:76451d1978b95ba6507a039090ba076105c87cc76fc3efd5d35d72093964d49a \
--hash=sha256:78cdf0d578b15148b009ccf18c686aa4f719d887e76e6b40c38ffb61d264a552 \ --hash=sha256:78cdf0d578b15148b009ccf18c686aa4f719d887e76e6b40c38ffb61d264a552 \
--hash=sha256:79be69cf7f3bf9b0deeeb062eab7ac7f36cd4cc4c4dd694bd28921ba4d8596cc \ --hash=sha256:79be69cf7f3bf9b0deeeb062eab7ac7f36cd4cc4c4dd694bd28921ba4d8596cc \
--hash=sha256:7b322db1284a2ed3aa28ffd8ebe3db91c929b7a333c0820abec3d838ef5b3525 \
--hash=sha256:7d41eead3cc673cbd38a4417deb7fd0b4ca26954ff7dc6078e33f6ff97bed940 \
--hash=sha256:7eda778067ad7ffccd23ecffce537dface96212576a07924cbf0d8799d2ded5a \
--hash=sha256:7f57b33491e281e962021de110b451ab8a24182589be17e12a22c79047935e23 \
--hash=sha256:8248977c2e33aecb2ced42fef99f2d319e9904a36e55a8a68b69207fb7e43edc \
--hash=sha256:845f352911777a8e722bfce168958214951e07e47e5d5d9744109fa5fe77f79b \
--hash=sha256:85480adfb35ffc32d40918aad81b89c69c9cc5661a9b8a81476d3e645321a056 \ --hash=sha256:85480adfb35ffc32d40918aad81b89c69c9cc5661a9b8a81476d3e645321a056 \
--hash=sha256:8e798c266c378da2bd819b0677df41ab46d78065fb2a399558f3f6cae78b2fbb \ --hash=sha256:8e798c266c378da2bd819b0677df41ab46d78065fb2a399558f3f6cae78b2fbb \
--hash=sha256:9181a3ccead280b828fae232df12b16652702b49d41e99d657f46cc7b1f6ec7a \
--hash=sha256:9351229c8c8407645840edcc277f4a2d44814d1bc34a2128c11c2a031d45a5dd \
--hash=sha256:93550784d9281e374fb5a12bf1324cc8a963fd63b2d2f223503ef0fd4aa339ea \
--hash=sha256:9401ebc7ef522f01d01d45532c68c5ac40fb27113019b6b7d8b208f6e9baa126 \
--hash=sha256:ad27098a189e5838900ce4c2a99f2fe42a0bf0c2093c17c69b45a71579e8d4a2 \ --hash=sha256:ad27098a189e5838900ce4c2a99f2fe42a0bf0c2093c17c69b45a71579e8d4a2 \
--hash=sha256:ae4578f8528569d3cf303fef2ea569c7f4c4059a38c8667ccef15c6e1f118aa5 \ --hash=sha256:ae4578f8528569d3cf303fef2ea569c7f4c4059a38c8667ccef15c6e1f118aa5 \
--hash=sha256:b1ec7b6b6e93255f952e27ab58fbc68dcc468844b16ecbee881aeb29b6ab4d8d \
--hash=sha256:b66a2da594b6068b48b2692f043f35d4d3693fb639d5ea8b39533c2ad9ac3ab9 \
--hash=sha256:b720ce6a88a2755f7c697c23268ddc47a571b88052e6b155224347389fdf6a3b \
--hash=sha256:b7b38448866e83176e28086674fe7368ab8590e4610fb662b44e345b86d63ffa \
--hash=sha256:b8eb931ee8e6d8243e253e5ed7336deea6904369d2fd8ae6e43f68abbf167092 \
--hash=sha256:bd60d4fe2f6fa7dff9223ca1bbc9f05d2b6697bc5961072e5d3b952d46e1b1ea \
--hash=sha256:c35eb28c1d085eb7d8c9b3296567a1bebe03ce72962e932431b9a61f28facf26 \
--hash=sha256:c4240e7eded42d131a2d2c4dec70374b781b043ddc79a9de4d55ca71f8e98aea \ --hash=sha256:c4240e7eded42d131a2d2c4dec70374b781b043ddc79a9de4d55ca71f8e98aea \
--hash=sha256:caa421e2684e382c5d8973ac55e4f36bed6821a9bad5c953494de960c74595c9 \ --hash=sha256:caa421e2684e382c5d8973ac55e4f36bed6821a9bad5c953494de960c74595c9 \
--hash=sha256:dae88bc0fc77edaa65c14be099bd57ee140cf507e6bfdeea7938457ab387efb0 \
--hash=sha256:de6defc1c9badbf8b9e67ae90fd00519186d6ab64e5cc5f3d21359c2a9b2c1d3 \
--hash=sha256:e5c8f6ed1e61a8b2dcdf31eb0b9bbf0130750ca79c1c49eb898e2ad86f5ccc91 \ --hash=sha256:e5c8f6ed1e61a8b2dcdf31eb0b9bbf0130750ca79c1c49eb898e2ad86f5ccc91 \
--hash=sha256:e6f70dec1cc557e52df5306d051ef56003f74d56e9c4dd7ddb07e07ef32a84dd \
--hash=sha256:e87f6c587c3f34356c3759f0420693e35e7eb0e2e41e4c011cb6ec6ecbbf1db7 \
--hash=sha256:eb30bf180de3f632cd043322dad5751390e5385108b2807368997d1a92a509d0 \ --hash=sha256:eb30bf180de3f632cd043322dad5751390e5385108b2807368997d1a92a509d0 \
--hash=sha256:eb88b316ec33760714a4720feb2816a3a59180fd58c1985012054fa7aebee4c2 \
--hash=sha256:eb9078108fbf0bcdde37c3f4779303673c2fa1fe8f7956e68d447d0dd426d38a \ --hash=sha256:eb9078108fbf0bcdde37c3f4779303673c2fa1fe8f7956e68d447d0dd426d38a \
--hash=sha256:ecae9737b72408d6a950f7e525f30aca12d4bd8dd95e37342e5beb3a2a8c4f71 \ --hash=sha256:ecae9737b72408d6a950f7e525f30aca12d4bd8dd95e37342e5beb3a2a8c4f71
--hash=sha256:ee756f00726693e5ba94d6df2bdfd64d4852d23b09bb0bc700e3b30e6f333985 \
--hash=sha256:f4594c67d8a7c89cf922d9df0438c7c7bb022ad506eddb0fdb2863359ff78242 \
--hash=sha256:f53d492307962561ac7de4cd1de3e363589b000ab69617c6156a16ba7237998d \
--hash=sha256:fb07dc5da7e849e2ad31a5d74e9bece81f30ecf5a42909d0a695f8bd1874d6af \
--hash=sha256:fb26a934946a6afe0e326aebe0730cdff393a8bc0bbb65a2f41e30feddca399c \
--hash=sha256:fdfc1e28e7c7cdce44985b3043bc13bbd9c747520f94a4d7164af8260b3d91f0
# via pytest-cov # via pytest-cov
cryptography==46.0.5 ; platform_machine != 'ppc64le' and platform_machine != 's390x' and sys_platform == 'linux' \
--hash=sha256:039917b0dc418bb9f6edce8a906572d69e74bd330b0b3fea4f79dab7f8ddd235 \
--hash=sha256:1abfdb89b41c3be0365328a410baa9df3ff8a9110fb75e7b52e66803ddabc9a9 \
--hash=sha256:3ce58ba46e1bc2aac4f7d9290223cead56743fa6ab94a5d53292ffaac6a91614 \
--hash=sha256:3ee190460e2fbe447175cda91b88b84ae8322a104fc27766ad09428754a618ed \
--hash=sha256:420d0e909050490d04359e7fdb5ed7e667ca5c3c402b809ae2563d7e66a92229 \
--hash=sha256:4c3341037c136030cb46e4b1e17b7418ea4cbd9dd207e4a6f3b2b24e0d4ac731 \
--hash=sha256:4d7e3d356b8cd4ea5aff04f129d5f66ebdc7b6f8eae802b93739ed520c47c79b \
--hash=sha256:4e817a8920bfbcff8940ecfd60f23d01836408242b30f1a708d93198393a80b4 \
--hash=sha256:50bfb6925eff619c9c023b967d5b77a54e04256c4281b0e21336a130cd7fc263 \
--hash=sha256:582f5fcd2afa31622f317f80426a027f30dc792e9c80ffee87b993200ea115f1 \
--hash=sha256:5be7bf2fb40769e05739dd0046e7b26f9d4670badc7b032d6ce4db64dddc0678 \
--hash=sha256:7d1f30a86d2757199cb2d56e48cce14deddf1f9c95f1ef1b64ee91ea43fe2e18 \
--hash=sha256:7d731d4b107030987fd61a7f8ab512b25b53cef8f233a97379ede116f30eb67d \
--hash=sha256:80a8d7bfdf38f87ca30a5391c0c9ce4ed2926918e017c29ddf643d0ed2778ea1 \
--hash=sha256:890bcb4abd5a2d3f852196437129eb3667d62630333aacc13dfd470fad3aaa82 \
--hash=sha256:9f16fbdf4da055efb21c22d81b89f155f02ba420558db21288b3d0035bafd5f4 \
--hash=sha256:a3d1fae9863299076f05cb8a778c467578262fae09f9dc0ee9b12eb4268ce663 \
--hash=sha256:a3d507bb6a513ca96ba84443226af944b0f7f47dcc9a399d110cd6146481d24c \
--hash=sha256:abace499247268e3757271b2f1e244b36b06f8515cf27c4d49468fc9eb16e93d \
--hash=sha256:ba2a27ff02f48193fc4daeadf8ad2590516fa3d0adeeb34336b96f7fa64c1e3a \
--hash=sha256:c18ff11e86df2e28854939acde2d003f7984f721eba450b56a200ad90eeb0e6b \
--hash=sha256:c4143987a42a2397f2fc3b4d7e3a7d313fbe684f67ff443999e803dd75a76826 \
--hash=sha256:c69fd885df7d089548a42d5ec05be26050ebcd2283d89b3d30676eb32ff87dee \
--hash=sha256:ced80795227d70549a411a4ab66e8ce307899fad2220ce5ab2f296e687eacde9 \
--hash=sha256:d66e421495fdb797610a08f43b05269e0a5ea7f5e652a89bfd5a7d3c1dee3648 \
--hash=sha256:e9251e3be159d1020c4030bd2e5f84d6a43fe54b6c19c12f51cde9542a2817b2 \
--hash=sha256:f145bba11b878005c496e93e257c1e88f154d278d2638e6450d17e0f31e558d2 \
--hash=sha256:fe346b143ff9685e40192a4960938545c699054ba11d4f9029f94751e3f71d87
# via secretstorage
decorator==5.2.1 \ decorator==5.2.1 \
--hash=sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360 \ --hash=sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360 \
--hash=sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a --hash=sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a
# via ipython # via ipython
docutils==0.22.4 \
--hash=sha256:4db53b1fde9abecbb74d91230d32ab626d94f6badfc575d6db9194a49df29968 \
--hash=sha256:d0013f540772d1420576855455d050a2180186c91c15779301ac2ccb3eeb68de
# via readme-renderer
executing==2.2.1 \ executing==2.2.1 \
--hash=sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4 \ --hash=sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4 \
--hash=sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017 --hash=sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017
# via stack-data # via stack-data
frozenlist==1.8.0 \
--hash=sha256:0325024fe97f94c41c08872db482cf8ac4800d80e79222c6b0b7b162d5b13686 \
--hash=sha256:06be8f67f39c8b1dc671f5d83aaefd3358ae5cdcf8314552c57e7ed3e6475bdd \
--hash=sha256:073f8bf8becba60aa931eb3bc420b217bb7d5b8f4750e6f8b3be7f3da85d38b7 \
--hash=sha256:0c18a16eab41e82c295618a77502e17b195883241c563b00f0aa5106fc4eaa0d \
--hash=sha256:102e6314ca4da683dca92e3b1355490fed5f313b768500084fbe6371fddfdb79 \
--hash=sha256:119fb2a1bd47307e899c2fac7f28e85b9a543864df47aa7ec9d3c1b4545f096f \
--hash=sha256:154e55ec0655291b5dd1b8731c637ecdb50975a2ae70c606d100750a540082f7 \
--hash=sha256:168c0969a329b416119507ba30b9ea13688fafffac1b7822802537569a1cb0ef \
--hash=sha256:28bd570e8e189d7f7b001966435f9dac6718324b5be2990ac496cf1ea9ddb7fe \
--hash=sha256:2c5dcbbc55383e5883246d11fd179782a9d07a986c40f49abe89ddf865913930 \
--hash=sha256:2dc43a022e555de94c3b68a4ef0b11c4f747d12c024a520c7101709a2144fb37 \
--hash=sha256:2f05983daecab868a31e1da44462873306d3cbfd76d1f0b5b69c473d21dbb128 \
--hash=sha256:33139dc858c580ea50e7e60a1b0ea003efa1fd42e6ec7fdbad78fff65fad2fd2 \
--hash=sha256:33f48f51a446114bc5d251fb2954ab0164d5be02ad3382abcbfe07e2531d650f \
--hash=sha256:342c97bf697ac5480c0a7ec73cd700ecfa5a8a40ac923bd035484616efecc2df \
--hash=sha256:39ecbc32f1390387d2aa4f5a995e465e9e2f79ba3adcac92d68e3e0afae6657c \
--hash=sha256:3e0761f4d1a44f1d1a47996511752cf3dcec5bbdd9cc2b4fe595caf97754b7a0 \
--hash=sha256:3ede829ed8d842f6cd48fc7081d7a41001a56f1f38603f9d49bf3020d59a31ad \
--hash=sha256:4314debad13beb564b708b4a496020e5306c7333fa9a3ab90374169a20ffab30 \
--hash=sha256:4970ece02dbc8c3a92fcc5228e36a3e933a01a999f7094ff7c23fbd2beeaa67c \
--hash=sha256:54b2077180eb7f83dd52c40b2750d0a9f175e06a42e3213ce047219de902717a \
--hash=sha256:778a11b15673f6f1df23d9586f83c4846c471a8af693a22e066508b77d201ec8 \
--hash=sha256:8009897cdef112072f93a0efdce29cd819e717fd2f649ee3016efd3cd885a7ed \
--hash=sha256:92db2bf818d5cc8d9c1f1fc56b897662e24ea5adb36ad1f1d82875bd64e03c24 \
--hash=sha256:97260ff46b207a82a7567b581ab4190bd4dfa09f4db8a8b49d1a958f6aa4940e \
--hash=sha256:974b28cf63cc99dfb2188d8d222bc6843656188164848c4f679e63dae4b0708e \
--hash=sha256:b2a095d45c5d46e5e79ba1e5b9cb787f541a8dee0433836cea4b96a2c439dcd8 \
--hash=sha256:bac9c42ba2ac65ddc115d930c78d24ab8d4f465fd3fc473cdedfccadb9429806 \
--hash=sha256:cb89a7f2de3602cfed448095bab3f178399646ab7c61454315089787df07733a \
--hash=sha256:cba69cb73723c3f329622e34bdbf5ce1f80c21c290ff04256cff1cd3c2036ed2 \
--hash=sha256:cee686f1f4cadeb2136007ddedd0aaf928ab95216e7691c63e50a8ec066336d0 \
--hash=sha256:d1eaff1d00c7751b7c6662e9c5ba6eb2c17a2306ba5e2a37f24ddf3cc953402b \
--hash=sha256:d3bb933317c52d7ea5004a1c442eef86f426886fba134ef8cf4226ea6ee1821d \
--hash=sha256:eab8145831a0d56ec9c4139b6c3e594c7a83c2c8be25d5bcf2d86136a532287a
# via
# aiohttp
# aiosignal
id==1.6.1 \
--hash=sha256:d0732d624fb46fd4e7bc4e5152f00214450953b9e772c182c1c22964def1a069 \
--hash=sha256:f5ec41ed2629a508f5d0988eda142e190c9c6da971100612c4de9ad9f9b237ca
# via twine
idna==3.11 \
--hash=sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea \
--hash=sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902
# via
# requests
# yarl
iniconfig==2.3.0 \ iniconfig==2.3.0 \
--hash=sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730 \ --hash=sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730 \
--hash=sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12 --hash=sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12
@ -108,14 +241,39 @@ ipython-pygments-lexers==1.1.1 \
--hash=sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81 \ --hash=sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81 \
--hash=sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c --hash=sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c
# via ipython # via ipython
jaraco-classes==3.4.0 ; platform_machine != 'ppc64le' and platform_machine != 's390x' \
--hash=sha256:47a024b51d0239c0dd8c8540c6c7f484be3b8fcf0b2d85c13825780d3b3f3acd \
--hash=sha256:f662826b6bed8cace05e7ff873ce0f9283b5c924470fe664fff1c2f00f581790
# via keyring
jaraco-context==6.1.0 ; platform_machine != 'ppc64le' and platform_machine != 's390x' \
--hash=sha256:129a341b0a85a7db7879e22acd66902fda67882db771754574338898b2d5d86f \
--hash=sha256:a43b5ed85815223d0d3cfdb6d7ca0d2bc8946f28f30b6f3216bda070f68badda
# via keyring
jaraco-functools==4.4.0 ; platform_machine != 'ppc64le' and platform_machine != 's390x' \
--hash=sha256:9eec1e36f45c818d9bf307c8948eb03b2b56cd44087b3cdc989abca1f20b9176 \
--hash=sha256:da21933b0417b89515562656547a77b4931f98176eb173644c0d35032a33d6bb
# via keyring
jedi==0.19.2 \ jedi==0.19.2 \
--hash=sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0 \ --hash=sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0 \
--hash=sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9 --hash=sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9
# via ipython # via ipython
jeepney==0.9.0 ; platform_machine != 'ppc64le' and platform_machine != 's390x' and sys_platform == 'linux' \
--hash=sha256:97e5714520c16fc0a45695e5365a2e11b81ea79bba796e26f9f1d178cb182683 \
--hash=sha256:cf0e9e845622b81e4a28df94c40345400256ec608d0e55bb8a3feaa9163f5732
# via
# keyring
# secretstorage
jinja2==3.1.6 \ jinja2==3.1.6 \
--hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \ --hash=sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d \
--hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67 --hash=sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67
# via pytest-textual-snapshot # via
# aiohttp-jinja2
# pytest-textual-snapshot
# textual-serve
keyring==25.7.0 ; platform_machine != 'ppc64le' and platform_machine != 's390x' \
--hash=sha256:be4a0b195f149690c166e850609a477c532ddbfbaed96a404d4e43f8d5e2689f \
--hash=sha256:fe01bd85eb3f8fb3dd0405defdeac9a5b4f6f0439edbb3149577f244a2e8245b
# via twine
linkify-it-py==2.0.3 \ linkify-it-py==2.0.3 \
--hash=sha256:68cda27e162e9215c17d786649d1da0021a451bdc436ef9e0fa0ba5234b9b048 \ --hash=sha256:68cda27e162e9215c17d786649d1da0021a451bdc436ef9e0fa0ba5234b9b048 \
--hash=sha256:6bcbc417b0ac14323382aef5c5192c0075bf8a9d6b41820a2b66371eac6b6d79 --hash=sha256:6bcbc417b0ac14323382aef5c5192c0075bf8a9d6b41820a2b66371eac6b6d79
@ -130,52 +288,19 @@ markdown-it-py==4.0.0 \
markupsafe==3.0.3 \ markupsafe==3.0.3 \
--hash=sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf \ --hash=sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf \
--hash=sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175 \ --hash=sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175 \
--hash=sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219 \
--hash=sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb \
--hash=sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6 \
--hash=sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab \ --hash=sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab \
--hash=sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce \
--hash=sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218 \
--hash=sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634 \ --hash=sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634 \
--hash=sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73 \
--hash=sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c \
--hash=sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe \ --hash=sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe \
--hash=sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa \ --hash=sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa \
--hash=sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37 \
--hash=sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f \
--hash=sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d \
--hash=sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97 \ --hash=sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97 \
--hash=sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19 \
--hash=sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9 \ --hash=sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9 \
--hash=sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9 \
--hash=sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc \ --hash=sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc \
--hash=sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4 \ --hash=sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4 \
--hash=sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354 \
--hash=sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698 \ --hash=sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698 \
--hash=sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9 \ --hash=sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9 \
--hash=sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b \
--hash=sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc \
--hash=sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485 \
--hash=sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f \
--hash=sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12 \
--hash=sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025 \
--hash=sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009 \
--hash=sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d \ --hash=sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d \
--hash=sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a \
--hash=sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5 \
--hash=sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f \
--hash=sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1 \
--hash=sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287 \
--hash=sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6 \
--hash=sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581 \ --hash=sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581 \
--hash=sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed \
--hash=sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b \
--hash=sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026 \ --hash=sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026 \
--hash=sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676 \
--hash=sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e \
--hash=sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d \
--hash=sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d \
--hash=sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795 \
--hash=sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5 \ --hash=sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5 \
--hash=sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d \ --hash=sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d \
--hash=sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe \ --hash=sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe \
@ -197,10 +322,110 @@ mdurl==0.1.2 \
--hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \
--hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba --hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba
# via markdown-it-py # via markdown-it-py
more-itertools==10.8.0 ; platform_machine != 'ppc64le' and platform_machine != 's390x' \
--hash=sha256:52d4362373dcf7c52546bc4af9a86ee7c4579df9a8dc268be0a2f949d376cc9b \
--hash=sha256:f638ddf8a1a0d134181275fb5d58b086ead7c6a72429ad725c67503f13ba30bd
# via
# jaraco-classes
# jaraco-functools
msgpack==1.1.2 \
--hash=sha256:04fb995247a6e83830b62f0b07bf36540c213f6eac8e851166d8d86d83cbd014 \
--hash=sha256:180759d89a057eab503cf62eeec0aa61c4ea1200dee709f3a8e9397dbb3b6931 \
--hash=sha256:1d1418482b1ee984625d88aa9585db570180c286d942da463533b238b98b812b \
--hash=sha256:3b60763c1373dd60f398488069bcdc703cd08a711477b5d480eecc9f9626f47e \
--hash=sha256:5559d03930d3aa0f3aacb4c42c776af1a2ace2611871c84a75afe436695e6245 \
--hash=sha256:59415c6076b1e30e563eb732e23b994a61c159cec44deaf584e5cc1dd662f2af \
--hash=sha256:5a46bf7e831d09470ad92dff02b8b1ac92175ca36b087f904a0519857c6be3ff \
--hash=sha256:6c15b7d74c939ebe620dd8e559384be806204d73b4f9356320632d783d1f7939 \
--hash=sha256:70c5a7a9fea7f036b716191c29047374c10721c389c21e9ffafad04df8c52c90 \
--hash=sha256:80a0ff7d4abf5fecb995fcf235d4064b9a9a8a40a3ab80999e6ac1e30b702717 \
--hash=sha256:897c478140877e5307760b0ea66e0932738879e7aa68144d9b78ea4c8302a84a \
--hash=sha256:8e22ab046fa7ede9e36eeb4cfad44d46450f37bb05d5ec482b02868f451c95e2 \
--hash=sha256:99e2cb7b9031568a2a5c73aa077180f93dd2e95b4f8d3b8e14a73ae94a9e667e \
--hash=sha256:9ade919fac6a3e7260b7f64cea89df6bec59104987cbea34d34a2fa15d74310b \
--hash=sha256:a668204fa43e6d02f89dbe79a30b0d67238d9ec4c5bd8a940fc3a004a47b721b \
--hash=sha256:d62ce1f483f355f61adb5433ebfd8868c5f078d1a52d042b0a998682b4fa8c27 \
--hash=sha256:d99ef64f349d5ec3293688e91486c5fdb925ed03807f64d98d205d2713c60b46 \
--hash=sha256:e23ce8d5f7aa6ea6d2a2b326b4ba46c985dbb204523759984430db7114f8aa00 \
--hash=sha256:f2cb069d8b981abc72b41aea1c580ce92d57c673ec61af4c500153a626cb9e20
# via textual-dev
multidict==6.7.1 \
--hash=sha256:0458c978acd8e6ea53c81eefaddbbee9c6c5e591f41b3f5e8e194780fe026581 \
--hash=sha256:0e161ddf326db5577c3a4cc2d8648f81456e8a20d40415541587a71620d7a7d1 \
--hash=sha256:14525a5f61d7d0c94b368a42cff4c9a4e7ba2d52e2672a7b23d84dc86fb02b0c \
--hash=sha256:17307b22c217b4cf05033dabefe68255a534d637c6c9b0cc8382718f87be4262 \
--hash=sha256:1e3a8bb24342a8201d178c3b4984c26ba81a577c80d4d525727427460a50c22d \
--hash=sha256:233b398c29d3f1b9676b4b6f75c518a06fcb2ea0b925119fb2c1bc35c05e1601 \
--hash=sha256:283ddac99f7ac25a4acadbf004cb5ae34480bbeb063520f70ce397b281859362 \
--hash=sha256:2bbd113e0d4af5db41d5ebfe9ccaff89de2120578164f86a5d17d5a576d1e5b2 \
--hash=sha256:2e1425e2f99ec5bd36c15a01b690a1a2456209c5deed58f95469ffb46039ccbb \
--hash=sha256:3ab8b9d8b75aef9df299595d5388b14530839f6422333357af1339443cff777d \
--hash=sha256:4885cb0e817aef5d00a2e8451d4665c1808378dc27c2705f1bf4ef8505c0d2e5 \
--hash=sha256:497394b3239fc6f0e13a78a3e1b61296e72bf1c5f94b4c4eb80b265c37a131cd \
--hash=sha256:497bde6223c212ba11d462853cfa4f0ae6ef97465033e7dc9940cdb3ab5b48e5 \
--hash=sha256:538cec1e18c067d0e6103aa9a74f9e832904c957adc260e61cd9d8cf0c3b3d37 \
--hash=sha256:55d97cc6dae627efa6a6e548885712d4864b81110ac76fa4e534c03819fa4a56 \
--hash=sha256:5e01429a929600e7dab7b166062d9bb54a5eed752384c7384c968c2afab8f50f \
--hash=sha256:5fa6a95dfee63893d80a34758cd0e0c118a30b8dcb46372bf75106c591b77889 \
--hash=sha256:6b10359683bd8806a200fd2909e7c8ca3a7b24ec1d8132e483d58e791d881048 \
--hash=sha256:7a7e590ff876a3eaf1c02a4dfe0724b6e69a9e9de6d8f556816f29c496046e59 \
--hash=sha256:7eee46ccb30ff48a1e35bb818cc90846c6be2b68240e42a78599166722cea709 \
--hash=sha256:841189848ba629c3552035a6a7f5bf3b02eb304e9fea7492ca220a8eda6b0e5c \
--hash=sha256:8f333ec9c5eb1b7105e3b84b53141e66ca05a19a605368c55450b6ba208cb9ee \
--hash=sha256:9004d8386d133b7e6135679424c91b0b854d2d164af6ea3f289f8f2761064609 \
--hash=sha256:93b1818e4a6e0930454f0f2af7dfce69307ca03cdcfb3739bf4d91241967b6c1 \
--hash=sha256:97231140a50f5d447d3164f994b86a0bed7cd016e2682f8650d6a9158e14fd31 \
--hash=sha256:98655c737850c064a65e006a3df7c997cd3b220be4ec8fe26215760b9697d4d7 \
--hash=sha256:9f9af11306994335398293f9958071019e3ab95e9a707dc1383a35613f6abcb9 \
--hash=sha256:a0543217a6a017692aa6ae5cc39adb75e587af0f3a82288b1492eb73dd6cc2a4 \
--hash=sha256:a407f13c188f804c759fc6a9f88286a565c242a76b27626594c133b82883b5c2 \
--hash=sha256:b26684587228afed0d50cf804cc71062cc9c1cdf55051c4c6345d372947b268c \
--hash=sha256:b4938326284c4f1224178a560987b6cf8b4d38458b113d9b8c1db1a836e640a2 \
--hash=sha256:c0abd12629b0af3cf590982c0b413b1e7395cd4ec026f30986818ab95bfaa94a \
--hash=sha256:ce1bbd7d780bb5a0da032e095c951f7014d6b0a205f8318308140f1a6aba159e \
--hash=sha256:e628ef0e6859ffd8273c69412a2465c4be4a9517d07261b33334b5ec6f3c7489 \
--hash=sha256:ec6652a1bee61c53a3e5776b6049172c53b6aaba34f18c9ad04f82712bac623d \
--hash=sha256:f33dc2a3abe9249ea5d8360f969ec7f4142e7ac45ee7014d8f8d5acddf178b7b \
--hash=sha256:f99fe611c312b3c1c0ace793f92464d8cd263cc3b26b5721950d977b006b6c4d \
--hash=sha256:fa263a02f4f2dd2d11a7b1bb4362aa7cb1049f84a9235d31adf63f30143469a0
# via
# aiohttp
# yarl
nh3==0.3.3 \
--hash=sha256:0d5eb734a78ac364af1797fef718340a373f626a9ff6b4fb0b4badf7927e7b81 \
--hash=sha256:185ed41b88c910b9ca8edc89ca3b4be688a12cb9de129d84befa2f74a0039fee \
--hash=sha256:1ef87f8e916321a88b45f2d597f29bd56e560ed4568a50f0f1305afab86b7189 \
--hash=sha256:21a63ccb18ddad3f784bb775955839b8b80e347e597726f01e43ca1abcc5c808 \
--hash=sha256:21b058cd20d9f0919421a820a2843fdb5e1749c0bf57a6247ab8f4ba6723c9fc \
--hash=sha256:24769a428e9e971e4ccfb24628f83aaa7dc3c8b41b130c8ddc1835fa1c924489 \
--hash=sha256:2efd17c0355d04d39e6d79122b42662277ac10a17ea48831d90b46e5ef7e4fc0 \
--hash=sha256:3a62b8ae7c235481715055222e54c682422d0495a5c73326807d4e44c5d14691 \
--hash=sha256:45fe0d6a607264910daec30360c8a3b5b1500fd832d21b2da608256287bcb92d \
--hash=sha256:4c730617bdc15d7092dcc0469dc2826b914c8f874996d105b4bc3842a41c1cd9 \
--hash=sha256:52e973cb742e95b9ae1b35822ce23992428750f4b46b619fe86eba4205255b30 \
--hash=sha256:5a4b2c1f3e6f3cbe7048e17f4fefad3f8d3e14cc0fd08fb8599e0d5653f6b181 \
--hash=sha256:5bc1d4b30ba1ba896669d944b6003630592665974bd11a3dc2f661bde92798a7 \
--hash=sha256:90126a834c18af03bfd6ff9a027bfa6bbf0e238527bc780a24de6bd7cc1041e2 \
--hash=sha256:92a958e6f6d0100e025a5686aafd67e3c98eac67495728f8bb64fbeb3e474493 \
--hash=sha256:9ed40cf8449a59a03aa465114fedce1ff7ac52561688811d047917cc878b19ca \
--hash=sha256:a446eae598987f49ee97ac2f18eafcce4e62e7574bd1eb23782e4702e54e217d \
--hash=sha256:b50c3770299fb2a7c1113751501e8878d525d15160a4c05194d7fe62b758aad8 \
--hash=sha256:b7a18ee057761e455d58b9d31445c3e4b2594cff4ddb84d2e331c011ef46f462 \
--hash=sha256:b838e619f483531483d26d889438e53a880510e832d2aafe73f93b7b1ac2bce2 \
--hash=sha256:e8ee96156f7dfc6e30ecda650e480c5ae0a7d38f0c6fafc3c1c655e2500421d9 \
--hash=sha256:e974850b131fdffa75e7ad8e0d9c7a855b96227b093417fdf1bd61656e530f37 \
--hash=sha256:e98fa3dbfd54e25487e36ba500bc29bca3a4cab4ffba18cfb1a35a2d02624297 \
--hash=sha256:f433a2dd66545aad4a720ad1b2150edcdca75bfff6f4e6f378ade1ec138d5e77 \
--hash=sha256:f4400a73c2a62859e769f9d36d1b5a7a5c65c4179d1dddd2f6f3095b2db0cbfc \
--hash=sha256:f508ddd4e2433fdcb78c790fc2d24e3a349ba775e5fa904af89891321d4844a3 \
--hash=sha256:fc305a2264868ec8fa16548296f803d8fd9c1fa66cd28b88b605b1bd06667c0b
# via readme-renderer
packaging==26.0 \ packaging==26.0 \
--hash=sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4 \ --hash=sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4 \
--hash=sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529 --hash=sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529
# via pytest # via
# pytest
# twine
parso==0.8.6 \ parso==0.8.6 \
--hash=sha256:2b9a0332696df97d454fa67b81618fd69c35a7b90327cbe6ba5c92d2c68a7bfd \ --hash=sha256:2b9a0332696df97d454fa67b81618fd69c35a7b90327cbe6ba5c92d2c68a7bfd \
--hash=sha256:2c549f800b70a5c4952197248825584cb00f033b29c692671d3bf08bf380baff --hash=sha256:2c549f800b70a5c4952197248825584cb00f033b29c692671d3bf08bf380baff
@ -223,6 +448,42 @@ prompt-toolkit==3.0.52 \
--hash=sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855 \ --hash=sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855 \
--hash=sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955 --hash=sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955
# via ipython # via ipython
propcache==0.4.1 \
--hash=sha256:005f08e6a0529984491e37d8dbc3dd86f84bd78a8ceb5fa9a021f4c48d4984be \
--hash=sha256:05674a162469f31358c30bcaa8883cb7829fa3110bf9c0991fe27d7896c42d85 \
--hash=sha256:060b16ae65bc098da7f6d25bf359f1f31f688384858204fe5d652979e0015e5b \
--hash=sha256:120c964da3fdc75e3731aa392527136d4ad35868cc556fd09bb6d09172d9a367 \
--hash=sha256:3f7124c9d820ba5548d431afb4632301acf965db49e666aa21c305cbe8c6de12 \
--hash=sha256:49a2dc67c154db2c1463013594c458881a069fcf98940e61a0569016a583020a \
--hash=sha256:4c3c70630930447f9ef1caac7728c8ad1c56bc5015338b20fed0d08ea2480b3a \
--hash=sha256:521a463429ef54143092c11a77e04056dd00636f72e8c45b70aaa3140d639726 \
--hash=sha256:5558992a00dfd54ccbc64a32726a3357ec93825a418a401f5cc67df0ac5d9e49 \
--hash=sha256:55c72fd6ea2da4c318e74ffdf93c4fe4e926051133657459131a95c846d16d44 \
--hash=sha256:5a103c3eb905fcea0ab98be99c3a9a5ab2de60228aa5aceedc614c0281cf6153 \
--hash=sha256:5c3310452e0d31390da9035c348633b43d7e7feb2e37be252be6da45abd1abcc \
--hash=sha256:6f6ff873ed40292cd4969ef5310179afd5db59fdf055897e282485043fc80ad0 \
--hash=sha256:74c1fb26515153e482e00177a1ad654721bf9207da8a494a0c05e797ad27b992 \
--hash=sha256:824e908bce90fb2743bd6b59db36eb4f45cd350a39637c9f73b1c1ea66f5b75f \
--hash=sha256:8326e144341460402713f91df60ade3c999d601e7eb5ff8f6f7862d54de0610d \
--hash=sha256:89eb3fa9524f7bec9de6e83cf3faed9d79bffa560672c118a96a171a6f55831e \
--hash=sha256:8e57061305815dfc910a3634dcf584f08168a8836e6999983569f51a8544cd89 \
--hash=sha256:990f6b3e2a27d683cb7602ed6c86f15ee6b43b1194736f9baaeb93d0016633b1 \
--hash=sha256:9f302f4783709a78240ebc311b793f123328716a60911d667e0c036bc5dcbded \
--hash=sha256:ab2943be7c652f09638800905ee1bab2c544e537edb57d527997a24c13dc1455 \
--hash=sha256:ab4c29b49d560fe48b696cdcb127dd36e0bc2472548f3bf56cc5cb3da2b2984f \
--hash=sha256:af2a6052aeb6cf17d3e46ee169099044fd8224cbaf75c76a2ef596e8163e2237 \
--hash=sha256:c0d4b719b7da33599dfe3b22d3db1ef789210a0597bc650b7cee9c77c2be8c5c \
--hash=sha256:c2b5e7db5328427c57c8e8831abda175421b709672f6cfc3d630c3b7e2146393 \
--hash=sha256:c80ee5802e3fb9ea37938e7eecc307fb984837091d5fd262bb37238b1ae97641 \
--hash=sha256:c9b822a577f560fbd9554812526831712c1436d2c046cedee4c3796d3543b144 \
--hash=sha256:d8f353eb14ee3441ee844ade4277d560cdd68288838673273b978e3d6d2c8f36 \
--hash=sha256:dee69d7015dc235f526fe80a9c90d65eb0039103fe565776250881731f06349f \
--hash=sha256:ecef2343af4cc68e05131e45024ba34f6095821988a9d0a02aa7c73fcc448aa9 \
--hash=sha256:ed5a841e8bb29a55fb8159ed526b26adc5bdd7e8bd7bf793ce647cb08656cdf4 \
--hash=sha256:f48107a8c637e80362555f37ecf49abe20370e557cc4ab374f04ec4423c97c3d
# via
# aiohttp
# yarl
ptyprocess==0.7.0 ; sys_platform != 'emscripten' and sys_platform != 'win32' \ ptyprocess==0.7.0 ; sys_platform != 'emscripten' and sys_platform != 'win32' \
--hash=sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35 \ --hash=sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35 \
--hash=sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220 --hash=sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220
@ -231,6 +492,10 @@ pure-eval==0.2.3 \
--hash=sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0 \ --hash=sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0 \
--hash=sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42 --hash=sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42
# via stack-data # via stack-data
pycparser==3.0 ; implementation_name != 'PyPy' and platform_machine != 'ppc64le' and platform_machine != 's390x' and platform_python_implementation != 'PyPy' and sys_platform == 'linux' \
--hash=sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29 \
--hash=sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992
# via cffi
pygments==2.19.2 \ pygments==2.19.2 \
--hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887 \ --hash=sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887 \
--hash=sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b --hash=sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b
@ -238,6 +503,7 @@ pygments==2.19.2 \
# ipython # ipython
# ipython-pygments-lexers # ipython-pygments-lexers
# pytest # pytest
# readme-renderer
# rich # rich
# textual # textual
pytest==9.0.2 \ pytest==9.0.2 \
@ -257,12 +523,40 @@ pytest-cov==7.0.0 \
pytest-textual-snapshot==1.0.0 \ pytest-textual-snapshot==1.0.0 \
--hash=sha256:065217055ed833b8a16f2320a0613f39a0154e8d9fee63535f29f32c6414b9d7 \ --hash=sha256:065217055ed833b8a16f2320a0613f39a0154e8d9fee63535f29f32c6414b9d7 \
--hash=sha256:dd3a421491a6b1987ee7b4336d7f65299524924d2b0a297e69733b73b01570e1 --hash=sha256:dd3a421491a6b1987ee7b4336d7f65299524924d2b0a297e69733b73b01570e1
pywin32-ctypes==0.2.3 ; platform_machine != 'ppc64le' and platform_machine != 's390x' and sys_platform == 'win32' \
--hash=sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8 \
--hash=sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755
# via keyring
readme-renderer==44.0 \
--hash=sha256:2fbca89b81a08526aadf1357a8c2ae889ec05fb03f5da67f9769c9a592166151 \
--hash=sha256:8712034eabbfa6805cacf1402b4eeb2a73028f72d1166d6f5cb7f9c047c5d1e1
# via twine
requests==2.32.5 \
--hash=sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6 \
--hash=sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf
# via
# requests-toolbelt
# twine
requests-toolbelt==1.0.0 \
--hash=sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6 \
--hash=sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06
# via twine
rfc3986==2.0.0 \
--hash=sha256:50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd \
--hash=sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c
# via twine
rich==14.3.2 \ rich==14.3.2 \
--hash=sha256:08e67c3e90884651da3239ea668222d19bea7b589149d8014a21c633420dbb69 \ --hash=sha256:08e67c3e90884651da3239ea668222d19bea7b589149d8014a21c633420dbb69 \
--hash=sha256:e712f11c1a562a11843306f5ed999475f09ac31ffb64281f73ab29ffdda8b3b8 --hash=sha256:e712f11c1a562a11843306f5ed999475f09ac31ffb64281f73ab29ffdda8b3b8
# via # via
# pytest-textual-snapshot # pytest-textual-snapshot
# textual # textual
# textual-serve
# twine
secretstorage==3.5.0 ; platform_machine != 'ppc64le' and platform_machine != 's390x' and sys_platform == 'linux' \
--hash=sha256:0ce65888c0725fcb2c5bc0fdb8e5438eece02c523557ea40ce0703c266248137 \
--hash=sha256:f04b8e4689cbce351744d5537bf6b1329c6fc68f91fa666f60a380edddcd11be
# via keyring
stack-data==0.6.3 \ stack-data==0.6.3 \
--hash=sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9 \ --hash=sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9 \
--hash=sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695 --hash=sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695
@ -274,24 +568,80 @@ syrupy==5.1.0 \
textual==7.5.0 \ textual==7.5.0 \
--hash=sha256:849dfee9d705eab3b2d07b33152b7bd74fb1f5056e002873cc448bce500c6374 \ --hash=sha256:849dfee9d705eab3b2d07b33152b7bd74fb1f5056e002873cc448bce500c6374 \
--hash=sha256:c730cba1e3d704e8f1ca915b6a3af01451e3bca380114baacf6abf87e9dac8b6 --hash=sha256:c730cba1e3d704e8f1ca915b6a3af01451e3bca380114baacf6abf87e9dac8b6
# via pytest-textual-snapshot # via
# pytest-textual-snapshot
# textual-dev
# textual-serve
textual-dev==1.8.0 \
--hash=sha256:227b6d24a485fbbc77e302aa21f4fdf3083beb57eb45cd95bae082c81cbeddeb \
--hash=sha256:7e56867b0341405a95e938cac0647e6d2763d38d0df08710469ad6b6a8db76df
textual-serve==1.1.3 \
--hash=sha256:207a472bc6604e725b1adab4ab8bf12f4c4dc25b04eea31e4d04731d8bf30f18 \
--hash=sha256:f8f636ae2f5fd651b79d965473c3e9383d3521cdf896f9bc289709185da3f683
# via textual-dev
traitlets==5.14.3 \ traitlets==5.14.3 \
--hash=sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7 \ --hash=sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7 \
--hash=sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f --hash=sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f
# via # via
# ipython # ipython
# matplotlib-inline # matplotlib-inline
twine==6.2.0 \
--hash=sha256:418ebf08ccda9a8caaebe414433b0ba5e25eb5e4a927667122fbe8f829f985d8 \
--hash=sha256:e5ed0d2fd70c9959770dce51c8f39c8945c574e18173a7b81802dab51b4b75cf
typing-extensions==4.15.0 \ typing-extensions==4.15.0 \
--hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \ --hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \
--hash=sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548 --hash=sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548
# via # via
# pytest-asyncio
# textual # textual
# textual-dev
uc-micro-py==1.0.3 \ uc-micro-py==1.0.3 \
--hash=sha256:d321b92cff673ec58027c04015fcaa8bb1e005478643ff4a500882eaab88c48a \ --hash=sha256:d321b92cff673ec58027c04015fcaa8bb1e005478643ff4a500882eaab88c48a \
--hash=sha256:db1dffff340817673d7b466ec86114a9dc0e9d4d9b5ba229d9d60e5c12600cd5 --hash=sha256:db1dffff340817673d7b466ec86114a9dc0e9d4d9b5ba229d9d60e5c12600cd5
# via linkify-it-py # via linkify-it-py
urllib3==2.6.3 \
--hash=sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed \
--hash=sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4
# via
# id
# requests
# twine
wcwidth==0.6.0 \ wcwidth==0.6.0 \
--hash=sha256:1a3a1e510b553315f8e146c54764f4fb6264ffad731b3d78088cdb1478ffbdad \ --hash=sha256:1a3a1e510b553315f8e146c54764f4fb6264ffad731b3d78088cdb1478ffbdad \
--hash=sha256:cdc4e4262d6ef9a1a57e018384cbeb1208d8abbc64176027e2c2455c81313159 --hash=sha256:cdc4e4262d6ef9a1a57e018384cbeb1208d8abbc64176027e2c2455c81313159
# via prompt-toolkit # via prompt-toolkit
yarl==1.22.0 \
--hash=sha256:078a8aefd263f4d4f923a9677b942b445a2be970ca24548a8102689a3a8ab8da \
--hash=sha256:0b5bcc1a9c4839e7e30b7b30dd47fe5e7e44fb7054ec29b5bb8d526aa1041093 \
--hash=sha256:0d6e6885777af0f110b0e5d7e5dda8b704efed3894da26220b7f3d887b839a79 \
--hash=sha256:0dd9a702591ca2e543631c2a017e4a547e38a5c0f29eece37d9097e04a7ac683 \
--hash=sha256:131a085a53bfe839a477c0845acf21efc77457ba2bcf5899618136d64f3303a2 \
--hash=sha256:1380560bdba02b6b6c90de54133c81c9f2a453dee9912fe58c1dcced1edb7cff \
--hash=sha256:1e7ce67c34138a058fd092f67d07a72b8e31ff0c9236e751957465a24b28910c \
--hash=sha256:22b029f2881599e2f1b06f8f1db2ee63bd309e2293ba2d566e008ba12778b8da \
--hash=sha256:334b8721303e61b00019474cc103bdac3d7b1f65e91f0bfedeec2d56dfe74b53 \
--hash=sha256:33e32a0dd0c8205efa8e83d04fc9f19313772b78522d1bdc7d9aed706bfd6138 \
--hash=sha256:34b36c2c57124530884d89d50ed2c1478697ad7473efd59cfd479945c95650e4 \
--hash=sha256:45c2842ff0e0d1b35a6bf1cd6c690939dacb617a70827f715232b2e0494d55d1 \
--hash=sha256:4792b262d585ff0dff6bcb787f8492e40698443ec982a3568c2096433660c694 \
--hash=sha256:594fcab1032e2d2cc3321bb2e51271e7cd2b516c7d9aee780ece81b07ff8244b \
--hash=sha256:68986a61557d37bb90d3051a45b91fa3d5c516d177dfc6dd6f2f436a07ff2b6b \
--hash=sha256:6a635ea45ba4ea8238463b4f7d0e721bad669f80878b7bfd1f89266e2ae63da2 \
--hash=sha256:8009b3173bcd637be650922ac455946197d858b3630b6d8787aa9e5c4564533e \
--hash=sha256:8218f4e98d3c10d683584cb40f0424f4b9fd6e95610232dd75e13743b070ee33 \
--hash=sha256:852863707010316c973162e703bddabec35e8757e67fcb8ad58829de1ebc8590 \
--hash=sha256:9f6d73c1436b934e3f01df1e1b21ff765cd1d28c77dfb9ace207f746d4610ee1 \
--hash=sha256:9fb17ea16e972c63d25d4a97f016d235c78dd2344820eb35bc034bc32012ee27 \
--hash=sha256:bca03b91c323036913993ff5c738d0842fc9c60c4648e5c8d98331526df89784 \
--hash=sha256:bebf8557577d4401ba8bd9ff33906f1376c877aa78d1fe216ad01b4d6745af71 \
--hash=sha256:bf4a21e58b9cde0e401e683ebd00f6ed30a06d14e93f7c8fd059f8b6e8f87b6a \
--hash=sha256:c0232bce2170103ec23c454e54a57008a9a72b5d1c3105dc2496750da8cfa47c \
--hash=sha256:c4647674b6150d2cae088fc07de2738a84b8bcedebef29802cf0b0a82ab6face \
--hash=sha256:d77e1b2c6d04711478cb1c4ab90db07f1609ccf06a287d5607fcd90dc9863acf \
--hash=sha256:d947071e6ebcf2e2bee8fce76e10faca8f7a14808ca36a910263acaacef08eca \
--hash=sha256:e4b582bab49ac33c8deb97e058cd67c2c50dac0dd134874106d9c774fd272529 \
--hash=sha256:e51ac5435758ba97ad69617e13233da53908beccc6cfcd6c34bbed8dcbede486 \
--hash=sha256:ebd4549b108d732dba1d4ace67614b9545b21ece30937a63a65dd34efa19732d \
--hash=sha256:efb07073be061c8f79d03d04139a80ba33cbd390ca8f0297aae9cce6411e4c6b \
--hash=sha256:f3d7a87a78d46a2e3d5b72587ac14b4c16952dd0887dbb051451eceac774411e \
--hash=sha256:f87ac53513d22240c7d59203f25cc3beac1e574c6cd681bbfd321987b69f95fd
# via aiohttp

File diff suppressed because it is too large Load diff

View file

@ -1,10 +1,14 @@
import os import os
from sqlmodel import SQLModel, create_engine from sqlmodel import SQLModel, create_engine
import logging
logger = logging.getLogger(__name__)
sqlite_url = os.environ.get("DATABASE_URL", "sqlite:///database.db") sqlite_url = os.environ.get("DATABASE_URL", "sqlite:///database.db")
engine = create_engine(sqlite_url, echo=False) engine = create_engine(sqlite_url, echo=False)
def create_db_and_tables(): def create_db_and_tables(engine):
SQLModel.metadata.create_all(engine) SQLModel.metadata.create_all(engine)
logger.debug("Created tables, if not already present")

View file

@ -4,25 +4,98 @@ This is where the application is implemented.
import logging import logging
from textual.app import App from textual import on
from textual.app import App, ComposeResult
from textual.containers import HorizontalGroup
from textual.logging import TextualHandler from textual.logging import TextualHandler
from textual.screen import Screen
from textual.widget import Widget
from textual.widgets import Button, DataTable, Footer, Header, Input, Static
from .database import create_db_and_tables from .database import create_db_and_tables, engine
from .tui import AddInventoryScreen from .models import add_to_database, load_initial_data, make_teilchen_input
# Make it so that log messages go to Textual; we should be able to then see
# these in the console
logging.basicConfig( logging.basicConfig(
level="NOTSET", level="NOTSET",
handlers=[TextualHandler()], handlers=[TextualHandler()],
) )
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
TEILCHEN_DATA_HEADER = "pk Name Description Number Tags".split()
class SammlerApp(App): class SammlerApp(App):
async def on_mount(self) -> None: async def on_mount(self) -> None:
create_db_and_tables() create_db_and_tables(engine)
_ = self.push_screen(AddInventoryScreen()) self.push_screen(AddInventoryScreen())
class SearchBar(Static):
DEFAULT_CSS = """
#teilchen-input {
width: 4fr;
}
#button-search, #button-add {
width: 1fr;
}
"""
def compose(self) -> ComposeResult:
with HorizontalGroup(id="search-bar-widget"):
yield Input(
placeholder='This is a name. "This is the description" #these #are #tags',
tooltip=(
"Enter a name followed by a period, then a description "
'enclosed in double quotes ("). You should use #hashtags for any meta information. '
"Hashtags can be placed anywhere."
),
id="teilchen-input",
type="text",
)
yield Button("Add", variant="success", classes="search-bar-buttons", id="button-add")
yield Button(
"Search",
variant="default",
classes="search-bar-buttons",
id="button-search",
)
@on(Input.Submitted)
async def parse_input(self, event: Input.Submitted) -> None:
if not (tc := await make_teilchen_input(event.value)):
logger.debug("could not create TeilchenCreate from data: %s", event.value)
return
event.input.value = ""
teilchen = await add_to_database(tc, engine)
self.screen.query_one(DataTable).add_row(
teilchen.id, teilchen.name, teilchen.description, teilchen.number, teilchen.tags
)
class SearchResults(Widget):
def compose(self) -> ComposeResult:
yield DataTable(id="table-search-result", cursor_type="row", zebra_stripes=True)
async def on_mount(self) -> None:
table: DataTable = self.query_one(DataTable)
table.add_columns(*TEILCHEN_DATA_HEADER)
table.add_rows(await load_initial_data(engine))
class AddInventoryScreen(Screen):
def compose(self) -> ComposeResult:
yield Header()
yield SearchBar()
yield SearchResults()
yield Footer()
# so we can import it without running it
app = SammlerApp() app = SammlerApp()

View file

@ -3,12 +3,13 @@ import uuid
from sqlmodel import ( from sqlmodel import (
Field, Field,
SQLModel,
Session,
select,
Sequence, Sequence,
Session,
SQLModel,
select,
) )
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -35,6 +36,7 @@ async def make_teilchen_input(text: str) -> TeilchenCreate | None:
Returns `None` otherwise. Returns `None` otherwise.
""" """
import re import re
from natsort import natsorted from natsort import natsorted
text = text.strip() text = text.strip()
@ -79,12 +81,41 @@ async def make_teilchen_input(text: str) -> TeilchenCreate | None:
return teilchen return teilchen
async def load_initial_data() -> Sequence[Teilchen]: async def load_initial_data(engine) -> Sequence[Teilchen]:
from .database import engine """Retrieve all Teilchen records from the database.
Args:
engine (sqlalchemy.Engine): the engine or connection or whatever
Returns:
List of Teilchen, potentially empty
"""
with Session(engine) as session: with Session(engine) as session:
statement = select( statement = select(
Teilchen.id, Teilchen.name, Teilchen.description, Teilchen.number, Teilchen.tags Teilchen.id, Teilchen.name, Teilchen.description, Teilchen.number, Teilchen.tags
) # ty:ignore[no-matching-overload] ) # ty:ignore[no-matching-overload]
all_teilchen = session.exec(statement).all() all_teilchen = session.exec(statement).all()
logger.debug("Loading initial data: found %s records", len(all_teilchen))
return all_teilchen return all_teilchen
async def add_to_database(tc: TeilchenCreate, engine) -> Teilchen:
"""Add given data as a new record into the database.
Args:
engine (sqlalchemy.Engine): the engine or connection or whatever
tc: Teilchen data (no `id` yet)
Returns:
The newly created Teilchen (this time with `id`)
"""
logger.debug("received: %s", str(tc))
with Session(engine) as session:
teilchen = Teilchen.model_validate(tc)
session.add(teilchen)
session.commit()
session.refresh(teilchen)
logger.debug("created: %s", str(teilchen))
return teilchen

View file

@ -1,59 +0,0 @@
from textual.app import ComposeResult
from textual.containers import HorizontalGroup
from textual.screen import Screen
from textual.widget import Widget
from textual.widgets import Button, DataTable, Footer, Header, Input, Static
from .models import load_initial_data
TEILCHEN_DATA_HEADER = "pk Name Description Number Tags".split()
class SearchBar(Static):
DEFAULT_CSS = """
#teilchen-input {
width: 4fr;
}
#button-search, #button-add {
width: 1fr;
}
"""
def compose(self) -> ComposeResult:
with HorizontalGroup(id="search-bar-widget"):
yield Input(
placeholder="Enter Teilchen information: name, description, #tags",
tooltip=(
"This is a free-form field: Enter a name and "
"description any way you like. You should use #hashtags for any "
"meta information."
),
id="teilchen-input",
type="text",
)
yield Button("Add", variant="success", classes="search-bar-buttons", id="button-add")
yield Button(
"Search",
variant="default",
classes="search-bar-buttons",
id="button-search",
)
class SearchResults(Widget):
def compose(self) -> ComposeResult:
yield DataTable(id="table-search-result", cursor_type="row", zebra_stripes=True)
async def on_mount(self) -> None:
table: DataTable = self.query_one(DataTable)
table.add_columns(*TEILCHEN_DATA_HEADER)
table.add_rows(await load_initial_data())
class AddInventoryScreen(Screen):
def compose(self) -> ComposeResult:
yield Header()
yield SearchBar()
yield SearchResults()
yield Footer()

119
tests.py
View file

@ -1,6 +1,19 @@
import pytest from teilchensammler_cli.database import create_db_and_tables
from sqlalchemy.sql import text
import uuid
from typing import Generator
from teilchensammler_cli.models import TeilchenCreate, make_teilchen_input import pytest
from sqlalchemy import Engine
from sqlmodel import Session, SQLModel, create_engine
from teilchensammler_cli.models import (
Teilchen,
TeilchenCreate,
add_to_database,
load_initial_data,
make_teilchen_input,
)
@pytest.mark.final # don't run while we are fiddling with the app @pytest.mark.final # don't run while we are fiddling with the app
@ -10,7 +23,7 @@ def test_initial_layout(snap_compare):
assert snap_compare(app, terminal_size=(130, 40)) assert snap_compare(app, terminal_size=(130, 40))
empty_teilchen = { empty_teilchen_data = {
"name": "", "name": "",
"description": "", "description": "",
"tags": "", "tags": "",
@ -32,7 +45,7 @@ def TC(**kwargs) -> TeilchenCreate | None:
- an instance of `TeilchenCreate` - an instance of `TeilchenCreate`
""" """
if kwargs: if kwargs:
arguments = empty_teilchen | kwargs arguments = empty_teilchen_data | kwargs
return TeilchenCreate(**arguments) # ty:ignore[invalid-argument-type] return TeilchenCreate(**arguments) # ty:ignore[invalid-argument-type]
@ -46,11 +59,15 @@ def TC(**kwargs) -> TeilchenCreate | None:
(".a.", TC()), (".a.", TC()),
("a", TC()), ("a", TC()),
("aa", TC()), ("aa", TC()),
(" .", TC()), # still an empty string
# Just enough for "name" # Just enough for "name"
("a.", TC(name="a", text="a.")), ("a.", TC(name="a", text="a.")),
("aa.", TC(name="aa", text="aa.")), ("aa.", TC(name="aa", text="aa.")),
("a..", TC(name="a", text="a..")), ("a..", TC(name="a", text="a..")),
("a.b.", TC(name="a", text="a.b.")), ("a.b.", TC(name="a", text="a.b.")),
("1.", TC(name="1", text="1.")), # numbers can be names
("_.", TC(name="_", text="_.")), # underscores can be names
("a b.", TC(name="a b", text="a b.")), # names can contain spaces
# Just enough for "name" and "description" # Just enough for "name" and "description"
('a."b"', TC(name="a", description="b", text='a."b"')), ('a."b"', TC(name="a", description="b", text='a."b"')),
('a. "b"', TC(name="a", description="b", text='a. "b"')), ('a. "b"', TC(name="a", description="b", text='a. "b"')),
@ -68,6 +85,7 @@ def TC(**kwargs) -> TeilchenCreate | None:
("a. ##b", TC(name="a", description="", tags="#b", text="a. ##b")), ("a. ##b", TC(name="a", description="", tags="#b", text="a. ##b")),
("a. #", TC(name="a", description="", tags="", text="a. #")), ("a. #", TC(name="a", description="", tags="", text="a. #")),
("a. ##", TC(name="a", description="", tags="", text="a. ##")), ("a. ##", TC(name="a", description="", tags="", text="a. ##")),
("a. #tag with spaces", TC(name="a", tags="#tag", text="a. #tag with spaces")),
# do we care about "number"? # do we care about "number"?
], ],
) )
@ -78,3 +96,96 @@ async def test_maketeilcheninput_can_create_desired_teilchen(
actual = await make_teilchen_input(example_input) actual = await make_teilchen_input(example_input)
assert expected == actual assert expected == actual
@pytest.fixture(name="engine")
def in_memory_db() -> Generator[Engine]:
"""Creates an in-memory sqlite database
Yields:
The engine used to create the database.
"""
engine = create_engine("sqlite:///:memory:")
yield engine
engine.dispose()
@pytest.fixture(name="app_db")
def database_ready_to_use(engine: Engine) -> Generator[Engine]:
SQLModel.metadata.create_all(engine)
yield engine
@pytest.fixture(name="db_teilchen")
def teilchen_in_db(app_db: Engine) -> Generator[Teilchen]:
"""Creates a new Teilchen and stores it in the database.
Args:
engine: an instance of sqlalchemy.Engine which was used to create the database.
Yields:
The Teilchen refreshed from the database.
"""
import uuid
teilchen = Teilchen(
id=uuid.uuid7(), name="TT", description="Test Teilchen", number=1, tags="", text=""
)
with Session(app_db) as session:
session.add(teilchen)
session.commit()
session.refresh(teilchen)
yield teilchen
with Session(app_db) as session:
session.delete(teilchen)
session.commit()
async def test_loadinitialdata_returns_expected_data(app_db: Engine, db_teilchen: Teilchen):
all_data = await load_initial_data(app_db)
assert len(all_data) == 1
fetched_data: tuple = all_data[0]
teilchen_data: dict[str, str | int] = {
"id": fetched_data[0],
"name": fetched_data[1],
"description": fetched_data[2],
"number": 1,
"tags": "",
"text": "",
}
fetched_teilchen = Teilchen.model_validate(teilchen_data)
assert fetched_teilchen == db_teilchen
async def test_data_provided_to_addtodatabase_ends_up_in_database(app_db: Engine):
all_data = await load_initial_data(app_db)
assert len(all_data) == 0
teilchen = Teilchen(
id=uuid.uuid7(), name="test", description="test", tags="#test", number=1, text="test"
)
db_teilchen = await add_to_database(teilchen, app_db)
assert teilchen == db_teilchen
async def test_created_database_contains_expected_tables(engine: Engine):
statement = text("SELECT name from sqlite_schema WHERE type = 'table'")
with engine.connect() as connection:
results = connection.execute(statement).all()
assert len(results) == 0
create_db_and_tables(engine)
results = connection.execute(statement).all()
assert len(results) == 1

2
uv.lock generated
View file

@ -1153,7 +1153,7 @@ wheels = [
[[package]] [[package]]
name = "teilchensammler-cli" name = "teilchensammler-cli"
version = "0.4.1" version = "0.5.3"
source = { editable = "." } source = { editable = "." }
dependencies = [ dependencies = [
{ name = "ciso8601" }, { name = "ciso8601" },