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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ dmypy.json
# Cython debug symbols
cython_debug/

# Claude settings
.claude/*

# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
Expand Down
Empty file added Image/__init__.py
Empty file.
5,190 changes: 5,190 additions & 0 deletions poetry.lock

Large diffs are not rendered by default.

172 changes: 172 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
[tool.poetry]
name = "unireplknet"
version = "0.1.0"
description = "Universal Representation Learning with Large Kernel Networks"
authors = ["UniRepLKNet Team"]
readme = "README.md"
packages = [
{ include = "Audio" },
{ include = "Image" },
{ include = "Point" },
{ include = "Time-Series", from = "." },
{ include = "Video" },
{ include = "detection" },
{ include = "segmentation" }
]

[tool.poetry.dependencies]
python = "^3.8.1"
# Core ML/DL Dependencies
torch = ">=1.2"
torchvision = "*"
torchaudio = "*"
deepspeed = "*"
timm = "0.4.12"
triton = {version = "1.0.0", optional = true}
tensorboard = "2.9.0"
tensorboardX = "1.8"

# Data Processing
pandas = "*"
numpy = "*"
scipy = "*"
einops = "*"
scikit-learn = "*"

# Computer Vision
opencv-python = "*"
pillow = "*"
av = "*"
decord = {version = "*", optional = true}

# Visualization
matplotlib = "*"

[tool.poetry.group.dev.dependencies]
pytest = "^7.4.0"
pytest-cov = "^4.1.0"
pytest-mock = "^3.11.1"
black = "^23.7.0"
isort = "^5.12.0"
flake8 = "^6.1.0"
mypy = "^1.4.1"
pre-commit = "^3.3.3"

[tool.poetry.scripts]
test = "pytest:main"
tests = "pytest:main"

[tool.pytest.ini_options]
minversion = "7.0"
testpaths = ["tests"]
python_files = ["test_*.py", "*_test.py"]
python_classes = ["Test*", "*Tests"]
python_functions = ["test_*"]
addopts = [
"-ra",
"--strict-markers",
"--cov=.",
"--cov-branch",
"--cov-report=term-missing",
"--cov-report=html:htmlcov",
"--cov-report=xml:coverage.xml",
"--cov-fail-under=0",
"-vv",
"--tb=short",
"--maxfail=1"
]
markers = [
"unit: Unit tests (fast, isolated tests)",
"integration: Integration tests (may require external resources)",
"slow: Slow tests (use sparingly)"
]
filterwarnings = [
"ignore::DeprecationWarning",
"ignore::PendingDeprecationWarning"
]

[tool.coverage.run]
source = ["."]
omit = [
"*/tests/*",
"*/test_*.py",
"*/__pycache__/*",
"*/site-packages/*",
"setup.py",
"*/migrations/*",
"*/__init__.py",
"*/conftest.py",
"*/venv/*",
"*/env/*",
".venv/*"
]

[tool.coverage.report]
precision = 2
show_missing = true
skip_covered = false
exclude_lines = [
"pragma: no cover",
"def __repr__",
"if self.debug:",
"if settings.DEBUG",
"raise AssertionError",
"raise NotImplementedError",
"if 0:",
"if __name__ == .__main__.:",
"if TYPE_CHECKING:",
"class .*\\bProtocol\\):",
"@(abc\\.)?abstractmethod"
]

[tool.coverage.html]
directory = "htmlcov"

[tool.coverage.xml]
output = "coverage.xml"

[tool.isort]
profile = "black"
multi_line_output = 3
include_trailing_comma = true
force_grid_wrap = 0
use_parentheses = true
ensure_newline_before_comments = true
line_length = 88
skip_gitignore = true

[tool.black]
line-length = 88
target-version = ['py38', 'py39', 'py310', 'py311']
include = '\.pyi?$'
extend-exclude = '''
/(
# directories
\.eggs
| \.git
| \.hg
| \.mypy_cache
| \.tox
| \.venv
| build
| dist
)/
'''

[tool.mypy]
python_version = "3.8"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = false
ignore_missing_imports = true
exclude = [
"tests/",
"venv/",
".venv/",
"build/",
"dist/"
]

