-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Expand file tree
/
Copy pathpyproject.toml
More file actions
418 lines (394 loc) · 18.8 KB
/
Copy pathpyproject.toml
File metadata and controls
418 lines (394 loc) · 18.8 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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
[build-system]
requires = ["setuptools>=42", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "rfdetr"
version = "1.10.0.dev1"
description = "RF-DETR"
readme = "README.md"
authors = [
{name = "Roboflow, Inc", email = "develop@roboflow.com"}
]
license = {text = "Apache License 2.0"}
requires-python = ">=3.10"
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"Intended Audience :: Education",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3 :: Only",
"Topic :: Software Development",
"Topic :: Scientific/Engineering",
"Topic :: Scientific/Engineering :: Artificial Intelligence",
"Typing :: Typed",
"Operating System :: POSIX",
"Operating System :: Unix",
"Operating System :: MacOS"
]
keywords = ["machine-learning", "deep-learning", "vision", "ML", "DL", "AI", "DETR", "RF-DETR", "Roboflow"]
dependencies = [
"requests", # weight download from remote URLs
"numpy", # array conversion throughout inference, evaluation, export, and visualization
"torch>=2.2.0", # core tensor ops and model forward pass
"torchvision>=0.17.0", # image transforms and ops (aligned with torch>=2.2.0)
"tqdm", # progress bars during weight download
"transformers>=5.1.0,<6.0.0", # DINOv2 backbone loading
"pydantic>=2.0,<3", # ModelConfig / TrainConfig validation
"supervision>=0.29.0", # inference output (Detections, Masks)
"pyDeprecate>=0.9,<0.10", # deprecation warnings for legacy APIs; >=0.6 for deprecated_class
]
[project.optional-dependencies]
lora = [
"peft", # LoRA backbone fine-tuning
]
train = [
"peft", # LoRA backbone fine-tuning (available during training)
"pytorch_lightning>=2.6,<3,!=2.6.2,!=2.6.3", # Keep exclusions; see issue #1016 / related advisory for why 2.6.2 and 2.6.3 are blocked
"torchmetrics[detection]>=1.8.2,<1.9.0", # one-pass COCO adapter validates the TorchMetrics 1.8 private backend contract; re-verify _validate_private_contract() (src/rfdetr/training/coco_map.py) against 1.9+ before widening this pin
"faster-coco-eval>=1.7.2",
"pycocotools",
"scipy",
# Batched Hungarian solver for the matcher (Apache-2.0). Speeds up the CUDA path only — its
# Triton backend needs Linux + compute capability >= 8.0 + torch >= 2.4; everywhere else it
# falls back internally to the same SciPy solve the matcher would have called, so only speed
# differs. The >=0.1.0 floor excludes the 0.0.x line, whose sdist compiled against nvcc.
# Measurement evidence: .plans/active/plan-native-linear-assignment.md Phase M3 Item 2.
# TODO: 0.1.0 is not on PyPI yet, so it comes from a branch archive meanwhile. RELEASE BLOCKER —
# the URL lands verbatim in built metadata as `Requires-Dist`, and PEP 440 has public indexes
# reject direct references, so publish-release.yml fails at the PyPI upload step while this
# entry is a URL and `twine check --strict` does not catch it. Once 0.1.0 ships, replace this
# TODO and the URL — nothing else — with: "torch-linear-assignment>=0.1.0,<0.2.0",
"torch-linear-assignment @ https://github.com/Borda/torch-hungarian/archive/refs/heads/refactor/triton.zip",
"roboflow",
]
augment = [
"albumentations>=1.4.24,<3.0.0", # optional custom CPU augmentations
"kornia>=0.7,<1", # optional GPU-side augmentation
]
onnx = [
"onnx>=1.16.0,<2.0",
"onnxsim>=0.7.0", # 0.7.0 ships wheels for cp310/311/312-abi3 (3.10-3.13) on linux x86_64+aarch64, win_amd64 and macOS arm64. The old <0.6.0 pin resolved to 0.5.0, which lacks cp311/cp313/aarch64 wheels, so pip built onnxsim's bundled onnxruntime/onnx from source and the install hung (#749).
"onnx_graphsurgeon",
# onnxruntime dropped cp310 wheels after 1.23.2; 1.24.0+ ship cp311-cp314 only. Unpinned,
# a 3.10 resolve picks the newest release and then fails at install with "no source
# distribution or wheel for the current platform". Remove the split when the project's
# requires-python floor moves past 3.10.
"onnxruntime<1.24; python_version < '3.11'",
"onnxruntime; python_version >= '3.11'",
"polygraphy",
]
tensorrt = [
"onnxruntime-gpu",
"tensorrt>=8.6.1",
"polygraphy",
]
# pycuda is only used by async TRTInference in rfdetr.export.benchmark. It ships as an sdist
# and builds against the CUDA toolkit dev headers (cuda.h), which a GPU driver alone does not
# provide. Keep it out of the base [tensorrt] extra so the ONNX->engine parity path (polygraphy
# TrtRunner, no pycuda) installs on a driver-only runner; async benchmarking opts into it here.
tensorrt-bench = [
"pycuda>=2024.1",
]
tflite = [
# TFLite conversion routes every export through the ONNX pipeline first (export_onnx's
# graph optimization/simplification), so these are needed here directly rather than via
# the separate [onnx] extra — onnxruntime is NOT included: it's only for running ONNX
# inference, never touched by the TFLite export path.
"onnx>=1.20.0,<2.0; python_version >= '3.12' and python_version < '3.13'",
"onnxsim>=0.7.0; python_version >= '3.12' and python_version < '3.13'", # 0.7.0 ships a cp312 abi3 wheel; the old <0.6.0 pin resolved to 0.5.0 whose wheels don't cover every platform, so pip built from source and hung (#749).
"onnx_graphsurgeon; python_version >= '3.12' and python_version < '3.13'",
"polygraphy; python_version >= '3.12' and python_version < '3.13'",
"onnx2tf>=2.4.0,<3.0.0; python_version >= '3.12' and python_version < '3.13'",
"flatbuffers>=23.5.26; python_version >= '3.12' and python_version < '3.13'",
"tf-keras>=2.16.0; python_version >= '3.12' and python_version < '3.13'",
"tensorflow>=2.16.0; python_version >= '3.12' and python_version < '3.13'",
]
executorch = [
# torch.export -> .pte, XNNPACK CPU delegate; validated on 1.3.1.
# executorch publishes cp310-cp313 wheels only (1.3.1 is current) and has no sdist, so a
# 3.14 install fails on wheel availability rather than resolution. The marker keeps the
# extra installable-but-empty on 3.14, matching how [tflite] is gated to 3.12. Drop the
# `python_version < '3.14'` marker once executorch ships cp314 wheels.
"executorch>=1.3,<2.0; python_version < '3.14'",
]
coreml = [
# torch.export (ExportedProgram) support added in coremltools 8.0 (see
# src/rfdetr/export/_coreml/torch_ops.py, op_coverage.py for the private-API surface this pin
# guards — coremltools._TORCH_OPS_REGISTRY internals can rename across minors).
"coremltools>=8.0,<10.0",
# torch>=2.12 sharply raises the rate of a CoreML/eager numeric-parity divergence on real-image
# input (coremltools 9.0): bisected 2026-07-28 on RFDETRNano with random-init weights —
# torch<2.12 failed ~1/6 repeat runs, torch>=2.12.0 failed ~6/7 (up to ~1.0 abs diff on raw
# query outputs; tests/export/test_coreml_export.py::TestCoreMLEndToEnd::
# test_outputs_match_pytorch_supervision_image[detection]). Same decomposed op set both sides —
# looks like a coremltools MIL lowering regression exposed by torch 2.12's export graph, not a
# missing/renamed op. This pin reduces the failure rate, it does not eliminate it — the
# underlying instability (random/untrained-weight activations pushing some op toward
# overflow/nan during MIL conversion; see the divide-by-zero/overflow RuntimeWarnings logged
# during convert) is present at some low rate on torch<2.12 too. Raise this cap once the root
# cause is understood/fixed upstream; don't treat it as a guaranteed-deterministic fix.
"torch<2.12",
]
loggers = [
"tensorboard>=2.13.0",
"protobuf>=3.20.0", # Cap <4.0.0 removed — tensorflow>=2.16.0 (required by [tflite]) needs protobuf>=3.20.3 and is incompatible with <4.0.0 (see #1041)
"wandb",
"mlflow",
"clearml",
]
visual = [
"matplotlib",
"pandas",
"seaborn",
]
cli = ["jsonargparse[signatures]>=4.27.7"]
plus = ["rfdetr_plus>=1.0.1, <2.0.0"]
# XLA backend for TPU training AND hardware-free XLA validation on CPU/GPU PJRT.
# torch_xla is built on top of torch (NOT mutually exclusive — it requires torch present) and its
# _XLAC extension is ABI-locked to ONE torch minor (a mismatch surfaces as an `undefined symbol`
# ImportError on `import torch_xla`). torch_xla does not hard-pin torch in requires_dist, and PEP 508
# cannot express "equal minor", so we pin BOTH to the current known-good pair (2.9) — bump the two
# together when a newer torch_xla ships. Wheels are Linux x86_64 only (py3.10-3.13) -> sys_platform
# marker keeps macOS/Windows installs of this extra a no-op. The bare wheel runs the CPU PJRT plugin
# (PJRT_DEVICE=CPU) with no libtpu; real TPU adds torch_xla[tpu] (libtpu), GPU PJRT needs the separate
# CUDA plugin wheel. Used by ci-tests-xla.yml to exercise @pytest.mark.xla paths.
xla = [
"torch==2.9.*; sys_platform == 'linux'",
"torch_xla==2.9.*; sys_platform == 'linux'",
]
[dependency-groups]
# TODO: Temporary: GPU runner only has CUDA 12.8 driver (12080); torch>=2.11 requires a newer driver.
# Remove this group and the --group ci-gpu-pin references in CI once the driver is updated.
# Does not affect users installing rfdetr from PyPI.
ci-gpu-pin = [
"torch<2.11",
"torchvision<0.26",
]
# TODO: Temporary: executorch==1.3.1's prebuilt wheel is compiled against ~torch-2.12.x's C10 ABI
# (executorch itself only floors torch>=2.12.0a0, no ceiling). torch>=2.13.0 removed/changed a C10
# symbol the wheel links, breaking executorch.runtime at dlopen (undefined symbol). Empirically
# validated: torch==2.12.1 + executorch==1.3.1 imports executorch.runtime cleanly; torch==2.13.0
# does not. Remove this group and the --group ci-executorch-pin reference in CI once executorch
# ships a release compatible with newer torch. Does not affect users installing rfdetr from PyPI —
# see rfdetr.export._executorch.converter._check_executorch_available(require_runtime=True) for the
# equivalent runtime guidance surfaced to end users who hit this.
ci-executorch-pin = [
"torch<2.13",
]
build = [
"twine>=5.1.1",
"wheel>=0.40",
"build>=0.10"
]
tests = [
"pytest>=7.2,<10",
"pytest-cov>=4,<8",
"pytest-xdist>=3.6,<4",
"pytest-rerunfailures>=10,<15",
"pytest-timeout>=2,<3",
"pytest-doctestplus>=1.2,<2",
"pandas", # imported directly by tests/training/test_metrics_csv.py to read CSVLogger output
"tomli>=2.0; python_version < '3.11'",
]
typing = [
# Keep this pin aligned with the local mypy hook in .pre-commit-config.yaml.
"mypy==1.19.1",
# mypy 1.19.x can crash while processing NumPy 2.4 symbols in strict mode.
"numpy<2.4",
"types-PyYAML",
"types-requests",
"types-tqdm",
]
docs = [
"mkdocs-material[imaging]>=9.7",
"mkdocstrings>=0.25.2,<0.30.0",
"mkdocstrings-python>=1.10.9",
"mike>=2.0.0",
"mkdocs-jupyter>=0.24.3",
"mkdocs-git-committers-plugin-2>=2.4.1",
"mkdocs-git-revision-date-localized-plugin>=1.2.4",
"tomli>=2.0; python_version < '3.11'",
]
[project.urls]
Homepage = "https://github.com/roboflow/rf-detr"
[project.scripts]
rfdetr = "rfdetr.cli:main"
[tool.uv]
# onnx2tf>=2.4.0 pins numpy==1.26.4 (exact). Its dependency ml-dtypes==0.5.1 in turn requires
# numpy>=2.1.0 on python_full_version>='3.13' — contradicting the numpy==1.26.4 pin on 3.13.
# tflite deps carry python_version>='3.12' and <'3.13' markers because onnx2tf's numpy pin
# cannot be satisfied on 3.13 via any available release; when onnx2tf relaxes the exact pin,
# remove the <'3.13' upper bound from the tflite deps AND from the override below.
override-dependencies = [
"ml-dtypes==0.5.1; python_version >= '3.12' and python_version < '3.13'",
]
# ci-gpu-pin (torch<2.11, GPU-driver constraint) and the executorch extra (torch>=2.12.0a0,
# from executorch's own metadata) are unsatisfiable together -- no CI job combines them, but
# `uv sync --all-groups` and a plain `uv lock` need to know that so the universal resolver
# forks the two instead of failing to find one lockfile that satisfies both at once.
#
# coreml (torch<2.12, see coreml extra comment) and executorch (torch>=2.12.0a0) are likewise
# unsatisfiable together -- no CI job combines them either, same fork rationale.
conflicts = [
[
{ group = "ci-gpu-pin" },
{ extra = "executorch" },
],
[
{ extra = "coreml" },
{ extra = "executorch" },
],
# executorch and tflite extras are unsatisfiable together; declare a conflict so `uv lock` / `uv sync --all-groups` can fork.
[
{ extra = "executorch" },
{ extra = "tflite" },
],
# xla (torch==2.9.*, pinned to torch_xla's companion release) and executorch
# (torch>=2.12.0a0) are likewise unsatisfiable together -- same fork rationale.
[
{ extra = "executorch" },
{ extra = "xla" },
],
]
[tool.setuptools.packages.find]
where = ["src"]
include = ["rfdetr*"]
[tool.setuptools]
include-package-data = false
[tool.setuptools.package-data]
rfdetr = ["py.typed", "models/backbone/dinov2_configs/*.json"]
[tool.ruff]
fix = true
line-length = 120
target-version = "py310"
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort
"N", # pep8-naming: lowercase variables (N806) and arguments (N803)
]
extend-select = [
"RUF100", # yesqa
]
ignore = [
"E722", # todo: Do not use bare `except`
]
[tool.ruff.lint.per-file-ignores]
"notebooks/*.py" = ["E402"] # cell-local imports are intentional in percent-format scripts
"docs/cookbooks/*.ipynb" = [
"E402", # cell-local imports are intentional in percent-format scripts
"E501", # jupytext notebook — markdown prose lines are intentionally unwrapped
]
"docs/cookbooks/*.py" = [
"E402", # cell-local imports are intentional in percent-format scripts
"E501", # .py mirror of jupytext notebook — markdown prose lines are intentionally unwrapped
]
[tool.docformatter]
wrap-summaries = 120
wrap-descriptions = 120
[tool.pytest.ini_options]
addopts = [
"-v", # verbose output
"--color=yes", # colored output
"--doctest-plus", # run doctests from all modules (pytest-doctestplus)
]
# Doctest collection is intentionally enabled across tests/ (no doctest_norecursedirs exclusion) so
# helper-function doctests in test modules run. This previously blanket-excluded tests/* because
# doctestplus walking every test module's attributes after the TF/ai_edge_litert stack is imported by
# the tflite export tests grows unittest.mock.call's cached child-mock graph unboundedly — observed
# 38 GB RSS and a silent SIGKILL during collection. If that recurs, reintroduce
# `doctest_norecursedirs = ["tests/*"]` or scope it to `tests/export/test_tflite_inference.py`.
pythonpath = ["src", "."]
markers = [
"gpu: tests that require GPU or are slow on CPU",
"xla: tests that require an XLA device or torch_xla runtime (TPU, or CPU/GPU PJRT)",
"tpu: tests that require real TPU hardware (libtpu/MXU); not runnable on CPU/GPU PJRT",
"coco17: tests that require COCO 2017 images or annotations",
# `flaky` is provided by pytest-rerunfailures; registered here too for clarity and to stay
# safe under --strict-markers (used by tests/benchmarks/test_training_*.py).
"flaky: tests that may fail due to nondeterminism and are retried via pytest-rerunfailures",
"e2e_executorch: ExecuTorch end-to-end export + numerical parity (opt-in)",
"e2e_coreml: CoreML end-to-end convert + numerical parity (structured and photo inputs; opt-in)",
"e2e_tensorrt: TensorRT end-to-end ONNX->engine build + parity (GPU, opt-in)",
"e2e_roboflow: live deploy_to_roboflow() upload + train-status validation (issue #1116); requires ROBOFLOW_API_KEY (opt-in)",
]
filterwarnings = [
# pytest-xdist workers close their channel before teardown completes;
# this is a known false-positive that does not affect test results.
"ignore::pluggy.PluggyTeardownRaisedWarning",
# Many tests instantiate ModelConfig variants with `pretrain_weights=None`
# to skip downloads. The pretrain-compat warning is intentional UX for
# end users; silence it globally for the test suite and re-enable it
# explicitly in the dedicated tests via `warnings.catch_warnings` plus
# `warnings.simplefilter("always")`.
# NOTE: expressed as a message regex (not as
# ``ignore::rfdetr.config.PretrainWeightsCompatibilityWarning``) because a
# class-path filter forces pytest to import ``rfdetr.config`` at
# config-parse time — before ``pytest-cov`` starts tracing — which makes
# the module's top-level statements appear uncovered.
"ignore:.*was instantiated with pretrain_weights=None:UserWarning",
"ignore:.*was instantiated with overrides that differ from the variant:UserWarning",
]
[tool.codespell]
skip = "*.pth"
ignore-words-list = "ane"
[tool.mypy]
python_version = "3.10"
ignore_missing_imports = false
explicit_package_bases = true
strict = true
mypy_path = "src"
exclude = [
"^docs/(hooks|scripts)/",
]
overrides = [
{ module = [
"tests.*",
"einops", "einops.*",
"matplotlib", "matplotlib.*",
"pandas", "pandas.*",
"seaborn", "seaborn.*",
], ignore_errors = true },
{ module = [
"torchvision", "torchvision.*",
"pycocotools", "pycocotools.*",
"timm", "timm.*",
"einops", "einops.*",
"deprecate", "deprecate.*",
"faster_coco_eval", "faster_coco_eval.*",
"matplotlib", "matplotlib.*",
"pandas", "pandas.*",
"requests", "requests.*",
"seaborn", "seaborn.*",
"tqdm", "tqdm.*",
"kornia", "kornia.*",
"albumentations", "albumentations.*",
"onnx", "onnx.*",
"onnx2tf", "onnx2tf.*",
"onnx_graphsurgeon", "onnx_graphsurgeon.*",
"onnxruntime", "onnxruntime.*",
"onnxsim", "onnxsim.*",
"polygraphy", "polygraphy.*",
"tensorrt", "tensorrt.*",
"pycuda", "pycuda.*",
"jsonargparse", "jsonargparse.*",
"tflite_runtime", "tflite_runtime.*",
"tensorflow", "tensorflow.*",
"executorch", "executorch.*",
"coremltools", "coremltools.*",
"roboflow", "roboflow.*",
"rfdetr_plus", "rfdetr_plus.*",
], ignore_missing_imports = true },
# Optional-import None assignments in console.py: type: ignore[assignment, misc] is needed when
# rich IS installed (full-venv mypy sees the assignment error) but flagged as unused by the
# pre-commit hook (which runs mypy with --ignore-missing-imports so rich types are unresolved).
{ module = ["rfdetr.utilities.console"], warn_unused_ignores = false },
]