···11+# Byte-compiled / optimized / DLL files
22+__pycache__/
33+*.py[codz]
44+*$py.class
55+66+# C extensions
77+*.so
88+99+# Distribution / packaging
1010+.Python
1111+build/
1212+develop-eggs/
1313+dist/
1414+downloads/
1515+eggs/
1616+.eggs/
1717+lib/
1818+lib64/
1919+parts/
2020+sdist/
2121+var/
2222+wheels/
2323+share/python-wheels/
2424+*.egg-info/
2525+.installed.cfg
2626+*.egg
2727+MANIFEST
2828+2929+# PyInstaller
3030+# Usually these files are written by a python script from a template
3131+# before PyInstaller builds the exe, so as to inject date/other infos into it.
3232+*.manifest
3333+*.spec
3434+3535+# Installer logs
3636+pip-log.txt
3737+pip-delete-this-directory.txt
3838+3939+# Unit test / coverage reports
4040+htmlcov/
4141+.tox/
4242+.nox/
4343+.coverage
4444+.coverage.*
4545+.cache
4646+nosetests.xml
4747+coverage.xml
4848+*.cover
4949+*.py.cover
5050+.hypothesis/
5151+.pytest_cache/
5252+cover/
5353+5454+# Translations
5555+*.mo
5656+*.pot
5757+5858+# Django stuff:
5959+*.log
6060+local_settings.py
6161+db.sqlite3
6262+db.sqlite3-journal
6363+6464+# Flask stuff:
6565+instance/
6666+.webassets-cache
6767+6868+# Scrapy stuff:
6969+.scrapy
7070+7171+# Sphinx documentation
7272+docs/_build/
7373+7474+# PyBuilder
7575+.pybuilder/
7676+target/
7777+7878+# Jupyter Notebook
7979+.ipynb_checkpoints
8080+8181+# IPython
8282+profile_default/
8383+ipython_config.py
8484+8585+# pyenv
8686+# For a library or package, you might want to ignore these files since the code is
8787+# intended to run in multiple environments; otherwise, check them in:
8888+# .python-version
8989+9090+# pipenv
9191+# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
9292+# However, in case of collaboration, if having platform-specific dependencies or dependencies
9393+# having no cross-platform support, pipenv may install dependencies that don't work, or not
9494+# install all needed dependencies.
9595+#Pipfile.lock
9696+9797+# UV
9898+# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
9999+# This is especially recommended for binary packages to ensure reproducibility, and is more
100100+# commonly ignored for libraries.
101101+#uv.lock
102102+103103+# poetry
104104+# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105105+# This is especially recommended for binary packages to ensure reproducibility, and is more
106106+# commonly ignored for libraries.
107107+# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108108+#poetry.lock
109109+#poetry.toml
110110+111111+# pdm
112112+# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
113113+# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
114114+# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
115115+#pdm.lock
116116+#pdm.toml
117117+.pdm-python
118118+.pdm-build/
119119+120120+# pixi
121121+# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
122122+#pixi.lock
123123+# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
124124+# in the .venv directory. It is recommended not to include this directory in version control.
125125+.pixi
126126+127127+# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
128128+__pypackages__/
129129+130130+# Celery stuff
131131+celerybeat-schedule
132132+celerybeat.pid
133133+134134+# SageMath parsed files
135135+*.sage.py
136136+137137+# Environments
138138+.env
139139+.envrc
140140+.venv
141141+env/
142142+venv/
143143+ENV/
144144+env.bak/
145145+venv.bak/
146146+147147+# Spyder project settings
148148+.spyderproject
149149+.spyproject
150150+151151+# Rope project settings
152152+.ropeproject
153153+154154+# mkdocs documentation
155155+/site
156156+157157+# mypy
158158+.mypy_cache/
159159+.dmypy.json
160160+dmypy.json
161161+162162+# Pyre type checker
163163+.pyre/
164164+165165+# pytype static type analyzer
166166+.pytype/
167167+168168+# Cython debug symbols
169169+cython_debug/
170170+171171+# PyCharm
172172+# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
173173+# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
174174+# and can be added to the global gitignore or merged into this file. For a more nuclear
175175+# option (not recommended) you can uncomment the following to ignore the entire idea folder.
176176+#.idea/
177177+178178+# Abstra
179179+# Abstra is an AI-powered process automation framework.
180180+# Ignore directories containing user credentials, local state, and settings.
181181+# Learn more at https://abstra.io/docs
182182+.abstra/
183183+184184+# Visual Studio Code
185185+# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
186186+# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
187187+# and can be added to the global gitignore or merged into this file. However, if you prefer,
188188+# you could uncomment the following to ignore the entire vscode folder
189189+# .vscode/
190190+191191+# Ruff stuff:
192192+.ruff_cache/
193193+194194+# PyPI configuration file
195195+.pypirc
196196+197197+# Marimo
198198+marimo/_static/
199199+marimo/_lsp/
200200+__marimo__/
201201+202202+# Streamlit
203203+.streamlit/secrets.toml
···6868 if feed_url not in user.feeds:
6969 user.feeds.append(feed_url)
7070 return True
7171- return False7171+ return False
+5-2
src/thicket/models/feed.py
···11"""Feed and entry models for thicket."""
2233from datetime import datetime
44-from typing import Optional
44+from typing import TYPE_CHECKING, Optional
5566from pydantic import BaseModel, ConfigDict, EmailStr, HttpUrl
77+88+if TYPE_CHECKING:
99+ from .config import UserConfig
710811912class AtomEntry(BaseModel):
···8386 duplicate_id
8487 for duplicate_id, canonical in self.duplicates.items()
8588 if canonical == canonical_id
8686- ]8989+ ]
+1-2
src/thicket/models/user.py
···6868 """Update entry count for a user and total."""
6969 user = self.get_user(username)
7070 if user:
7171- old_count = user.entry_count
7271 user.increment_entry_count(count)
7372 self.total_entries += count
7473 self.last_updated = datetime.now()
···7675 def recalculate_totals(self) -> None:
7776 """Recalculate total entries from all users."""
7877 self.total_entries = sum(user.entry_count for user in self.users.values())
7979- self.last_updated = datetime.now()7878+ self.last_updated = datetime.now()
+1-1
src/thicket/utils/__init__.py
···11"""Utility modules for thicket."""
2233# This module will contain shared utilities
44-# For now, it's empty but can be expanded with common functions44+# For now, it's empty but can be expanded with common functions