============ Contributing ============ Thank you for your interest in contributing to ALY! This guide will help you get started. .. contents:: :local: :class: toc-hidden :depth: 2 Getting Started --------------- Development Setup ~~~~~~~~~~~~~~~~~ 1. Fork the repository on GitHub 2. Clone your fork: .. code-block:: bash git clone https://github.com/your-username/aly-tool.git cd aly-tool 3. Create a virtual environment: .. code-block:: bash python -m venv venv source venv/bin/activate # or venv\Scripts\activate on Windows 4. Install in development mode: .. code-block:: bash pip install -e ".[dev]" Project Structure ~~~~~~~~~~~~~~~~~ .. code-block:: text aly-tool/ +-- src/aly/ # Main source code | +-- app/ # CLI commands | +-- config/ # Configuration system | +-- templates/ # Project templates +-- tests/ # Test suite +-- docs/ # Documentation Development Workflow -------------------- Creating a Branch ~~~~~~~~~~~~~~~~~ Create a feature branch from ``main``: .. code-block:: bash git checkout main git pull origin main git checkout -b feature/my-new-feature Branch naming conventions: - ``feature/`` - New features - ``fix/`` - Bug fixes - ``docs/`` - Documentation updates - ``refactor/`` - Code refactoring Making Changes ~~~~~~~~~~~~~~ 1. Write your code following the style guidelines 2. Add tests for new functionality 3. Update documentation as needed 4. Run the test suite: .. code-block:: bash pytest tests/ 5. Run linting: .. code-block:: bash ruff check src/ ruff format src/ Submitting Changes ~~~~~~~~~~~~~~~~~~ 1. Commit your changes: .. code-block:: bash git add . git commit -m "feat: add support for new simulator" 2. Push to your fork: .. code-block:: bash git push origin feature/my-new-feature 3. Open a Pull Request on GitHub Code Style ---------- Python Style ~~~~~~~~~~~~ We follow PEP 8 with these additions: - Line length: 88 characters (Black default) - Use type hints for function signatures - Use docstrings for public functions and classes .. code-block:: python def load_manifest(path: Path) -> RTLManifest: """Load an RTL manifest from a YAML file. Args: path: Path to the manifest file. Returns: Loaded RTLManifest object. Raises: FileNotFoundError: If the manifest file doesn't exist. ValueError: If the manifest is invalid. """ if not path.exists(): raise FileNotFoundError(f"Manifest not found: {path}") with open(path) as f: data = yaml.safe_load(f) return RTLManifest.from_dict(data, path) Commit Messages ~~~~~~~~~~~~~~~ Follow `Conventional Commits `_: .. code-block:: text (): [optional body] [optional footer] Types: - ``feat``: New feature - ``fix``: Bug fix - ``docs``: Documentation - ``refactor``: Code refactoring - ``test``: Adding tests - ``chore``: Maintenance Examples: .. code-block:: text feat(simulation): add QuestaSim backend support fix(synthesis): handle spaces in file paths docs: update installation guide Testing ------- Running Tests ~~~~~~~~~~~~~ .. code-block:: bash # Run all tests pytest tests/ # Run with coverage pytest tests/ --cov=src/aly --cov-report=html # Run specific test file pytest tests/test_config.py # Run specific test pytest tests/test_config.py::test_load_project_config Writing Tests ~~~~~~~~~~~~~ Place tests in the ``tests/`` directory: .. code-block:: python # tests/test_rtl_manifest.py import pytest from pathlib import Path from aly.config.models import RTLManifest @pytest.fixture def sample_manifest(tmp_path): manifest_file = tmp_path / "manifest.yaml" manifest_file.write_text(""" name: test_design type: rtl modules: - name: counter top: counter files: - counter.sv """) return manifest_file def test_load_manifest(sample_manifest): manifest = RTLManifest.load(sample_manifest) assert manifest.name == "test_design" assert len(manifest.modules) == 1 def test_invalid_manifest(tmp_path): invalid = tmp_path / "invalid.yaml" invalid.write_text("not: valid: yaml:") with pytest.raises(ValueError): RTLManifest.load(invalid) Documentation ------------- Building Documentation ~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: bash cd docs make html # View locally open build/html/index.html Writing Documentation ~~~~~~~~~~~~~~~~~~~~~ - Use reStructuredText format - Include code examples - Add diagrams where helpful (PlantUML, Graphviz) Example: .. code-block:: rst New Feature ----------- Description of the feature. .. code-block:: bash aly new-command --option value .. uml:: @startuml Alice -> Bob: Hello @enduml Adding New Features ------------------- Adding a Simulator Backend ~~~~~~~~~~~~~~~~~~~~~~~~~~ 1. Create a new backend file: .. code-block:: python # src/aly/sim_newsim.py from pathlib import Path from typing import List, Dict class NewSimBackend: def __init__(self, config): self.config = config def compile(self, sources: List[Path], options: Dict) -> bool: # Implementation pass def elaborate(self, top: str, options: Dict) -> bool: # Implementation pass def simulate(self, options: Dict): # Implementation pass 2. Register the backend in ``backends.py`` 3. Add configuration options in ``config/models/tools.py`` 4. Update documentation 5. Add tests Adding a CLI Command ~~~~~~~~~~~~~~~~~~~~ 1. Create command module in ``app/``: .. code-block:: python # src/aly/app/mycommand.py import typer from aly.log import get_logger logger = get_logger(__name__) app = typer.Typer() @app.command() def mycommand( option: str = typer.Option(..., help="Description") ): """Command description.""" logger.info(f"Running with {option}") # Implementation 2. Register in ``app/main.py``: .. code-block:: python from aly.app import mycommand app.add_typer(mycommand.app, name="mycommand") 3. Add tests and documentation Release Process --------------- Version Bumping ~~~~~~~~~~~~~~~ 1. Update version in ``pyproject.toml`` 2. Update ``CHANGELOG.md`` 3. Create a release commit: .. code-block:: bash git commit -am "chore: release v1.2.0" git tag v1.2.0 4. Push with tags: .. code-block:: bash git push origin main --tags Getting Help ------------ - Open an issue on GitHub for bugs or features - Join discussions for questions - Review existing issues before creating new ones License ------- By contributing, you agree that your contributions will be licensed under the Apache 2.0 License.