Repository navigation
Expand file tree
/
Copy pathpyproject.toml
More file actions
139 lines (127 loc) · 4 KB
/
Copy pathpyproject.toml
File metadata and controls
139 lines (127 loc) · 4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
[project]
name = "httpware"
description = "Typed, resilient HTTP clients for Python, sync and async"
authors = [{ name = "Artur Shiriev", email = "me@shiriev.ru" }]
requires-python = ">=3.11,<4"
license = "MIT"
readme = "README.md"
keywords = [
"http-client",
"httpx",
"asyncio",
"resilience",
"retry",
"circuit-breaker",
"bulkhead",
"middleware",
"pydantic",
"msgspec",
"python",
]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Programming Language :: Python :: 3.15",
"Programming Language :: Python :: Free Threading :: 2 - Beta",
"Typing :: Typed",
"Topic :: Software Development :: Libraries",
"Topic :: Internet :: WWW/HTTP",
"Framework :: AsyncIO",
]
version = "0"
dependencies = [
"httpx2>=2.0.0,<3.0",
# 4.14.0 is the first whose closed TypedDicts keep their keys on Python 3.14, and the
# cp314 pydantic floor (2.12) needs 4.14.1.
"typing-extensions>=4.14.1",
]
[project.optional-dependencies]
pydantic = [
# pydantic-core ships no cp312 wheel before pydantic 2.1, no cp313 wheel before 2.8.1 and no
# cp314 wheel before 2.12.
"pydantic>=2.0,<3.0; python_version < '3.12'",
"pydantic>=2.1,<3.0; python_version == '3.12'",
"pydantic>=2.8.1,<3.0; python_version == '3.13'",
"pydantic>=2.12,<3.0; python_version >= '3.14'",
]
msgspec = [
# 0.18.5 is the first release whose can_decode agrees with decode on Annotated types;
# 0.19 is the first with a cp313 wheel and 0.20 the first with a cp314 one.
"msgspec>=0.18.5; python_version < '3.13'",
"msgspec>=0.19; python_version == '3.13'",
"msgspec>=0.20; python_version >= '3.14'",
]
otel = ["opentelemetry-api>=1.20"]
all = ["httpware[pydantic,msgspec,otel]"]
[project.urls]
Homepage = "https://httpware.modern-python.org"
Documentation = "https://httpware.modern-python.org"
Repository = "https://github.com/modern-python/httpware"
Issues = "https://github.com/modern-python/httpware/issues"
Changelog = "https://github.com/modern-python/httpware/releases"
[build-system]
requires = ["uv_build>=0.11,<1.0"]
build-backend = "uv_build"
[tool.uv.build-backend]
module-name = "httpware"
module-root = "src"
[dependency-groups]
dev = [
"pytest>=8",
"pytest-cov>=5",
"pytest-asyncio>=0.24",
"pytest-repeat>=0.9",
"pytest-benchmark>=4",
"hypothesis>=6.20",
]
lint = [
"ruff",
"ty",
"eof-fixer",
"typing-extensions",
]
[tool.ruff]
fix = true
unsafe-fixes = true
line-length = 120
[tool.ruff.lint]
select = ["ALL"]
ignore = [
"D1", # docstrings are not forced; a docstring exists when it says something
"D203", # conflicts with D211
"D213", # conflicts with D212
"COM812", # conflicts with the formatter
"ISC001", # conflicts with the formatter
"CPY001", # no per-file copyright header
"FBT", # boolean positional arguments are fine
"TCH", # imports stay real; TYPE_CHECKING-only imports break runtime introspection
]
isort.lines-after-imports = 2
isort.no-lines-before = ["standard-library", "local-folder"]
[tool.ruff.lint.per-file-ignores]
"src/httpware/client.py" = ["ASYNC109", "ANN401"]
"tests/**" = ["S101"]
[[tool.ty.overrides]]
include = ["scripts/**"]
rules = { unresolved-import = "ignore" }
[[tool.ty.overrides]]
include = ["tests/test_client_typing.py"]
rules = { unused-ignore-comment = "error" }
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = ""
asyncio_mode = "auto"
pythonpath = ["src"]
asyncio_default_fixture_loop_scope = "function"
markers = [
"stress: concurrency stress test; proves thread-safety under free-threaded CPython (3.14t). Runs under the GIL too, so it counts toward coverage.",
]
[tool.coverage]
run.concurrency = ["thread"]
run.omit = ["benchmarks/*", "scripts/*"]
report.exclude_also = ["if typing.TYPE_CHECKING:"]
report.fail_under = 100