Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# SCM syntax highlighting & preventing 3-way merges
pixi.lock merge=binary linguist-language=YAML linguist-generated=true
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# Core maintainers
* @slecleach @pculbertson-bdai
* @slecleach @pculbertson @pculbertson-bdai @alberthli
44 changes: 0 additions & 44 deletions .github/workflows/build.yml

This file was deleted.

10 changes: 10 additions & 0 deletions .github/workflows/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
groups:
dependencies:
patterns:
- "*"
17 changes: 10 additions & 7 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,31 @@ permissions:

jobs:
docs:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
steps:
# Check out source
- uses: actions/checkout@v4

# Set up Python
- name: "Set up Python 3.10"
- uses: prefix-dev/setup-pixi@v0.8.8
with:
pixi-version: v0.47.0
cache: true

- name: "Set up Python 3.13"
uses: actions/setup-python@v5
with:
python-version: "3.10"
python-version: "3.13"

# Build documentation
- name: Building documentation
run: |
pip install uv
uv pip install --system -e ".[dev]"
uv pip install --system -r docs/requirements.txt
sphinx-build docs/source docs/build -b dirhtml

# Deploy
- name: Deploy to GitHub Pages
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs/build
force_orphan: true
60 changes: 36 additions & 24 deletions .github/workflows/precommit.yml
Original file line number Diff line number Diff line change
@@ -1,38 +1,50 @@
name: Pre-commit Checks
name: Precommit

on:
push:
branches: [ main ]
branches: [main]
pull_request:
workflow_dispatch:
branches: [main]

permissions:
contents: read

jobs:
precommit:
runs-on: ubuntu-22.04

build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
python-version: ['3.10']
os: [ubuntu-22.04]

os: [ubuntu-22.04, ubuntu-24.04]
python-version: ['3.10', '3.11', '3.12', '3.13']
steps:
- name: Checkout code
uses: actions/checkout@v4
- uses: actions/checkout@v4

- uses: prefix-dev/setup-pixi@v0.8.8
with:
pixi-version: v0.47.0
cache: true

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Restore typings cache
uses: actions/cache@v4
id: typings-cache
with:
path: typings
key: typings-${{ matrix.os }}-${{ matrix.python-version }}-${{ hashFiles('pyproject.toml') }}

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Generate stubs if cache miss
if: steps.typings-cache.outputs.cache-hit != 'true'
run: pixi run -e dev pybind11-stubgen mujoco -o typings/

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pre-commit
- name: Run Ruff Linter
run: pixi run -e dev ruff check judo/ tests/ --output-format=github

- name: Install pre-commit hooks
run: pre-commit install
- name: Run Ruff Formatter
run: pixi run -e dev ruff format judo/ tests/ --diff

- name: Run pre-commit hooks
run: pre-commit run --all-files
- name: Run Pyright
run: pixi run -e dev pyright
33 changes: 33 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Test

on:
push:
branches: [main]
pull_request:
branches: [main]

permissions:
contents: read

jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-22.04, ubuntu-24.04]
python-version: ['3.10', '3.11', '3.12', '3.13']
steps:
- uses: actions/checkout@v4

- uses: prefix-dev/setup-pixi@v0.8.8
with:
pixi-version: v0.47.0
cache: true

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Test with pytest
run: pixi run -e dev pytest -rsx
40 changes: 30 additions & 10 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
# model weights
**/*.pt

# Byte-compiled / optimized / DLL files
**/__pycache__
__pycache__/
*.py[cod]
*$py.class
Expand All @@ -29,7 +25,6 @@ share/python-wheels/
.installed.cfg
*.egg
MANIFEST
bin

# PyInstaller
# Usually these files are written by a python script from a template
Expand Down Expand Up @@ -99,6 +94,12 @@ ipython_config.py
# install all needed dependencies.
#Pipfile.lock

# UV
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
#uv.lock

# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
Expand All @@ -111,8 +112,10 @@ ipython_config.py
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
.pdm.toml
.pdm-python
.pdm-build/

# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
Expand All @@ -126,7 +129,6 @@ celerybeat.pid

# Environments
.env
.docs_venv
.venv
env/
venv/
Expand Down Expand Up @@ -165,8 +167,26 @@ cython_debug/
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

# Ruff
# Ruff stuff:
.ruff_cache/

# VSCode
.vscode/
# PyPI configuration file
.pypirc

# typings
# see: https://github.com/google-deepmind/mujoco/issues/1292
typings/

# dora
out/
outputs/

# pixi environments
.pixi

# mujoco
MUJOCO_LOG.TXT

# assets
*.obj
*.stl
72 changes: 72 additions & 0 deletions .hooks/python_headers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Copyright (c) 2025 Robotics and AI Institute LLC. All rights reserved.

import re
import sys
from datetime import datetime
from pathlib import Path

HEADER_TEMPLATE = "# Copyright (c) {year} Robotics and AI Institute LLC. All rights reserved."
HEADER_REGEX = r"^# Copyright \(c\) (\d{4}) Robotics and AI Institute LLC\. All rights reserved\."


def get_header_year(lines: list[str]) -> int | None:
"""Return the year from header if found in first 5 lines, else None."""
for line in lines[:5]:
m = re.match(HEADER_REGEX, line)
if m:
return int(m.group(1))
return None


def add_header_to_file(file_path: str) -> int:
"""Add or update header in the Python file."""
path = Path(file_path)
if path.suffix != ".py":
return 0

content = path.read_text(encoding="utf-8").splitlines(keepends=True)
current_year = datetime.now().year
header_line_new = HEADER_TEMPLATE.format(year=current_year) + "\n"

modified = False

# respect existing shebang line
insert_at = 1 if content and content[0].startswith("#!") else 0

existing_year = get_header_year(content)
if existing_year is not None:
# header exists, check if year is wrong
if existing_year != current_year:
# find the exact header line index and replace it
for idx, line in enumerate(content[:5]):
if re.match(HEADER_REGEX, line):
content[idx] = header_line_new
modified = True
break
# else: year is up to date, no change needed
else:
# no header found, insert new header
new_header = [header_line_new, "\n"]
content = content[:insert_at] + new_header + content[insert_at:]
modified = True

if modified:
path.write_text("".join(content), encoding="utf-8")
return 1
return 0


def main() -> int:
"""Main function to process files passed as arguments."""
modified = 0
for file_path in sys.argv[1:]:
try:
modified += add_header_to_file(file_path)
except Exception as e:
print(f"Error processing {file_path}: {e}", file=sys.stderr)
return 1
return 0


if __name__ == "__main__":
sys.exit(main())
Loading