Merge pull request #4 from SELab-3-2026/chore/setup-dev-environment
chore: Configure development environment
This commit is contained in:
commit
af9cf1fdc5
21 changed files with 581 additions and 11 deletions
20
.agents/rules/architecture.md
Normal file
20
.agents/rules/architecture.md
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# Architecture and Code Formatting Rules
|
||||
|
||||
When writing or modifying code in this project, adhere strictly to the following rules:
|
||||
|
||||
## 1. Core Frameworks & Tooling
|
||||
- **PPO & CleanRL**: Proximal Policy Optimization (PPO) is the baseline algorithm. Use CleanRL as the starting framework for PPO, ensuring adaptation for continuous action spaces.
|
||||
- **JAX / Flax**: All Artificial Neural Network (ANN) controller architectures must be implemented using Flax (neural networks in JAX). Ensure full compatibility with the JAX/Flax ecosystem.
|
||||
- **MuJoCo**: The simulation environment uses a MuJoCo brittle star. Ensure that XML structures (sensors, actuators, joints, morphology) respect realistic constraints and adhere to the project requirements.
|
||||
|
||||
## 2. Clean Code Principles
|
||||
- **Naming Conventions**: Variables and functions must have consistent, intention-revealing names. A descriptive name is universally preferred over a short name with an explanatory comment.
|
||||
- **Single Responsibility Function Design**: Functions must be modular. Minimize arguments and completely avoid boolean flag arguments that control execution behavior.
|
||||
- **Commenting**: Code explains the "how". Comments are strictly reserved for explaining the "why".
|
||||
- **No Commented-out Code**: The AI must **never** generate commented-out or dead code. Delete it using version control instead.
|
||||
- **YAGNI & Complexity Management**: You Aren't Gonna Need It. Avoid premature optimization or unnecessary abstraction. Only introduce complexity with documented justification. Break large functions into small, testable blocks.
|
||||
- **No Notebooks for Core Logic**: Jupyter Notebooks are explicitly forbidden for general software development as they discourage modularity. They should only be used for prototyping, tutorials, or post-processing analysis.
|
||||
|
||||
## 3. Formatting & Linting
|
||||
- **Ruff**: Output perfectly formatted code adhering to the Google style standard. Always format and lint the code using `ruff` (see `pyproject.toml` and `ruff.toml`).
|
||||
- **Separation of Concerns**: Configuration code must be completely separated from implementation logic. Core logic must never be mixed with scripts or notebooks.
|
||||
15
.agents/rules/general.md
Normal file
15
.agents/rules/general.md
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# General AI Agent Rules
|
||||
|
||||
When assisting with this project, the AI Agent must strictly abide by these overarching operational rules:
|
||||
|
||||
## 1. Scientific Integrity
|
||||
- **No Hallucinations**: You must never fabricate results, hallucinate citations, or generate false empirical claims. Do not guess what happened if a process fails; rely strictly on outputs and logs.
|
||||
|
||||
## 2. Agent Operational Constraints
|
||||
- **Absolute Paths**: Always use absolute paths when making tool calls or reading/writing files.
|
||||
- **Refactoring Guardrails**: Do not commence massive files/directory refactors or major system migrations without explicitly communicating the plan and asking for user clarification or approval first.
|
||||
- **No Boilerplate Feedback**: The AI must not produce generic boilerplate summaries or overly generic advice. Ensure all outputs are completely contextual, robust, and well-reasoned.
|
||||
|
||||
## 3. Communication
|
||||
- **Artifacts and UI**: Use artifacts (like `implementation_plan.md` or `task.md`) appropriately for tracking design phases and updates.
|
||||
- **Explicit Documenting**: If performing design choices, list them explicitly. Keep the output focused on the exact task.
|
||||
25
.agents/rules/git-workflow.md
Normal file
25
.agents/rules/git-workflow.md
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# Git Workflow & Repository Structure Rules
|
||||
|
||||
When performing Git operations and managing the repository layout, follow these rules:
|
||||
|
||||
## 1. Committing Practices
|
||||
- **Frequent & Small**: Produce small, logical commits instead of massive monolithic ones.
|
||||
- **Conventional Commits**: Commit messages must adhere to the Conventional Commits specification (e.g., `feat: ...`, `fix: ...`, `refactor: ...`).
|
||||
- **Single Functionality**: Each commit should relate to exactly one piece of functionality or distinct structural change.
|
||||
|
||||
## 2. Branching & Merging
|
||||
- **Branch `dev`**: The `dev` branch is the primary integration branch for pushing and merging code.
|
||||
- **Branch `main`**: Only stable, finalized releases may be pushed to `main`.
|
||||
- **Feature Branches**: Organize distinct work into logical feature branches when pushing to the remote server, maintaining an organized Git history.
|
||||
|
||||
## 3. Artifact Management & Exclusions
|
||||
- **LFS Only**: Data files, trained models, and large datasets must **never** be committed directly to Git. Ensure they are tracked with Git Large File Storage (LFS). **CRITICAL**: Every developer and AI agent must have `git-lfs` installed locally for the repository hooks to successfully pull these large files. Run `git lfs install` after cloning or setting up your environment.
|
||||
|
||||
## 4. Repository Layout Strictness
|
||||
Ensure generated code is meticulously placed in the correct directories:
|
||||
- `src/` for algorithms, network designs, and core agent modules.
|
||||
- `env/` for MuJoCo wrappers and environment definitions.
|
||||
- `config/` for experiment configurations (using json, gin, or yaml).
|
||||
- `experiments/` for executable scripts.
|
||||
- `docs/` for ReadTheDocs or Doxygen documentation, and decision logs.
|
||||
- `tests/` for unit tests and verification scripts.
|
||||
14
.agents/rules/method.md
Normal file
14
.agents/rules/method.md
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# Methodology and Process Rules
|
||||
|
||||
The agent must adhere to the following scientific and operational practices, focused on robustness and reproducibility:
|
||||
|
||||
## 1. Scientific Context & Methodology
|
||||
- **Research Focus**: Maintain focus on the project's objective: studying how controller modularity affects learning speed, coordination, and fault tolerance in brittle-star locomotion.
|
||||
- **Hypothesis-Driven Design**: Base execution on clear hypotheses. Document all design decisions prior to implementation (in `/docs/decisions/` or via Artifacts/Plans).
|
||||
- **Scaffolding Approach**: Start development with simple setups before scaling to complex environments and varying morphologies.
|
||||
- **Value of Negative Results**: Understand that a controller failing to learn locomotion, when coupled with a thorough analysis of the failure, holds strong scientific value. Do not artificially force a positive result.
|
||||
|
||||
## 2. Reproducibility Protection
|
||||
- **Dependency Management (uv)**: This project strictly prefers `uv`. Do **not** manually modify the `uv.lock` file. Add dependencies via `uv add <package>` and sync environments via `uv sync --frozen` (or via devcontainers).
|
||||
- **Consistent Initialization**: The AI must avoid hidden randomness. Ensure that all runs use consistent seed initialization.
|
||||
- **Experiment Tracking**: Use Weights & Biases (wandb) for tracking and logging all experiments and parameters. Ensure every experiment-friendly parameter is properly logged.
|
||||
24
.agents/skills/lint/SKILL.md
Normal file
24
.agents/skills/lint/SKILL.md
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
name: Lint and Format Code
|
||||
description: Instructions for checking code style and formatting using Ruff.
|
||||
---
|
||||
|
||||
# Skill: Lint and Format Code
|
||||
|
||||
The goal of this skill is to enforce the project's adherence to the Google style standard and to maintain high code quality across the python source files.
|
||||
|
||||
## Instructions
|
||||
|
||||
1. **Format Code**: To automatically format all Python files according to the `ruff.toml` specifications:
|
||||
```bash
|
||||
uv run ruff format .
|
||||
```
|
||||
|
||||
2. **Check for Lints / Auto-fix**: To check the repository for style violations and automatically fix safe corrections:
|
||||
```bash
|
||||
uv run ruff check --fix .
|
||||
```
|
||||
|
||||
## Important Considerations
|
||||
- The `ruff.toml` file at the root handles all lint and format configuration. Do not ignore configurations when applying fixes.
|
||||
- If Ruff points out complex errors that cannot be auto-fixed, analyze the code and manually address the violations, prioritizing descriptive naming and adherence to the single-responsibility principle.
|
||||
25
.agents/skills/test/SKILL.md
Normal file
25
.agents/skills/test/SKILL.md
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
name: Run Tests
|
||||
description: Instructions for executing the project test suite to verify code correctness.
|
||||
---
|
||||
|
||||
# Skill: Run Tests
|
||||
|
||||
The goal of this skill is to verify that the project is functioning correctly after development changes.
|
||||
|
||||
## Instructions
|
||||
|
||||
1. **Verify Environment**: The project operates dynamically with hardware acceleration (GPU via JAX) and uses `uv` for dependency/execution management.
|
||||
2. **Execute Tests**:
|
||||
- To run basic verification (e.g., checking JAX initialization and hardware detection), run the test script:
|
||||
```bash
|
||||
uv run python -m tests.test_jax_init
|
||||
```
|
||||
- If a broader suite of modular tests is added (e.g., `pytest`), execute tests in the `tests/` directory with:
|
||||
```bash
|
||||
uv run pytest tests/
|
||||
```
|
||||
|
||||
## Important Considerations
|
||||
- If you are running tests inside the local environment without a Devcontainer, verify whether `uv sync --frozen` (for CPU) or `uv sync --frozen --extra cuda` (for GPU) has been executed to avoid import errors.
|
||||
- Do not run bare `python ...` without `uv run` locally, unless you are strictly operating inside a pre-activated `.venv` inside a Devcontainer.
|
||||
3
.commitlintrc.json
Normal file
3
.commitlintrc.json
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"extends": ["@commitlint/config-conventional"]
|
||||
}
|
||||
30
.devcontainer/Dockerfile
Normal file
30
.devcontainer/Dockerfile
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
FROM mcr.microsoft.com/devcontainers/python:3.12
|
||||
|
||||
# Install uv for dependency management
|
||||
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
|
||||
|
||||
# Install system dependencies for JAX, OpenGL, and Mujoco
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
libgl1 \
|
||||
libosmesa6-dev \
|
||||
libglew-dev \
|
||||
libglfw3 \
|
||||
patchelf \
|
||||
&& apt-get clean && rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Set environment variables for hardware acceleration and rendering
|
||||
ENV LD_LIBRARY_PATH=/usr/lib/nvidia
|
||||
ENV NVIDIA_VISIBLE_DEVICES=all
|
||||
ENV NVIDIA_DRIVER_CAPABILITIES=compute,utility,graphics
|
||||
|
||||
# Set the workspace path (defaults to /workspaces/project but can be overridden)
|
||||
ARG WORKSPACE_PATH=/workspaces/project
|
||||
ENV WORKSPACE_PATH=$WORKSPACE_PATH
|
||||
ENV PATH="$WORKSPACE_PATH/.venv/bin:$PATH"
|
||||
|
||||
# Ensure the workspace and .venv directories exist and are owned by the vscode user
|
||||
# This prevents permission errors when the postCreateCommand runs uv sync
|
||||
RUN mkdir -p $WORKSPACE_PATH/.venv && chown -R vscode:vscode $WORKSPACE_PATH
|
||||
|
||||
USER vscode
|
||||
WORKDIR $WORKSPACE_PATH
|
||||
49
.devcontainer/devcontainer.json
Normal file
49
.devcontainer/devcontainer.json
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"name": "Brittle Star JAX/CUDA",
|
||||
"build": {
|
||||
"dockerfile": "Dockerfile",
|
||||
"context": "..",
|
||||
"args": {
|
||||
"WORKSPACE_PATH": "/workspaces/${localWorkspaceFolderBasename}"
|
||||
}
|
||||
},
|
||||
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"ms-python.python",
|
||||
"charliermarsh.ruff",
|
||||
"ms-python.vscode-pylance",
|
||||
"ms-toolsai.jupyter"
|
||||
],
|
||||
"settings": {
|
||||
"python.defaultInterpreterPath": "${containerWorkspaceFolder}/.venv/bin/python",
|
||||
"python.analysis.localRoot": "${containerWorkspaceFolder}",
|
||||
"python.analysis.extraPaths": [
|
||||
"${containerWorkspaceFolder}/.venv/lib/python3.12/site-packages"
|
||||
]
|
||||
}
|
||||
},
|
||||
"jetbrains": {
|
||||
"plugins": [
|
||||
"Pythonid",
|
||||
"fleet.python",
|
||||
"com.koxudaxi.ruff"
|
||||
]
|
||||
}
|
||||
},
|
||||
"remoteUser": "vscode",
|
||||
"runArgs": [
|
||||
"--gpus",
|
||||
"all"
|
||||
],
|
||||
// Ensure the .venv persists using a named volume for performance and parity
|
||||
"mounts": [
|
||||
"source=${localWorkspaceFolderBasename}-venv,target=${containerWorkspaceFolder}/.venv,type=volume"
|
||||
],
|
||||
// Invoke the hardware-aware sync script
|
||||
"postCreateCommand": "bash ./.devcontainer/post-create.sh",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/common-utils:1": {}
|
||||
}
|
||||
}
|
||||
18
.devcontainer/post-create.sh
Normal file
18
.devcontainer/post-create.sh
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Detect if a GPU is available via nvidia-smi.
|
||||
# This works for Linux hosts and Windows (WSL2) with NVIDIA Container Toolkit.
|
||||
# On Mac (Apple Silicon) or systems without NVIDIA GPUs, this will skip the 'cuda' extra.
|
||||
if command -v nvidia-smi &> /dev/null && nvidia-smi &> /dev/null; then
|
||||
echo "GPU detected. Syncing with 'cuda' extra..."
|
||||
uv sync --frozen --extra cuda
|
||||
else
|
||||
echo "No GPU detected or nvidia-smi failed. Syncing without 'cuda' extra..."
|
||||
uv sync --frozen
|
||||
fi
|
||||
|
||||
echo "Environment synced successfully."
|
||||
|
||||
# Install pre-commit hooks so they are active in the devcontainer
|
||||
uv run pre-commit install
|
||||
14
.gitattributes
vendored
Normal file
14
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# Model weights
|
||||
*.pt filter=lfs diff=lfs merge=lfs -text
|
||||
*.pth filter=lfs diff=lfs merge=lfs -text
|
||||
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
||||
*.onnx filter=lfs diff=lfs merge=lfs -text
|
||||
*.h5 filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
# Media
|
||||
*.mp4 filter=lfs diff=lfs merge=lfs -text
|
||||
*.avi filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
# Datasets
|
||||
*.csv filter=lfs diff=lfs merge=lfs -text
|
||||
*.npz filter=lfs diff=lfs merge=lfs -text
|
||||
23
.github/workflows/lint.yml
vendored
Normal file
23
.github/workflows/lint.yml
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
name: Lint
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, ready_for_review]
|
||||
branches:
|
||||
- main
|
||||
- dev
|
||||
|
||||
jobs:
|
||||
ruff:
|
||||
if: ${{ !github.event.pull_request.draft }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Run Ruff check
|
||||
uses: astral-sh/ruff-action@v1
|
||||
with:
|
||||
args: "check"
|
||||
- name: Run Ruff format check
|
||||
uses: astral-sh/ruff-action@v1
|
||||
with:
|
||||
args: "format --check"
|
||||
31
.github/workflows/test.yml
vendored
Normal file
31
.github/workflows/test.yml
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
name: Test
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, ready_for_review]
|
||||
branches:
|
||||
- main
|
||||
- dev
|
||||
|
||||
jobs:
|
||||
pytest:
|
||||
if: ${{ !github.event.pull_request.draft }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v5
|
||||
with:
|
||||
version: "latest"
|
||||
|
||||
- name: Setup python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version-file: ".python-version"
|
||||
|
||||
- name: Install dependencies
|
||||
run: uv sync --frozen
|
||||
|
||||
- name: Run tests with pytest
|
||||
run: uv run pytest tests/
|
||||
20
.pre-commit-config.yaml
Normal file
20
.pre-commit-config.yaml
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
repos:
|
||||
- repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook
|
||||
rev: v9.16.0
|
||||
hooks:
|
||||
- id: commitlint
|
||||
stages: [commit-msg]
|
||||
additional_dependencies: ["@commitlint/config-conventional"]
|
||||
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.9.9
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: [ --fix ]
|
||||
- id: ruff-format
|
||||
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v5.0.0
|
||||
hooks:
|
||||
- id: no-commit-to-branch
|
||||
args: ['--branch', 'main', '--branch', 'dev']
|
||||
35
docs/CONTRIBUTING.md
Normal file
35
docs/CONTRIBUTING.md
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
# Contribution Guidelines
|
||||
|
||||
This document outlines the contribution protocols for the scientific software engineering project focusing on bio-inspired control architectures for brittle-star-like robots. The primary objective of this project is to produce scientific insight, rather than a commercial product.
|
||||
|
||||
## 1. Scientific Context & Methodology
|
||||
|
||||
* **Research Focus:** The goal is to study how controller modularity affects learning speed, coordination, and fault tolerance in brittle-star locomotion.
|
||||
* **Hypothesis-Driven Design:** Clear hypotheses must dictate a structured methodology and rigorous evaluation. All design decisions must be formally documented prior to implementation.
|
||||
* **Scaffolding Approach:** Development must start with simple setups before progressively increasing the complexity of environments and morphologies.
|
||||
* **Evaluation of Results:** Negative results possess scientific validity when thoroughly analyzed. If a controller fails to learn locomotion, providing a comprehensive analysis of the failure is considered a strong scientific contribution.
|
||||
* **Reproducibility:** Contributors must utilize fixed library versions. Configuration systems (such as json, gin, or yaml) must be employed to ensure reproducible runs.
|
||||
|
||||
## 2. Clean Code & Code Quality
|
||||
|
||||
Code readability is paramount, as code is read far more frequently than it is written.
|
||||
|
||||
* **Naming Conventions:** Variables and functions must utilize consistent, intention-revealing names. A long, descriptive name is strictly preferred over a short name accompanied by a comment.
|
||||
* **Function Design:** Functions must be modular and adhere to the single responsibility principle. Arguments must be minimized, and boolean flag arguments controlling behavior should be avoided.
|
||||
* **Commenting:** Code must document the "how," while comments are strictly reserved for documenting the "why". Commented-out code is prohibited and must be deleted via version control.
|
||||
* **YAGNI:** Contributors must adhere to the "You Aren't Gonna Need It" (YAGNI) principle and actively avoid premature optimization.
|
||||
* **Notebooks:** Jupyter Notebooks are strictly limited to quick prototyping, tutorials, demonstrations, or post-processing analysis. They are explicitly forbidden for general software development because they discourage modularity.
|
||||
|
||||
## 3. Version Control & Repository Structure
|
||||
|
||||
* **Git Practices:** Commits must be frequent and small. Each commit should relate to exactly one piece of functionality.
|
||||
* **Branching Strategy:** The `dev` branch serves as the integration branch for pushing and merging code. Only stable releases may be pushed to the `main` branch.
|
||||
* **Artifact Management:** Data files, trained models, and large datasets must never be committed directly to Git. Git Large File Storage (LFS) must be used for tracking large files. **All developers must have `git-lfs` installed locally** (see `DEVELOPMENT.md` for setup).
|
||||
* **Repository Layout:** The repository must maintain the following core directories: `src/` for algorithms, `env/` for MuJoCo wrappers, `config/` for experiment configurations, `experiments/` for scripts, `docs/` for Doxygen or ReadTheDocs documentation, and `tests/` for unit tests.
|
||||
|
||||
## 4. Architecture & Tooling
|
||||
|
||||
* **Algorithms & Frameworks:** Proximal Policy Optimization (PPO) is the recommended baseline algorithm. CleanRL should be used as a starting point and adapted for continuous action spaces. All Artificial Neural Network (ANN) controller architectures must be implemented using Flax.
|
||||
* **Simulation:** The simulation environment utilizes a MuJoCo brittle star. XML MuJoCo structures must remain realistic and respect morphological constraints.
|
||||
* **Experiment Tracking:** Weights & Biases (wandb) must be utilized for tracking and logging all experiments.
|
||||
* **Code Styling:** All code must conform to the chosen style guide (i.e. Google standard). This is enforced using build tools and pre-commit hooks such as flake8, black, or isort.
|
||||
61
docs/DEVELOPMENT.md
Normal file
61
docs/DEVELOPMENT.md
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# Development Guide
|
||||
|
||||
This guide outlines how to set up the development environment for this project, prioritizing **reproducible builds**, **environment parity**, and **cross-hardware compatibility**.
|
||||
|
||||
## Reproducibility &uv
|
||||
|
||||
This project uses [uv](https://github.com/astral-sh/uv) to manage dependencies and virtual environments. The `uv.lock` file is the absolute source of truth for package versions and must always be committed.
|
||||
|
||||
### Source of Truth
|
||||
|
||||
- **Never modify `uv.lock` manually.**
|
||||
- To add a dependency, run `uv add <package>`.
|
||||
- To update dependencies, run `uv lock --upgrade`.
|
||||
- To sync your environment with the lockfile, run `uv sync --frozen`.
|
||||
|
||||
## Git LFS (Critical)
|
||||
|
||||
**All developers must have Git LFS installed locally.** This repository tracks model weights (`.pt`, `.safetensors`, etc.), recordings (`.mp4`), and datasets using Git LFS.
|
||||
|
||||
- **Setup:** Run `git lfs install` after cloning this repository. If you are using the `.devcontainer` or `flake.nix`, LFS is typically available automatically.
|
||||
- If you clone without LFS installed, run `git lfs pull` after installation to fetch the actual data files instead of the small pointer files.
|
||||
|
||||
## Devcontainer Setup (Recommended)
|
||||
|
||||
The devcontainer provides an identical experience to local development but with all system dependencies pre-configured. It automatically detects your hardware (GPU vs CPU) and syncs the appropriate dependencies.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Docker Desktop or Docker Engine.
|
||||
- [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html) (for GPU support).
|
||||
|
||||
### Setup for VS Code
|
||||
|
||||
1. Install the [Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) extension.
|
||||
2. Open the project and click **Reopen in Container**.
|
||||
3. On first launch, the `post-create.sh` script will:
|
||||
- Detect if an NVIDIA GPU is available via `nvidia-smi`.
|
||||
- Run `uv sync --frozen --extra cuda` if a GPU is found.
|
||||
- Run `uv sync --frozen` otherwise.
|
||||
4. The environment is stored in a **named volume** for `.venv` to ensure persistence and performance.
|
||||
|
||||
### Setup for JetBrains IDEs
|
||||
|
||||
1. The IDE will detect the `.devcontainer/devcontainer.json` file.
|
||||
2. The environment is pre-configured to point to `/workspaces/project/.venv`.
|
||||
3. The hardware-aware sync will run automatically during container creation.
|
||||
|
||||
## Local Development (Alternative)
|
||||
|
||||
If you prefer not to use Docker:
|
||||
1. Install [uv](https://docs.astral.sh/uv/getting-started/installation/).
|
||||
2. Run `uv sync --frozen` (CPU) or `uv sync --frozen --extra cuda` (GPU).
|
||||
|
||||
## Hardware Acceleration (JAX)
|
||||
|
||||
Verify your setup by running the JAX initialization test:
|
||||
|
||||
```bash
|
||||
uv run pytest tests/test_jax_init.py
|
||||
```
|
||||
In the devcontainer, this will succeed on both CPU and GPU. A `GpuDevice` is expected if a GPU is detected and the `cuda` extra was installed.
|
||||
|
|
@ -29,6 +29,10 @@
|
|||
# Editor of your choice
|
||||
(nix-jetbrains-plugins.lib.buildIdeWithPlugins pkgs "pycharm" pluginList)
|
||||
];
|
||||
|
||||
shellHook = ''
|
||||
uv run pre-commit install
|
||||
'';
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ dependencies = [
|
|||
"biorobot==0.4.2",
|
||||
"evosax==0.2.0",
|
||||
"ipykernel==7.2.0",
|
||||
"jax[cuda13]==0.9.0.1",
|
||||
"jax==0.9.0.1",
|
||||
"matplotlib==3.10.8",
|
||||
"mediapy==1.2.6",
|
||||
"pyopengl>=3.1.10",
|
||||
|
|
@ -16,7 +16,14 @@ dependencies = [
|
|||
"wandb==0.24.2",
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
cuda = [
|
||||
"jax[cuda13]==0.9.0.1",
|
||||
]
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"pre-commit>=4.0.0",
|
||||
"pytest>=8.0.0",
|
||||
"ruff>=0.15.2",
|
||||
]
|
||||
|
|
|
|||
15
ruff.toml
15
ruff.toml
|
|
@ -1,3 +1,4 @@
|
|||
[lint]
|
||||
extend-select = [
|
||||
# "PLC0103", # invalid-name
|
||||
# "PLC0104", # disallowed-name
|
||||
|
|
@ -40,10 +41,10 @@ extend-select = [
|
|||
"PLC2401", # non-ascii-name
|
||||
# "PLC2403", # non-ascii-module-import
|
||||
# "PLC2503", # bad-file-encoding
|
||||
"PLC2801", # unnecessary-dunder-call
|
||||
# "PLC2801", # unnecessary-dunder-call (requires preview)
|
||||
# "PLC3001", # unnecessary-lambda-assignment
|
||||
"PLC3002", # unnecessary-direct-lambda-call
|
||||
"E999", # syntax-error
|
||||
# "E999", # syntax-error (removed from ruff)
|
||||
# "PLE0011", # unrecognized-inline-option
|
||||
# "PLE0013", # bad-plugin-value
|
||||
# "PLE0014", # bad-configuration-section
|
||||
|
|
@ -130,7 +131,7 @@ extend-select = [
|
|||
# "PLE1137", # unsupported-assignment-operation
|
||||
# "PLE1138", # unsupported-delete-operation
|
||||
# "PLE1139", # invalid-metaclass
|
||||
"PLE1141", # dict-iter-missing-items
|
||||
# "PLE1141", # dict-iter-missing-items (requires preview)
|
||||
"PLE1142", # await-outside-async
|
||||
# "PLE1143", # unhashable-member
|
||||
# "PLE1144", # invalid-slice-step
|
||||
|
|
@ -168,7 +169,7 @@ extend-select = [
|
|||
# "PLE3102", # positional-only-arguments-expected
|
||||
# "PLE3701", # invalid-field-call
|
||||
# "PLE4702", # modified-iterating-dict
|
||||
"PLE4703", # modified-iterating-set
|
||||
# "PLE4703", # modified-iterating-set (requires preview)
|
||||
# "PLF0001", # fatal
|
||||
# "PLF0002", # astroid-error
|
||||
# "PLF0010", # parse-error
|
||||
|
|
@ -210,7 +211,7 @@ extend-select = [
|
|||
# "PLW0238", # unused-private-member
|
||||
# "PLW0239", # overridden-final-method
|
||||
# "PLW0240", # subclassed-final-class
|
||||
"PLW0244", # redefined-slots-in-subclass
|
||||
# "PLW0244", # redefined-slots-in-subclass (requires preview)
|
||||
"PLW0245", # super-without-brackets
|
||||
# "PLW0246", # useless-parent-delegation
|
||||
# "PLW0301", # unnecessary-semicolon
|
||||
|
|
@ -274,7 +275,7 @@ extend-select = [
|
|||
"PLW1508", # invalid-envvar-default
|
||||
"PLW1509", # subprocess-popen-preexec-fn
|
||||
# "PLW1510", # subprocess-run-check
|
||||
"PLW1514", # unspecified-encoding
|
||||
# "PLW1514", # unspecified-encoding (requires preview)
|
||||
# "PLW1515", # forgotten-debug-statement
|
||||
# "PLW1518", # method-cache-max-size-none
|
||||
"PLW2101", # useless-with-lock
|
||||
|
|
@ -298,7 +299,7 @@ extend-select = [
|
|||
# "PLW4906", # deprecated-attribute
|
||||
]
|
||||
|
||||
ignore = [
|
||||
extend-ignore = [
|
||||
# "PLC0116", # missing-function-docstring
|
||||
# "PLC0200", # consider-using-enumerate
|
||||
# "PLC0305", # trailing-newlines
|
||||
|
|
|
|||
7
tests/test_jax_init.py
Normal file
7
tests/test_jax_init.py
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import jax
|
||||
|
||||
|
||||
def test_jax_initializes():
|
||||
"""Verify that JAX initializes and exposes at least one device."""
|
||||
devices = jax.devices()
|
||||
assert len(devices) > 0, "JAX should expose at least one device"
|
||||
150
uv.lock
generated
150
uv.lock
generated
|
|
@ -14,7 +14,7 @@ dependencies = [
|
|||
{ name = "biorobot" },
|
||||
{ name = "evosax" },
|
||||
{ name = "ipykernel" },
|
||||
{ name = "jax", extra = ["cuda13"] },
|
||||
{ name = "jax" },
|
||||
{ name = "matplotlib" },
|
||||
{ name = "mediapy" },
|
||||
{ name = "pyopengl" },
|
||||
|
|
@ -22,8 +22,15 @@ dependencies = [
|
|||
{ name = "wandb" },
|
||||
]
|
||||
|
||||
[package.optional-dependencies]
|
||||
cuda = [
|
||||
{ name = "jax", extra = ["cuda13"] },
|
||||
]
|
||||
|
||||
[package.dev-dependencies]
|
||||
dev = [
|
||||
{ name = "pre-commit" },
|
||||
{ name = "pytest" },
|
||||
{ name = "ruff" },
|
||||
]
|
||||
|
||||
|
|
@ -32,16 +39,22 @@ requires-dist = [
|
|||
{ name = "biorobot", specifier = "==0.4.2" },
|
||||
{ name = "evosax", specifier = "==0.2.0" },
|
||||
{ name = "ipykernel", specifier = "==7.2.0" },
|
||||
{ name = "jax", extras = ["cuda13"], specifier = "==0.9.0.1" },
|
||||
{ name = "jax", specifier = "==0.9.0.1" },
|
||||
{ name = "jax", extras = ["cuda13"], marker = "extra == 'cuda'", specifier = "==0.9.0.1" },
|
||||
{ name = "matplotlib", specifier = "==3.10.8" },
|
||||
{ name = "mediapy", specifier = "==1.2.6" },
|
||||
{ name = "pyopengl", specifier = ">=3.1.10" },
|
||||
{ name = "pyopengl-accelerate", specifier = ">=3.1.10" },
|
||||
{ name = "wandb", specifier = "==0.24.2" },
|
||||
]
|
||||
provides-extras = ["cuda"]
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [{ name = "ruff", specifier = ">=0.15.2" }]
|
||||
dev = [
|
||||
{ name = "pre-commit", specifier = ">=4.0.0" },
|
||||
{ name = "pytest", specifier = ">=8.0.0" },
|
||||
{ name = "ruff", specifier = ">=0.15.2" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "absl-py"
|
||||
|
|
@ -151,6 +164,15 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", size = 177762, upload-time = "2025-09-08T23:22:59.668Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfgv"
|
||||
version = "3.5.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/4e/b5/721b8799b04bf9afe054a3899c6cf4e880fcf8563cc71c15610242490a0c/cfgv-3.5.0.tar.gz", hash = "sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132", size = 7334, upload-time = "2025-11-19T20:55:51.612Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0", size = 7445, upload-time = "2025-11-19T20:55:50.744Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "charset-normalizer"
|
||||
version = "3.4.4"
|
||||
|
|
@ -285,6 +307,15 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/4e/8c/f3147f5c4b73e7550fe5f9352eaa956ae838d5c51eb58e7a25b9f3e2643b/decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a", size = 9190, upload-time = "2025-02-24T04:41:32.565Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "distlib"
|
||||
version = "0.4.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d", size = 614605, upload-time = "2025-07-17T16:52:00.465Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047, upload-time = "2025-07-17T16:51:58.613Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dm-control"
|
||||
version = "1.0.37"
|
||||
|
|
@ -406,6 +437,15 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/05/2c/ffc08c54c05cdce6fbed2aeebc46348dbe180c6d2c541c7af7ba0aa5f5f8/Farama_Notifications-0.0.4-py3-none-any.whl", hash = "sha256:14de931035a41961f7c056361dc7f980762a143d05791ef5794a751a2caf05ae", size = 2511, upload-time = "2023-02-27T18:28:39.447Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "filelock"
|
||||
version = "3.25.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/94/b8/00651a0f559862f3bb7d6f7477b192afe3f583cc5e26403b44e59a55ab34/filelock-3.25.2.tar.gz", hash = "sha256:b64ece2b38f4ca29dd3e810287aa8c48182bbecd1ae6e9ae126c9b35f1382694", size = 40480, upload-time = "2026-03-11T20:45:38.487Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/a5/842ae8f0c08b61d6484b52f99a03510a3a72d23141942d216ebe81fefbce/filelock-3.25.2-py3-none-any.whl", hash = "sha256:ca8afb0da15f229774c9ad1b455ed96e85a81373065fb10446672f64444ddf70", size = 26759, upload-time = "2026-03-11T20:45:37.437Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flax"
|
||||
version = "0.12.2"
|
||||
|
|
@ -511,6 +551,14 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/5a/3f/efeb7c6801c46e11bd666a5180f0d615f74f72264212f74f39586c6fda9d/glfw-2.10.0-py2.py27.py3.py30.py31.py32.py33.py34.py35.py36.py37.py38.py39.py310.py311.py312.py313.py314-none-manylinux_2_28_x86_64.whl", hash = "sha256:ce6724bb7cb3d0543dcba17206dce909f94176e68220b8eafee72e9f92bcf542", size = 243522, upload-time = "2026-01-28T05:58:03.517Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cf/b9/b04c3aa0aad2870cfe799f32f8b59789c98e1816bbce9e83f4823c5b840b/glfw-2.10.0-py2.py27.py3.py30.py31.py32.py33.py34.py35.py36.py37.py38.py39.py310.py311.py312.py313.py314-none-win32.whl", hash = "sha256:fca724a21a372731edb290841edd28a9fb1ee490f833392752844ac807c0086a", size = 552682, upload-time = "2026-01-28T05:58:05.649Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/e1/6d6816b296a529ac9b897ad228b1e084eb1f92319e96371880eebdc874a6/glfw-2.10.0-py2.py27.py3.py30.py31.py32.py33.py34.py35.py36.py37.py38.py39.py310.py311.py312.py313.py314-none-win_amd64.whl", hash = "sha256:823c0bd7770977d4b10e0ed0aef2f3682276b7c88b8b65cfc540afce5951392f", size = 559464, upload-time = "2026-01-28T05:58:07.261Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/a8/d4dab8a58fc2e6981fc7a58c4e56ba9d777fb24931cec6a22152edbb3540/glfw-2.10.0-py2.py3-none-macosx_10_6_intel.whl", hash = "sha256:a0d1f29f206219cc291edfb6cace663a86da2470632551c998e3db82d48ea177", size = 105288, upload-time = "2026-03-10T17:21:19.929Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/61/68d35e001872a7705112418da236fa2418d4f2e5419f8b2837f9b81bb3da/glfw-2.10.0-py2.py3-none-macosx_11_0_arm64.whl", hash = "sha256:d28d6f3ef217e64e35dc6fd0a7acb4cec9bfe7cd14dd9b35a7228a87002de154", size = 102139, upload-time = "2026-03-10T17:21:21.645Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/e1/ca5984081aaae07c9d371cb11dc4e4ff603510678ed9b73e58b6c351fe63/glfw-2.10.0-py2.py3-none-manylinux2014_aarch64.whl", hash = "sha256:f968b522bb6a0e04aaf4dcac30a476d7229308bb2bac406a60587debb5a61e29", size = 229998, upload-time = "2026-03-10T17:21:23.549Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/c4/82ac75fdcfba2896da7a573c0fc7f8ceb8f77ead6866d500d06c32f1c464/glfw-2.10.0-py2.py3-none-manylinux2014_x86_64.whl", hash = "sha256:68cf3752bdadb6f4bc0a876247c28c88c7251ac39f8af076ed938fdfd71e72dd", size = 241944, upload-time = "2026-03-10T17:21:26.102Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e3/96/9f691823cca5eb6a08f346bd0ff03b78032db9370b509a1e9c8976fb20a5/glfw-2.10.0-py2.py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:44d98de5dbf8f727e0cb29f9b29d29528ea7570f2e6f42f8430a69df05f12b48", size = 231009, upload-time = "2026-03-10T17:21:28.481Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3f/93/977b9e679e356871d428ae7a1139ec767dd5177bed58a6344b4d2199e00f/glfw-2.10.0-py2.py3-none-manylinux_2_28_x86_64.whl", hash = "sha256:cca5158d62189e08792b1ae54f92307a282921a0e7783315b467e21b0a381c88", size = 243480, upload-time = "2026-03-10T17:21:30.538Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f9/bd/cea9569c8f2188b0a104472951420434a3e1f5cf26f5836ef9d7227a1a30/glfw-2.10.0-py2.py3-none-win32.whl", hash = "sha256:5e024509989740e8e7b86cc4aab508195495f79879072b0e1f68bd036a2916ad", size = 552641, upload-time = "2026-03-10T17:21:32.653Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cc/9b/4366ad3e1c0688146c70aa6143584d6a8d88583b9390f106250e25a3d5cd/glfw-2.10.0-py2.py3-none-win_amd64.whl", hash = "sha256:7f787ee8645781f10e8800438ce4357ab38c573ffb191aba380c1e72eba6311c", size = 559423, upload-time = "2026-03-10T17:21:34.766Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -537,6 +585,15 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/c5/7b/bca5613a0c3b542420cf92bd5e5fb8ebd5435ce1011a091f66bb7693285e/humanize-4.15.0-py3-none-any.whl", hash = "sha256:b1186eb9f5a9749cd9cb8565aee77919dd7c8d076161cf44d70e59e3301e1769", size = 132203, upload-time = "2025-12-20T20:16:11.67Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "identify"
|
||||
version = "2.6.18"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/46/c4/7fb4db12296cdb11893d61c92048fe617ee853f8523b9b296ac03b43757e/identify-2.6.18.tar.gz", hash = "sha256:873ac56a5e3fd63e7438a7ecbc4d91aca692eb3fefa4534db2b7913f3fc352fd", size = 99580, upload-time = "2026-03-15T18:39:50.319Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/46/33/92ef41c6fad0233e41d3d84ba8e8ad18d1780f1e5d99b3c683e6d7f98b63/identify-2.6.18-py2.py3-none-any.whl", hash = "sha256:8db9d3c8ea9079db92cafb0ebf97abdc09d52e97f4dcf773a2e694048b7cd737", size = 99394, upload-time = "2026-03-15T18:39:48.915Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.11"
|
||||
|
|
@ -568,6 +625,15 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/a4/ed/1f1afb2e9e7f38a545d628f864d562a5ae64fe6f7a10e28ffb9b185b4e89/importlib_resources-6.5.2-py3-none-any.whl", hash = "sha256:789cfdc3ed28c78b67a06acb8126751ced69a3d5f79c095a98298cd8a760ccec", size = 37461, upload-time = "2025-01-03T18:51:54.306Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iniconfig"
|
||||
version = "2.3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ipykernel"
|
||||
version = "7.2.0"
|
||||
|
|
@ -983,6 +1049,15 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c", size = 5195, upload-time = "2024-01-21T14:25:17.223Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nodeenv"
|
||||
version = "1.10.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611, upload-time = "2025-12-20T14:08:54.006Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "numpy"
|
||||
version = "2.4.2"
|
||||
|
|
@ -1285,6 +1360,31 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/48/31/05e764397056194206169869b50cf2fee4dbbbc71b344705b9c0d878d4d8/platformdirs-4.9.2-py3-none-any.whl", hash = "sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd", size = 21168, upload-time = "2026-02-16T03:56:08.891Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pluggy"
|
||||
version = "1.6.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pre-commit"
|
||||
version = "4.5.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "cfgv" },
|
||||
{ name = "identify" },
|
||||
{ name = "nodeenv" },
|
||||
{ name = "pyyaml" },
|
||||
{ name = "virtualenv" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/40/f1/6d86a29246dfd2e9b6237f0b5823717f60cad94d47ddc26afa916d21f525/pre_commit-4.5.1.tar.gz", hash = "sha256:eb545fcff725875197837263e977ea257a402056661f09dae08e4b149b030a61", size = 198232, upload-time = "2025-12-16T21:14:33.552Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/5d/19/fd3ef348460c80af7bb4669ea7926651d1f95c23ff2df18b9d24bab4f3fa/pre_commit-4.5.1-py2.py3-none-any.whl", hash = "sha256:3b3afd891e97337708c1674210f8eba659b52a38ea5f822ff142d10786221f77", size = 226437, upload-time = "2025-12-16T21:14:32.409Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "prompt-toolkit"
|
||||
version = "3.0.52"
|
||||
|
|
@ -1439,6 +1539,22 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/10/bd/c038d7cc38edc1aa5bf91ab8068b63d4308c66c4c8bb3cbba7dfbc049f9c/pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", size = 122781, upload-time = "2026-01-21T03:57:55.912Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "9.0.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
{ name = "iniconfig" },
|
||||
{ name = "packaging" },
|
||||
{ name = "pluggy" },
|
||||
{ name = "pygments" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d1/db/7ef3487e0fb0049ddb5ce41d3a49c235bf9ad299b6a25d5780a89f19230f/pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11", size = 1568901, upload-time = "2025-12-06T21:30:51.014Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python-dateutil"
|
||||
version = "2.9.0.post0"
|
||||
|
|
@ -1451,6 +1567,19 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python-discovery"
|
||||
version = "1.2.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "filelock" },
|
||||
{ name = "platformdirs" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9c/90/bcce6b46823c9bec1757c964dc37ed332579be512e17a30e9698095dcae4/python_discovery-1.2.0.tar.gz", hash = "sha256:7d33e350704818b09e3da2bd419d37e21e7c30db6e0977bb438916e06b41b5b1", size = 58055, upload-time = "2026-03-19T01:43:08.248Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/3c/2005227cb951df502412de2fa781f800663cccbef8d90ec6f1b371ac2c0d/python_discovery-1.2.0-py3-none-any.whl", hash = "sha256:1e108f1bbe2ed0ef089823d28805d5ad32be8e734b86a5f212bf89b71c266e4a", size = 31524, upload-time = "2026-03-19T01:43:07.045Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyyaml"
|
||||
version = "6.0.3"
|
||||
|
|
@ -1786,6 +1915,21 @@ wheels = [
|
|||
{ url = "https://files.pythonhosted.org/packages/99/39/6b3f7d234ba3964c428a6e40006340f53ba37993f46ed6e111c6e9141d18/uvloop-0.22.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:512fec6815e2dd45161054592441ef76c830eddaad55c8aa30952e6fe1ed07c0", size = 4296343, upload-time = "2025-10-16T22:16:35.149Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "virtualenv"
|
||||
version = "21.2.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "distlib" },
|
||||
{ name = "filelock" },
|
||||
{ name = "platformdirs" },
|
||||
{ name = "python-discovery" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/aa/92/58199fe10049f9703c2666e809c4f686c54ef0a68b0f6afccf518c0b1eb9/virtualenv-21.2.0.tar.gz", hash = "sha256:1720dc3a62ef5b443092e3f499228599045d7fea4c79199770499df8becf9098", size = 5840618, upload-time = "2026-03-09T17:24:38.013Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c6/59/7d02447a55b2e55755011a647479041bc92a82e143f96a8195cb33bd0a1c/virtualenv-21.2.0-py3-none-any.whl", hash = "sha256:1bd755b504931164a5a496d217c014d098426cddc79363ad66ac78125f9d908f", size = 5825084, upload-time = "2026-03-09T17:24:35.378Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wandb"
|
||||
version = "0.24.2"
|
||||
|
|
|
|||
Reference in a new issue