Mirrored from GitHub
github.com/roostorg/osprey
1[build-system]
2requires = ["uv_build>=0.8.12,<0.9.0"]
3build-backend = "uv_build"
4
5[dependency-groups]
6common = [
7 "blinker==1.9.0",
8 "click==7.1.2",
9 "datadog==0.51.0",
10 "ddtrace==2.21.11",
11 "deepmerge==0.3.0",
12 "dnspython==2.6.1",
13 "faker==4.18.0",
14 "flask==1.1.4",
15 "gevent==24.2.1",
16 "google-api-core==2.19.2",
17 "google-auth==2.40.3",
18 "google-cloud-bigquery==3.27.0",
19 "google-cloud-bigtable==2.10.0",
20 "google-cloud-core==2.6.0",
21 "google-cloud-kms==3.5.1",
22 "google-cloud-pubsub==2.15.2",
23 "google-cloud-storage==2.10.0",
24 "google-resumable-media==2.7.2",
25 "googleapis-common-protos==1.70.0",
26 "graphviz==0.20",
27 "greenlet",
28 "grpc-google-iam-v1==0.14.4",
29 "grpcio==1.49.1; platform_machine == 'x86_64'",
30 "grpcio==1.53.*; platform_machine != 'x86_64'",
31 "grpcio-health-checking==1.44.0",
32 "grpcio-reflection==1.44.0",
33 "grpcio-status==1.49.1; platform_machine == 'x86_64'",
34 "grpcio-status==1.53.*; platform_machine != 'x86_64'",
35 "grpcio-tools==1.49.1; platform_machine == 'x86_64'",
36 "grpcio-tools==1.53.*; platform_machine != 'x86_64'",
37 "gunicorn",
38 "intervals==0.9.2",
39 "jsonpath-rw",
40 "kafka-python==1.4.7",
41 # Flask 1.1.4 / Jinja2 2.11 import `markupsafe.soft_unicode`, which was removed in
42 # markupsafe 2.1.0. Pin to <2.1 until the Flask 1.x stack is upgraded.
43 "markupsafe<2.1",
44 "minio>=7.2.16",
45 "mmh3==3.0.0",
46 "msgpack==1.2.1",
47 "phone-iso3166==0.3.8",
48 "pluggy==1.5.0",
49 "protobuf==4.25.8",
50 "psycogreen==1.0.2",
51 "psycopg2-binary==2.9.10",
52 "pycryptodome==3.21.0",
53 "pydantic==1.10.26",
54 "pydruid==0.6.9",
55 "pytest==9.0.3",
56 "pytest-mock==3.14.1",
57 "python-dateutil==2.8.0",
58 "python-json-logger==0.1.10",
59 "pytz==2022.1",
60 "pyyaml==6.0.1",
61 "rapidfuzz==3.14.5",
62 "requests==2.33.0",
63 "result==0.5.0",
64 "sentry-sdk==2.61.1",
65 "simplejson==3.20.2",
66 "six==1.16.0",
67 "sqlalchemy==1.4.54",
68 "sqlalchemy-utils==0.41.1",
69 "tenacity==8.1.0",
70 "tink==1.9.0",
71 "tld==0.12.7",
72 "traitlets==5.14.3",
73 "typing-extensions==4.12.2",
74 "typing-inspect==0.9.0",
75 "anyascii==0.3.3",
76 "werkzeug==1.0.1",
77 # --- Type stubs (used by mypy, not imported directly) ---
78 "types-cachetools==6.1.0.20250717",
79 "types-click==7.1.8",
80 "types-flask==1.1.6",
81 "types-ipaddress==1.0.8",
82 "types-jinja2==2.11.9",
83 "types-markupsafe==1.1.10",
84 "types-maxminddb==1.5.0",
85 "types-protobuf==4.24.0.1",
86 "types-psycopg2>=2.9.21.20250809",
87 "types-python-dateutil==2.9.0.20260518",
88 "types-pytz==2025.2.0.20250516",
89 "types-pyyaml==6.0.12.20250516",
90 "types-requests==2.27.7",
91 "types-simplejson==3.20.0.20250326",
92 "types-six==1.17.0.20250515",
93 "types-urllib3==1.26.25.14",
94 "types-werkzeug==1.0.9",
95]
96dev = [
97 "ipdb==0.13.13",
98 "pytest-asyncio",
99 "ipython==9.4.0",
100 "memray==1.19.2",
101 "mypy>=1.13.0",
102 "mypy-extensions==1.1.0",
103 "mypy-protobuf==3.6.0",
104 "pre-commit>=4.3.0",
105 "pytest-flask==1.3.0",
106 "pytest-order==1.3.0",
107 "requests-mock==1.12.1",
108 "ruff>=0.12.9",
109 "setuptools==80.9.0",
110 "sqlalchemy[mypy]>=1.4.31",
111 "sqlalchemy2-stubs==0.0.2a38",
112 "types-flask-cors>=3.0.10",
113]
114
115
116[tool.uv]
117override-dependencies = ["ddtrace>=2.17.2,<3.0.0"]
118default-groups = ["common", "dev"]
119
120[tool.uv.sources]
121greenlet = { git = "https://github.com/discord/greenlet.git", rev = "a75d78f1547c74a81134644a179467525a255466" }
122gunicorn = { git = "https://github.com/discord/gunicorn.git", rev = "979efdcb918daa536d8923668241c6e6bf1edb58" }
123jsonpath-rw = { url = "https://github.com/kennknowles/python-jsonpath-rw/archive/6f5647bb3ad2395c20f0191fef07a1df51c9fed8.tar.gz" }
124osprey_rpc = { workspace = true }
125osprey_worker = { workspace = true }
126osprey_async_worker = { workspace = true }
127example_plugins = { workspace = true }
128example_atproto_plugins = { workspace = true }
129
130[tool.uv.workspace]
131members = [
132 "osprey_rpc",
133 "osprey_worker",
134 "osprey_async_worker",
135 "example_plugins",
136 "example_atproto_plugins",
137]
138
139
140[tool.ruff]
141target-version = "py311"
142line-length = 120
143fix = true
144force-exclude = true # Needed for pre-commit to work on staged files
145extend-exclude = [
146 # Exclude protobuf generated files
147 "**/*_pb2*.py",
148 "**/*_pb2*.pyi",
149]
150
151[tool.ruff.format]
152quote-style = "single"
153indent-style = "space"
154skip-magic-trailing-comma = false
155line-ending = "auto"
156
157[tool.ruff.lint]
158select = [
159 "E", # pycodestyle errors
160 "F", # pyflakes (includes F401 unused imports)
161 "I", # isort
162 "B006", # flake8-bugbear, B006 catches mutable defaults
163]
164ignore = [
165 "E501", # Formatter already does a best effort of handling line-length, but some lines just can't be shortened anymore
166]
167
168[tool.ruff.lint.isort]
169known-first-party = ["osprey_worker", "osprey_async_worker", "osprey_rpc", "example_plugins", "example_atproto_plugins"]
170
171[tool.fawltydeps]
172code = ["osprey_worker/src", "osprey_async_worker/src", "osprey_rpc/src", "example_plugins/src", "example_atproto_plugins/src"]
173deps = ["pyproject.toml"]
174ignore_unused = [
175 # Type stubs: used by mypy, never imported directly
176 "types-cachetools",
177 "types-click",
178 "types-flask",
179 "types-flask-cors",
180 "types-ipaddress",
181 "types-jinja2",
182 "types-markupsafe",
183 "types-maxminddb",
184 "types-protobuf",
185 "types-psycopg2",
186 "types-python-dateutil",
187 "types-pytz",
188 "types-pyyaml",
189 "types-requests",
190 "types-simplejson",
191 "types-six",
192 "types-urllib3",
193 "types-werkzeug",
194 "sqlalchemy2-stubs",
195 # Dev CLI tools: run as commands, not imported
196 "grpcio-tools",
197 "ipdb",
198 "ipython",
199 "memray",
200 "mypy",
201 "mypy-extensions",
202 "mypy-protobuf",
203 "pre-commit",
204 "pytest-asyncio",
205 "pytest-flask",
206 "pytest-order",
207 "requests-mock",
208 "ruff",
209 "setuptools",
210 # Runtime CLI: started via command line, not imported in source
211 "gunicorn",
212 # Optional runtime dep of sentry-sdk for FlaskIntegration
213 "blinker",
214 # Transitive of Flask 1.x / Jinja2 2.11; pinned <2.1 here so soft_unicode
215 # is still exported. Not imported by our source directly.
216 "markupsafe",
217 # gRPC server extensions: registered at startup, not imported directly
218 "grpcio-health-checking",
219 "grpcio-reflection",
220 "grpcio-status",
221 # Required at module load by tink.integration.gcpkms (imported in
222 # osprey.worker.lib.encryption.base). Not imported directly by our code.
223 "google-cloud-kms",
224]
225
226[tool.pytest.ini_options]
227testpaths = ["osprey_worker", "example_plugins", "example_atproto_plugins"]
228asyncio_mode = "auto"
229
230[tool.mypy]
231plugins = ["pydantic.mypy", "sqlalchemy.ext.mypy.plugin"]
232python_version = "3.11"
233namespace_packages = true
234explicit_package_bases = true
235disable_error_code = ["annotation-unchecked"]
236
237mypy_path = [
238 "osprey_rpc/src",
239 "osprey_worker/src",
240 "osprey_async_worker/src",
241 "example_plugins/src",
242 "example_atproto_plugins/src",
243]
244
245# Strict mode includes the following flags. When these are all True, they can be replaced with strict mode.
246# Mostly disabled to match old config
247warn_unused_configs = true
248disallow_any_generics = true
249disallow_subclassing_any = true
250disallow_untyped_calls = false
251disallow_untyped_defs = false
252disallow_incomplete_defs = false
253check_untyped_defs = false
254disallow_untyped_decorators = false
255warn_redundant_casts = true
256warn_return_any = false
257no_implicit_reexport = false
258strict_equality = false
259
260# Additional checks we want to turn on eventually (disabled for now)
261disallow_any_unimported = false
262disallow_any_expr = false
263disallow_any_decorated = false
264disallow_any_explicit = false
265warn_unreachable = false
266
267exclude = [
268 "^.*/venv/.*$",
269 ".*/setup\\.py$",
270 ".*_pb2\\.py$",
271 ".*_pb2\\.pyi$",
272 ".*_pb2_grpc\\.py$",
273 ".*/tests/.*",
274 ".*/test_.*\\.py$",
275]
276
277# required until pydantic explicitly exports Extra
278[[tool.mypy.overrides]]
279module = "pydantic.main"
280implicit_reexport = true
281
282[[tool.mypy.overrides]]
283module = ["jsonpath_rw", "minio.*"]
284ignore_missing_imports = true
285
286# third party packages we don't care about
287[[tool.mypy.overrides]]
288module = [
289 "stubs.*",
290 "google.*",
291 "perf_tools.*",
292 "gevent.*",
293 "grpc.*",
294 "pydruid.*",
295 "phone_iso3166.*",
296 "typing_inspect.*",
297 "tink.*",
298 "sqlalchemy_utils.*",
299 "graphviz.*",
300 "psycogreen.*",
301 "deepmerge.*",
302 "greenlet.*",
303 "kafka.*",
304 "pythonjsonlogger.*",
305 "msgpack.*",
306 "jose.*",
307]
308ignore_errors = true
309disable_error_code = ["annotation-unchecked", "import-untyped"]
310ignore_missing_imports = true
311# At least for now, ignore tests.
312# TODO: Remove these exclusions once they're fixed
313[[tool.mypy.overrides]]
314module = "osprey.worker.*.tests.*"
315ignore_errors = true
316
317[[tool.mypy.overrides]]
318module = ["osprey.rpc.*"]
319ignore_errors = true