mirror of
https://github.com/huggingface/lerobot.git
synced 2026-08-08 17:39:44 +00:00
6c73c413eb
* docs: add API documentation infrastructure
LeRobot's documentation build passes `--not_python_module`, which tells
doc-builder there is no importable Python package and disables `[[autodoc]]`
entirely. The result is that all 90+ pages are hand-written guides and there is
no generated API reference at all.
This is the machinery to change that. It deliberately contains no docstring
changes of its own — every docstring edit lives in the follow-up PR, so this
one can be reviewed as tooling and configuration alone.
**The standard.** `docs/source/writing_docstrings.mdx` is the contract: Google
section headers with Hugging Face type formatting, the machine-checked argument
line, `**Attributes**:`, doc-builder cross-references, fenced doctest examples.
It also records three behaviours that are not discoverable from the source and
were verified against a local build: `[[autodoc]]` silently skips members with
no docstring; doc-builder does not inherit docstrings from base classes, so a
registered config shim whose body is `pass` renders every field with no
description; and module-level aliases resolve to the canonical class.
**Autodoc turned on**, with two changes that are not obvious:
- `--version main` on the main-docs job. Without `--not_python_module`,
doc-builder resolves the version from `lerobot.__version__` and only maps it
to the default branch when it contains "dev". transformers relies on that;
our main carries 0.6.2. Verified by building both ways — dropping the flag
alone would publish the main docs to /lerobot/v0.6.2/ instead of
/lerobot/main/ and disable notebook building.
- `pre_command` on both jobs. doc-builder ships a mock-deps registry entry for
lerobot, so the reusable workflow takes its light-install path, which cannot
import the package. The heavy dependencies cannot be mocked either: draccus
runs `register_subclass` at import time and `processor/converters.py` calls
`functools.singledispatch.register(torch.Tensor)`, which needs a real class.
`[dataset]` is the only extra required.
Workflow triggers gain `src/**`, since the reference is now generated from
docstrings. `docs/source/api/` is excluded from the prettier hook, which reads
`[[autodoc]]` member lists as lazy paragraph continuations and joins a ten-entry
list onto one line.
Nine API reference pages, scaffolded with each module's base class.
**Doctests.** `LeRobotDocTestParser` is mandatory rather than optional here:
ruff's `docstring-code-format = true` drops the blank line before a closing
fence, after which stdlib's `_EXAMPLE_RE` reads the fence as expected output and
every example with output fails. It is written against the installed pytest
rather than copied from transformers, whose version predates pytest 9's
`import_path` signature and its own fix for the `@property` line-number bug.
`preprocess_string` also diverges: the upstream fenced-block split puts a
single-line example's code in a chunk with no `>>>` in it, so neither the CUDA
skip nor the `+IGNORE_RESULT` injection fires for it.
**Checkers.** `utils/check_docstrings.py` is the ~300-line core of the
2203-line transformers original; the `@auto_docstring` system, modular
propagation, GitPython and `checkers.py` are not ported.
`utils/check_config_docstrings.py` checks that every registered robot config
documents its port and calibration semantics.
**Gates**, all set to values that pass today: ruff `D` with per-file-ignores
per unconverted module, `interrogate` at `fail-under = 52` against a measured
52.1%, and Makefile targets wired into the quality workflow. The doctest
allowlist ships empty and the `doctest` target handles that, because the files
carrying runnable examples arrive with the docstring PR.
* ci: build the docs on Python 3.12
The shared doc-builder workflows create their virtualenv with the runner's
system Python, which is 3.10.12 on ubuntu-22.04. lerobot requires >=3.12, so
the build died during "Setup environment":
× No solution found when resolving dependencies:
╰─▶ Because the current Python version (3.10.12) does not satisfy
Python>=3.12 and lerobot==0.6.2 depends on Python>=3.12 ...
That step runs before `pre_command`, so the real install this workflow already
performs never got the chance to run. There was no fix available on the caller
side either: `env:` does not propagate into a reusable workflow, so `UV_PYTHON`
is unavailable, and `uv venv` runs in the runner workspace root rather than the
checkout, so a `.python-version` file cannot reach it. The non-light fallback
(`uv pip install "./pkg[dev]"`) fails identically, so this is not specific to
the mock-deps path — it blocks any package requiring 3.12+.
huggingface/doc-builder#808 adds a `python_version` input to both build
workflows, which this passes. Pins move to that merge commit, picking up three
unrelated fixes in the same range (#810, #811, #812); the upload workflow is
unchanged there and is bumped only to keep all three pins on one SHA.
* chore: sort imports in vla_jepa tests
Enabling pydocstyle in the previous commit changes how ruff determines where a
module's import block ends, which makes I001 fire on three vla_jepa tests that
were clean before. The blank line between the `conftest` and `lerobot` imports
is the trigger: both are first-party, so isort wants them in one contiguous
block, and the docstring-aware analysis is what makes it notice.
These files are unrelated to the API reference, so the fix is only to satisfy
the new gate.
639 lines
24 KiB
TOML
639 lines
24 KiB
TOML
# Copyright 2024 The HuggingFace Inc. team. All rights reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
[build-system]
|
|
requires = ["setuptools"]
|
|
build-backend = "setuptools.build_meta"
|
|
|
|
[project.urls]
|
|
homepage = "https://huggingface.co/lerobot"
|
|
documentation = "https://huggingface.co/docs/lerobot/index"
|
|
source = "https://github.com/huggingface/lerobot"
|
|
issues = "https://github.com/huggingface/lerobot/issues"
|
|
discord = "https://discord.gg/s3KuuzsPFb"
|
|
|
|
[project]
|
|
name = "lerobot"
|
|
version = "0.6.2"
|
|
description = "🤗 LeRobot: State-of-the-art Machine Learning for Real-World Robotics in Pytorch"
|
|
dynamic = ["readme"]
|
|
license = { text = "Apache-2.0" }
|
|
requires-python = ">=3.12"
|
|
authors = [
|
|
{ name = "Rémi Cadène", email = "re.cadene@gmail.com" },
|
|
{ name = "Simon Alibert", email = "alibert.sim@gmail.com" },
|
|
{ name = "Alexander Soare", email = "alexander.soare159@gmail.com" },
|
|
{ name = "Quentin Gallouédec", email = "quentin.gallouedec@ec-lyon.fr" },
|
|
{ name = "Steven Palma", email = "imstevenpmwork@ieee.org" },
|
|
{ name = "Pepijn Kooijmans", email = "pepijnkooijmans@outlook.com"},
|
|
{ name = "Michel Aractingi", email = "michel.aractingi@gmail.com"},
|
|
{ name = "Adil Zouitine", email = "adilzouitinegm@gmail.com" },
|
|
{ name = "Dana Aubakirova", email = "danaaubakirova17@gmail.com"},
|
|
{ name = "Caroline Pascal", email = "caroline8.pascal@gmail.com"},
|
|
{ name = "Martino Russi", email = "nopyeps@gmail.com"},
|
|
{ name = "Thomas Wolf", email = "thomaswolfcontact@gmail.com" },
|
|
]
|
|
classifiers = [
|
|
"Development Status :: 3 - Alpha",
|
|
"Intended Audience :: Developers",
|
|
"Intended Audience :: Education",
|
|
"Intended Audience :: Science/Research",
|
|
"License :: OSI Approved :: Apache Software License",
|
|
"Programming Language :: Python :: 3.12",
|
|
"Programming Language :: Python :: 3.13",
|
|
"Topic :: Software Development :: Build Tools",
|
|
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
]
|
|
keywords = ["lerobot", "huggingface", "robotics", "machine learning", "artificial intelligence"]
|
|
|
|
dependencies = [
|
|
# Core ML
|
|
"torch>=2.7,<2.12.0",
|
|
"torchvision>=0.22.0,<0.27.0",
|
|
"numpy>=2.0.0,<2.3.0", # NOTE: Explicitly listing numpy helps the resolver converge faster. Upper bound imposed by opencv-python-headless.
|
|
"opencv-python-headless>=4.9.0,<4.14.0",
|
|
"Pillow>=10.0.0,<13.0.0",
|
|
"einops>=0.8.0,<0.9.0",
|
|
|
|
# Config & Hub
|
|
"draccus>=0.11.6,<0.12.0",
|
|
"huggingface-hub>=1.6.0,<2.0.0",
|
|
"requests>=2.32.0,<3.0.0",
|
|
|
|
# Environments
|
|
# NOTE: gymnasium is used in lerobot.envs (lerobot-train, lerobot-eval), policies/factory,
|
|
# and robots/unitree. Moving it to an optional extra would require import guards across many
|
|
# tightly-coupled modules. Candidate for a future refactor to decouple envs from the core.
|
|
"gymnasium>=1.1.1,<2.0.0",
|
|
|
|
# Serialization & checkpointing
|
|
"safetensors>=0.4.3,<1.0.0",
|
|
|
|
# Lightweight utilities
|
|
"packaging>=24.2,<26.0",
|
|
"termcolor>=2.4.0,<4.0.0",
|
|
"tqdm>=4.66.0,<5.0.0",
|
|
|
|
# Build tools (required by opencv-python-headless on some platforms)
|
|
"cmake>=3.29.0.1,<4.2.0",
|
|
"setuptools>=71.0.0,<82.0.0", # torch 2.11 requires setuptools<82; a higher cap makes the resolver downgrade torch
|
|
]
|
|
|
|
# Optional dependencies
|
|
[project.optional-dependencies]
|
|
|
|
# ── Feature-scoped extras ──────────────────────────────────
|
|
dataset = [
|
|
"datasets>=4.8.0,<5.0.0",
|
|
"pandas>=2.0.0,<3.0.0", # NOTE: Transitive dependency of datasets
|
|
"pyarrow>=21.0.0,<30.0.0", # NOTE: Transitive dependency of datasets
|
|
"lerobot[av-dep]",
|
|
|
|
# NOTE: torchcodec wheel availability matrix (PyPI):
|
|
# - linux x86_64/amd64 + macOS arm64 : wheels since 0.3.0 (the historic supported set).
|
|
# - win32 x86_64 : wheels since 0.7.0 (needs torch>=2.8).
|
|
# - linux aarch64/arm64 : wheels since 0.11.0 (needs torch>=2.11).
|
|
# - macOS x86_64 (Intel) and linux armv7l: no wheels in any released version -> fall through to the PyAV decoder.
|
|
# Each platform gets its own line so the resolver picks the minimum version that has a wheel for it.
|
|
|
|
# Other torch/torchcodec pairings (informational): 0.8.1 = ffmpeg>=8 support, 0.10 = system-wide ffmpeg support, 0.12 needs torch==2.12.
|
|
"torchcodec>=0.3.0,<0.12.0; (sys_platform == 'linux' and (platform_machine == 'x86_64' or platform_machine == 'AMD64')) or (sys_platform == 'darwin' and platform_machine == 'arm64')",
|
|
"torchcodec>=0.7.0,<0.12.0; sys_platform == 'win32'",
|
|
"torchcodec>=0.11.0,<0.12.0; sys_platform == 'linux' and (platform_machine == 'aarch64' or platform_machine == 'arm64')",
|
|
"jsonlines>=4.0.0,<5.0.0",
|
|
]
|
|
training = [
|
|
"lerobot[dataset]",
|
|
"wandb>=0.24.0,<0.28.0",
|
|
"lerobot[accelerate-dep]",
|
|
]
|
|
hardware = [
|
|
"lerobot[pynput-dep]",
|
|
"lerobot[pyserial-dep]",
|
|
"lerobot[deepdiff-dep]",
|
|
]
|
|
viz = [
|
|
"rerun-sdk>=0.24.0,<0.34.0",
|
|
"foxglove-sdk>=0.25.1,<0.26.0",
|
|
]
|
|
# ── User-facing composite extras (map to CLI scripts) ─────
|
|
# lerobot-record, lerobot-replay, lerobot-calibrate, lerobot-teleoperate, etc.
|
|
core_scripts = ["lerobot[dataset]", "lerobot[hardware]", "lerobot[viz]"]
|
|
# lerobot-eval -- base evaluation framework. You also need the policy's extra (e.g., lerobot[pi])
|
|
# and the environment's extra (e.g., lerobot[pusht]) if evaluating in simulation.
|
|
evaluation = ["lerobot[av-dep]"]
|
|
# lerobot-dataset-viz, lerobot-imgtransform-viz
|
|
dataset_viz = ["lerobot[dataset]", "lerobot[viz]"]
|
|
|
|
# Common
|
|
av-dep = ["av>=15.0.0,<16.0.0"]
|
|
pygame-dep = ["pygame>=2.5.1,<2.7.0"]
|
|
# NOTE: 0.9.16 links against liburdfdom_sensor.so.4, which is unavailable on Ubuntu 24.04
|
|
# (noble ships urdfdom 3.x). Cap below 0.9.16 until system urdfdom 4.x is broadly available.
|
|
#
|
|
# NOTE: placo pulls in pin (Pinocchio), whose binary wheels dlopen specific cmeel sonames
|
|
# (liburdfdom_sensor.so.4.0, libtinyxml2.so.10) but declare only `>=` floors on their cmeel
|
|
# packages. The 2026-05-21 major bumps (cmeel-urdfdom 6.0.0 -> .so.6, cmeel-tinyxml2 11.0.0
|
|
# -> .so.11) ship newer sonames, so left unpinned the resolver grabs them and `import placo`
|
|
# fails at load with "liburdfdom_sensor.so.4.0: cannot open shared object file" (see #3755).
|
|
# There is no cmeel-urdfdom 5.x; <5 selects the 4.x ABI the placo/pin wheels are built against.
|
|
placo-dep = ["placo>=0.9.6,<0.9.16", "cmeel-urdfdom>=4,<5", "cmeel-tinyxml2<11"]
|
|
transformers-dep = ["transformers>=5.4.0,<5.6.0"]
|
|
grpcio-dep = ["grpcio>=1.73.1,<2.0.0", "protobuf>=6.31.1,<8.0.0"]
|
|
accelerate-dep = ["accelerate>=1.14.0,<2.0.0"]
|
|
can-dep = ["python-can>=4.2.0,<5.0.0"]
|
|
peft-dep = ["peft>=0.18.0,<1.0.0"]
|
|
scipy-dep = ["scipy>=1.14.0,<2.0.0"]
|
|
diffusers-dep = ["diffusers>=0.38.0,<0.40.0"]
|
|
qwen-vl-utils-dep = ["qwen-vl-utils>=0.0.11,<0.1.0"]
|
|
matplotlib-dep = ["matplotlib>=3.10.3,<4.0.0", "contourpy>=1.3.0,<2.0.0"] # NOTE: Explicitly listing contourpy helps the resolver converge faster.
|
|
pyserial-dep = ["pyserial>=3.5,<4.0"]
|
|
deepdiff-dep = ["deepdiff>=7.0.1,<9.0.0"]
|
|
pynput-dep = ["pynput>=1.7.8,<1.9.0"]
|
|
pyzmq-dep = ["pyzmq>=26.2.1,<28.0.0"]
|
|
motorbridge-dep = ["motorbridge>=0.3.2,<0.4.0"]
|
|
motorbridge-smart-servo-dep = ["motorbridge-smart-servo>=0.0.4,<0.1.0"]
|
|
timm-dep = ["timm>=1.0.0,<1.1.0"]
|
|
|
|
# Motors
|
|
feetech = ["feetech-servo-sdk>=1.0.0,<2.0.0", "lerobot[pyserial-dep]", "lerobot[deepdiff-dep]"]
|
|
dynamixel = ["dynamixel-sdk>=3.7.31,<3.9.0", "lerobot[pyserial-dep]", "lerobot[deepdiff-dep]"]
|
|
damiao = ["lerobot[can-dep]"]
|
|
robstride = ["lerobot[can-dep]"]
|
|
|
|
# Robots
|
|
openarms = ["lerobot[damiao]"]
|
|
gamepad = ["lerobot[pygame-dep]", "hidapi>=0.14.0,<0.15.0"]
|
|
hopejr = ["lerobot[feetech]", "lerobot[pygame-dep]"]
|
|
lekiwi = ["lerobot[feetech]", "lerobot[pyzmq-dep]"]
|
|
unitree_g1 = [
|
|
# "unitree-sdk2==1.0.1",
|
|
"lerobot[pyzmq-dep]",
|
|
"lerobot[pyserial-dep]",
|
|
"onnxruntime>=1.16.0,<2.0.0",
|
|
"onnx>=1.16.0,<2.0.0",
|
|
"meshcat>=0.3.0,<0.4.0",
|
|
"lerobot[matplotlib-dep]",
|
|
"lerobot[pygame-dep]",
|
|
]
|
|
# reachy2-sdk caps grpcio<=1.73.1 and protobuf<=6.32.0; quarantined here so downstream users aren't held back. reachy2-sdk is unlikely to release new versions.
|
|
reachy2 = [
|
|
"reachy2_sdk>=1.0.15,<1.1.0",
|
|
"grpcio<=1.73.1",
|
|
"protobuf<=6.32.0",
|
|
]
|
|
# Seeed Studio reBot B601-DM follower (motorbridge / CAN) + StarArm102 / reBot Arm 102
|
|
# leader (motorbridge-smart-servo / FashionStar UART servos).
|
|
rebot = ["lerobot[motorbridge-dep]", "lerobot[motorbridge-smart-servo-dep]"]
|
|
kinematics = ["lerobot[placo-dep]"]
|
|
intelrealsense = [
|
|
"pyrealsense2>=2.55.1.6486,<2.57.0 ; sys_platform != 'darwin'",
|
|
"pyrealsense2-macosx>=2.54,<2.57.0 ; sys_platform == 'darwin'",
|
|
]
|
|
phone = ["hebi-py>=2.8.0,<2.12.0", "teleop>=0.1.0,<0.2.0", "fastapi<1.0", "lerobot[scipy-dep]"]
|
|
|
|
# Policies
|
|
diffusion = ["lerobot[diffusers-dep]"]
|
|
wallx = [
|
|
"lerobot[transformers-dep]",
|
|
"lerobot[peft-dep]",
|
|
"lerobot[scipy-dep]",
|
|
"torchdiffeq>=0.2.4,<0.3.0",
|
|
"lerobot[qwen-vl-utils-dep]",
|
|
]
|
|
pi = ["lerobot[transformers-dep]", "lerobot[scipy-dep]"]
|
|
molmoact2 = ["lerobot[transformers-dep]", "lerobot[peft-dep]", "lerobot[scipy-dep]"]
|
|
smolvla = ["lerobot[transformers-dep]", "num2words>=0.5.14,<0.6.0", "lerobot[accelerate-dep]"]
|
|
multi_task_dit = ["lerobot[transformers-dep]", "lerobot[diffusers-dep]"]
|
|
groot = [
|
|
"lerobot[transformers-dep]",
|
|
"lerobot[peft-dep]",
|
|
"lerobot[diffusers-dep]",
|
|
"lerobot[dataset]", # NOTE: processor_groot builds a LeRobotDataset for relative-action training stats
|
|
"dm-tree>=0.1.8,<1.0.0",
|
|
"lerobot[timm-dep]",
|
|
"decord>=0.6.0,<1.0.0; (platform_machine == 'AMD64' or platform_machine == 'x86_64')",
|
|
]
|
|
sarm = ["lerobot[transformers-dep]", "pydantic>=2.0.0,<3.0.0", "faker>=33.0.0,<35.0.0", "lerobot[matplotlib-dep]", "lerobot[qwen-vl-utils-dep]"]
|
|
robometer = ["lerobot[transformers-dep]", "lerobot[qwen-vl-utils-dep]", "lerobot[peft-dep]"]
|
|
topreward = ["lerobot[transformers-dep]"]
|
|
xvla = ["lerobot[transformers-dep]"]
|
|
eo1 = ["lerobot[transformers-dep]", "lerobot[qwen-vl-utils-dep]"]
|
|
fastwam = [
|
|
"lerobot[transformers-dep]",
|
|
"lerobot[diffusers-dep]",
|
|
]
|
|
evo1 = ["lerobot[transformers-dep]"]
|
|
hilserl = ["lerobot[transformers-dep]", "lerobot[dataset]", "gym-hil>=0.1.14,<0.2.0", "lerobot[grpcio-dep]", "lerobot[placo-dep]"]
|
|
vla_jepa = ["lerobot[transformers-dep]", "lerobot[diffusers-dep]", "lerobot[qwen-vl-utils-dep]"]
|
|
lingbot_va = ["lerobot[transformers-dep]", "lerobot[diffusers-dep]", "lerobot[accelerate-dep]"]
|
|
|
|
# Features
|
|
async = ["lerobot[grpcio-dep]", "lerobot[matplotlib-dep]"]
|
|
peft = ["lerobot[transformers-dep]", "lerobot[peft-dep]"]
|
|
|
|
# Annotation pipeline (lerobot-annotate). The only backend is ``openai``,
|
|
# which talks to any OpenAI-compatible server (``vllm serve`` /
|
|
# ``transformers serve`` / hosted). Distributed runs use Hugging Face Jobs
|
|
# (see examples/annotations/run_hf_job.py).
|
|
annotations = [
|
|
"lerobot[dataset]",
|
|
"lerobot[transformers-dep]",
|
|
"openai>=1.40,<2.0",
|
|
# ``vllm`` is intentionally NOT a hard dep: it pins an older torch, and
|
|
# uv's single unified lock would then cap ``torch`` for every extra
|
|
# (e.g. forcing 2.8 while ``torchcodec`` in [dataset] needs 2.11 -> ABI
|
|
# break in CI). The HF Jobs image (``vllm/vllm-openai``) provides vLLM;
|
|
# install it locally only if you run your own ``vllm serve``.
|
|
]
|
|
|
|
# Development
|
|
dev = ["pre-commit>=3.7.0,<5.0.0", "debugpy>=1.8.1,<1.9.0", "lerobot[grpcio-dep]", "grpcio-tools>=1.73.1,<2.0.0", "mypy>=1.19.1", "ruff>=0.14.1", "lerobot[notebook]"]
|
|
notebook = ["jupyter>=1.0.0,<2.0.0", "ipykernel>=6.0.0,<7.0.0"]
|
|
test = ["pytest>=8.1.0,<10.0.0", "pytest-timeout>=2.4.0,<3.0.0", "pytest-cov>=5.0.0,<8.0.0", "mock-serial>=0.0.1,<0.1.0 ; sys_platform != 'win32'"]
|
|
video_benchmark = ["scikit-image>=0.23.2,<0.26.0", "pandas>=2.2.2,<2.4.0"]
|
|
|
|
# Simulation
|
|
# NOTE: Explicitly listing scipy helps flatten the dependecy tree.
|
|
aloha = ["lerobot[dataset]", "gym-aloha>=0.1.4,<0.2.0", "lerobot[scipy-dep]"]
|
|
pusht = ["lerobot[dataset]", "gym-pusht>=0.1.5,<0.2.0", "pymunk>=6.6.0,<7.0.0"] # TODO: Fix pymunk version in gym-pusht instead
|
|
libero = ["lerobot[dataset]", "lerobot[transformers-dep]", "hf-libero>=0.1.4,<0.2.0; sys_platform == 'linux'", "lerobot[scipy-dep]"]
|
|
metaworld = ["lerobot[dataset]", "metaworld==3.0.0", "lerobot[scipy-dep]"]
|
|
# NOTE: vlabench is NOT exposed as a `lerobot` extra. Its only distribution
|
|
# is the OpenMOSS/VLABench GitHub repo (package name `VLABench`, no PyPI
|
|
# release), so any `vlabench>=X` pip spec is unresolvable. Install it
|
|
# manually alongside MuJoCo / dm-control — see docs/source/vlabench.mdx
|
|
# for the recipe.
|
|
# NOTE: robomme is NOT a pyproject extra — mani-skill hard-pins numpy<2
|
|
# which conflicts with lerobot's numpy>=2 base pin, so the two trees can't
|
|
# resolve into a single env. Install it only in the RoboMME Docker image
|
|
# via `uv pip install --override` (see docker/Dockerfile.benchmark.robomme).
|
|
# NOTE: robocasa is NOT exposed as a `lerobot` extra. Its setup.py pins
|
|
# `lerobot==0.3.3` in install_requires, which cyclically shadows our own
|
|
# workspace `lerobot` and makes the graph unsolvable under any resolver
|
|
# (uv, pip). Install it manually alongside robosuite — see
|
|
# docs/source/robocasa.mdx for the recipe.
|
|
|
|
# All
|
|
all = [
|
|
# Feature-scoped extras
|
|
"lerobot[dataset]",
|
|
"lerobot[training]",
|
|
"lerobot[hardware]",
|
|
"lerobot[viz]",
|
|
# NOTE(resolver hint): scipy is pulled in transitively via lerobot[scipy-dep] through
|
|
# multiple extras (aloha, metaworld, pi, wallx, phone). Listing it explicitly
|
|
# helps pip's resolver converge by constraining scipy early, before it encounters
|
|
# the loose scipy requirements from transitive deps like dm-control and metaworld.
|
|
"scipy>=1.14.0,<2.0.0",
|
|
"lerobot[dynamixel]",
|
|
"lerobot[feetech]",
|
|
"lerobot[damiao]",
|
|
"lerobot[robstride]",
|
|
"lerobot[gamepad]",
|
|
"lerobot[hopejr]",
|
|
"lerobot[lekiwi]",
|
|
"lerobot[openarms]",
|
|
"lerobot[reachy2]",
|
|
"lerobot[rebot]",
|
|
"lerobot[kinematics]",
|
|
"lerobot[intelrealsense]",
|
|
"lerobot[diffusion]",
|
|
"lerobot[multi_task_dit]",
|
|
"lerobot[wallx]",
|
|
"lerobot[pi]",
|
|
"lerobot[molmoact2]",
|
|
"lerobot[smolvla]",
|
|
"lerobot[fastwam]",
|
|
"lerobot[groot]",
|
|
"lerobot[xvla]",
|
|
"lerobot[evo1]",
|
|
"lerobot[hilserl]",
|
|
"lerobot[vla_jepa]",
|
|
"lerobot[lingbot_va]",
|
|
"lerobot[async]",
|
|
"lerobot[dev]",
|
|
"lerobot[test]",
|
|
"lerobot[video_benchmark]",
|
|
"lerobot[aloha]",
|
|
"lerobot[pusht]",
|
|
"lerobot[phone]",
|
|
"lerobot[libero]; sys_platform == 'linux'",
|
|
"lerobot[metaworld]",
|
|
"lerobot[sarm]",
|
|
"lerobot[robometer]",
|
|
"lerobot[topreward]",
|
|
"lerobot[peft]",
|
|
# "lerobot[unitree_g1]", TODO: Unitree requires specific installation instructions for unitree_sdk2
|
|
]
|
|
|
|
[project.scripts]
|
|
lerobot-calibrate="lerobot.scripts.lerobot_calibrate:main"
|
|
lerobot-find-cameras="lerobot.scripts.lerobot_find_cameras:main"
|
|
lerobot-find-port="lerobot.scripts.lerobot_find_port:main"
|
|
lerobot-record="lerobot.scripts.lerobot_record:main"
|
|
lerobot-replay="lerobot.scripts.lerobot_replay:main"
|
|
lerobot-setup-motors="lerobot.scripts.lerobot_setup_motors:main"
|
|
lerobot-teleoperate="lerobot.scripts.lerobot_teleoperate:main"
|
|
lerobot-convert-dcp="lerobot.scripts.lerobot_convert_dcp:main"
|
|
lerobot-eval="lerobot.scripts.lerobot_eval:main"
|
|
lerobot-train="lerobot.scripts.lerobot_train:main"
|
|
lerobot-train-tokenizer="lerobot.scripts.lerobot_train_tokenizer:main"
|
|
lerobot-dataset-viz="lerobot.scripts.lerobot_dataset_viz:main"
|
|
lerobot-info="lerobot.scripts.lerobot_info:main"
|
|
lerobot-find-joint-limits="lerobot.scripts.lerobot_find_joint_limits:main"
|
|
lerobot-imgtransform-viz="lerobot.scripts.lerobot_imgtransform_viz:main"
|
|
lerobot-edit-dataset="lerobot.scripts.lerobot_edit_dataset:main"
|
|
lerobot-setup-can="lerobot.scripts.lerobot_setup_can:main"
|
|
lerobot-annotate="lerobot.scripts.lerobot_annotate:main"
|
|
lerobot-rollout="lerobot.scripts.lerobot_rollout:main"
|
|
|
|
# ---------------- Tool Configurations ----------------
|
|
|
|
# cu128 wheels keep broad hardware reach; the driver floor is 570.86.
|
|
# To use a different CUDA variant, reinstall torch with an explicit index, e.g.:
|
|
# uv pip install --force-reinstall torch torchvision \
|
|
# --index-url https://download.pytorch.org/whl/cu130
|
|
[[tool.uv.index]]
|
|
name = "pytorch-cu128"
|
|
url = "https://download.pytorch.org/whl/cu128"
|
|
explicit = true
|
|
|
|
[tool.uv.sources]
|
|
torch = [{ index = "pytorch-cu128", marker = "sys_platform == 'linux'" }]
|
|
torchvision = [{ index = "pytorch-cu128", marker = "sys_platform == 'linux'" }]
|
|
|
|
[tool.setuptools.package-data]
|
|
lerobot = ["envs/*.json", "annotations/steerable_pipeline/prompts/*.txt"]
|
|
|
|
[tool.setuptools.packages.find]
|
|
where = ["src"]
|
|
|
|
[tool.ruff]
|
|
target-version = "py312"
|
|
line-length = 110
|
|
exclude = ["tests/artifacts/**/*.safetensors", "*_pb2.py", "*_pb2_grpc.py"]
|
|
|
|
[tool.ruff.lint]
|
|
# E, W: pycodestyle errors and warnings
|
|
# F: PyFlakes
|
|
# I: isort
|
|
# UP: pyupgrade
|
|
# B: flake8-bugbear (good practices, potential bugs)
|
|
# C4: flake8-comprehensions (more concise comprehensions)
|
|
# A: flake8-builtins (shadowing builtins)
|
|
# SIM: flake8-simplify
|
|
# RUF: Ruff-specific rules
|
|
# D: pydocstyle (for docstring style/formatting)
|
|
# S: flake8-bandit (some security checks, complements Bandit)
|
|
# T20: flake8-print (discourage print statements in production code)
|
|
# N: pep8-naming
|
|
# TODO: Uncomment rules when ready to use
|
|
select = [
|
|
"E", "W", "F", "I", "B", "C4", "T20", "N", "UP", "SIM", "D" #, "A", "S", "RUF"
|
|
]
|
|
ignore = [
|
|
"E501", # Line too long
|
|
"T201", # Print statement found
|
|
"T203", # Pprint statement found
|
|
"B008", # Perform function call in argument defaults
|
|
]
|
|
|
|
[tool.ruff.lint.per-file-ignores]
|
|
"__init__.py" = ["F401", "F403", "E402", "D104"]
|
|
# E402: conditional-import guards (TYPE_CHECKING / is_package_available) must precede the imports they protect
|
|
"src/lerobot/scripts/convert_dataset_v21_to_v30.py" = ["E402"]
|
|
|
|
# D (pydocstyle) is enabled globally, but only holds for code that has been converted to the docstring
|
|
# standard in docs/source/writing_docstrings.mdx. Every module below is still on the old style; each entry
|
|
# is deleted as that module is converted, and this block can be removed once it is empty.
|
|
#
|
|
# Not part of the API reference and not planned for conversion: tests, examples, benchmarks, templates,
|
|
# CI helper scripts and the packaging shim.
|
|
"tests/**" = ["D"]
|
|
"examples/**" = ["D"]
|
|
"benchmarks/**" = ["D"]
|
|
"scripts/**" = ["D"]
|
|
"setup.py" = ["D"]
|
|
"src/lerobot/templates/**" = ["D"]
|
|
# Vendored from transformers; keeps its upstream docstring style so syncs stay clean.
|
|
"src/lerobot/policies/molmoact2/molmoact2_hf_model/**" = ["D"]
|
|
# Awaiting conversion, one PR per module.
|
|
"src/lerobot/annotations/**" = ["D"]
|
|
"src/lerobot/async_inference/**" = ["D"]
|
|
"src/lerobot/cameras/**" = ["D"]
|
|
"src/lerobot/common/**" = ["D"]
|
|
"src/lerobot/configs/**" = ["D"]
|
|
"src/lerobot/data_processing/**" = ["D"]
|
|
"src/lerobot/datasets/**" = ["D"]
|
|
"src/lerobot/distributed/**" = ["D"]
|
|
"src/lerobot/envs/**" = ["D"]
|
|
"src/lerobot/jobs/**" = ["D"]
|
|
"src/lerobot/model/**" = ["D"]
|
|
"src/lerobot/motors/**" = ["D"]
|
|
"src/lerobot/optim/**" = ["D"]
|
|
"src/lerobot/policies/**" = ["D"]
|
|
"src/lerobot/processor/**" = ["D"]
|
|
"src/lerobot/rewards/**" = ["D"]
|
|
"src/lerobot/rl/**" = ["D"]
|
|
"src/lerobot/robots/**" = ["D"]
|
|
"src/lerobot/rollout/**" = ["D"]
|
|
"src/lerobot/scripts/**" = ["D"]
|
|
"src/lerobot/teleoperators/**" = ["D"]
|
|
"src/lerobot/transforms/**" = ["D"]
|
|
"src/lerobot/transport/**" = ["D"]
|
|
"src/lerobot/utils/**" = ["D"]
|
|
"src/lerobot/lerobot_types.py" = ["D"]
|
|
# Package root: two one-line docstring fixes land with the docstring PR.
|
|
"src/lerobot/__init__.py" = ["D"]
|
|
"src/lerobot/__version__.py" = ["D"]
|
|
[tool.ruff.lint.isort]
|
|
combine-as-imports = true
|
|
known-first-party = ["lerobot"]
|
|
|
|
[tool.ruff.lint.pydocstyle]
|
|
convention = "google"
|
|
|
|
[tool.ruff.format]
|
|
quote-style = "double"
|
|
indent-style = "space"
|
|
skip-magic-trailing-comma = false
|
|
line-ending = "auto"
|
|
docstring-code-format = true
|
|
|
|
[tool.bandit]
|
|
exclude_dirs = [
|
|
"tests",
|
|
"benchmarks",
|
|
"src/lerobot/datasets/push_dataset_to_hub",
|
|
]
|
|
skips = ["B101", "B311", "B404", "B603", "B615"]
|
|
|
|
[tool.typos]
|
|
default.extend-ignore-re = [
|
|
"(?Rm)^.*(#|//)\\s*spellchecker:disable-line$", # spellchecker:disable-line
|
|
"(?s)(#|//)\\s*spellchecker:off.*?\\n\\s*(#|//)\\s*spellchecker:on", # spellchecker:<on|off>
|
|
]
|
|
default.extend-ignore-identifiers-re = [
|
|
# Add individual words here to ignore them
|
|
"2nd",
|
|
"pn",
|
|
"ser",
|
|
"ein",
|
|
"thw",
|
|
"inpt",
|
|
"arange",
|
|
"is_compileable",
|
|
"ROBOTIS",
|
|
"OT_VALUE",
|
|
"VanderBilt",
|
|
"seperated_timestep",
|
|
]
|
|
|
|
# Docstring coverage gate. `fail-under` is a RATCHET, not a target: it is set just below the currently
|
|
# measured coverage so it passes today, and is raised in the same PR that documents a module. Never set it
|
|
# to a value that fails on main. The destination is 100; see docs/source/writing_docstrings.mdx.
|
|
[tool.interrogate]
|
|
ignore-init-module = true
|
|
ignore-init-method = true
|
|
ignore-nested-functions = false
|
|
ignore-magic = false
|
|
ignore-semiprivate = false
|
|
ignore-private = false
|
|
ignore-property-decorators = false
|
|
ignore-module = false
|
|
ignore-setters = false
|
|
fail-under = 52
|
|
output-format = "term-missing"
|
|
color = true
|
|
paths = ["src/lerobot"]
|
|
exclude = ["src/lerobot/policies/molmoact2/molmoact2_hf_model"]
|
|
|
|
# TODO: Enable mypy gradually module by module across multiple PRs
|
|
# Uncomment [tool.mypy] first, then uncomment individual module overrides as they get proper type annotations
|
|
|
|
[tool.pytest.ini_options]
|
|
markers = [
|
|
"multigpu: distributed tests needing 2-4 GPUs (CI: docker_publish.yml lane)",
|
|
"multigpu_heavy: 8-GPU sweeps and soak tests; never run in CI",
|
|
]
|
|
|
|
[tool.mypy]
|
|
python_version = "3.12"
|
|
ignore_missing_imports = true
|
|
follow_imports = "skip"
|
|
# warn_return_any = true
|
|
# warn_unused_configs = true
|
|
# strict = true
|
|
# disallow_untyped_defs = true
|
|
# disallow_incomplete_defs = true
|
|
# check_untyped_defs = true
|
|
|
|
[[tool.mypy.overrides]]
|
|
module = "lerobot.*"
|
|
ignore_errors = true
|
|
|
|
[[tool.mypy.overrides]]
|
|
module = "lerobot.envs.*"
|
|
ignore_errors = false
|
|
|
|
[[tool.mypy.overrides]]
|
|
module = "lerobot.annotations.*"
|
|
ignore_errors = false
|
|
disallow_untyped_defs = true
|
|
disallow_incomplete_defs = true
|
|
check_untyped_defs = true
|
|
|
|
[[tool.mypy.overrides]]
|
|
module = "lerobot.transforms.*"
|
|
ignore_errors = false
|
|
disallow_untyped_defs = true
|
|
disallow_incomplete_defs = true
|
|
check_untyped_defs = true
|
|
|
|
# [[tool.mypy.overrides]]
|
|
# module = "lerobot.utils.*"
|
|
# ignore_errors = false
|
|
|
|
[[tool.mypy.overrides]]
|
|
module = "lerobot.configs.*"
|
|
ignore_errors = false
|
|
|
|
# extra strictness for configs
|
|
disallow_untyped_defs = true
|
|
disallow_incomplete_defs = true
|
|
check_untyped_defs = true
|
|
|
|
[[tool.mypy.overrides]]
|
|
module = "lerobot.distributed.*"
|
|
ignore_errors = false
|
|
|
|
# extra strictness for the distributed engine
|
|
disallow_untyped_defs = true
|
|
disallow_incomplete_defs = true
|
|
check_untyped_defs = true
|
|
|
|
[[tool.mypy.overrides]]
|
|
module = "lerobot.optim.*"
|
|
ignore_errors = false
|
|
|
|
[[tool.mypy.overrides]]
|
|
module = "lerobot.model.*"
|
|
ignore_errors = false
|
|
|
|
# [[tool.mypy.overrides]]
|
|
# module = "lerobot.processor.*"
|
|
# ignore_errors = false
|
|
|
|
# [[tool.mypy.overrides]]
|
|
# module = "lerobot.datasets.*"
|
|
# ignore_errors = false
|
|
|
|
[[tool.mypy.overrides]]
|
|
module = "lerobot.cameras.*"
|
|
ignore_errors = false
|
|
|
|
[[tool.mypy.overrides]]
|
|
module = "lerobot.motors.*"
|
|
ignore_errors = false
|
|
|
|
# [[tool.mypy.overrides]]
|
|
# module = "lerobot.robots.*"
|
|
# ignore_errors = false
|
|
|
|
# [[tool.mypy.overrides]]
|
|
# module = "lerobot.teleoperators.*"
|
|
# ignore_errors = false
|
|
|
|
# [[tool.mypy.overrides]]
|
|
# module = "lerobot.policies.*"
|
|
# ignore_errors = false
|
|
|
|
# [[tool.mypy.overrides]]
|
|
# module = "lerobot.rl.*"
|
|
# ignore_errors = false
|
|
|
|
|
|
# [[tool.mypy.overrides]]
|
|
# module = "lerobot.async_inference.*"
|
|
# ignore_errors = false
|
|
|
|
[[tool.mypy.overrides]]
|
|
module = "lerobot.transport.*"
|
|
ignore_errors = false
|
|
|
|
# [[tool.mypy.overrides]]
|
|
# module = "lerobot.scripts.*"
|
|
# ignore_errors = false
|