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
139 changes: 139 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# Testing
.pytest_cache/
.coverage
.coverage.*
htmlcov/
coverage.xml
*.cover
*.py,cover
.hypothesis/
.tox/
.nox/
coverage/
.cache
nosetests.xml
test-results/
junit/
*.log

# Claude settings
.claude/*

# Virtual environments
env/
venv/
ENV/
env.bak/
venv.bak/
.venv/
virtualenv/

# IDEs and editors
.idea/
.vscode/
*.swp
*.swo
*~
.project
.pydevproject
.settings/
.DS_Store
*.sublime-project
*.sublime-workspace

# Jupyter Notebook
.ipynb_checkpoints
*.ipynb_checkpoints/

# pyenv
.python-version

# pipenv
Pipfile.lock

# Poetry
# Note: poetry.lock should be committed for applications
# but can be ignored for libraries
# poetry.lock

# PEP 582
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.env.*
*.env

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

# Local development
local/
scratch/
tmp/
temp/

# OS files
Thumbs.db
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
282 changes: 282 additions & 0 deletions poetry.lock

Large diffs are not rendered by default.

90 changes: 90 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
[tool.poetry]
name = "ml-projects"
version = "0.1.0"
description = "Machine Learning and Reinforcement Learning Projects"
authors = ["Your Name <you@example.com>"]
readme = "README.md"
packages = [{include = "*.py"}]

[tool.poetry.dependencies]
python = "^3.8"

[tool.poetry.group.dev.dependencies]
pytest = "^7.4.3"
pytest-cov = "^4.1.0"
pytest-mock = "^3.12.0"

[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*"]
python_functions = ["test_*"]
addopts = [
"-ra",
"--strict-markers",
"-vv",
"--tb=short",
"--maxfail=1",
]
markers = [
"unit: Unit tests",
"integration: Integration tests",
"slow: Slow tests",
]
# To run with coverage, use: poetry run pytest --cov=. --cov-report=html --cov-report=term-missing
filterwarnings = [
"error",
"ignore::UserWarning",
"ignore::DeprecationWarning",
]

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

[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"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
Empty file added tests/__init__.py
Empty file.
160 changes: 160 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import pytest
import tempfile
import shutil
import os
from pathlib import Path
from unittest.mock import Mock, MagicMock


@pytest.fixture
def temp_dir():
"""Create a temporary directory for test files."""
temp_path = tempfile.mkdtemp()
yield Path(temp_path)
shutil.rmtree(temp_path)


@pytest.fixture
def temp_file(temp_dir):
"""Create a temporary file in the temporary directory."""
def _temp_file(filename="test_file.txt", content=""):
file_path = temp_dir / filename
file_path.write_text(content)
return file_path
return _temp_file


@pytest.fixture
def mock_config():
"""Provide a mock configuration object."""
config = MagicMock()
config.debug = False
config.verbose = True
config.timeout = 30
config.max_retries = 3
return config


@pytest.fixture
def mock_logger():
"""Provide a mock logger for testing."""
logger = Mock()
logger.debug = Mock()
logger.info = Mock()
logger.warning = Mock()
logger.error = Mock()
logger.critical = Mock()
return logger


@pytest.fixture
def sample_data():
"""Provide sample data for testing."""
return {
"integers": [1, 2, 3, 4, 5],
"floats": [1.0, 2.5, 3.7, 4.2, 5.9],
"strings": ["alpha", "beta", "gamma", "delta", "epsilon"],
"mixed": [1, "two", 3.0, True, None],
"nested": {
"level1": {
"level2": {
"data": "deep_value"
}
}
}
}


@pytest.fixture
def env_vars():
"""Temporarily set environment variables."""
original_env = os.environ.copy()

def _set_env(**kwargs):
for key, value in kwargs.items():
os.environ[key] = str(value)
return os.environ

yield _set_env

# Restore original environment
os.environ.clear()
os.environ.update(original_env)


@pytest.fixture
def mock_file_system(monkeypatch):
"""Mock file system operations."""
mock_open_func = Mock()
mock_exists = Mock(return_value=True)
mock_isfile = Mock(return_value=True)
mock_isdir = Mock(return_value=False)

monkeypatch.setattr("builtins.open", mock_open_func)
monkeypatch.setattr("os.path.exists", mock_exists)
monkeypatch.setattr("os.path.isfile", mock_isfile)
monkeypatch.setattr("os.path.isdir", mock_isdir)

return {
"open": mock_open_func,
"exists": mock_exists,
"isfile": mock_isfile,
"isdir": mock_isdir
}


@pytest.fixture(autouse=True)
def reset_imports():
"""Reset imports between tests to ensure clean state."""
import sys
modules_before = set(sys.modules.keys())
yield
modules_after = set(sys.modules.keys())
for module in modules_after - modules_before:
if module.startswith("test_"):
del sys.modules[module]


@pytest.fixture
def capture_stdout(monkeypatch):
"""Capture stdout for testing print statements."""
import io
import sys

captured = io.StringIO()
monkeypatch.setattr(sys, "stdout", captured)

def get_output():
return captured.getvalue()

return get_output


@pytest.fixture(scope="session")
def test_resources_dir():
"""Provide path to test resources directory."""
resources_path = Path(__file__).parent / "resources"
resources_path.mkdir(exist_ok=True)
return resources_path


@pytest.fixture
def mock_requests(monkeypatch):
"""Mock requests library for HTTP testing."""
mock_response = Mock()
mock_response.status_code = 200
mock_response.json.return_value = {"status": "success"}
mock_response.text = "Mock response text"

mock_get = Mock(return_value=mock_response)
mock_post = Mock(return_value=mock_response)

mock_requests = Mock()
mock_requests.get = mock_get
mock_requests.post = mock_post
mock_requests.Response = Mock

monkeypatch.setattr("requests.get", mock_get)
monkeypatch.setattr("requests.post", mock_post)

return mock_requests
Empty file added tests/integration/__init__.py
Empty file.
Loading