A unified Python library for JEPA, V-JEPA, LeJEPA world models, and physical intelligence research.
Project description
py-jepa
A unified Python library for Joint Embedding Predictive Architecture (JEPA) models, LeWorldModel (LeWM) world models, and physical intelligence research.
pyjepa provides one consistent API covering pre-training (I-JEPA, V-JEPA), end-to-end world-model training (LeWM), finetuning (linear probe, attentive pooler), model-predictive planning (CEM, MPPI), and inference — running identically on Apple Silicon (Metal/MPS), NVIDIA CUDA, and plain CPU.
Table of Contents
- Overview
- Installation
- Quick Start
- Architecture Overview
- Supported Hardware
- Training Guide
- Finetuning
- Planning
- Inference
- Custom Models
- Configuration
- CLI Reference
- Performance Notes
- Citation
Overview
pyjepa unifies three families of models under one clean API:
| Model | Paper | Key idea |
|---|---|---|
| I-JEPA | Assran et al., CVPR 2023 | Predict representations of masked image regions in latent space (not pixel space). An EMA target encoder prevents collapse. |
| V-JEPA | Bardes et al., arXiv 2024 | Extends I-JEPA to video with 3-D spatiotemporal masking (tube + multi-block). |
| LeWM | Maes, Le Lidec et al., arXiv 2026 | End-to-end JEPA world model trained from raw pixels with just two losses: prediction MSE and SIGReg. No EMA encoder. ~15 M parameters. Trains on a single GPU in hours. |
All three share the same VisionTransformer encoder backbone, the same optimizer and scheduler utilities, and a common checkpoint format. You can pre-train with I-JEPA, finetune a classifier head, and then adapt the encoder into a LeWM world model — with no code changes beyond swapping the training wrapper.
Installation
From PyPI
pip install pyjepa
Install with optional extras for your use case:
pip install pyjepa[vision] # torchvision + Pillow for image datasets
pip install pyjepa[video] # av + decord for video loading
pip install pyjepa[data] # h5py + datasets for trajectory data
pip install pyjepa[train] # wandb + tensorboard experiment tracking
pip install pyjepa[planning] # scipy for advanced planning utilities
pip install pyjepa[all] # everything above
From Source
git clone https://github.com/your-org/py-jepa.git
cd py-jepa
pip install -e ".[dev]" # editable install + dev tools (pytest, ruff, black)
Apple Silicon (macOS, M1/M2/M3/M4)
No extra configuration needed. pyjepa auto-detects the MPS (Metal Performance Shaders) backend and uses it transparently. Install PyTorch 2.1+ from pytorch.org with the standard macOS wheel — the MPS backend is included.
pip install torch torchvision # MPS included in standard macOS PyTorch wheel
pip install pyjepa[vision]
Windows (CUDA)
Install the CUDA-enabled PyTorch wheel for your toolkit version first:
# Example for CUDA 12.1 — see pytorch.org for the correct command for your setup
pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121
pip install pyjepa[all]
Quick Start
I-JEPA Image Pre-training
import torch
from torch.utils.data import DataLoader
from pyjepa import IJEPA, IJEPATrainer, IJEPAConfig, TrainConfig
from pyjepa import vit_small, vit_predictor, MultiBlockMaskCollator
from pyjepa.models.wrappers import MultiMaskWrapper, PredictorMultiMaskWrapper
# Build encoder and predictor
enc = vit_small(img_size=224, patch_size=16)
pred = vit_predictor(img_size=224, patch_size=16, embed_dim=enc.embed_dim, depth=4)
model = IJEPA(encoder=MultiMaskWrapper(enc), predictor=PredictorMultiMaskWrapper(pred))
# Mask collator with 1 context config and 1 prediction config
cfgs_mask = [
{"spatial_scale": (0.85, 1.0), "aspect_ratio": (0.75, 1.5), "num_blocks": 1}, # context
{"spatial_scale": (0.15, 0.2), "aspect_ratio": (0.75, 1.5), "num_blocks": 4}, # prediction
]
collator = MultiBlockMaskCollator(cfgs_mask, crop_size=224, patch_size=16)
def collate_fn(batch):
imgs = torch.stack([b[0] for b in batch])
return collator([[img] for img in imgs])
loader = DataLoader(your_dataset, batch_size=256, collate_fn=collate_fn)
# Train with IJEPATrainer
train_cfg = TrainConfig(output_dir="./output/ijepa", epochs=300, device="auto")
ijepa_cfg = IJEPAConfig(lr=1e-3, weight_decay=0.04, warmup_epochs=40)
trainer = IJEPATrainer(model, train_cfg, ijepa_cfg, iterations_per_epoch=len(loader))
trainer.fit(loader)
V-JEPA Video Pre-training
import torch
from torch.utils.data import DataLoader
from pyjepa import IJEPA, VJEPATrainer, VJEPAConfig, TrainConfig
from pyjepa import vit_small, vit_predictor, MultiBlock3DMaskCollator
from pyjepa.models.wrappers import MultiMaskWrapper, PredictorMultiMaskWrapper
# Build 3D video encoder and predictor
enc = vit_small(img_size=224, patch_size=16, num_frames=16, tubelet_size=2)
pred = vit_predictor(img_size=224, patch_size=16, num_frames=16, embed_dim=enc.embed_dim, depth=4)
model = IJEPA(encoder=MultiMaskWrapper(enc), predictor=PredictorMultiMaskWrapper(pred))
# 3D mask collator with spatiotemporal configs
cfgs_mask = [
{"spatial_scale": (0.85, 1.0), "temporal_scale": (1.0, 1.0),
"aspect_ratio": (0.75, 1.5), "num_blocks": 1}, # context
{"spatial_scale": (0.15, 0.2), "temporal_scale": (0.5, 1.0),
"aspect_ratio": (0.75, 1.5), "num_blocks": 4}, # prediction
]
collator = MultiBlock3DMaskCollator(cfgs_mask, crop_size=224, patch_size=16,
num_frames=16, tubelet_size=2)
def collate_fn(batch):
clips = torch.stack([b[0] for b in batch])
return collator([[clip] for clip in clips])
loader = DataLoader(your_video_dataset, batch_size=32, collate_fn=collate_fn)
# Train with IJEPATrainer (same trainer works for V-JEPA)
train_cfg = TrainConfig(output_dir="./output/vjepa", epochs=200, device="auto")
ijepa_cfg = IJEPAConfig(lr=6e-4, weight_decay=0.04, warmup_epochs=20)
trainer = IJEPATrainer(model, train_cfg, ijepa_cfg, iterations_per_epoch=len(loader))
trainer.fit(loader)
LeWM World Model Training
import torch
from torch.utils.data import DataLoader
from pyjepa import vit_small, build_lewm, LeWMTrainer, LeWMConfig, TrainConfig
from pyjepa.data import TrajectoryDataset
# Build world model
encoder = vit_small(img_size=84, patch_size=12)
model = build_lewm(
encoder, action_dim=4, history_size=3,
emb_dim=192, # match encoder output
action_emb_dim=64,
pred_depth=6, pred_heads=6, pred_mlp_dim=1024,
)
# Create trajectory dataset from episodes
# Each episode: {"pixels": (T, 3, H, W), "action": (T, action_dim), ...}
dataset = TrajectoryDataset(episodes, window=8) # history_size + num_preds
loader = DataLoader(dataset, batch_size=128)
# Train world model
train_cfg = TrainConfig(output_dir="./output/lewm", epochs=100, device="auto")
lewm_cfg = LeWMConfig(
lr=3e-4, history_size=3, num_preds=5,
sigreg_weight=0.1, sigreg_knots=17, sigreg_num_proj=1024,
)
trainer = LeWMTrainer(model, train_cfg, lewm_cfg)
trainer.fit(loader)
LeWM Planning with CEM
import torch
from pyjepa import vit_small, build_lewm, CEMPlanner, PlanConfig
# Load trained model
encoder = vit_small(img_size=84, patch_size=12)
model = build_lewm(encoder, action_dim=4, history_size=3, emb_dim=192)
model.eval()
# Observation window (context) and goal representation
B, T_ctx = 1, 3
info = {
"pixels": torch.randn(B, T_ctx, 3, 84, 84), # (B, T_ctx, C, H, W) context
"goal": torch.randn(B, 1, 3, 84, 84), # (B, 1, C, H, W) target goal image
}
# CEM planner: iteratively optimize action sequence to reach goal
cfg = PlanConfig(
horizon=10, # planning horizon (steps)
action_dim=4, # action space dimension
num_samples=512, # candidate trajectories per iteration
num_elites=64, # elite fraction for CEM
num_iters=5, # optimization iterations
action_min=-1.0, # action bounds
action_max=1.0,
)
planner = CEMPlanner(cfg)
with torch.no_grad():
best_action_seq = planner(model, info) # (H, A)
# Execute first action in the environment
action_to_execute = best_action_seq[0].numpy() # (4,)
Architecture Overview
I-JEPA
I-JEPA (Image JEPA) trains a VisionTransformer encoder end-to-end with a masked prediction objective in latent space. Given an image, a context block is encoded by the online encoder; 4 target blocks are encoded by an EMA (exponential moving average) copy of the encoder. A lightweight cross-attention predictor maps context embeddings to predicted target embeddings.
The training objective is:
L_JEPA = (1/M) * sum_m ||predictor(enc(x_ctx), mask_m) - sg(enc_ema(x, mask_m))||^2
where sg(·) is stop-gradient on the EMA branch. The variance regularizer VR(z) = mean(relu(1 - sqrt(var(z) + eps))) can optionally penalize representation collapse.
V-JEPA
V-JEPA extends I-JEPA to video by replacing 2-D spatial masking with 3-D spatiotemporal masking. Masks are sampled as volumetric blocks (tubes) across the temporal dimension; the predictor must recover embeddings of masked space-time regions conditioned on the visible context. The architecture is otherwise identical — the VisionTransformer switches to 3-D tubelet patch embeddings when num_frames > 1.
LeWM (LeWorldModel)
LeWM trains a world model entirely end-to-end from pixels with two losses:
L = ||AR_predictor(enc(x_t), a_t) - enc(x_{t+1})||^2 + lambda * SIGReg(enc(x))
SIGReg (Sketched Isotropic Gaussian Regularizer) prevents representation collapse by matching the empirical characteristic function of latent embeddings to that of a standard Gaussian, using random 1-D projections:
SIGReg(Z) = (1/K) * sum_k | (1/N) * sum_n exp(i * w_k^T z_n) - exp(-||w_k||^2/2) |^2
The autoregressive predictor (ARPredictor) is a causal Transformer conditioned on action embeddings via AdaLN-zero blocks, making next-state predictions that are used directly for model-predictive planning.
Supported Hardware
| Backend | Device string | AMP dtype | torch.compile |
Notes |
|---|---|---|---|---|
| NVIDIA CUDA | cuda / cuda:N |
float16 or bfloat16 (SM80+) |
Supported | Flash-Attention 2 via SDPA |
| Apple Silicon MPS | mps |
float32 (MPS autocast experimental) |
Not recommended | Math SDPA kernel; no cuda.sdp_kernel context |
| CPU | cpu |
float32 |
Supported (slow) | Fallback for testing |
| AMD ROCm | cuda (HIP) |
float16 |
Supported | Detected via torch.version.hip |
| Intel XPU | xpu |
— | — | Basic support via torch.xpu |
pyjepa auto-selects the device via PYJEPA_DEVICE environment variable or get_device():
import pyjepa
device = pyjepa.get_device() # auto: CUDA → MPS → CPU
device = pyjepa.get_device("mps") # explicit
device = pyjepa.get_device("cuda:1") # specific GPU
info = pyjepa.DeviceInfo.from_current() # structured hardware snapshot
print(info) # shows memory, bf16, sdpa, compile support
Training Guide
IJEPATrainer
from pyjepa.training import IJEPATrainer, IJEPAConfig, TrainConfig
train_cfg = TrainConfig(
output_dir="./output/ijepa",
device="auto", # or "cuda", "mps", "cpu"
epochs=300,
amp_dtype="float16", # "float16", "bfloat16", "float32"
grad_clip=10.0,
compile_model=False, # True only on CUDA; MPS not supported
save_every_epochs=10,
keep_last_ckpts=3,
)
ijepa_cfg = IJEPAConfig(
lr=1e-3,
start_lr=2e-4,
final_lr=1e-6,
weight_decay=0.04,
warmup_epochs=40,
momentum_start=0.996, # EMA momentum schedule
momentum_end=1.0,
loss_exp=1.0,
reg_coeff=0.0, # variance regularizer weight
)
trainer = IJEPATrainer(
model, train_cfg, ijepa_cfg,
iterations_per_epoch=len(loader),
)
trainer.fit(loader)
Hook into the training loop with callbacks:
@trainer.on_step
def log_step(metrics):
print(f"step {metrics['step']}: loss={metrics['loss']:.4f}")
@trainer.on_epoch_end
def checkpoint_epoch(epoch, metrics):
if metrics["val_loss"] < best_val:
trainer.save_checkpoint("best.pth")
LeWMTrainer
from pyjepa.training import LeWMTrainer, LeWMConfig, TrainConfig
lewm_cfg = LeWMConfig(
lr=3e-4,
history_size=3,
num_preds=5,
sigreg_weight=0.1,
sigreg_knots=17,
sigreg_num_proj=1024,
)
trainer = LeWMTrainer(model, TrainConfig(output_dir="./output/lewm"), lewm_cfg)
trainer.fit(loader)
Each training batch must contain a window = history_size + num_preds observation window. Configure your TrajectoryDataset accordingly:
dataset = TrajectoryDataset(episodes, obs_key="pixels", act_key="action",
window=history_size + num_preds)
One-Call Training
For simple use cases that do not need custom callbacks:
pyjepa.train_ijepa(model, loader, epochs=300, lr=1e-3, output_dir="./out")
pyjepa.train_vjepa(model, loader, epochs=200, lr=6e-4, output_dir="./out")
pyjepa.train_lewm(model, loader, epochs=100, lr=3e-4, sigreg_weight=0.1,
history_size=3, num_preds=5, output_dir="./out")
Config-Driven Training (YAML)
pyjepa train ijepa --config configs/ijepa_base.yaml
pyjepa train vjepa --config configs/vjepa_base.yaml
pyjepa train lewm --config configs/lewm_base.yaml
Load and extend configs programmatically:
from pyjepa import load_config, save_config
cfg = load_config("configs/ijepa_base.yaml", overrides={"training.lr": 5e-4})
print(cfg.training.lr) # 0.0005
print(cfg["training.lr"]) # also works
Distributed Training
pyjepa uses torch.distributed for multi-GPU training. Launch with torchrun:
torchrun --nproc_per_node=8 train.py --config configs/ijepa_base.yaml
Initialize in your script:
from pyjepa.utils.distributed import init_distributed, AllReduce
init_distributed() # reads RANK/WORLD_SIZE/MASTER_ADDR from environment
Finetuning
Linear Probe
from pyjepa.training.finetune import LinearProbeTrainer, FinetuneConfig
ft_cfg = FinetuneConfig(
num_classes=1000,
head="linear", # "linear" or "attentive"
freeze_encoder=True,
lr=1e-3,
label_smoothing=0.1,
)
trainer = LinearProbeTrainer(ijepa_model.encoder, train_cfg, ft_cfg)
trainer.fit(train_loader, val_loader)
Attentive Pooler
The attentive pooler uses learned query tokens + cross-attention over patch tokens — stronger than a single CLS token:
ft_cfg = FinetuneConfig(num_classes=1000, head="attentive", freeze_encoder=True)
One-Call Finetuning
pyjepa.finetune_classifier(
encoder=model.encoder,
train_loader=train_loader,
val_loader=val_loader,
num_classes=1000,
head="attentive",
freeze_encoder=True,
epochs=100,
lr=1e-3,
output_dir="./output/finetune",
)
The AttentivePooler and AttentiveClassifier are also available as standalone modules:
from pyjepa import AttentivePooler, AttentiveClassifier
pooler = AttentivePooler(embed_dim=384, num_heads=6, num_query_tokens=1)
cls = AttentiveClassifier(embed_dim=384, num_heads=6, num_classes=1000)
Planning
All planners share a unified PlanConfig and implement __call__(model, info, action_init) -> Tensor(H, A).
from pyjepa import PlanConfig, CEMPlanner, MPPIPlanner, RandomShootingPlanner
cfg = PlanConfig(
horizon=10, # planning horizon (number of steps)
action_dim=4, # action space dimension
num_samples=512, # candidate trajectories per iteration
num_elites=64, # elite fraction (CEM only)
num_iters=5, # optimization iterations
action_min=-1.0, # action bounds
action_max=1.0,
temperature=0.1, # softmax temperature (MPPI only)
)
cem = CEMPlanner(cfg)
mppi = MPPIPlanner(cfg)
rs = RandomShootingPlanner(cfg)
Cross-Entropy Method (CEM): Iteratively refits a diagonal Gaussian to the top-K lowest-cost candidates. Deterministic convergence, good for short horizons.
MPPI: Soft-min reweighting — every candidate contributes to the mean update proportional to exp(-cost / temperature). No hard cutoff; smoother gradient.
Random Shooting: Single-shot sampling. Cheap; useful as a warm-start for CEM or as a baseline.
WorldModelPolicy
WorldModelPolicy wraps any world model + planner into a stateful policy that can be stepped at each environment interaction:
from pyjepa.planning import WorldModelPolicy, PlanConfig, CEMPlanner
policy = WorldModelPolicy(
model=lewm_model,
solver=CEMPlanner(PlanConfig(horizon=10, action_dim=4, num_samples=512)),
config=PlanConfig(horizon=10, action_dim=4),
)
# At each environment step:
obs = env.reset()
action = policy.act({"pixels": obs_tensor, "goal": goal_tensor})
Inference
Embedding Images and Video
from pyjepa import Encoder, embed_image, embed_video
# Stateful wrapper with optional pooling and L2 normalization
enc = Encoder(ijepa_model.encoder, device="mps", pooling="mean", normalize=True)
feats = enc.embed_image(images) # (B, D)
feats = enc.embed_video(video) # (B, D)
# Functional helpers (no state)
feats = embed_image(ijepa_model.encoder, images)
feats = embed_video(ijepa_model.encoder, video_clips)
Latent Rollout
from pyjepa import rollout_latent
from pyjepa.inference import Rollout
# Functional: roll out a full action sequence at once
initial = {"pixels": obs_tensor} # (B, T, C, H, W)
predicted_embs = rollout_latent(lewm_model, initial, actions, history_size=3)
# returns (B, T_total, D)
# Stateful: step one action at a time
roll = Rollout(lewm_model, history_size=3)
roll.reset(initial_obs_tensor)
emb_1 = roll.step(action_1)
emb_2 = roll.step(action_2)
Surprise Scoring
The surprise score measures how well the world model predicts the next observation — a proxy for physical plausibility or anomaly detection:
from pyjepa import surprise_score
# Per-step prediction error along a trajectory
scores = surprise_score(lewm_model, info, history_size=3, reduction="per_step")
# (B, T)
# Mean error over whole trajectory
mean_err = surprise_score(lewm_model, info, reduction="mean")
# (B,)
Custom Models
Registering a Custom Encoder
from pyjepa import register_encoder, create_encoder
from pyjepa.models.vit import VisionTransformer
@register_encoder("my_vit_128")
def my_vit(**kwargs):
return VisionTransformer(
img_size=128, patch_size=8,
embed_dim=512, depth=10, num_heads=8,
**kwargs
)
# Now usable everywhere by name
enc = create_encoder("my_vit_128")
model = pyjepa.create_jepa("ijepa", encoder="my_vit_128", img_size=128, patch_size=8)
Registering a Custom Predictor
from pyjepa import register_predictor
import torch.nn as nn
@register_predictor("my_mlp_predictor")
class MLPPredictor(nn.Module):
def __init__(self, embed_dim, **kwargs):
super().__init__()
self.net = nn.Sequential(nn.Linear(embed_dim, embed_dim * 4),
nn.GELU(), nn.Linear(embed_dim * 4, embed_dim))
def forward(self, x, masks_x=None, masks=None):
return [self.net(xi) for xi in x]
Listing Available Models
import pyjepa
print(pyjepa.available_encoders()) # ['vit_base', 'vit_giant', 'vit_huge', ...]
print(pyjepa.available_predictors()) # ['ar_predictor', 'vit_predictor']
print(pyjepa.available_jepas()) # user-registered JEPAs
Configuration
Example I-JEPA config (configs/ijepa_base.yaml):
model:
type: ijepa
encoder: vit_base
predictor: vit_predictor
img_size: 224
patch_size: 16
pred_depth: 6
pred_embed_dim: 384
mask:
type: multiblock
num_enc_masks: 1
num_pred_masks: 4
enc_mask_scale: [0.85, 1.0]
pred_mask_scale: [0.15, 0.2]
aspect_ratio: [0.75, 1.5]
training:
output_dir: ./output/ijepa_base
device: auto
epochs: 300
batch_size: 512
lr: 0.001
weight_decay: 0.04
warmup_epochs: 40
momentum_start: 0.996
momentum_end: 1.0
amp_dtype: float16
grad_clip: 10.0
save_every_epochs: 10
Example LeWM config (configs/lewm_base.yaml):
model:
type: lewm
encoder: vit_small
img_size: 84
patch_size: 12
action_dim: 4
history_size: 3
emb_dim: 384
action_emb_dim: 64
pred_depth: 6
pred_heads: 6
pred_mlp_dim: 1024
training:
output_dir: ./output/lewm_base
device: auto
epochs: 100
batch_size: 128
lr: 0.0003
history_size: 3
num_preds: 5
sigreg_weight: 0.1
amp_dtype: float16
grad_clip: 1.0
CLI Reference
# Show device and version info
pyjepa info
# List all registered encoders, predictors, and jepas
pyjepa list
# Train with a YAML config
pyjepa train ijepa --config configs/ijepa_base.yaml
pyjepa train vjepa --config configs/vjepa_base.yaml
pyjepa train lewm --config configs/lewm_base.yaml
Performance Notes
Automatic Mixed Precision
pyjepa selects AMP dtype automatically based on hardware:
- CUDA SM80+ (A100, H100):
bfloat16(more stable range, no loss scaling needed) - CUDA SM70- (V100, T4):
float16with gradient scaler - MPS (Apple Silicon):
float32(MPS autocast is experimental; disabled by default) - CPU:
float32
Override with:
trainer = IJEPATrainer(model, TrainConfig(amp_dtype="bfloat16"), ijepa_cfg)
torch.compile
torch.compile is enabled on CUDA only. On Apple Silicon MPS, it is disabled by default due to graph-break issues with attention masking. Check at runtime:
from pyjepa.device import supports_compile
print(supports_compile()) # True on CUDA, False on MPS-only machines
DataLoader on Apple Silicon
from pyjepa.device import pin_memory_supported, get_device
device = get_device()
loader = DataLoader(
dataset, batch_size=256,
num_workers=4,
pin_memory=pin_memory_supported(device), # True only on CUDA
)
Gradient Scaler
get_grad_scaler() returns a real GradScaler on CUDA with fp16, and a no-op scaler on MPS/CPU/bfloat16, so training loop code is device-agnostic:
from pyjepa.device import get_grad_scaler
scaler = get_grad_scaler(device, enabled=(amp_dtype == "float16"))
with pyjepa.autocast(device, dtype=torch.float16):
loss = model(batch)
scaler.scale(loss).backward()
scaler.step(optimizer)
scaler.update()
Citation
If you use pyjepa in your research, please cite the relevant works:
I-JEPA
@inproceedings{assran2023ijepa,
title = {Self-Supervised Learning from Images with a Joint-Embedding Predictive Architecture},
author = {Mahmoud Assran and Quentin Duval and Ishan Misra and Piotr Bojanowski
and Pascal Vincent and Michael Rabbat and Yann LeCun and Nicolas Ballas},
booktitle = {IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR)},
year = {2023},
}
V-JEPA
@article{bardes2024vjepa,
title = {V-JEPA: Latent Video Prediction for Visual Representation Learning},
author = {Adrien Bardes and Quentin Garrido and Jean Ponce and Xinlei Chen
and Michael Rabbat and Yann LeCun and Mido Assran and Nicolas Ballas},
journal = {arXiv preprint arXiv:2404.08471},
year = {2024},
}
LeWM (LeWorldModel)
@article{maes2026lewm,
title = {LeWorldModel: Stable End-to-End Joint-Embedding Predictive Architecture from Pixels},
author = {Quentin Maes and Etienne Le Lidec and others},
journal = {arXiv preprint arXiv:2603.19312},
year = {2026},
url = {https://le-wm.github.io/},
}
License
Apache 2.0. See LICENSE for details.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyjepa-0.1.0.tar.gz.
File metadata
- Download URL: pyjepa-0.1.0.tar.gz
- Upload date:
- Size: 124.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3ea65a0cdffe8dc5d51c857e7fd1a99df3b5a1c7c9866684b4aa85638e3365eb
|
|
| MD5 |
cdbaadb28fcc2eddecbe156551400319
|
|
| BLAKE2b-256 |
c6d72360668f4b1284bc23ba5d24b24baa9937c4fbb14cb83094caf2cdadcc70
|
File details
Details for the file pyjepa-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pyjepa-0.1.0-py3-none-any.whl
- Upload date:
- Size: 117.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
461b080a5d3280c8c91b4473b99e72580b0a022aff3dfd7ae495ff629520ae1c
|
|
| MD5 |
8f9574c0d0c7a95f1dc8dab8a98c507b
|
|
| BLAKE2b-256 |
adeed4cafdd5b45baf3092e65c913bc366a19f19e70f59d8fcd0dc0a18b63fe9
|