Merge branch 'main' into local_logging_tensorboard

This commit is contained in:
j 2024-05-13 10:55:45 -04:00
commit ccf2782d8a
30 changed files with 430 additions and 278 deletions

View File

@ -57,6 +57,38 @@ jobs:
&& rm -rf tests/outputs outputs && rm -rf tests/outputs outputs
pytest-minimal:
name: Pytest (minimal install)
runs-on: ubuntu-latest
env:
DATA_DIR: tests/data
MUJOCO_GL: egl
steps:
- uses: actions/checkout@v4
- name: Install poetry
run: |
pipx install poetry && poetry config virtualenvs.in-project true
echo "${{ github.workspace }}/.venv/bin" >> $GITHUB_PATH
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install poetry dependencies
run: |
poetry install --extras "test"
- name: Test with pytest
run: |
pytest tests -v --cov=./lerobot --durations=0 \
-W ignore::DeprecationWarning:imageio_ffmpeg._utils:7 \
-W ignore::UserWarning:torch.utils.data.dataloader:558 \
-W ignore::UserWarning:gymnasium.utils.env_checker:247 \
&& rm -rf tests/outputs outputs
end-to-end: end-to-end:
name: End-to-end name: End-to-end
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@ -22,9 +22,8 @@ test-end-to-end:
${MAKE} test-act-ete-eval ${MAKE} test-act-ete-eval
${MAKE} test-diffusion-ete-train ${MAKE} test-diffusion-ete-train
${MAKE} test-diffusion-ete-eval ${MAKE} test-diffusion-ete-eval
# TODO(rcadene, alexander-soare): enable end-to-end tests for tdmpc ${MAKE} test-tdmpc-ete-train
# ${MAKE} test-tdmpc-ete-train ${MAKE} test-tdmpc-ete-eval
# ${MAKE} test-tdmpc-ete-eval
${MAKE} test-default-ete-eval ${MAKE} test-default-ete-eval
test-act-ete-train: test-act-ete-train:
@ -80,7 +79,7 @@ test-tdmpc-ete-train:
policy=tdmpc \ policy=tdmpc \
env=xarm \ env=xarm \
env.task=XarmLift-v0 \ env.task=XarmLift-v0 \
dataset_repo_id=lerobot/xarm_lift_medium_replay \ dataset_repo_id=lerobot/xarm_lift_medium \
wandb.enable=False \ wandb.enable=False \
training.offline_steps=2 \ training.offline_steps=2 \
training.online_steps=2 \ training.online_steps=2 \

View File

