From c3d5983d239503f85cca38fe6e037df25386ff9e Mon Sep 17 00:00:00 2001 From: bronsen Date: Wed, 18 Feb 2026 18:23:38 +0100 Subject: [PATCH 1/8] codestyle: remove assignment to `_`: we no longer need to quieten the LSP --- src/teilchensammler_cli/tui.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/teilchensammler_cli/tui.py b/src/teilchensammler_cli/tui.py index 37c44f9..03716c9 100644 --- a/src/teilchensammler_cli/tui.py +++ b/src/teilchensammler_cli/tui.py @@ -7,7 +7,7 @@ from textual.widgets import Button, DataTable, Footer, Header, Input, Static from .models import load_initial_data -FAKE_DATA_HEADER = "pk Name Description Number Tags".split() +TEILCHEN_DATA_HEADER = "pk Name Description Number Tags".split() class SearchBar(Static): @@ -46,9 +46,9 @@ class SearchResults(Widget): yield DataTable(id="table-search-result", cursor_type="row", zebra_stripes=True) async def on_mount(self) -> None: - table: DataTable[None] = self.query_one(DataTable[None]) - _ = table.add_columns(*FAKE_DATA_HEADER) - _ = table.add_rows(await load_initial_data()) + table: DataTable = self.query_one(DataTable) + table.add_columns(*TEILCHEN_DATA_HEADER) + table.add_rows(await load_initial_data()) class AddInventoryScreen(Screen[None]): From eb51024ca0288795eb1998c1caad3e93aa3cd940 Mon Sep 17 00:00:00 2001 From: bronsen Date: Wed, 18 Feb 2026 20:40:17 +0100 Subject: [PATCH 2/8] database: inhibit echoing to console This interferes very much with the app. --- src/teilchensammler_cli/database.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/teilchensammler_cli/database.py b/src/teilchensammler_cli/database.py index e226215..b58456b 100644 --- a/src/teilchensammler_cli/database.py +++ b/src/teilchensammler_cli/database.py @@ -3,7 +3,7 @@ from sqlmodel import SQLModel, create_engine sqlite_url = os.environ.get("DATABASE_URL", "sqlite:///database.db") -engine = create_engine(sqlite_url, echo=True) +engine = create_engine(sqlite_url, echo=False) def create_db_and_tables(): From b0e7089389921dbf2f550723a7507acc54808b7e Mon Sep 17 00:00:00 2001 From: bronsen Date: Wed, 18 Feb 2026 20:40:58 +0100 Subject: [PATCH 3/8] codestyle: ty needs less hinting --- src/teilchensammler_cli/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/teilchensammler_cli/main.py b/src/teilchensammler_cli/main.py index c1706ef..4b0364b 100644 --- a/src/teilchensammler_cli/main.py +++ b/src/teilchensammler_cli/main.py @@ -17,7 +17,7 @@ logging.basicConfig( logger = logging.getLogger(__name__) -class SammlerApp(App[None]): +class SammlerApp(App): async def on_mount(self) -> None: create_db_and_tables() _ = self.push_screen(AddInventoryScreen()) From 0ae116afa9049b8a2e8e139ff55b7d0181cf5735 Mon Sep 17 00:00:00 2001 From: bronsen Date: Thu, 19 Feb 2026 20:38:29 +0100 Subject: [PATCH 4/8] tests: finally another test! --- tests.py | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/tests.py b/tests.py index 521a238..0b547c6 100644 --- a/tests.py +++ b/tests.py @@ -1,4 +1,54 @@ +from typing import TypedDict +import pytest +import logging + +from teilchensammler_cli.models import TeilchenCreate, make_teilchen_input + +logger = logging.getLogger(__name__) + + def test_initial_layout(snap_compare): from teilchensammler_cli.main import app assert snap_compare(app, terminal_size=(130, 40)) + + +class Teilchen(TypedDict): + """The things I do for my LSP...""" + + name: str + description: str + tags: str + text: str + number: int + + +empty_teilchen: Teilchen = { + "name": "", + "description": "", + "tags": "", + "text": "", + "number": 1, +} + + +@pytest.mark.parametrize( + "example_input,expected", + [ + ("", None), + ("a", None), + ("a.", {"name": "a", "text": "a."}), + ("aa", None), + ("aa.", {"name": "aa", "text": "aa."}), + ], +) +async def test_teilchendata_must_include_period( + example_input: str, expected: dict[str, str | int] | None +) -> None: + + thing = expected + if expected: + arguments = empty_teilchen | expected + thing = TeilchenCreate(**arguments) # ty:ignore[invalid-argument-type] + + assert await make_teilchen_input(example_input) == thing From 49a21ca9cf9c02f9bebe3f15ae3372b2b986415f Mon Sep 17 00:00:00 2001 From: bronsen Date: Thu, 19 Feb 2026 20:42:50 +0100 Subject: [PATCH 5/8] models: be even more defensive when parsing input also we finally read the documentation for str.find() https://docs.python.org/3/library/stdtypes.html#str.find --- src/teilchensammler_cli/models.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/teilchensammler_cli/models.py b/src/teilchensammler_cli/models.py index 86233f4..134c648 100644 --- a/src/teilchensammler_cli/models.py +++ b/src/teilchensammler_cli/models.py @@ -37,12 +37,20 @@ async def make_teilchen_input(text: str) -> TeilchenCreate | None: import re from natsort import natsorted + text = text.strip() + if not text: logger.error("Empty text.") return None name_end = text.find(".") - name = text[0:name_end] + if name_end == -1: # "." not in text + logger.warning("Missing period '.' from text.") + logger.debug("Could not find period symbol in input: %s", text) + return None + else: + name = text[0:name_end] + if not name: logger.error("Could not extract name.") logger.debug("Could not extract name from input: %s", text) From 9b04902825872eecc38118828deb838eec0ad4cb Mon Sep 17 00:00:00 2001 From: bronsen Date: Thu, 19 Feb 2026 20:44:18 +0100 Subject: [PATCH 6/8] models: it's not an error if we can continue operating --- src/teilchensammler_cli/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/teilchensammler_cli/models.py b/src/teilchensammler_cli/models.py index 134c648..f72650e 100644 --- a/src/teilchensammler_cli/models.py +++ b/src/teilchensammler_cli/models.py @@ -52,7 +52,7 @@ async def make_teilchen_input(text: str) -> TeilchenCreate | None: name = text[0:name_end] if not name: - logger.error("Could not extract name.") + logger.warning("Could not extract name.") logger.debug("Could not extract name from input: %s", text) return None From c3b749ec37ff3f93c4d0e685946f6e474a1688e8 Mon Sep 17 00:00:00 2001 From: bronsen Date: Thu, 19 Feb 2026 20:44:56 +0100 Subject: [PATCH 7/8] codestyle: ty needs less help here too --- src/teilchensammler_cli/tui.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/teilchensammler_cli/tui.py b/src/teilchensammler_cli/tui.py index 03716c9..87ffa62 100644 --- a/src/teilchensammler_cli/tui.py +++ b/src/teilchensammler_cli/tui.py @@ -51,7 +51,7 @@ class SearchResults(Widget): table.add_rows(await load_initial_data()) -class AddInventoryScreen(Screen[None]): +class AddInventoryScreen(Screen): def compose(self) -> ComposeResult: yield Header() yield SearchBar() From f41f8e28e504d4976b5b5255f7bb3dcd191c33e2 Mon Sep 17 00:00:00 2001 From: bronsen Date: Thu, 19 Feb 2026 20:49:09 +0100 Subject: [PATCH 8/8] release: bump version to 0.3.3 --- pyproject.toml | 2 +- uv.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index bd6e26c..d170fad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "teilchensammler-cli" -version = "0.3.2" +version = "0.3.3" description = "Build up and maintain an inventory of electronics parts and tools." readme = "README.md" requires-python = ">=3.12,<4.0" diff --git a/uv.lock b/uv.lock index 73025de..015d5a5 100644 --- a/uv.lock +++ b/uv.lock @@ -1249,7 +1249,7 @@ wheels = [ [[package]] name = "teilchensammler-cli" -version = "0.3.2" +version = "0.3.3" source = { editable = "." } dependencies = [ { name = "ciso8601" },