Manage Atom feeds in a persistent git repository
1[build-system]
2requires = ["hatchling"]
3build-backend = "hatchling.build"
4
5[project]
6name = "thicket"
7dynamic = ["version"]
8description = "A CLI tool for persisting Atom/RSS feeds in Git repositories"
9readme = "README.md"
10license = "MIT"
11requires-python = ">=3.9"
12authors = [
13 {name = "thicket", email = "thicket@example.com"},
14]
15classifiers = [
16 "Development Status :: 3 - Alpha",
17 "Intended Audience :: Developers",
18 "License :: OSI Approved :: MIT License",
19 "Operating System :: OS Independent",
20 "Programming Language :: Python :: 3",
21 "Programming Language :: Python :: 3.9",
22 "Programming Language :: Python :: 3.10",
23 "Programming Language :: Python :: 3.11",
24 "Programming Language :: Python :: 3.12",
25 "Programming Language :: Python :: 3.13",
26 "Topic :: Internet :: WWW/HTTP :: Dynamic Content :: News/Diary",
27 "Topic :: Software Development :: Version Control :: Git",
28 "Topic :: Text Processing :: Markup :: XML",
29]
30dependencies = [
31 "typer>=0.15.0",
32 "rich>=13.0.0",
33 "GitPython>=3.1.40",
34 "feedparser>=6.0.11",
35 "pydantic>=2.11.0",
36 "pydantic-settings>=2.10.0",
37 "httpx>=0.28.0",
38 "pendulum>=3.0.0",
39 "bleach>=6.0.0",
40 "platformdirs>=4.0.0",
41 "pyyaml>=6.0.0",
42 "email_validator",
43 "jinja2>=3.1.6",
44]
45
46[project.optional-dependencies]
47dev = [
48 "pytest>=8.0.0",
49 "pytest-asyncio>=0.24.0",
50 "pytest-cov>=6.0.0",
51 "black>=24.0.0",
52 "ruff>=0.8.0",
53 "mypy>=1.13.0",
54 "types-PyYAML>=6.0.0",
55]
56
57[project.urls]
58Homepage = "https://github.com/example/thicket"
59Documentation = "https://github.com/example/thicket"
60Repository = "https://github.com/example/thicket"
61"Bug Tracker" = "https://github.com/example/thicket/issues"
62
63[project.scripts]
64thicket = "thicket.cli.main:app"
65
66[tool.hatch.version]
67path = "src/thicket/__init__.py"
68
69[tool.hatch.build.targets.wheel]
70packages = ["src/thicket"]
71
72[tool.black]
73line-length = 88
74target-version = ['py39']
75include = '\.pyi?$'
76extend-exclude = '''
77/(
78 # directories
79 \.eggs
80 | \.git
81 | \.hg
82 | \.mypy_cache
83 | \.tox
84 | \.venv
85 | build
86 | dist
87)/
88'''
89
90[tool.ruff]
91target-version = "py39"
92line-length = 88
93
94[tool.ruff.lint]
95select = [
96 "E", # pycodestyle errors
97 "W", # pycodestyle warnings
98 "F", # pyflakes
99 "I", # isort
100 "B", # flake8-bugbear
101 "C4", # flake8-comprehensions
102 "UP", # pyupgrade
103]
104ignore = [
105 "E501", # line too long, handled by black
106 "B008", # do not perform function calls in argument defaults
107 "C901", # too complex
108]
109
110[tool.ruff.lint.per-file-ignores]
111"__init__.py" = ["F401"]
112
113[tool.mypy]
114python_version = "3.9"
115check_untyped_defs = true
116disallow_any_generics = true
117disallow_incomplete_defs = true
118disallow_untyped_defs = true
119no_implicit_optional = true
120warn_redundant_casts = true
121warn_unused_ignores = true
122warn_return_any = true
123strict_optional = true
124
125[[tool.mypy.overrides]]
126module = [
127 "feedparser",
128 "git",
129 "bleach",
130]
131ignore_missing_imports = true
132
133[tool.pytest.ini_options]
134testpaths = ["tests"]
135python_files = ["test_*.py"]
136python_classes = ["Test*"]
137python_functions = ["test_*"]
138addopts = [
139 "-ra",
140 "--strict-markers",
141 "--strict-config",
142 "--cov=src/thicket",
143 "--cov-report=term-missing",
144 "--cov-report=html",
145 "--cov-report=xml",
146]
147filterwarnings = [
148 "error",
149 "ignore::UserWarning",
150 "ignore::DeprecationWarning",
151]
152markers = [
153 "slow: marks tests as slow (deselect with '-m \"not slow\"')",
154 "integration: marks tests as integration tests",
155]
156
157[tool.coverage.run]
158source = ["src"]
159branch = true
160
161[tool.coverage.report]
162exclude_lines = [
163 "pragma: no cover",
164 "def __repr__",
165 "if self.debug:",
166 "if settings.DEBUG",
167 "raise AssertionError",
168 "raise NotImplementedError",
169 "if 0:",
170 "if __name__ == .__main__.:",
171 "class .*\\bProtocol\\):",
172 "@(abc\\.)?abstractmethod",
173]