Skip to content

terranagai/lol

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 

Repository files navigation

CONTRIBUTING.md 🧱 Architecture Overview Components

This repository implements a component-based architecture for a modular, evolvable Python application. It separates the codebase into isolated components, each encapsulating a single responsibility and exposing a minimal interface. The main components are:

core/ – Contains shared abstractions, base protocols, and interfaces that define contracts between components.

mail_client/ – Implements the main business logic for handling email-related functionality, relying only on the defined interfaces.

storage/ – Responsible for persistence logic (reading/writing from a datastore or filesystem) behind a consistent interface.

cli/ – Provides the command-line entry point that wires dependencies and initializes components using dependency injection.

tests/ – Contains unit, integration, and E2E tests validating correctness at multiple levels.

Each component can be developed, tested, and replaced independently. The uv workspace at the root unifies these components under a single project while maintaining separation of concerns.

Interface Design

The repository uses explicit interfaces to define what each component provides and requires. Interfaces are defined using abstract base classes (ABCs) from Python’s abc module and typing hints to declare expected method signatures.

This design follows John Ousterhout’s principle of clear abstractions:

“A good interface exposes what is necessary and hides what is unnecessary.”

Interfaces make dependencies explicit, allow for testing via mocks, and enable components to evolve without tight coupling.

Example interface:

from abc import ABC, abstractmethod

class MailClientInterface(ABC): @abstractmethod def send_email(self, recipient: str, subject: str, body: str) -> None: pass

(Extra Credit)

The repository uses ABCs rather than Protocol (from typing) because ABCs enforce method implementation at runtime, while Protocol is structural and used mainly for static type checking. ABCs provide runtime enforcement, ensuring contract compliance in dynamic environments.

Implementation Details

Concrete classes (e.g., MailClient, FileStorage) implement the interfaces and are injected at runtime. The pattern leverages:

abc.ABC and abstractmethod for explicit contracts.

Type hints for static validation.

init.py exports for controlled namespace exposure.

Dependency Injection

The repository uses constructor-based dependency injection, meaning dependencies are passed into classes during initialization rather than instantiated inside them.

Example:

class MailService: def init(self, client: MailClientInterface, storage: StorageInterface): self.client = client self.storage = storage

Injection occurs in the CLI bootstrap layer:

def main(): storage = LocalStorage() client = SMTPMailClient(storage) app = MailService(client, storage) app.run()

This pattern allows contributors to swap implementations (e.g., mock storage for tests or replace SMTP with another transport) without modifying the service logic.

📂 Repository Structure Project Organization osdp-team6/ │ ├── core/ # Shared abstractions, base interfaces ├── mail_client/ # Primary business logic component ├── storage/ # Persistence layer (data management) ├── cli/ # CLI entry points and app orchestration ├── tests/ # Organized by unit, integration, and E2E tests │ ├── pyproject.toml # Root project configuration └── README.md # Project overview

Configuration Files

Root pyproject.toml – Declares the workspace and shared dependencies across all components. It manages tools like ruff, pytest, and mypy globally.

Component-level pyproject.toml – Defines component-specific dependencies and metadata. This modular structure allows each component to be built and tested independently.

Package Structure

Each package includes an init.py to mark it as importable and control what is exported.

Keep init.py slim — it should only expose high-level interfaces or classes:

mail_client/init.py

from .service import MailClient all = ["MailClient"]

Avoid defining logic or performing imports with side effects inside init.py.

Import Guidelines

Use absolute imports (preferred) for clarity and IDE support:

from mail_client.interface import MailClientInterface

Use relative imports only for intra-component imports when refactoring within the same module.

Avoid circular imports by respecting component boundaries.

🧪 Testing Strategy Testing Philosophy

Following Prof. Nikolai’s “Building Quality In” lecture:

Quality is the absence of defects, not the presence of tests.

Every contributor is responsible for maintaining quality. Tests must be:

Fast (milliseconds to run)

Isolated (independent of other tests)

Repeatable (same input → same output)

Self-verifying (contain clear assertions)

Timely (written alongside new code)

Tests follow the Arrange–Act–Assert pattern:

def test_send_email_success(): # Arrange client = DummyMailClient() # Act result = client.send_email("[email protected]", "Subject", "Body") # Assert assert result is True

Test Organization

Tests are located under /tests and divided into:

tests/ ├── unit/ # Test individual functions/classes ├── integration/ # Test interactions between components └── e2e/ # Full system workflow tests

Each test directory contains its own init.py to mark it as a package, enabling relative imports and test discovery.

Test Abstraction Levels

Unit Tests → smallest scope, most reliable

Integration Tests → test component interactions

End-to-End Tests → validate complete execution flow

Code Coverage

Tool: pytest-cov (integrated with uv run)

Threshold: Minimum 90% coverage

Run tests and generate a coverage report:

uv run pytest --cov=. uv run pytest --cov=. --cov-report=html

Coverage reports are stored in the htmlcov/ directory.

🧰 Development Tools Workspace Management

This repo uses uv workspaces to coordinate multiple components in one environment.

Setup and usage:

uv sync --dev # install dependencies for all components uv run pytest # run tests uv run ruff check . # lint the codebase uv build # build packages for all components

The root pyproject.toml defines shared configuration and workspace metadata. Component-level pyproject.toml files define local dependencies and versioning.

Static Analysis and Code Formatting

Tools:

Ruff → static analysis + formatting

Mypy → type checking

Black (via Ruff) → code style enforcement

Run manually:

uv run ruff check . uv run ruff format . uv run mypy .

Why it matters: Static analysis catches style and logic issues early, ensuring consistency across contributors. Ruff is integrated with uv for consistent dependency management.

Documentation Generation

Documentation is generated using MkDocs with material theme integration.

To build docs:

uv run mkdocs serve # local dev server uv run mkdocs build # generate static site in site/

All docstrings and module comments are included automatically in the generated site.

Continuous Integration (CI)

The CI pipeline (configured in .github/workflows/ci.yml) includes these jobs:

Job Purpose Trigger lint Runs Ruff & Mypy to ensure code quality On every push & PR test Executes full test suite with coverage On PR & push to main/root build Validates workspace build via uv build On tagged commits docs Builds and deploys documentation On merge to main 🤝 Contributing Workflow

Clone the repository and create a branch for your work:

git clone https://github.com/kiamygomes/osdp-team6.git git checkout -b hw1

Install dependencies:

uv sync --dev

Run static checks before committing:

uv run ruff check . uv run mypy .

Run tests to ensure nothing is broken:

uv run pytest

Push changes and open a pull request targeting the root branch.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors