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
62 changes: 62 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,64 @@
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg

# Testing
.pytest_cache/
.coverage
htmlcov/
coverage.xml
*.cover
.hypothesis/
.tox/

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

# IDE
.vscode/
.idea/
*.swp
*.swo
*~

# Claude
.claude/*

# OS
**/.DS_Store
.DS_Store
Thumbs.db

# Project specific
*.pdf
*.html
combined_*.md
test_*.md
test_*.pdf
test_*.html

# Package manager
# Note: Do not ignore poetry.lock or uv.lock
.poetry/
757 changes: 757 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 = "machine-learning-yearning"
version = "0.1.0"
description = "Vietnamese translation of Machine Learning Yearning by Andrew Ng"
authors = ["Machine Learning Yearning Translation Team"]
readme = "README.md"
package-mode = false

[tool.poetry.dependencies]
python = "^3.8"
pdfkit = "^1.0.0"
grip = "4.5.2"

[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", "tests.py"]
python_classes = ["Test*", "*Tests"]
python_functions = ["test_*"]
addopts = [
"-ra",
"--strict-markers",
"--cov=.",
"--cov-branch",
"--cov-report=term-missing:skip-covered",
"--cov-report=html",
"--cov-report=xml",
"--cov-fail-under=80",
]
markers = [
"unit: marks tests as unit tests",
"integration: marks tests as integration tests",
"slow: marks tests as slow running",
]
filterwarnings = [
"error",
"ignore::UserWarning",
"ignore::DeprecationWarning",
]

[tool.coverage.run]
source = ["."]
omit = [
"*/tests/*",
"*/__pycache__/*",
"*/venv/*",
"*/virtualenv/*",
"*/.venv/*",
"*/site-packages/*",
"*/dist/*",
"*/build/*",
"*/.eggs/*",
"*/setup.py",
"*/conftest.py",
]

[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"def __repr__",
"if self.debug:",
"if __name__ == .__main__.:",
"raise AssertionError",
"raise NotImplementedError",
"if 0:",
"if False:",
"pass",
]
precision = 2
skip_covered = true
show_missing = true

[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.
180 changes: 180 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
"""Shared pytest fixtures and configuration for all tests."""

import os
import shutil
import tempfile
from pathlib import Path
from typing import Generator

import pytest


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

Yields:
Path: Path to the temporary directory
"""
temp_path = Path(tempfile.mkdtemp())
yield temp_path
shutil.rmtree(temp_path)


@pytest.fixture
def sample_markdown_content() -> str:
"""Provide sample markdown content for testing.

Returns:
str: Sample markdown text
"""
return """# Sample Chapter

This is a **sample** chapter with:
- Bullet points
- [Links](https://example.com)
- `Code snippets`

## Subsection

More content here.
"""


@pytest.fixture
def sample_chapter_file(temp_dir: Path) -> Path:
"""Create a sample chapter file for testing.

Args:
temp_dir: Temporary directory fixture

Returns:
Path: Path to the created chapter file
"""
chapter_path = temp_dir / "ch01.md"
chapter_path.write_text("""# Chapter 01 - Introduction

This is the first chapter of the book.

## Key Concepts

- Machine Learning
- Deep Learning
- Neural Networks
""")
return chapter_path


@pytest.fixture
def mock_chapters_dir(temp_dir: Path) -> Path:
"""Create a mock chapters directory with sample files.

Args:
temp_dir: Temporary directory fixture

Returns:
Path: Path to the chapters directory
"""
chapters_dir = temp_dir / "chapters"
chapters_dir.mkdir()

# Create sample chapter files
for i in range(1, 4):
chapter_file = chapters_dir / f"ch{i:02d}.md"
chapter_file.write_text(f"# Chapter {i:02d}\n\nContent for chapter {i}.")

return chapters_dir


@pytest.fixture
def mock_imgs_dir(temp_dir: Path) -> Path:
"""Create a mock images directory.

Args:
temp_dir: Temporary directory fixture

Returns:
Path: Path to the images directory
"""
imgs_dir = temp_dir / "imgs"
imgs_dir.mkdir()

# Create a placeholder image file
(imgs_dir / "sample.png").write_text("placeholder")

return imgs_dir


@pytest.fixture
def mock_project_structure(temp_dir: Path, mock_chapters_dir: Path, mock_imgs_dir: Path) -> Path:
"""Create a complete mock project structure.

Args:
temp_dir: Temporary directory fixture
mock_chapters_dir: Mock chapters directory
mock_imgs_dir: Mock images directory

Returns:
Path: Path to the project root
"""
# Create additional files
(temp_dir / "README.md").write_text("# Machine Learning Yearning")
(temp_dir / "acknowledgement.md").write_text("# Acknowledgements\n\nThanks to everyone.")
(temp_dir / "glossary_vi.md").write_text("# Glossary\n\nML terms in Vietnamese.")

return temp_dir


@pytest.fixture
def env_vars() -> dict:
"""Provide test environment variables.

Returns:
dict: Dictionary of environment variables
"""
return {
"TEST_MODE": "true",
"PYTHONPATH": str(Path.cwd()),
}


@pytest.fixture
def mock_pdf_config() -> dict:
"""Provide mock PDF configuration.

Returns:
dict: PDF configuration options
"""
return {
"page-size": "A4",
"margin-top": "1in",
"margin-right": "1in",
"margin-bottom": "1in",
"margin-left": "1in",
"encoding": "UTF-8",
"enable-local-file-access": None,
}


@pytest.fixture(autouse=True)
def cleanup_test_files():
"""Automatically clean up any test files created during tests."""
yield
# Clean up any files created in the current directory during tests
test_patterns = ["test_*.md", "test_*.pdf", "test_*.html", "combined_*.md"]
for pattern in test_patterns:
for file in Path.cwd().glob(pattern):
if file.exists():
file.unlink()


@pytest.fixture
def monkeypatch_env(monkeypatch, env_vars):
"""Automatically set environment variables for tests.

Args:
monkeypatch: pytest monkeypatch fixture
env_vars: Environment variables fixture
"""
for key, value in env_vars.items():
monkeypatch.setenv(key, value)
Empty file added tests/integration/__init__.py
Empty file.
Loading