[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
Empty file added tests/__init__.py
Empty file.
191 changes: 191 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
"""Shared pytest fixtures and configuration for UniRepLKNet tests."""

import os
import tempfile
from pathlib import Path
from typing import Generator, Dict, Any
from unittest.mock import MagicMock

import pytest
import torch
import numpy as np


@pytest.fixture
def temp_dir() -> Generator[Path, None, None]:
"""Create a temporary directory for test files."""
with tempfile.TemporaryDirectory() as tmpdir:
yield Path(tmpdir)


@pytest.fixture
def mock_config() -> Dict[str, Any]:
"""Provide a mock configuration dictionary for testing."""
return {
"model": {
"name": "unireplknet",
"num_classes": 10,
"input_size": 224,
"patch_size": 16,
"embed_dim": 768,
"depth": 12,
"num_heads": 12,
},
"training": {
"batch_size": 32,
"learning_rate": 0.001,
"epochs": 100,
"warmup_epochs": 5,
"weight_decay": 0.05,
},
"data": {
"dataset": "test_dataset",
"data_path": "/tmp/test_data",
"num_workers": 4,
"pin_memory": True,
},
"augmentation": {
"mixup": 0.8,
"cutmix": 1.0,
"cutmix_minmax": None,
"mixup_prob": 1.0,
"mixup_switch_prob": 0.5,
"mixup_mode": "batch",
},
}


@pytest.fixture
def sample_image_tensor() -> torch.Tensor:
"""Create a sample image tensor for testing."""
return torch.randn(1, 3, 224, 224)


@pytest.fixture
def sample_batch() -> Dict[str, torch.Tensor]:
"""Create a sample batch of data for testing."""
batch_size = 4
return {
"images": torch.randn(batch_size, 3, 224, 224),
"labels": torch.randint(0, 10, (batch_size,)),
"masks": torch.ones(batch_size, 224, 224),
}


@pytest.fixture
def sample_audio_tensor() -> torch.Tensor:
"""Create a sample audio tensor for testing."""
# 1 second of audio at 16kHz sample rate
return torch.randn(1, 16000)


@pytest.fixture
def sample_video_tensor() -> torch.Tensor:
"""Create a sample video tensor for testing."""
# batch_size=1, num_frames=8, channels=3, height=224, width=224
return torch.randn(1, 8, 3, 224, 224)


@pytest.fixture
def sample_point_cloud() -> torch.Tensor:
"""Create a sample point cloud tensor for testing."""
# num_points=1024, dimensions=3 (x, y, z)
return torch.randn(1024, 3)


@pytest.fixture
def sample_time_series() -> np.ndarray:
"""Create a sample time series data for testing."""
# 100 time steps with 5 features
return np.random.randn(100, 5)


@pytest.fixture
def mock_model() -> MagicMock:
"""Create a mock model for testing."""
model = MagicMock()
model.forward.return_value = torch.randn(1, 10) # Mock output
model.parameters.return_value = [torch.randn(10, 10)]
model.state_dict.return_value = {"layer1.weight": torch.randn(10, 10)}
return model


@pytest.fixture
def mock_dataset() -> MagicMock:
"""Create a mock dataset for testing."""
dataset = MagicMock()
dataset.__len__.return_value = 100
dataset.__getitem__.return_value = (torch.randn(3, 224, 224), 0)
return dataset


@pytest.fixture
def mock_dataloader(mock_dataset) -> MagicMock:
"""Create a mock dataloader for testing."""
dataloader = MagicMock()
dataloader.__iter__.return_value = iter([
(torch.randn(32, 3, 224, 224), torch.randint(0, 10, (32,)))
for _ in range(3)
])
dataloader.dataset = mock_dataset
return dataloader


@pytest.fixture
def device() -> torch.device:
"""Get the appropriate device for testing."""
return torch.device("cuda" if torch.cuda.is_available() else "cpu")


@pytest.fixture
def random_seed() -> int:
"""Set and return a fixed random seed for reproducible tests."""
seed = 42
torch.manual_seed(seed)
np.random.seed(seed)
return seed


@pytest.fixture(autouse=True)
def cleanup_gpu_memory():
"""Automatically clean up GPU memory after each test."""
yield
if torch.cuda.is_available():
torch.cuda.empty_cache()


@pytest.fixture
def checkpoint_path(temp_dir: Path) -> Path:
"""Create a path for saving checkpoints during tests."""
checkpoint_dir = temp_dir / "checkpoints"
checkpoint_dir.mkdir(exist_ok=True)
return checkpoint_dir / "test_checkpoint.pth"


@pytest.fixture
def sample_checkpoint(checkpoint_path: Path, mock_model) -> Path:
"""Create a sample checkpoint file for testing."""
checkpoint = {
"epoch": 10,
"model_state_dict": mock_model.state_dict(),
"optimizer_state_dict": {"param_groups": [{"lr": 0.001}]},
"loss": 0.5,
"accuracy": 0.85,
}
torch.save(checkpoint, checkpoint_path)
return checkpoint_path


@pytest.fixture
def env_setup(monkeypatch):
"""Set up environment variables for testing."""
monkeypatch.setenv("CUDA_VISIBLE_DEVICES", "0")
monkeypatch.setenv("OMP_NUM_THREADS", "1")
monkeypatch.setenv("TORCH_HOME", "/tmp/torch_cache")


@pytest.fixture
def capture_logs(caplog):
"""Fixture to capture and return logs during tests."""
with caplog.at_level("DEBUG"):
yield caplog
Empty file added tests/integration/__init__.py
Empty file.
Loading