@ -57,7 +57,6 @@
- Thanks to Tony Zaho, Zipeng Fu and colleagues for open sourcing ACT policy, ALOHA environments and datasets. Ours are adapted from [ALOHA](https://tonyzhaozh.github.io/aloha) and [Mobile ALOHA](https://mobile-aloha.github.io). - Thanks to Tony Zaho, Zipeng Fu and colleagues for open sourcing ACT policy, ALOHA environments and datasets. Ours are adapted from [ALOHA](https://tonyzhaozh.github.io/aloha) and [Mobile ALOHA](https://mobile-aloha.github.io).
- Thanks to Cheng Chi, Zhenjia Xu and colleagues for open sourcing Diffusion policy, Pusht environment and datasets, as well as UMI datasets. Ours are adapted from [Diffusion Policy](https://diffusion-policy.cs.columbia.edu) and [UMI Gripper](https://umi-gripper.github.io). - Thanks to Cheng Chi, Zhenjia Xu and colleagues for open sourcing Diffusion policy, Pusht environment and datasets, as well as UMI datasets. Ours are adapted from [Diffusion Policy](https://diffusion-policy.cs.columbia.edu) and [UMI Gripper](https://umi-gripper.github.io).
- Thanks to Nicklas Hansen, Yunhai Feng and colleagues for open sourcing TDMPC policy, Simxarm environments and datasets. Ours are adapted from [TDMPC](https://github.com/nicklashansen/tdmpc) and [FOWM](https://www.yunhaifeng.com/FOWM). - Thanks to Nicklas Hansen, Yunhai Feng and colleagues for open sourcing TDMPC policy, Simxarm environments and datasets. Ours are adapted from [TDMPC](https://github.com/nicklashansen/tdmpc) and [FOWM](https://www.yunhaifeng.com/FOWM).
- Thanks to Vincent Moens and colleagues for open sourcing [TorchRL](https://github.com/pytorch/rl). It allowed for quick experimentations on the design of `LeRobot`.
- Thanks to Antonio Loquercio and Ashish Kumar for their early support. - Thanks to Antonio Loquercio and Ashish Kumar for their early support.

View File

@ -7,6 +7,11 @@ ARG DEBIAN_FRONTEND=noninteractive
# Install apt dependencies # Install apt dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \ RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential cmake \ build-essential cmake \
git git-lfs openssh-client \
nano vim \
htop atop nvtop \
sed gawk grep curl wget \
tcpdump sysstat screen \
libglib2.0-0 libgl1-mesa-glx libegl1-mesa \ libglib2.0-0 libgl1-mesa-glx libegl1-mesa \
python${PYTHON_VERSION} python${PYTHON_VERSION}-venv \ python${PYTHON_VERSION} python${PYTHON_VERSION}-venv \
&& apt-get clean && rm -rf /var/lib/apt/lists/* && apt-get clean && rm -rf /var/lib/apt/lists/*
@ -18,7 +23,8 @@ ENV PATH="/opt/venv/bin:$PATH"
RUN echo "source /opt/venv/bin/activate" >> /root/.bashrc RUN echo "source /opt/venv/bin/activate" >> /root/.bashrc
# Install LeRobot # Install LeRobot
COPY . /lerobot RUN git lfs install
RUN git clone https://github.com/huggingface/lerobot.git
WORKDIR /lerobot WORKDIR /lerobot
RUN pip install --upgrade --no-cache-dir pip RUN pip install --upgrade --no-cache-dir pip
RUN pip install --no-cache-dir ".[test, aloha, xarm, pusht]" RUN pip install --no-cache-dir ".[test, aloha, xarm, pusht]"

View File

@ -88,9 +88,9 @@ class Logger:
# Also save the full Hydra config for the env configuration. # Also save the full Hydra config for the env configuration.
OmegaConf.save(self._cfg, save_dir / "config.yaml") OmegaConf.save(self._cfg, save_dir / "config.yaml")
if self._wandb and not self._disable_wandb_artifact: if self._wandb and not self._disable_wandb_artifact:
# note wandb artifact does not accept ":" in its name # note wandb artifact does not accept ":" or "/" in its name
artifact = self._wandb.Artifact( artifact = self._wandb.Artifact(
self._group.replace(":", "_") + "-" + str(self._seed) + "-" + str(identifier), f"{self._group.replace(':', '_').replace('/', '_')}-{self._seed}-{identifier}",
type="model", type="model",
) )
artifact.add_file(save_dir / SAFETENSORS_SINGLE_FILE) artifact.add_file(save_dir / SAFETENSORS_SINGLE_FILE)
@ -100,9 +100,10 @@ class Logger:
self._buffer_dir.mkdir(parents=True, exist_ok=True) self._buffer_dir.mkdir(parents=True, exist_ok=True)
fp = self._buffer_dir / f"{str(identifier)}.pkl" fp = self._buffer_dir / f"{str(identifier)}.pkl"
buffer.save(fp) buffer.save(fp)
if self._wandb: if self._wandb and not self._disable_wandb_artifact:
# note wandb artifact does not accept ":" or "/" in its name
artifact = self._wandb.Artifact( artifact = self._wandb.Artifact(
self._group + "-" + str(self._seed) + "-" + str(identifier), f"{self._group.replace(':', '_').replace('/', '_')}-{self._seed}-{identifier}",
type="buffer", type="buffer",
) )
artifact.add_file(fp) artifact.add_file(fp)
@ -120,6 +121,11 @@ class Logger:
assert mode in {"train", "eval"} assert mode in {"train", "eval"}
if self._wandb is not None: if self._wandb is not None:
for k, v in d.items(): for k, v in d.items():
if not isinstance(v, (int, float, str)):
logging.warning(
f'WandB logging of key "{k}" was ignored as its type is not handled by this wrapper.'
)
continue
self._wandb.log({f"{mode}/{k}": v}, step=step) self._wandb.log({f"{mode}/{k}": v}, step=step)
elif self._local_writer is not None: elif self._local_writer is not None:
for k, v in d.items(): for k, v in d.items():

View File

@ -101,7 +101,7 @@ class ACTPolicy(nn.Module, PyTorchModelHubMixin):
F.l1_loss(batch["action"], actions_hat, reduction="none") * ~batch["action_is_pad"].unsqueeze(-1) F.l1_loss(batch["action"], actions_hat, reduction="none") * ~batch["action_is_pad"].unsqueeze(-1)
).mean() ).mean()
loss_dict = {"l1_loss": l1_loss} loss_dict = {"l1_loss": l1_loss.item()}
if self.config.use_vae: if self.config.use_vae:
# Calculate Dₖₗ(latent_pdf || standard_normal). Note: After computing the KL-divergence for # Calculate Dₖₗ(latent_pdf || standard_normal). Note: After computing the KL-divergence for
# each dimension independently, we sum over the latent dimension to get the total # each dimension independently, we sum over the latent dimension to get the total
@ -110,7 +110,7 @@ class ACTPolicy(nn.Module, PyTorchModelHubMixin):
mean_kld = ( mean_kld = (
(-0.5 * (1 + log_sigma_x2_hat - mu_hat.pow(2) - (log_sigma_x2_hat).exp())).sum(-1).mean() (-0.5 * (1 + log_sigma_x2_hat - mu_hat.pow(2) - (log_sigma_x2_hat).exp())).sum(-1).mean()
) )
loss_dict["kld_loss"] = mean_kld loss_dict["kld_loss"] = mean_kld.item()
loss_dict["loss"] = l1_loss + mean_kld * self.config.kl_weight loss_dict["loss"] = l1_loss + mean_kld * self.config.kl_weight
else: else:
loss_dict["loss"] = l1_loss loss_dict["loss"] = l1_loss

View File

@ -51,6 +51,7 @@ class DiffusionConfig:
use_film_scale_modulation: FiLM (https://arxiv.org/abs/1709.07871) is used for the Unet conditioning. use_film_scale_modulation: FiLM (https://arxiv.org/abs/1709.07871) is used for the Unet conditioning.
Bias modulation is used be default, while this parameter indicates whether to also use scale Bias modulation is used be default, while this parameter indicates whether to also use scale
modulation. modulation.
noise_scheduler_type: Name of the noise scheduler to use. Supported options: ["DDPM", "DDIM"].
num_train_timesteps: Number of diffusion steps for the forward diffusion schedule. num_train_timesteps: Number of diffusion steps for the forward diffusion schedule.
beta_schedule: Name of the diffusion beta schedule as per DDPMScheduler from Hugging Face diffusers. beta_schedule: Name of the diffusion beta schedule as per DDPMScheduler from Hugging Face diffusers.
beta_start: Beta value for the first forward-diffusion step. beta_start: Beta value for the first forward-diffusion step.
@ -110,6 +111,7 @@ class DiffusionConfig:
diffusion_step_embed_dim: int = 128 diffusion_step_embed_dim: int = 128
use_film_scale_modulation: bool = True use_film_scale_modulation: bool = True
# Noise scheduler. # Noise scheduler.
noise_scheduler_type: str = "DDPM"
num_train_timesteps: int = 100 num_train_timesteps: int = 100
beta_schedule: str = "squaredcos_cap_v2" beta_schedule: str = "squaredcos_cap_v2"
beta_start: float = 0.0001 beta_start: float = 0.0001
@ -144,3 +146,9 @@ class DiffusionConfig:
raise ValueError( raise ValueError(
f"`prediction_type` must be one of {supported_prediction_types}. Got {self.prediction_type}." f"`prediction_type` must be one of {supported_prediction_types}. Got {self.prediction_type}."
) )
supported_noise_schedulers = ["DDPM", "DDIM"]
if self.noise_scheduler_type not in supported_noise_schedulers:
raise ValueError(
f"`noise_scheduler_type` must be one of {supported_noise_schedulers}. "
f"Got {self.noise_scheduler_type}."
)

View File

@ -13,6 +13,7 @@ import einops
import torch import torch
import torch.nn.functional as F # noqa: N812 import torch.nn.functional as F # noqa: N812
import torchvision import torchvision
from diffusers.schedulers.scheduling_ddim import DDIMScheduler
from diffusers.schedulers.scheduling_ddpm import DDPMScheduler from diffusers.schedulers.scheduling_ddpm import DDPMScheduler
from huggingface_hub import PyTorchModelHubMixin from huggingface_hub import PyTorchModelHubMixin
from robomimic.models.base_nets import SpatialSoftmax from robomimic.models.base_nets import SpatialSoftmax
@ -126,6 +127,19 @@ class DiffusionPolicy(nn.Module, PyTorchModelHubMixin):
return {"loss": loss} return {"loss": loss}
def _make_noise_scheduler(name: str, **kwargs: dict) -> DDPMScheduler | DDIMScheduler:
"""
Factory for noise scheduler instances of the requested type. All kwargs are passed
to the scheduler.
"""
if name == "DDPM":
return DDPMScheduler(**kwargs)
elif name == "DDIM":
return DDIMScheduler(**kwargs)
else:
raise ValueError(f"Unsupported noise scheduler type {name}")
class DiffusionModel(nn.Module): class DiffusionModel(nn.Module):
def __init__(self, config: DiffusionConfig): def __init__(self, config: DiffusionConfig):
super().__init__() super().__init__()
@ -138,12 +152,12 @@ class DiffusionModel(nn.Module):
* config.n_obs_steps, * config.n_obs_steps,
) )
self.noise_scheduler = DDPMScheduler( self.noise_scheduler = _make_noise_scheduler(
config.noise_scheduler_type,
num_train_timesteps=config.num_train_timesteps, num_train_timesteps=config.num_train_timesteps,
beta_start=config.beta_start, beta_start=config.beta_start,
beta_end=config.beta_end, beta_end=config.beta_end,
beta_schedule=config.beta_schedule, beta_schedule=config.beta_schedule,
variance_type="fixed_small",
clip_sample=config.clip_sample, clip_sample=config.clip_sample,
clip_sample_range=config.clip_sample_range, clip_sample_range=config.clip_sample_range,
prediction_type=config.prediction_type, prediction_type=config.prediction_type,
@ -315,11 +329,13 @@ class DiffusionRgbEncoder(nn.Module):
# Set up pooling and final layers. # Set up pooling and final layers.
# Use a dry run to get the feature map shape. # Use a dry run to get the feature map shape.
# The dummy input should take the number of image channels from `config.input_shapes` and it should use the
# height and width from `config.crop_shape`.
dummy_input = torch.zeros(size=(1, config.input_shapes["observation.image"][0], *config.crop_shape))
with torch.inference_mode(): with torch.inference_mode():
feat_map_shape = tuple( dummy_feature_map = self.backbone(dummy_input)
self.backbone(torch.zeros(size=(1, *config.input_shapes["observation.image"]))).shape[1:] feature_map_shape = tuple(dummy_feature_map.shape[1:])
) self.pool = SpatialSoftmax(feature_map_shape, num_kp=config.spatial_softmax_num_keypoints)
self.pool = SpatialSoftmax(feat_map_shape, num_kp=config.spatial_softmax_num_keypoints)
self.feature_dim = config.spatial_softmax_num_keypoints * 2 self.feature_dim = config.spatial_softmax_num_keypoints * 2
self.out = nn.Linear(config.spatial_softmax_num_keypoints * 2, self.feature_dim) self.out = nn.Linear(config.spatial_softmax_num_keypoints * 2, self.feature_dim)
self.relu = nn.ReLU() self.relu = nn.ReLU()

View File

@ -38,7 +38,8 @@ class Policy(Protocol):
def forward(self, batch: dict[str, Tensor]) -> dict: def forward(self, batch: dict[str, Tensor]) -> dict:
"""Run the batch through the model and compute the loss for training or validation. """Run the batch through the model and compute the loss for training or validation.
Returns a dictionary with "loss" and maybe other information. Returns a dictionary with "loss" and potentially other information. Apart from "loss" which is a Tensor, all
other items should be logging-friendly, native Python types.
""" """
def select_action(self, batch: dict[str, Tensor]): def select_action(self, batch: dict[str, Tensor]):

View File

@ -47,7 +47,7 @@ class TDMPCConfig:
elite_weighting_temperature: The temperature to use for softmax weighting (by trajectory value) of the elite_weighting_temperature: The temperature to use for softmax weighting (by trajectory value) of the
elites, when updating the gaussian parameters for CEM. elites, when updating the gaussian parameters for CEM.
gaussian_mean_momentum: Momentum (α) used for EMA updates of the mean parameter μ of the gaussian gaussian_mean_momentum: Momentum (α) used for EMA updates of the mean parameter μ of the gaussian
paramters optimized in CEM. Updates are calculated as μ αμ + (1-α)μ. parameters optimized in CEM. Updates are calculated as μ αμ + (1-α)μ.
max_random_shift_ratio: Maximum random shift (as a proportion of the image size) to apply to the max_random_shift_ratio: Maximum random shift (as a proportion of the image size) to apply to the
image(s) (in units of pixels) for training-time augmentation. If set to 0, no such augmentation image(s) (in units of pixels) for training-time augmentation. If set to 0, no such augmentation
is applied. Note that the input images are assumed to be square for this augmentation. is applied. Note that the input images are assumed to be square for this augmentation.

View File

@ -1,8 +1,10 @@
import logging import logging
import os.path as osp import os.path as osp
import random import random
from contextlib import contextmanager
from datetime import datetime from datetime import datetime
from pathlib import Path from pathlib import Path
from typing import Generator
import hydra import hydra
import numpy as np import numpy as np
@ -39,6 +41,31 @@ def set_global_seed(seed):
torch.cuda.manual_seed_all(seed) torch.cuda.manual_seed_all(seed)
@contextmanager
def seeded_context(seed: int) -> Generator[None, None, None]:
"""Set the seed when entering a context, and restore the prior random state at exit.
Example usage:
```
a = random.random() # produces some random number
with seeded_context(1337):
b = random.random() # produces some other random number
c = random.random() # produces yet another random number, but the same it would have if we never made `b`
```
"""
random_state = random.getstate()
np_random_state = np.random.get_state()
torch_random_state = torch.random.get_rng_state()
torch_cuda_random_state = torch.cuda.random.get_rng_state()
set_global_seed(seed)
yield None
random.setstate(random_state)
np.random.set_state(np_random_state)
torch.random.set_rng_state(torch_random_state)
torch.cuda.random.set_rng_state(torch_cuda_random_state)
def init_logging(): def init_logging():
def custom_format(record): def custom_format(record):
dt = datetime.now().strftime("%Y-%m-%d %H:%M:%S") dt = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

View File

@ -3,6 +3,12 @@
seed: 1000 seed: 1000
dataset_repo_id: lerobot/aloha_sim_insertion_human dataset_repo_id: lerobot/aloha_sim_insertion_human
override_dataset_stats:
observation.images.top:
# stats from imagenet, since we use a pretrained vision model
mean: [[[0.485]], [[0.456]], [[0.406]]] # (c,1,1)
std: [[[0.229]], [[0.224]], [[0.225]]] # (c,1,1)
training: training:
offline_steps: 80000 offline_steps: 80000
online_steps: 0 online_steps: 0
@ -18,12 +24,6 @@ training:
grad_clip_norm: 10 grad_clip_norm: 10
online_steps_between_rollouts: 1 online_steps_between_rollouts: 1
override_dataset_stats:
observation.images.top:
# stats from imagenet, since we use a pretrained vision model
mean: [[[0.485]], [[0.456]], [[0.406]]] # (c,1,1)
std: [[[0.229]], [[0.224]], [[0.225]]] # (c,1,1)
delta_timestamps: delta_timestamps:
action: "[i / ${fps} for i in range(${policy.chunk_size})]" action: "[i / ${fps} for i in range(${policy.chunk_size})]"

View File

@ -7,6 +7,20 @@
seed: 100000 seed: 100000
dataset_repo_id: lerobot/pusht dataset_repo_id: lerobot/pusht
override_dataset_stats:
# TODO(rcadene, alexander-soare): should we remove image stats as well? do we use a pretrained vision model?
observation.image:
mean: [[[0.5]], [[0.5]], [[0.5]]] # (c,1,1)
std: [[[0.5]], [[0.5]], [[0.5]]] # (c,1,1)
# TODO(rcadene, alexander-soare): we override state and action stats to use the same as the pretrained model
# from the original codebase, but we should remove these and train our own pretrained model
observation.state:
min: [13.456424, 32.938293]
max: [496.14618, 510.9579]
action:
min: [12.0, 25.0]
max: [511.0, 511.0]
training: training:
offline_steps: 200000 offline_steps: 200000
online_steps: 0 online_steps: 0
@ -34,20 +48,6 @@ eval:
n_episodes: 50 n_episodes: 50
batch_size: 50 batch_size: 50
override_dataset_stats:
# TODO(rcadene, alexander-soare): should we remove image stats as well? do we use a pretrained vision model?
observation.image:
mean: [[[0.5]], [[0.5]], [[0.5]]] # (c,1,1)
std: [[[0.5]], [[0.5]], [[0.5]]] # (c,1,1)
# TODO(rcadene, alexander-soare): we override state and action stats to use the same as the pretrained model
# from the original codebase, but we should remove these and train our own pretrained model
observation.state:
min: [13.456424, 32.938293]
max: [496.14618, 510.9579]
action:
min: [12.0, 25.0]
max: [511.0, 511.0]
policy: policy:
name: diffusion name: diffusion
@ -85,6 +85,7 @@ policy:
diffusion_step_embed_dim: 128 diffusion_step_embed_dim: 128
use_film_scale_modulation: True use_film_scale_modulation: True
# Noise scheduler. # Noise scheduler.
noise_scheduler_type: DDPM
num_train_timesteps: 100 num_train_timesteps: 100
beta_schedule: squaredcos_cap_v2 beta_schedule: squaredcos_cap_v2
beta_start: 0.0001 beta_start: 0.0001

View File

@ -1,7 +1,7 @@
# @package _global_ # @package _global_
seed: 1 seed: 1
dataset_repo_id: lerobot/xarm_lift_medium_replay dataset_repo_id: lerobot/xarm_lift_medium
training: training:
offline_steps: 25000 offline_steps: 25000

View File

@ -72,6 +72,7 @@ def make_optimizer_and_scheduler(cfg, policy):
def update_policy(policy, batch, optimizer, grad_clip_norm, lr_scheduler=None): def update_policy(policy, batch, optimizer, grad_clip_norm, lr_scheduler=None):
"""Returns a dictionary of items for logging."""
start_time = time.time() start_time = time.time()
policy.train() policy.train()
output_dict = policy.forward(batch) output_dict = policy.forward(batch)
@ -99,6 +100,7 @@ def update_policy(policy, batch, optimizer, grad_clip_norm, lr_scheduler=None):
"grad_norm": float(grad_norm), "grad_norm": float(grad_norm),
"lr": optimizer.param_groups[0]["lr"], "lr": optimizer.param_groups[0]["lr"],
"update_s": time.time() - start_time, "update_s": time.time() - start_time,
**{k: v for k, v in output_dict.items() if k != "loss"},
} }
return info return info
@ -122,7 +124,7 @@ def train_notebook(out_dir=None, job_name=None, config_name="default", config_pa
train(cfg, out_dir=out_dir, job_name=job_name) train(cfg, out_dir=out_dir, job_name=job_name)
def log_train_info(logger, info, step, cfg, dataset, is_offline): def log_train_info(logger: Logger, info, step, cfg, dataset, is_offline):
loss = info["loss"] loss = info["loss"]
grad_norm = info["grad_norm"] grad_norm = info["grad_norm"]
lr = info["lr"] lr = info["lr"]

View File

@ -47,6 +47,7 @@ local$ rerun ws://localhost:9087
""" """
import argparse import argparse
import gc
import logging import logging
import time import time
from pathlib import Path from pathlib import Path
@ -115,15 +116,17 @@ def visualize_dataset(
spawn_local_viewer = mode == "local" and not save spawn_local_viewer = mode == "local" and not save
rr.init(f"{repo_id}/episode_{episode_index}", spawn=spawn_local_viewer) rr.init(f"{repo_id}/episode_{episode_index}", spawn=spawn_local_viewer)
# Manually call python garbage collector after `rr.init` to avoid hanging in a blocking flush
# when iterating on a dataloader with `num_workers` > 0
# TODO(rcadene): remove `gc.collect` when rerun version 0.16 is out, which includes a fix
gc.collect()
if mode == "distant": if mode == "distant":
rr.serve(open_browser=False, web_port=web_port, ws_port=ws_port) rr.serve(open_browser=False, web_port=web_port, ws_port=ws_port)
logging.info("Logging to Rerun") logging.info("Logging to Rerun")
if num_workers > 0:
# TODO(rcadene): fix data workers hanging when `rr.init` is called
logging.warning("If data loader is hanging, try `--num-workers 0`.")
for batch in tqdm.tqdm(dataloader, total=len(dataloader)): for batch in tqdm.tqdm(dataloader, total=len(dataloader)):
# iterate over the batch # iterate over the batch
for i in range(len(batch["index"])): for i in range(len(batch["index"])):
@ -196,7 +199,7 @@ def main():
parser.add_argument( parser.add_argument(
"--num-workers", "--num-workers",
type=int, type=int,
default=0, default=4,
help="Number of processes of Dataloader for loading the data.", help="Number of processes of Dataloader for loading the data.",
) )
parser.add_argument( parser.add_argument(

396
poetry.lock generated
View File

@ -131,17 +131,6 @@ files = [
{file = "antlr4-python3-runtime-4.9.3.tar.gz", hash = "sha256:f224469b4168294902bb1efa80a8bf7855f24c99aef99cbefc1bcd3cce77881b"}, {file = "antlr4-python3-runtime-4.9.3.tar.gz", hash = "sha256:f224469b4168294902bb1efa80a8bf7855f24c99aef99cbefc1bcd3cce77881b"},
] ]
[[package]]
name = "appdirs"
version = "1.4.4"
description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
optional = false
python-versions = "*"
files = [
{file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"},
{file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"},
]
[[package]] [[package]]
name = "asciitree" name = "asciitree"
version = "0.3.3" version = "0.3.3"
@ -1108,67 +1097,67 @@ protobuf = ["grpcio-tools (>=1.63.0)"]
[[package]] [[package]]
name = "gym-aloha" name = "gym-aloha"
version = "0.1.0" version = "0.1.1"
description = "A gym environment for ALOHA" description = "A gym environment for ALOHA"
optional = true optional = true
python-versions = "<4.0,>=3.10" python-versions = "<4.0,>=3.10"
files = [ files = [
{file = "gym_aloha-0.1.0-py3-none-any.whl", hash = "sha256:62e36eeb09284422cbb7baca0292c6f65e38ec8774bf9b0bf7159ad5990cf29a"}, {file = "gym_aloha-0.1.1-py3-none-any.whl", hash = "sha256:2698037246dbb106828f0bc229b61007b0a21d5967c72cc373f7bc1083203584"},
{file = "gym_aloha-0.1.0.tar.gz", hash = "sha256:bab332f469ba5ffe655fc3e9647aead05d2cb3b950dfb1f299b9539b3857ad7e"}, {file = "gym_aloha-0.1.1.tar.gz", hash = "sha256:614ae1cf116323e7b5ae2f0e9bd282c4f052aee15e839e5587ddce45995359bc"},
] ]
[package.dependencies] [package.dependencies]
dm-control = "1.0.14" dm-control = ">=1.0.14"
gymnasium = ">=0.29.1,<0.30.0" gymnasium = ">=0.29.1"
imageio = {version = ">=2.34.0,<3.0.0", extras = ["ffmpeg"]} imageio = {version = ">=2.34.0", extras = ["ffmpeg"]}
mujoco = ">=2.3.7,<3.0.0" mujoco = ">=2.3.7,<3.0.0"
[package.extras] [package.extras]
dev = ["debugpy (>=1.8.1,<2.0.0)", "pre-commit (>=3.7.0,<4.0.0)"] dev = ["debugpy (>=1.8.1)", "pre-commit (>=3.7.0)"]
test = ["pytest (>=8.1.0,<9.0.0)", "pytest-cov (>=5.0.0,<6.0.0)"] test = ["pytest (>=8.1.0)", "pytest-cov (>=5.0.0)"]
[[package]] [[package]]
name = "gym-pusht" name = "gym-pusht"
version = "0.1.1" version = "0.1.3"
description = "A gymnasium environment for PushT." description = "A gymnasium environment for PushT."
optional = true optional = true
python-versions = "<4.0,>=3.10" python-versions = "<4.0,>=3.10"
files = [ files = [
{file = "gym_pusht-0.1.1-py3-none-any.whl", hash = "sha256:dcf8644713db48286e907aabb11e005b0592632e323baa40d1a4f2dfbbc76c3d"}, {file = "gym_pusht-0.1.3-py3-none-any.whl", hash = "sha256:feeb02493a03d1aacc45d43d6397962c50ed779ab7e4019d73af11d2f0b3831b"},
{file = "gym_pusht-0.1.1.tar.gz", hash = "sha256:0d1c9ffd4ad0e2411efcc724003a365a853f20b6d596980c113e7ec181ac021f"}, {file = "gym_pusht-0.1.3.tar.gz", hash = "sha256:c8e9a5256035ba49841ebbc7c32a06c4fa2daa52f5fad80da941b607c4553e28"},
] ]
[package.dependencies] [package.dependencies]
gymnasium = ">=0.29.1,<0.30.0" gymnasium = ">=0.29.1"
opencv-python = ">=4.9.0.80,<5.0.0.0" opencv-python = ">=4.9.0"
pygame = ">=2.5.2,<3.0.0" pygame = ">=2.5.2"
pymunk = ">=6.6.0,<7.0.0" pymunk = ">=6.6.0"
scikit-image = ">=0.22.0" scikit-image = ">=0.22.0"
shapely = ">=2.0.3,<3.0.0" shapely = ">=2.0.3"
[package.extras] [package.extras]
dev = ["debugpy (>=1.8.1,<2.0.0)", "pre-commit (>=3.7.0,<4.0.0)"] dev = ["debugpy (>=1.8.1)", "pre-commit (>=3.7.0)"]
test = ["pytest (>=8.1.0,<9.0.0)", "pytest-cov (>=5.0.0,<6.0.0)"] test = ["pytest (>=8.1.0)", "pytest-cov (>=5.0.0)"]
[[package]] [[package]]
name = "gym-xarm" name = "gym-xarm"
version = "0.1.0" version = "0.1.1"
description = "A gym environment for xArm" description = "A gym environment for xArm"
optional = true optional = true
python-versions = "<4.0,>=3.10" python-versions = "<4.0,>=3.10"
files = [ files = [
{file = "gym_xarm-0.1.0-py3-none-any.whl", hash = "sha256:d10ac19a59d302201a9b8bd913530211b1058467b787ad91a657907e40cdbc13"}, {file = "gym_xarm-0.1.1-py3-none-any.whl", hash = "sha256:3bd7e3c1c5521ba80a56536f01a5e11321580704d72160355ce47a828a8808ad"},
{file = "gym_xarm-0.1.0.tar.gz", hash = "sha256:fc05f9d02af1f0205275311669dc191ce431be484e221a96401eb544764eb986"}, {file = "gym_xarm-0.1.1.tar.gz", hash = "sha256:e455524561b02d06b92a4f7d524f448d84a7484d9a2dbc78600e3c66240e0fb7"},
] ]
[package.dependencies] [package.dependencies]
gymnasium = ">=0.29.1,<0.30.0" gymnasium = ">=0.29.1"
gymnasium-robotics = ">=1.2.4,<2.0.0" gymnasium-robotics = ">=1.2.4"
mujoco = ">=2.3.7,<3.0.0" mujoco = ">=2.3.7,<3.0.0"
[package.extras] [package.extras]
dev = ["debugpy (>=1.8.1,<2.0.0)", "pre-commit (>=3.7.0,<4.0.0)"] dev = ["debugpy (>=1.8.1)", "pre-commit (>=3.7.0)"]
test = ["pytest (>=8.1.0,<9.0.0)", "pytest-cov (>=5.0.0,<6.0.0)"] test = ["pytest (>=8.1.0)", "pytest-cov (>=5.0.0)"]
[[package]] [[package]]
name = "gymnasium" name = "gymnasium"
@ -1258,13 +1247,13 @@ numpy = ">=1.17.3"
[[package]] [[package]]
name = "huggingface-hub" name = "huggingface-hub"
version = "0.21.4" version = "0.23.0"
description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub" description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub"
optional = false optional = false
python-versions = ">=3.8.0" python-versions = ">=3.8.0"
files = [ files = [
{file = "huggingface_hub-0.21.4-py3-none-any.whl", hash = "sha256:df37c2c37fc6c82163cdd8a67ede261687d80d1e262526d6c0ce73b6b3630a7b"}, {file = "huggingface_hub-0.23.0-py3-none-any.whl", hash = "sha256:075c30d48ee7db2bba779190dc526d2c11d422aed6f9044c5e2fdc2c432fdb91"},
{file = "huggingface_hub-0.21.4.tar.gz", hash = "sha256:e1f4968c93726565a80edf6dc309763c7b546d0cfe79aa221206034d50155531"}, {file = "huggingface_hub-0.23.0.tar.gz", hash = "sha256:7126dedd10a4c6fac796ced4d87a8cf004efc722a5125c2c09299017fa366fa9"},
] ]
[package.dependencies] [package.dependencies]
@ -1277,15 +1266,16 @@ tqdm = ">=4.42.1"
typing-extensions = ">=3.7.4.3" typing-extensions = ">=3.7.4.3"
[package.extras] [package.extras]
all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "mypy (==1.5.1)", "numpy", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.1.3)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "mypy (==1.5.1)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.3.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"]
cli = ["InquirerPy (==0.3.4)"] cli = ["InquirerPy (==0.3.4)"]
dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "mypy (==1.5.1)", "numpy", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.1.3)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "mypy (==1.5.1)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.3.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"]
fastai = ["fastai (>=2.4)", "fastcore (>=1.3.27)", "toml"] fastai = ["fastai (>=2.4)", "fastcore (>=1.3.27)", "toml"]
hf-transfer = ["hf-transfer (>=0.1.4)"] hf-transfer = ["hf-transfer (>=0.1.4)"]
inference = ["aiohttp", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)"] inference = ["aiohttp", "minijinja (>=1.0)"]
quality = ["mypy (==1.5.1)", "ruff (>=0.1.3)"] quality = ["mypy (==1.5.1)", "ruff (>=0.3.0)"]
tensorflow = ["graphviz", "pydot", "tensorflow"] tensorflow = ["graphviz", "pydot", "tensorflow"]
testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "gradio", "jedi", "numpy", "pydantic (>1.1,<2.0)", "pydantic (>1.1,<3.0)", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "soundfile", "urllib3 (<2.0)"] tensorflow-testing = ["keras (<3.0)", "tensorflow"]
testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio", "jedi", "minijinja (>=1.0)", "numpy", "pytest", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "soundfile", "urllib3 (<2.0)"]
torch = ["safetensors", "torch"] torch = ["safetensors", "torch"]
typing = ["types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)"] typing = ["types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)"]
@ -2587,7 +2577,7 @@ xmp = ["defusedxml"]
name = "platformdirs" name = "platformdirs"
version = "4.2.1" version = "4.2.1"
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`."
optional = true optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "platformdirs-4.2.1-py3-none-any.whl", hash = "sha256:17d5a1161b3fd67b390023cb2d3b026bbd40abde6fdb052dfbd3a29c3ba22ee1"}, {file = "platformdirs-4.2.1-py3-none-any.whl", hash = "sha256:17d5a1161b3fd67b390023cb2d3b026bbd40abde6fdb052dfbd3a29c3ba22ee1"},
@ -2616,13 +2606,13 @@ testing = ["pytest", "pytest-benchmark"]
[[package]] [[package]]
name = "pre-commit" name = "pre-commit"
version = "3.7.0" version = "3.7.1"
description = "A framework for managing and maintaining multi-language pre-commit hooks." description = "A framework for managing and maintaining multi-language pre-commit hooks."
optional = true optional = true
python-versions = ">=3.9" python-versions = ">=3.9"
files = [ files = [
{file = "pre_commit-3.7.0-py2.py3-none-any.whl", hash = "sha256:5eae9e10c2b5ac51577c3452ec0a490455c45a0533f7960f993a0d01e59decab"}, {file = "pre_commit-3.7.1-py2.py3-none-any.whl", hash = "sha256:fae36fd1d7ad7d6a5a1c0b0d5adb2ed1a3bda5a21bf6c3e5372073d7a11cd4c5"},
{file = "pre_commit-3.7.0.tar.gz", hash = "sha256:e209d61b8acdcf742404408531f0c37d49d2c734fd7cff2d6076083d191cb060"}, {file = "pre_commit-3.7.1.tar.gz", hash = "sha256:8ca3ad567bc78a4972a3f1a477e94a79d4597e8140a6e0b651c5e33899c3654a"},
] ]
[package.dependencies] [package.dependencies]
@ -2870,67 +2860,67 @@ files = [
[[package]] [[package]]
name = "pymunk" name = "pymunk"
version = "6.7.0" version = "6.8.0"
description = "Pymunk is a easy-to-use pythonic 2D physics library" description = "Pymunk is a easy-to-use pythonic 2D physics library"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "pymunk-6.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4378774daf5cf2603c0558562221ba5a2ba9c6d7e4d830f4da9e1d6a00e6f3cd"}, {file = "pymunk-6.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:96b363241569e616bea1d62346552e3503f2b58d6715b5bda20a13ba2522cea2"},
{file = "pymunk-6.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:badbdbf499f79c3e937ba7044c3ce3a665d6ae76c2a7df2408994e07fd78b34b"}, {file = "pymunk-6.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:91aab5c0640cddaf100eaaf6df8578aa3b97b70c5e5e0c1d26f6826eefec8e96"},
{file = "pymunk-6.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46835d63bdcc579a488d2dfbc7cbec52bfc34a4ceb15086820d1372f70cb8695"}, {file = "pymunk-6.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78973d4ef0fa715e127ca408f6063c82722b883d98cf216dddd906aa00debf4e"},
{file = "pymunk-6.7.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c63f0153bcb4080cd83f3d40cec4f525773ac0f4ac2bf9b9506c2fa8af7b4e41"}, {file = "pymunk-6.8.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7944db455d81bc552fc1b2edadbf82a6b91b11ee75193552ef629d0b8106975b"},
{file = "pymunk-6.7.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:72596e57997856817202580557a4f4b46a0b1ddf0fbbbadf978f46778d5aa642"}, {file = "pymunk-6.8.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3ec2a1c2a3b2b0eac97ebd2b84dfd51bd98b2b753a33dce81f4f26fa9e1a8974"},
{file = "pymunk-6.7.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:43099a916c2bbd9740a740f259bb26341e8cb54fb0c06192ea0cc27606552596"}, {file = "pymunk-6.8.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3134ba935921e0e888d9013258f1de111bc2da05a02ec2a7d520a8c580f28fba"},
{file = "pymunk-6.7.0-cp310-cp310-win32.whl", hash = "sha256:2cf770c8ae5d14c51b7021768bf73b7c8c62d786d703dd9f6e1ec3ea12966f91"}, {file = "pymunk-6.8.0-cp310-cp310-win32.whl", hash = "sha256:a3222cb84481408faf6236f4cea6a17045881e5780a4dccc170344a7a4ad160a"},
{file = "pymunk-6.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:e0ea3a7cab752bc5078c202e40bf4db81435fd1d121190e851a960a1b9a070df"}, {file = "pymunk-6.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:7f13bffe06634f23e0453b0a5e388142cdbaa06f54a243aae98e2b9c2793ebb0"},
{file = "pymunk-6.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:803c0dfb8be18a8fac5d37732d7db29589d6157594a22608fa5e34ee87a5ff8e"}, {file = "pymunk-6.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b0db72af65205c80d15403e6784bdd7c559e620411394449356dc869b90ade1c"},
{file = "pymunk-6.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e82f817cdddd3b9babebc1ce964eed55f8d5686475b92e3e6d3d22dca5b93f3c"}, {file = "pymunk-6.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d6e5cc30d15eba4bc33e00b9fb8c366255dac47fe486f5276f6334e8a8c34754"},
{file = "pymunk-6.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3693a1aeb4ce8a68574b3b7557c6a1e15ce420820b850f95f34ab24663fdcb11"}, {file = "pymunk-6.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3752e8486a4b8bfaa988be59a9773f0371d0cd52a7901fe7ba9caed1ea5b6129"},
{file = "pymunk-6.7.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f32b352a87ad1705bfedef133253da697e9a0eeff764e125414a63231bfb06e"}, {file = "pymunk-6.8.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f20b3dfc56aee57cc910ce65505286e184e045c9169bd8d5eff50974b6a1e97"},
{file = "pymunk-6.7.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7ec996c4305666336c3e2908b59e0644f4095a526ed2f96f0f8d35bdc41a4575"}, {file = "pymunk-6.8.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6d807bba8fd7bae35754c29c2cb8809f0cf7817541c8cb4d134872e102899724"},
{file = "pymunk-6.7.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7e54923293dfa51c41f222d967cb3b79872f35a4a892ae0bd31bad9cefd1b8a6"}, {file = "pymunk-6.8.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ac39afd90800061b353cbeb71171109ef7411cc88f5607b10447b2906e4cde97"},
{file = "pymunk-6.7.0-cp311-cp311-win32.whl", hash = "sha256:d4622c2927789d7bc834763569fb4a947c266702eb9e5f12f815bd841c49f669"}, {file = "pymunk-6.8.0-cp311-cp311-win32.whl", hash = "sha256:4de7683f832c694b82dbe7c20469765663f06ee82f8b711bd72731684b452889"},
{file = "pymunk-6.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:031c74ed42e49474ca4fcdc11a9521c2084514d2213cb8b7df7cb50a66b66686"}, {file = "pymunk-6.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:6620fc590290c37e58c8495fb74e5eb433f24b7c7d46c8a7b4b54c56ca9990ab"},
{file = "pymunk-6.7.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c2316d188a9fc6d0661afc30fbb164a546b939faf359e98f082641ca41c924e2"}, {file = "pymunk-6.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6eee05919e1e8f63b64a75362e82691365918b0ea33af11d2b3aab1d81402a3d"},
{file = "pymunk-6.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5f494effad0dbd873851b52b22c1a812fe36f1fb1e29d28759066cee1afca1e9"}, {file = "pymunk-6.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1b99fa28a8fa5242560a7f2d59604b9e55eed865d8308dd5f93af97ad2605f84"},
{file = "pymunk-6.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:895deeae5a9c2ef3bbb842ef5d37e750160c8ba956a4149fbb89304eb7b4808e"}, {file = "pymunk-6.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d9be0614a4c0eaaff209656df464e9eb5653dc171a15230dd4d307a3f3564e6"},
{file = "pymunk-6.7.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f672762c176ba51c2327f7a66db10c0adfb5f3caaa4f586098c62c169b311f87"}, {file = "pymunk-6.8.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2c22598b75ef99dd70fb2c6b8989c55ab00fac379555ebf68cfe7adfa65fd94e"},
{file = "pymunk-6.7.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:9f0e26d53cb5aaf22042de97638c356d25c1062198594390a18810f2992cd4b5"}, {file = "pymunk-6.8.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:533bb7555df1c904f1056ac9149e59ab039ee195fa22c69500843ef7e3f57062"},
{file = "pymunk-6.7.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:c4985590a95d419a7684f2c01b33fc61e939debaae7b12d1cf0946070c1644f9"}, {file = "pymunk-6.8.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9de831180f7650c47fcfcadadf5d295e72065c8500a4c9a78f6d37229c2ca58b"},
{file = "pymunk-6.7.0-cp312-cp312-win32.whl", hash = "sha256:b63875005eee0126a0be32cfd9179be520a2f73235ae98408af2ba39255f8e07"}, {file = "pymunk-6.8.0-cp312-cp312-win32.whl", hash = "sha256:8bbc9189c71a6c51825f8246e94c6642823ef42a4b3ed9c2afa7f8ec48425929"},
{file = "pymunk-6.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:4a9438d29c1f0397b45b328f74eaed097593de03d8d0546fa84c20c3a5f158e6"}, {file = "pymunk-6.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:e3b61a162153dfdd0ebbab82eddb417da812085b3587ebf92a225d33df8e044d"},
{file = "pymunk-6.7.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:630ddc4a03f4ac9d5dfd13bb99e20146d804683212defb8d0633fbf4844035b4"}, {file = "pymunk-6.8.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8a4fa8e3672a3b49850adf71b0eabacabb73db0514cbece0649bc77e1a124924"},
{file = "pymunk-6.7.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca0c565e7c8ff8bc2ee477ed712973609a77a229e813a7a18c499ff5b96415a7"}, {file = "pymunk-6.8.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ada172ee87296fdfdf5ac0d88c43502b482697185ce9b6d03d0f0d4b5b11532"},
{file = "pymunk-6.7.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f0d79e89fc3ccee6007380a9df493017c178a606446a1382fc0e351bd48622d"}, {file = "pymunk-6.8.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c0c9d881ca7d9a9375ce248e90f24efb298d41e4abf8e16f5c7e78c66983c34"},
{file = "pymunk-6.7.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:827180ee032b3237be2980712cdfe1446c2f7aeeb7f13518ebb4cc022995d235"}, {file = "pymunk-6.8.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:e5a6e2a7ff652b2977e24b4ed2d33fc7d628bd4e54ddeb488515b1475f715d91"},
{file = "pymunk-6.7.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c401a6068b376dcd3d25948b498cea410e15a93108c4d8e03c94f9b61767593b"}, {file = "pymunk-6.8.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:12f0af3417a95c5ab97207a5e54fbc91a54c801b4560283532f5582401a1f36e"},
{file = "pymunk-6.7.0-cp37-cp37m-win32.whl", hash = "sha256:a38d8b70c6a7198fc0e746ab8dfedd70f9bf26579b6cd11789f3232f27d247fb"}, {file = "pymunk-6.8.0-cp37-cp37m-win32.whl", hash = "sha256:382aaa71d7615ded7cfc644a091391cf0fd3ecf7bc556e0145d0f6982c942ee7"},
{file = "pymunk-6.7.0-cp37-cp37m-win_amd64.whl", hash = "sha256:283746a11658288903af182605f1034bc5cffbb5de49fd4d8bea43330778ddfb"}, {file = "pymunk-6.8.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c40361a2b017107303568ace3e506d87ab46d67d31484f656ba7792901d20abd"},
{file = "pymunk-6.7.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8376aad8169a13a5368c597cf54b492f6dd6ef4c9273385af461b6f416f0205a"}, {file = "pymunk-6.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:54167f0f9b65a49f35fbde56746ce7020b74b39b86ef8cec8804ef9422d258c9"},
{file = "pymunk-6.7.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0bf0ec5142ae387789eca6210a315508943a0af14faf337154c1c6b2e20abaad"}, {file = "pymunk-6.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3e32c520ba2729c97fd5031cc0caa99de20a9b6dda85b8468cf769afa7a4a85c"},
{file = "pymunk-6.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e5469182821d23e43e1fe50b21a313f798eefafc59b0f25dd69a7b579cdbbbc"}, {file = "pymunk-6.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93c86daf68fb0785722cbea3fc36afcf9830af156de9ed99cbf2b6d6475240ab"},
{file = "pymunk-6.7.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cee5c5da3f624c1b4f10e566f6322f354f0925dc081c1d6dfdb56fa94ff6b2b7"}, {file = "pymunk-6.8.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:269576ad7d4241c75611df0f0e3ff0b19de436f4facabb21185e579a573c91d0"},
{file = "pymunk-6.7.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:130234abfb503a9d3aba57161bf7520eb57c27278ad6f47888f862a2808b1f8d"}, {file = "pymunk-6.8.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a4c90c82e6dfd35930ad779287859c3a867518065fce97fee6eeaf81a1754ea6"},
{file = "pymunk-6.7.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3532965ba0048057ce00eccbafca818586acabf77c4453d36e9be5f614dab260"}, {file = "pymunk-6.8.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06b5ce0a26a26b3490107c962632f4dd53137df14e11b0e55c9816005509dea1"},
{file = "pymunk-6.7.0-cp38-cp38-win32.whl", hash = "sha256:3dca5b72c34f4957c039ced8bd58ca484b929f0f6c4fc4f8a2268d89999d3b13"}, {file = "pymunk-6.8.0-cp38-cp38-win32.whl", hash = "sha256:ff3b4d086f47f4fee9980977ec4f1121909b5456ed05fcad3c0f2f6e224e1fef"},
{file = "pymunk-6.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:aaac3b0a2446575cf0fa90745ef6b99cd786837e1baaf2f530febf2824d07276"}, {file = "pymunk-6.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:82d8f7124ab9e5c69ab698d3836dc0d84e1a31d47b5e7ce6477cf5205d701887"},
{file = "pymunk-6.7.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6ee13324c8fdfdab03069eef00aadfe06d353d9d6c5e4a93e190c9b214166f8b"}, {file = "pymunk-6.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:47803f8229b95e9ae56cada9566e1b92b2789affe2229ed623d3a871fd307982"},
{file = "pymunk-6.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1fd1069c95061feebf7dfbbb32a2150e019d06001a0c8281442d27366d2a6f21"}, {file = "pymunk-6.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:194cf34146b7393ebdd2e37cb50d5579e737baf378f900a50ff477c909a163c9"},
{file = "pymunk-6.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7aeac2ba24977aae4e602a993c17c265f168374b018d09e13536c1df61cf4d5"}, {file = "pymunk-6.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af8d9d0a26dc4d504ac881407ac9d7689b0c89bf8c0535717c15583773eb965"},
{file = "pymunk-6.7.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e78eb9f6b6a7656837698ea9a6ceea00d84959de3126e625de41cf240084dba6"}, {file = "pymunk-6.8.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:79c50449c12120d05fdf515e4c937220580f945ed1eda8c374734a3418fc18e6"},
{file = "pymunk-6.7.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:927fa4262c62f409e79806ef282a3bee1dab5a69e680e5cf2ba26b58c850e9be"}, {file = "pymunk-6.8.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:45197c7fcebff6bc3d4b7f3ccef150a6c4c43f71860e03503e851c8ecc0af861"},
{file = "pymunk-6.7.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c127f39bd23c93e82f0ee0adc1edbd8ebdda441d12f9d09987372be9852edb74"}, {file = "pymunk-6.8.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:183ecbbafffe8a071ffb0efb6a5daa21f05d2b9a36c0538b47fbd15b6e6fa6e5"},
{file = "pymunk-6.7.0-cp39-cp39-win32.whl", hash = "sha256:ce582ae06e6fe8e8d1ad10dc061fe5716b360ea04b79925532d96848741a5452"}, {file = "pymunk-6.8.0-cp39-cp39-win32.whl", hash = "sha256:2453eff73e474c1f282088e70a5dfd970ebc9f565c1b39b1da69df1b43dee47f"},
{file = "pymunk-6.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:04874a4063270db73bd2e6b3522d2e6ffb193a183d06872bb1270385475412f8"}, {file = "pymunk-6.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:769aae66d3918fa7d9ac33fca4e693a53aba1ed801050450c1a42b4c8ecc7250"},
{file = "pymunk-6.7.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:032daa41f9219749e52b1ff3312cdff3eab24c31ec8495777da89003667137ad"}, {file = "pymunk-6.8.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:22153b93074e8f397e245aad2811e50ccc94502616341a1420c2a3a7332c1db0"},
{file = "pymunk-6.7.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210e067b29fda70a8c21f09a9a900d0b917d425e6d47209426e5b88388bd2a06"}, {file = "pymunk-6.8.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2b6d5d62b1f8ad3b8626be64817bed709edbbd03b578e33ae3e39ab7f9301055"},
{file = "pymunk-6.7.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:046e510d76976c41cd92b3d5b985c930f0a568c2fb4f0632e40aaab4619ad481"}, {file = "pymunk-6.8.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50d9ff9e7caa3a7f432f4c6da4d1acd0dd1208ca22fc4cea3d48d845ac4111b3"},
{file = "pymunk-6.7.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:27a4104a51ae690fc0feb2a567279234307decaf86214382a1dce89527365422"}, {file = "pymunk-6.8.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b0688613c641c5a018091ba9285a38cb6e53a64daa9ec3bc80006ea6c4531a32"},
{file = "pymunk-6.7.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:8ac7b714a8fc83325519254c6734baa9dd1498210c6d5e51facfd829a6b2de09"}, {file = "pymunk-6.8.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:42cf265d55dd90ab3441c9e0a1596094372b063713760d2a5489321d1b9beddb"},
{file = "pymunk-6.7.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09b22ce73222c5f7cf061f6cd71097c94f57c89b6364acfc30f707ca1d3c67e2"}, {file = "pymunk-6.8.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f199f1f291f7ad8ec3c00d529c6207bb7a67497b6ecd79ffb27df1aabe973d7"},
{file = "pymunk-6.7.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3313c5531e6678f249bc1cf84cb5c4993745e8652853f1962919678f6a0b4ec3"}, {file = "pymunk-6.8.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:79fe51090090f4dd4e41603bbc46926be4bae3c3f554664b907fc3fda65019f8"},
{file = "pymunk-6.7.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d8aaaebdd546b9b76d4905039835910a5965fff816261ce2b9558a7607206f52"}, {file = "pymunk-6.8.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:03100f749d276742244d560e12ae125cbcf13606d24fd60455b52d5b9a9f7a17"},
{file = "pymunk-6.7.0.tar.gz", hash = "sha256:7b3bff3852c46a87b497a1a73bb36bb2b2f7e38be2e7c232498b857e79197560"}, {file = "pymunk-6.8.0.tar.gz", hash = "sha256:882929eac3cc5107bec13da7bbe9b6a3868df87ecc373475d0d1aae82d2f5dda"},
] ]
[package.dependencies] [package.dependencies]
@ -3102,90 +3092,90 @@ files = [
[[package]] [[package]]
name = "regex" name = "regex"
version = "2024.4.28" version = "2024.5.10"
description = "Alternative regular expression module, to replace re." description = "Alternative regular expression module, to replace re."
optional = false optional = false
python-versions = ">=3.8" python-versions = ">=3.8"
files = [ files = [
{file = "regex-2024.4.28-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd196d056b40af073d95a2879678585f0b74ad35190fac04ca67954c582c6b61"}, {file = "regex-2024.5.10-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:eda3dd46df535da787ffb9036b5140f941ecb91701717df91c9daf64cabef953"},
{file = "regex-2024.4.28-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8bb381f777351bd534462f63e1c6afb10a7caa9fa2a421ae22c26e796fe31b1f"}, {file = "regex-2024.5.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1d5bd666466c8f00a06886ce1397ba8b12371c1f1c6d1bef11013e9e0a1464a8"},
{file = "regex-2024.4.28-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:47af45b6153522733aa6e92543938e97a70ce0900649ba626cf5aad290b737b6"}, {file = "regex-2024.5.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:32e5f3b8e32918bfbdd12eca62e49ab3031125c454b507127ad6ecbd86e62fca"},
{file = "regex-2024.4.28-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99d6a550425cc51c656331af0e2b1651e90eaaa23fb4acde577cf15068e2e20f"}, {file = "regex-2024.5.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:534efd2653ebc4f26fc0e47234e53bf0cb4715bb61f98c64d2774a278b58c846"},
{file = "regex-2024.4.28-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bf29304a8011feb58913c382902fde3395957a47645bf848eea695839aa101b7"}, {file = "regex-2024.5.10-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:193b7c6834a06f722f0ce1ba685efe80881de7c3de31415513862f601097648c"},
{file = "regex-2024.4.28-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:92da587eee39a52c91aebea8b850e4e4f095fe5928d415cb7ed656b3460ae79a"}, {file = "regex-2024.5.10-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:160ba087232c5c6e2a1e7ad08bd3a3f49b58c815be0504d8c8aacfb064491cd8"},
{file = "regex-2024.4.28-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6277d426e2f31bdbacb377d17a7475e32b2d7d1f02faaecc48d8e370c6a3ff31"}, {file = "regex-2024.5.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:951be1eae7b47660412dc4938777a975ebc41936d64e28081bf2e584b47ec246"},
{file = "regex-2024.4.28-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:28e1f28d07220c0f3da0e8fcd5a115bbb53f8b55cecf9bec0c946eb9a059a94c"}, {file = "regex-2024.5.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8a0f0ab5453e409586b11ebe91c672040bc804ca98d03a656825f7890cbdf88"},
{file = "regex-2024.4.28-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:aaa179975a64790c1f2701ac562b5eeb733946eeb036b5bcca05c8d928a62f10"}, {file = "regex-2024.5.10-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9e6d4d6ae1827b2f8c7200aaf7501c37cf3f3896c86a6aaf2566448397c823dd"},
{file = "regex-2024.4.28-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6f435946b7bf7a1b438b4e6b149b947c837cb23c704e780c19ba3e6855dbbdd3"}, {file = "regex-2024.5.10-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:161a206c8f3511e2f5fafc9142a2cc25d7fe9a1ec5ad9b4ad2496a7c33e1c5d2"},
{file = "regex-2024.4.28-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:19d6c11bf35a6ad077eb23852827f91c804eeb71ecb85db4ee1386825b9dc4db"}, {file = "regex-2024.5.10-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:44b3267cea873684af022822195298501568ed44d542f9a2d9bebc0212e99069"},
{file = "regex-2024.4.28-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:fdae0120cddc839eb8e3c15faa8ad541cc6d906d3eb24d82fb041cfe2807bc1e"}, {file = "regex-2024.5.10-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:560278c9975694e1f0bc50da187abf2cdc1e4890739ea33df2bc4a85eeef143e"},
{file = "regex-2024.4.28-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e672cf9caaf669053121f1766d659a8813bd547edef6e009205378faf45c67b8"}, {file = "regex-2024.5.10-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:70364a097437dd0a90b31cd77f09f7387ad9ac60ef57590971f43b7fca3082a5"},
{file = "regex-2024.4.28-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f57515750d07e14743db55d59759893fdb21d2668f39e549a7d6cad5d70f9fea"}, {file = "regex-2024.5.10-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:42be5de7cc8c1edac55db92d82b68dc8e683b204d6f5414c5a51997a323d7081"},
{file = "regex-2024.4.28-cp310-cp310-win32.whl", hash = "sha256:a1409c4eccb6981c7baabc8888d3550df518add6e06fe74fa1d9312c1838652d"}, {file = "regex-2024.5.10-cp310-cp310-win32.whl", hash = "sha256:9a8625849387b9d558d528e263ecc9c0fbde86cfa5c2f0eef43fff480ae24d71"},
{file = "regex-2024.4.28-cp310-cp310-win_amd64.whl", hash = "sha256:1f687a28640f763f23f8a9801fe9e1b37338bb1ca5d564ddd41619458f1f22d1"}, {file = "regex-2024.5.10-cp310-cp310-win_amd64.whl", hash = "sha256:903350bf44d7e4116b4d5898b30b15755d61dcd3161e3413a49c7db76f0bee5a"},
{file = "regex-2024.4.28-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:84077821c85f222362b72fdc44f7a3a13587a013a45cf14534df1cbbdc9a6796"}, {file = "regex-2024.5.10-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bf9596cba92ce7b1fd32c7b07c6e3212c7eed0edc271757e48bfcd2b54646452"},
{file = "regex-2024.4.28-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b45d4503de8f4f3dc02f1d28a9b039e5504a02cc18906cfe744c11def942e9eb"}, {file = "regex-2024.5.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:45cc13d398b6359a7708986386f72bd156ae781c3e83a68a6d4cee5af04b1ce9"},
{file = "regex-2024.4.28-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:457c2cd5a646dd4ed536c92b535d73548fb8e216ebee602aa9f48e068fc393f3"}, {file = "regex-2024.5.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ad45f3bccfcb00868f2871dce02a755529838d2b86163ab8a246115e80cfb7d6"},
{file = "regex-2024.4.28-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b51739ddfd013c6f657b55a508de8b9ea78b56d22b236052c3a85a675102dc6"}, {file = "regex-2024.5.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33d19f0cde6838c81acffff25c7708e4adc7dd02896c9ec25c3939b1500a1778"},
{file = "regex-2024.4.28-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:459226445c7d7454981c4c0ce0ad1a72e1e751c3e417f305722bbcee6697e06a"}, {file = "regex-2024.5.10-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0a9f89d7db5ef6bdf53e5cc8e6199a493d0f1374b3171796b464a74ebe8e508a"},
{file = "regex-2024.4.28-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:670fa596984b08a4a769491cbdf22350431970d0112e03d7e4eeaecaafcd0fec"}, {file = "regex-2024.5.10-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c6c71cf92b09e5faa72ea2c68aa1f61c9ce11cb66fdc5069d712f4392ddfd00"},
{file = "regex-2024.4.28-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe00f4fe11c8a521b173e6324d862ee7ee3412bf7107570c9b564fe1119b56fb"}, {file = "regex-2024.5.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7467ad8b0eac0b28e52679e972b9b234b3de0ea5cee12eb50091d2b68145fe36"},
{file = "regex-2024.4.28-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:36f392dc7763fe7924575475736bddf9ab9f7a66b920932d0ea50c2ded2f5636"}, {file = "regex-2024.5.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bc0db93ad039fc2fe32ccd3dd0e0e70c4f3d6e37ae83f0a487e1aba939bd2fbd"},
{file = "regex-2024.4.28-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:23a412b7b1a7063f81a742463f38821097b6a37ce1e5b89dd8e871d14dbfd86b"}, {file = "regex-2024.5.10-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fa9335674d7c819674467c7b46154196c51efbaf5f5715187fd366814ba3fa39"},
{file = "regex-2024.4.28-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f1d6e4b7b2ae3a6a9df53efbf199e4bfcff0959dbdb5fd9ced34d4407348e39a"}, {file = "regex-2024.5.10-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7dda3091838206969c2b286f9832dff41e2da545b99d1cfaea9ebd8584d02708"},
{file = "regex-2024.4.28-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:499334ad139557de97cbc4347ee921c0e2b5e9c0f009859e74f3f77918339257"}, {file = "regex-2024.5.10-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:504b5116e2bd1821efd815941edff7535e93372a098e156bb9dffde30264e798"},
{file = "regex-2024.4.28-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:0940038bec2fe9e26b203d636c44d31dd8766abc1fe66262da6484bd82461ccf"}, {file = "regex-2024.5.10-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:91b53dea84415e8115506cc62e441a2b54537359c63d856d73cb1abe05af4c9a"},
{file = "regex-2024.4.28-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:66372c2a01782c5fe8e04bff4a2a0121a9897e19223d9eab30c54c50b2ebeb7f"}, {file = "regex-2024.5.10-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1a3903128f9e17a500618e80c68165c78c741ebb17dd1a0b44575f92c3c68b02"},
{file = "regex-2024.4.28-cp311-cp311-win32.whl", hash = "sha256:c77d10ec3c1cf328b2f501ca32583625987ea0f23a0c2a49b37a39ee5c4c4630"}, {file = "regex-2024.5.10-cp311-cp311-win32.whl", hash = "sha256:236cace6c1903effd647ed46ce6dd5d76d54985fc36dafc5256032886736c85d"},
{file = "regex-2024.4.28-cp311-cp311-win_amd64.whl", hash = "sha256:fc0916c4295c64d6890a46e02d4482bb5ccf33bf1a824c0eaa9e83b148291f90"}, {file = "regex-2024.5.10-cp311-cp311-win_amd64.whl", hash = "sha256:12446827f43c7881decf2c126762e11425de5eb93b3b0d8b581344c16db7047a"},
{file = "regex-2024.4.28-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:08a1749f04fee2811c7617fdd46d2e46d09106fa8f475c884b65c01326eb15c5"}, {file = "regex-2024.5.10-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:14905ed75c7a6edf423eb46c213ed3f4507c38115f1ed3c00f4ec9eafba50e58"},
{file = "regex-2024.4.28-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b8eb28995771c087a73338f695a08c9abfdf723d185e57b97f6175c5051ff1ae"}, {file = "regex-2024.5.10-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4fad420b14ae1970a1f322e8ae84a1d9d89375eb71e1b504060ab2d1bfe68f3c"},
{file = "regex-2024.4.28-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:dd7ef715ccb8040954d44cfeff17e6b8e9f79c8019daae2fd30a8806ef5435c0"}, {file = "regex-2024.5.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c46a76a599fcbf95f98755275c5527304cc4f1bb69919434c1e15544d7052910"},
{file = "regex-2024.4.28-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb0315a2b26fde4005a7c401707c5352df274460f2f85b209cf6024271373013"}, {file = "regex-2024.5.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0faecb6d5779753a6066a3c7a0471a8d29fe25d9981ca9e552d6d1b8f8b6a594"},
{file = "regex-2024.4.28-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f2fc053228a6bd3a17a9b0a3f15c3ab3cf95727b00557e92e1cfe094b88cc662"}, {file = "regex-2024.5.10-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aab65121229c2ecdf4a31b793d99a6a0501225bd39b616e653c87b219ed34a49"},
{file = "regex-2024.4.28-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fe9739a686dc44733d52d6e4f7b9c77b285e49edf8570754b322bca6b85b4cc"}, {file = "regex-2024.5.10-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:50e7e96a527488334379e05755b210b7da4a60fc5d6481938c1fa053e0c92184"},
{file = "regex-2024.4.28-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74fcf77d979364f9b69fcf8200849ca29a374973dc193a7317698aa37d8b01c"}, {file = "regex-2024.5.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba034c8db4b264ef1601eb33cd23d87c5013b8fb48b8161debe2e5d3bd9156b0"},
{file = "regex-2024.4.28-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:965fd0cf4694d76f6564896b422724ec7b959ef927a7cb187fc6b3f4e4f59833"}, {file = "regex-2024.5.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:031219782d97550c2098d9a68ce9e9eaefe67d2d81d8ff84c8354f9c009e720c"},
{file = "regex-2024.4.28-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:2fef0b38c34ae675fcbb1b5db760d40c3fc3612cfa186e9e50df5782cac02bcd"}, {file = "regex-2024.5.10-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:62b5f7910b639f3c1d122d408421317c351e213ca39c964ad4121f27916631c6"},
{file = "regex-2024.4.28-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bc365ce25f6c7c5ed70e4bc674f9137f52b7dd6a125037f9132a7be52b8a252f"}, {file = "regex-2024.5.10-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:cd832bd9b6120d6074f39bdfbb3c80e416848b07ac72910f1c7f03131a6debc3"},
{file = "regex-2024.4.28-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:ac69b394764bb857429b031d29d9604842bc4cbfd964d764b1af1868eeebc4f0"}, {file = "regex-2024.5.10-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:e91b1976358e17197157b405cab408a5f4e33310cda211c49fc6da7cffd0b2f0"},
{file = "regex-2024.4.28-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:144a1fc54765f5c5c36d6d4b073299832aa1ec6a746a6452c3ee7b46b3d3b11d"}, {file = "regex-2024.5.10-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:571452362d552de508c37191b6abbbb660028b8b418e2d68c20779e0bc8eaaa8"},
{file = "regex-2024.4.28-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2630ca4e152c221072fd4a56d4622b5ada876f668ecd24d5ab62544ae6793ed6"}, {file = "regex-2024.5.10-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5253dcb0bfda7214523de58b002eb0090cb530d7c55993ce5f6d17faf953ece7"},
{file = "regex-2024.4.28-cp312-cp312-win32.whl", hash = "sha256:7f3502f03b4da52bbe8ba962621daa846f38489cae5c4a7b5d738f15f6443d17"}, {file = "regex-2024.5.10-cp312-cp312-win32.whl", hash = "sha256:2f30a5ab8902f93930dc6f627c4dd5da2703333287081c85cace0fc6e21c25af"},
{file = "regex-2024.4.28-cp312-cp312-win_amd64.whl", hash = "sha256:0dd3f69098511e71880fb00f5815db9ed0ef62c05775395968299cb400aeab82"}, {file = "regex-2024.5.10-cp312-cp312-win_amd64.whl", hash = "sha256:3799e36d60a35162bb35b2246d8bb012192b7437dff807ef79c14e7352706306"},
{file = "regex-2024.4.28-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:374f690e1dd0dbdcddea4a5c9bdd97632cf656c69113f7cd6a361f2a67221cb6"}, {file = "regex-2024.5.10-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:bbdc5db2c98ac2bf1971ffa1410c87ca7a15800415f788971e8ba8520fc0fda9"},
{file = "regex-2024.4.28-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:25f87ae6b96374db20f180eab083aafe419b194e96e4f282c40191e71980c666"}, {file = "regex-2024.5.10-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6ccdeef4584450b6f0bddd5135354908dacad95425fcb629fe36d13e48b60f32"},
{file = "regex-2024.4.28-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5dbc1bcc7413eebe5f18196e22804a3be1bfdfc7e2afd415e12c068624d48247"}, {file = "regex-2024.5.10-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:29d839829209f3c53f004e1de8c3113efce6d98029f044fa5cfee666253ee7e6"},
{file = "regex-2024.4.28-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f85151ec5a232335f1be022b09fbbe459042ea1951d8a48fef251223fc67eee1"}, {file = "regex-2024.5.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0709ba544cf50bd5cb843df4b8bb6701bae2b70a8e88da9add8386cbca5c1385"},
{file = "regex-2024.4.28-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:57ba112e5530530fd175ed550373eb263db4ca98b5f00694d73b18b9a02e7185"}, {file = "regex-2024.5.10-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:972b49f2fe1047b9249c958ec4fa1bdd2cf8ce305dc19d27546d5a38e57732d8"},
{file = "regex-2024.4.28-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:224803b74aab56aa7be313f92a8d9911dcade37e5f167db62a738d0c85fdac4b"}, {file = "regex-2024.5.10-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9cdbb1998da94607d5eec02566b9586f0e70d6438abf1b690261aac0edda7ab6"},
{file = "regex-2024.4.28-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a54a047b607fd2d2d52a05e6ad294602f1e0dec2291152b745870afc47c1397"}, {file = "regex-2024.5.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf7c8ee4861d9ef5b1120abb75846828c811f932d63311596ad25fa168053e00"},
{file = "regex-2024.4.28-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a2a512d623f1f2d01d881513af9fc6a7c46e5cfffb7dc50c38ce959f9246c94"}, {file = "regex-2024.5.10-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d35d4cc9270944e95f9c88af757b0c9fc43f396917e143a5756608462c5223b"},
{file = "regex-2024.4.28-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c06bf3f38f0707592898428636cbb75d0a846651b053a1cf748763e3063a6925"}, {file = "regex-2024.5.10-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:8722f72068b3e1156a4b2e1afde6810f1fc67155a9fa30a4b9d5b4bc46f18fb0"},
{file = "regex-2024.4.28-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:1031a5e7b048ee371ab3653aad3030ecfad6ee9ecdc85f0242c57751a05b0ac4"}, {file = "regex-2024.5.10-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:696639a73ca78a380acfaa0a1f6dd8220616a99074c05bba9ba8bb916914b224"},
{file = "regex-2024.4.28-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d7a353ebfa7154c871a35caca7bfd8f9e18666829a1dc187115b80e35a29393e"}, {file = "regex-2024.5.10-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea057306ab469130167014b662643cfaed84651c792948891d003cf0039223a5"},
{file = "regex-2024.4.28-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:7e76b9cfbf5ced1aca15a0e5b6f229344d9b3123439ffce552b11faab0114a02"}, {file = "regex-2024.5.10-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:b43b78f9386d3d932a6ce5af4b45f393d2e93693ee18dc4800d30a8909df700e"},
{file = "regex-2024.4.28-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:5ce479ecc068bc2a74cb98dd8dba99e070d1b2f4a8371a7dfe631f85db70fe6e"}, {file = "regex-2024.5.10-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:c43395a3b7cc9862801a65c6994678484f186ce13c929abab44fb8a9e473a55a"},
{file = "regex-2024.4.28-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7d77b6f63f806578c604dca209280e4c54f0fa9a8128bb8d2cc5fb6f99da4150"}, {file = "regex-2024.5.10-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0bc94873ba11e34837bffd7e5006703abeffc4514e2f482022f46ce05bd25e67"},
{file = "regex-2024.4.28-cp38-cp38-win32.whl", hash = "sha256:d84308f097d7a513359757c69707ad339da799e53b7393819ec2ea36bc4beb58"}, {file = "regex-2024.5.10-cp38-cp38-win32.whl", hash = "sha256:1118ba9def608250250f4b3e3f48c62f4562ba16ca58ede491b6e7554bfa09ff"},
{file = "regex-2024.4.28-cp38-cp38-win_amd64.whl", hash = "sha256:2cc1b87bba1dd1a898e664a31012725e48af826bf3971e786c53e32e02adae6c"}, {file = "regex-2024.5.10-cp38-cp38-win_amd64.whl", hash = "sha256:458d68d34fb74b906709735c927c029e62f7d06437a98af1b5b6258025223210"},
{file = "regex-2024.4.28-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7413167c507a768eafb5424413c5b2f515c606be5bb4ef8c5dee43925aa5718b"}, {file = "regex-2024.5.10-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:15e593386ec6331e0ab4ac0795b7593f02ab2f4b30a698beb89fbdc34f92386a"},
{file = "regex-2024.4.28-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:108e2dcf0b53a7c4ab8986842a8edcb8ab2e59919a74ff51c296772e8e74d0ae"}, {file = "regex-2024.5.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ca23b41355ba95929e9505ee04e55495726aa2282003ed9b012d86f857d3e49b"},
{file = "regex-2024.4.28-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f1c5742c31ba7d72f2dedf7968998730664b45e38827637e0f04a2ac7de2f5f1"}, {file = "regex-2024.5.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2c8982ee19ccecabbaeac1ba687bfef085a6352a8c64f821ce2f43e6d76a9298"},
{file = "regex-2024.4.28-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecc6148228c9ae25ce403eade13a0961de1cb016bdb35c6eafd8e7b87ad028b1"}, {file = "regex-2024.5.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7117cb7d6ac7f2e985f3d18aa8a1728864097da1a677ffa69e970ca215baebf1"},
{file = "regex-2024.4.28-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7d893c8cf0e2429b823ef1a1d360a25950ed11f0e2a9df2b5198821832e1947"}, {file = "regex-2024.5.10-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b66421f8878a0c82fc0c272a43e2121c8d4c67cb37429b764f0d5ad70b82993b"},
{file = "regex-2024.4.28-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4290035b169578ffbbfa50d904d26bec16a94526071ebec3dadbebf67a26b25e"}, {file = "regex-2024.5.10-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:224a9269f133564109ce668213ef3cb32bc72ccf040b0b51c72a50e569e9dc9e"},
{file = "regex-2024.4.28-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44a22ae1cfd82e4ffa2066eb3390777dc79468f866f0625261a93e44cdf6482b"}, {file = "regex-2024.5.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab98016541543692a37905871a5ffca59b16e08aacc3d7d10a27297b443f572d"},
{file = "regex-2024.4.28-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd24fd140b69f0b0bcc9165c397e9b2e89ecbeda83303abf2a072609f60239e2"}, {file = "regex-2024.5.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:51d27844763c273a122e08a3e86e7aefa54ee09fb672d96a645ece0454d8425e"},
{file = "regex-2024.4.28-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:39fb166d2196413bead229cd64a2ffd6ec78ebab83fff7d2701103cf9f4dfd26"}, {file = "regex-2024.5.10-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:853cc36e756ff673bf984e9044ccc8fad60b95a748915dddeab9488aea974c73"},
{file = "regex-2024.4.28-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9301cc6db4d83d2c0719f7fcda37229691745168bf6ae849bea2e85fc769175d"}, {file = "regex-2024.5.10-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4e7eaf9df15423d07b6050fb91f86c66307171b95ea53e2d87a7993b6d02c7f7"},
{file = "regex-2024.4.28-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7c3d389e8d76a49923683123730c33e9553063d9041658f23897f0b396b2386f"}, {file = "regex-2024.5.10-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:169fd0acd7a259f58f417e492e93d0e15fc87592cd1e971c8c533ad5703b5830"},
{file = "regex-2024.4.28-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:99ef6289b62042500d581170d06e17f5353b111a15aa6b25b05b91c6886df8fc"}, {file = "regex-2024.5.10-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:334b79ce9c08f26b4659a53f42892793948a613c46f1b583e985fd5a6bf1c149"},
{file = "regex-2024.4.28-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:b91d529b47798c016d4b4c1d06cc826ac40d196da54f0de3c519f5a297c5076a"}, {file = "regex-2024.5.10-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:f03b1dbd4d9596dd84955bb40f7d885204d6aac0d56a919bb1e0ff2fb7e1735a"},
{file = "regex-2024.4.28-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:43548ad74ea50456e1c68d3c67fff3de64c6edb85bcd511d1136f9b5376fc9d1"}, {file = "regex-2024.5.10-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cfa6d61a76c77610ba9274c1a90a453062bdf6887858afbe214d18ad41cf6bde"},
{file = "regex-2024.4.28-cp39-cp39-win32.whl", hash = "sha256:05d9b6578a22db7dedb4df81451f360395828b04f4513980b6bd7a1412c679cc"}, {file = "regex-2024.5.10-cp39-cp39-win32.whl", hash = "sha256:249fbcee0a277c32a3ce36d8e36d50c27c968fdf969e0fbe342658d4e010fbc8"},
{file = "regex-2024.4.28-cp39-cp39-win_amd64.whl", hash = "sha256:3986217ec830c2109875be740531feb8ddafe0dfa49767cdcd072ed7e8927962"}, {file = "regex-2024.5.10-cp39-cp39-win_amd64.whl", hash = "sha256:0ce56a923f4c01d7568811bfdffe156268c0a7aae8a94c902b92fe34c4bde785"},
{file = "regex-2024.4.28.tar.gz", hash = "sha256:83ab366777ea45d58f72593adf35d36ca911ea8bd838483c1823b883a121b0e4"}, {file = "regex-2024.5.10.tar.gz", hash = "sha256:304e7e2418146ae4d0ef0e9ffa28f881f7874b45b4994cc2279b21b6e7ae50c8"},
] ]
[[package]] [[package]]
@ -3813,13 +3803,13 @@ tests = ["pytest", "pytest-cov"]
[[package]] [[package]]
name = "tifffile" name = "tifffile"
version = "2024.5.3" version = "2024.5.10"
description = "Read and write TIFF files" description = "Read and write TIFF files"
optional = true optional = true
python-versions = ">=3.9" python-versions = ">=3.9"
files = [ files = [
{file = "tifffile-2024.5.3-py3-none-any.whl", hash = "sha256:cac4d939156ff7f16d65fd689637808a7b5b3ad58f9c73327fc009b0aa32c7d5"}, {file = "tifffile-2024.5.10-py3-none-any.whl", hash = "sha256:4154f091aa24d4e75bfad9ab2d5424a68c70e67b8220188066dc61946d4551bd"},
{file = "tifffile-2024.5.3.tar.gz", hash = "sha256:44521508ecc51ebaf0e47e9748913e9c7331a4e32fb571ff4dfc05cb8f4d8896"}, {file = "tifffile-2024.5.10.tar.gz", hash = "sha256:aa1e1b12be952ab20717d6848bd6d4a5ee88d2aa319f1152bff4354ad728ec86"},
] ]
[package.dependencies] [package.dependencies]
@ -4034,36 +4024,40 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess
[[package]] [[package]]
name = "wandb" name = "wandb"
version = "0.16.6" version = "0.17.0"
description = "A CLI and library for interacting with the Weights & Biases API." description = "A CLI and library for interacting with the Weights & Biases API."
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
files = [ files = [
{file = "wandb-0.16.6-py3-none-any.whl", hash = "sha256:5810019a3b981c796e98ea58557a7c380f18834e0c6bdaed15df115522e5616e"}, {file = "wandb-0.17.0-py3-none-any.whl", hash = "sha256:b1b056b4cad83b00436cb76049fd29ecedc6045999dcaa5eba40db6680960ac2"},
{file = "wandb-0.16.6.tar.gz", hash = "sha256:86f491e3012d715e0d7d7421a4d6de41abef643b7403046261f962f3e512fe1c"}, {file = "wandb-0.17.0-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:e1e6f04e093a6a027dcb100618ca23b122d032204b2ed4c62e4e991a48041a6b"},
{file = "wandb-0.17.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:feeb60d4ff506d2a6bc67f953b310d70b004faa789479c03ccd1559c6f1a9633"},
{file = "wandb-0.17.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7bed8a3dd404a639e6bf5fea38c6efe2fb98d416ff1db4fb51be741278ed328"},
{file = "wandb-0.17.0-py3-none-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56a1dd6e0e635cba3f6ed30b52c71739bdc2a3e57df155619d2d80ee952b4201"},
{file = "wandb-0.17.0-py3-none-win32.whl", hash = "sha256:1f692d3063a0d50474022cfe6668e1828260436d1cd40827d1e136b7f730c74c"},
{file = "wandb-0.17.0-py3-none-win_amd64.whl", hash = "sha256:ab582ca0d54d52ef5b991de0717350b835400d9ac2d3adab210022b68338d694"},
] ]
[package.dependencies] [package.dependencies]
appdirs = ">=1.4.3" click = ">=7.1,<8.0.0 || >8.0.0"
Click = ">=7.1,<8.0.0 || >8.0.0"
docker-pycreds = ">=0.4.0" docker-pycreds = ">=0.4.0"
GitPython = ">=1.0.0,<3.1.29 || >3.1.29" gitpython = ">=1.0.0,<3.1.29 || >3.1.29"
platformdirs = "*"
protobuf = {version = ">=3.19.0,<4.21.0 || >4.21.0,<5", markers = "python_version > \"3.9\" or sys_platform != \"linux\""} protobuf = {version = ">=3.19.0,<4.21.0 || >4.21.0,<5", markers = "python_version > \"3.9\" or sys_platform != \"linux\""}
psutil = ">=5.0.0" psutil = ">=5.0.0"
PyYAML = "*" pyyaml = "*"
requests = ">=2.0.0,<3" requests = ">=2.0.0,<3"
sentry-sdk = ">=1.0.0" sentry-sdk = ">=1.0.0"
setproctitle = "*" setproctitle = "*"
setuptools = "*" setuptools = "*"
[package.extras] [package.extras]
async = ["httpx (>=0.23.0)"]
aws = ["boto3"] aws = ["boto3"]
azure = ["azure-identity", "azure-storage-blob"] azure = ["azure-identity", "azure-storage-blob"]
gcp = ["google-cloud-storage"] gcp = ["google-cloud-storage"]
importers = ["filelock", "mlflow", "polars", "rich", "tenacity"] importers = ["filelock", "mlflow", "polars", "rich", "tenacity"]
kubeflow = ["google-cloud-storage", "kubernetes", "minio", "sh"] kubeflow = ["google-cloud-storage", "kubernetes", "minio", "sh"]
launch = ["PyYAML (>=6.0.0)", "awscli", "azure-containerregistry", "azure-identity", "azure-storage-blob", "boto3", "botocore", "chardet", "google-auth", "google-cloud-aiplatform", "google-cloud-artifact-registry", "google-cloud-compute", "google-cloud-storage", "iso8601", "kubernetes", "kubernetes-asyncio", "nbconvert", "nbformat", "optuna", "pydantic", "tomli", "typing-extensions"] launch = ["awscli", "azure-containerregistry", "azure-identity", "azure-storage-blob", "boto3", "botocore", "chardet", "google-auth", "google-cloud-aiplatform", "google-cloud-artifact-registry", "google-cloud-compute", "google-cloud-storage", "iso8601", "kubernetes", "kubernetes-asyncio", "nbconvert", "nbformat", "optuna", "pydantic", "pyyaml (>=6.0.0)", "tomli", "typing-extensions"]
media = ["bokeh", "moviepy", "numpy", "pillow", "plotly (>=5.18.0)", "rdkit-pypi", "soundfile"] media = ["bokeh", "moviepy", "numpy", "pillow", "plotly (>=5.18.0)", "rdkit-pypi", "soundfile"]
models = ["cloudpickle"] models = ["cloudpickle"]
perf = ["orjson"] perf = ["orjson"]
@ -4309,13 +4303,13 @@ multidict = ">=4.0"
[[package]] [[package]]
name = "zarr" name = "zarr"
version = "2.17.2" version = "2.18.0"
description = "An implementation of chunked, compressed, N-dimensional arrays for Python" description = "An implementation of chunked, compressed, N-dimensional arrays for Python"
optional = false optional = false
python-versions = ">=3.9" python-versions = ">=3.9"
files = [ files = [
{file = "zarr-2.17.2-py3-none-any.whl", hash = "sha256:70d7cc07c24280c380ef80644151d136b7503b0d83c9f214e8000ddc0f57f69b"}, {file = "zarr-2.18.0-py3-none-any.whl", hash = "sha256:7f8532b6a3f50f22e809e130e09353637ec8b5bb5e95a5a0bfaae91f63978b5d"},
{file = "zarr-2.17.2.tar.gz", hash = "sha256:2cbaa6cb4e342d45152d4a7a4b2013c337fcd3a8e7bc98253560180de60552ce"}, {file = "zarr-2.18.0.tar.gz", hash = "sha256:c3b7d2c85b8a42b0ad0ad268a36fb6886ca852098358c125c6b126a417e0a598"},
] ]
[package.dependencies] [package.dependencies]
@ -4354,4 +4348,4 @@ xarm = ["gym-xarm"]
[metadata] [metadata]
lock-version = "2.0" lock-version = "2.0"
python-versions = ">=3.10,<3.13" python-versions = ">=3.10,<3.13"
content-hash = "008a6af5ad9d9eafbd933c922c2c5d84fddae85aff8a9eefc0538b1319966f6e" content-hash = "2f0d2cbf4a2dec546e25b29b9b108ff1f97b4c278b718360b3f7f6a2bf9dcef8"

View File

@ -28,37 +28,37 @@ packages = [{include = "lerobot"}]
[tool.poetry.dependencies] [tool.poetry.dependencies]
python = ">=3.10,<3.13" python = ">=3.10,<3.13"
termcolor = "^2.4.0" termcolor = ">=2.4.0"
omegaconf = "^2.3.0" omegaconf = ">=2.3.0"
wandb = "^0.16.3" wandb = ">=0.16.3"
imageio = {extras = ["ffmpeg"], version = "^2.34.0"} imageio = {extras = ["ffmpeg"], version = ">=2.34.0"}
gdown = "^5.1.0" gdown = ">=5.1.0"
hydra-core = "^1.3.2" hydra-core = ">=1.3.2"
einops = "^0.8.0" einops = ">=0.8.0"
pymunk = "^6.6.0" pymunk = ">=6.6.0"
zarr = "^2.17.0" zarr = ">=2.17.0"
numba = "^0.59.0" numba = ">=0.59.0"
torch = "^2.2.1" torch = "^2.2.1"
opencv-python = "^4.9.0.80" opencv-python = ">=4.9.0"
diffusers = "^0.27.2" diffusers = "^0.27.2"
torchvision = "^0.18.0" torchvision = ">=0.18.0"
h5py = "^3.10.0" h5py = ">=3.10.0"
huggingface-hub = "^0.21.4" huggingface-hub = ">=0.21.4"
robomimic = "0.2.0" robomimic = "0.2.0"
gymnasium = "^0.29.1" gymnasium = ">=0.29.1"
cmake = "^3.29.0.1" cmake = ">=3.29.0.1"
gym-pusht = { version = "^0.1.1", optional = true} gym-pusht = { version = ">=0.1.3", optional = true}
gym-xarm = { version = "^0.1.0", optional = true} gym-xarm = { version = ">=0.1.1", optional = true}
gym-aloha = { version = "^0.1.0", optional = true} gym-aloha = { version = ">=0.1.1", optional = true}
pre-commit = {version = "^3.7.0", optional = true} pre-commit = {version = ">=3.7.0", optional = true}
debugpy = {version = "^1.8.1", optional = true} debugpy = {version = ">=1.8.1", optional = true}
pytest = {version = "^8.1.0", optional = true} pytest = {version = ">=8.1.0", optional = true}
pytest-cov = {version = "^5.0.0", optional = true} pytest-cov = {version = ">=5.0.0", optional = true}
datasets = "^2.19.0" datasets = "^2.19.0"
imagecodecs = { version = "^2024.1.1", optional = true } imagecodecs = { version = ">=2024.1.1", optional = true }
pyav = "^12.0.5" pyav = ">=12.0.5"
moviepy = "^1.0.3" moviepy = ">=1.0.3"
rerun-sdk = "^0.15.1" rerun-sdk = ">=0.15.1"
[tool.poetry.extras] [tool.poetry.extras]
@ -104,5 +104,5 @@ ignore-init-module-imports = true
[build-system] [build-system]
requires = ["poetry-core>=1.5.0"] requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api" build-backend = "poetry.core.masonry.api"

View File

@ -3,6 +3,8 @@ import subprocess
import sys import sys
from pathlib import Path from pathlib import Path
from tests.utils import require_package
def _find_and_replace(text: str, finds_and_replaces: list[tuple[str, str]]) -> str: def _find_and_replace(text: str, finds_and_replaces: list[tuple[str, str]]) -> str:
for f, r in finds_and_replaces: for f, r in finds_and_replaces:
@ -21,6 +23,7 @@ def test_example_1():
assert Path("outputs/examples/1_load_lerobot_dataset/episode_0.mp4").exists() assert Path("outputs/examples/1_load_lerobot_dataset/episode_0.mp4").exists()
@require_package("gym_pusht")
def test_examples_3_and_2(): def test_examples_3_and_2():
""" """
Train a model with example 3, check the outputs. Train a model with example 3, check the outputs.

View File

@ -236,7 +236,7 @@ def test_normalize(insert_temporal_dim):
@pytest.mark.parametrize( @pytest.mark.parametrize(
"env_name, policy_name, extra_overrides", "env_name, policy_name, extra_overrides",
[ [
# ("xarm", "tdmpc", ["policy.n_action_repeats=2"]), ("xarm", "tdmpc", []),
( (
"pusht", "pusht",
"diffusion", "diffusion",

38
tests/test_utils.py Normal file
View File

@ -0,0 +1,38 @@
import random
from typing import Callable
import numpy as np
import pytest
import torch
from lerobot.common.utils.utils import seeded_context, set_global_seed
@pytest.mark.parametrize(
"rand_fn",
[
random.random,
np.random.random,
lambda: torch.rand(1).item(),
]
+ [lambda: torch.rand(1, device="cuda")]
if torch.cuda.is_available()
else [],
)
def test_seeding(rand_fn: Callable[[], int]):
set_global_seed(0)
a = rand_fn()
with seeded_context(1337):
c = rand_fn()
b = rand_fn()
set_global_seed(0)
a_ = rand_fn()
b_ = rand_fn()
# Check that `set_global_seed` lets us reproduce a and b.
assert a_ == a
# Additionally, check that the `seeded_context` didn't interrupt the global RNG.
assert b_ == b
set_global_seed(1337)
c_ = rand_fn()
# Check that `seeded_context` and `global_seed` give the same reproducibility.
assert c_ == c

View File

@ -1,4 +1,5 @@
import platform import platform
from functools import wraps
import pytest import pytest
import torch import torch
@ -61,7 +62,6 @@ def require_env(func):
Decorator that skips the test if the required environment package is not installed. Decorator that skips the test if the required environment package is not installed.
As it need 'env_name' in args, it also checks whether it is provided as an argument. As it need 'env_name' in args, it also checks whether it is provided as an argument.
""" """
from functools import wraps
@wraps(func) @wraps(func)
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
@ -82,3 +82,20 @@ def require_env(func):
return func(*args, **kwargs) return func(*args, **kwargs)
return wrapper return wrapper
def require_package(package_name):
"""
Decorator that skips the test if the specified package is not installed.
"""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
if not is_package_available(package_name):
pytest.skip(f"{package_name} not installed")
return func(*args, **kwargs)
return wrapper
return decorator