Contributing

We love contributions! This guide will help you get started with contributing to gntplib.

Getting Started

Fork and Clone

  1. Fork the repository on GitHub

  2. Clone your fork locally:

    git clone https://github.com/cumulus13/gntplib.git
    cd gntplib
    
  3. Add upstream remote:

    git remote add upstream https://github.com/original/gntplib.git
    

Development Setup

Create a virtual environment and install development dependencies:

# Create virtual environment
python3 -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install package in editable mode with dev dependencies
pip install -e ".[dev,async,crypto]"

# Install pre-commit hooks (optional but recommended)
pre-commit install

Development Dependencies

The [dev] extra includes:

  • pytest - Testing framework

  • pytest-cov - Coverage reporting

  • pytest-asyncio - Async test support

  • black - Code formatting

  • flake8 - Linting

  • mypy - Type checking

  • sphinx - Documentation generation

Making Changes

Create a Branch

git checkout -b feature/your-feature-name
# or
git checkout -b fix/issue-description

Code Style

We follow PEP 8 with some modifications:

  • Line length: 88 characters (Black default)

  • Use type hints for all public APIs

  • Docstrings for all public modules, classes, and functions

  • Google-style docstrings

Format your code with Black:

black gntplib tests

Check with flake8:

flake8 gntplib tests

Type check with mypy:

mypy gntplib

Writing Tests

Run Tests

Run all tests:

pytest

Run with coverage:

pytest --cov=gntplib --cov-report=html

Run specific test file:

pytest tests/test_publisher.py

Test Structure

import pytest
from gntplib import Publisher, Event

class TestPublisher:
    """Test Publisher class."""

    def test_create_publisher(self):
        """Test publisher creation."""
        events = [Event('test')]
        publisher = Publisher('TestApp', events)
        assert publisher.name == 'TestApp'

    def test_register(self, mock_server):
        """Test registration with mock server."""
        # Your test code here
        pass

Async Tests

import pytest
from gntplib.async_gntp import AsyncPublisher

@pytest.mark.asyncio
async def test_async_publisher():
    """Test async publisher."""
    events = [Event('test')]
    publisher = AsyncPublisher('TestApp', events)
    # Test code here

Documentation

Building Docs

Build documentation locally:

cd docs
make html

View documentation:

open _build/html/index.html  # macOS
xdg-open _build/html/index.html  # Linux
start _build/html/index.html  # Windows

Live reload for development:

make livehtml

Writing Documentation

  • Use reStructuredText for documentation files

  • Add examples to docstrings

  • Update API reference if adding new public APIs

  • Add entries to changelog

Docstring Example

def my_function(param1: str, param2: int = 0) -> bool:
    """Short one-line description.

    More detailed description if needed. Can span multiple
    lines and paragraphs.

    Args:
        param1: Description of param1
        param2: Description of param2 (default: 0)

    Returns:
        Description of return value

    Raises:
        ValueError: When param1 is empty
        GNTPError: When connection fails

    Example:
        >>> result = my_function('test', 5)
        >>> print(result)
        True
    """
    if not param1:
        raise ValueError("param1 cannot be empty")
    return True

Submitting Changes

Commit Messages

Follow conventional commits format:

type(scope): short description

Longer description if needed.

Fixes #123

Types:

  • feat: New feature

  • fix: Bug fix

  • docs: Documentation changes

  • style: Code style changes (formatting, etc.)

  • refactor: Code refactoring

  • test: Test additions or modifications

  • chore: Build process or auxiliary tool changes

Examples:

feat(publisher): add timeout parameter to publish method

fix(async): handle connection errors in async mode

docs(tutorial): add example for encrypted notifications

Push and Create PR

  1. Push your changes:

    git push origin feature/your-feature-name
    
  2. Create Pull Request on GitHub

  3. Ensure CI passes

  4. Wait for review

Pull Request Checklist

  • [ ] Tests pass locally

  • [ ] New tests added for new features

  • [ ] Documentation updated

  • [ ] Changelog updated

  • [ ] Code follows style guidelines

  • [ ] Type hints added

  • [ ] Docstrings added/updated

Code Review

What We Look For

  • Correctness: Does the code work as intended?

  • Tests: Are there adequate tests?

  • Documentation: Is it well documented?

  • Style: Does it follow project conventions?

  • Performance: Are there obvious performance issues?

  • Security: Are there security concerns?

Responding to Feedback

  • Be open to feedback

  • Ask questions if something is unclear

  • Make requested changes promptly

  • Discuss alternatives constructively

Release Process

For Maintainers

  1. Update version in gntplib/__init__.py

  2. Update CHANGELOG.md

  3. Create release commit:

    git commit -am "Release vX.Y.Z"
    git tag vX.Y.Z
    git push origin main --tags
    
  4. Build and upload to PyPI:

    python -m build
    python -m twine upload dist/*
    

Getting Help

  • Questions: Open a discussion on GitHub

  • Bugs: Open an issue with reproduction steps

  • Features: Open an issue to discuss before implementing

  • Chat: Join our community chat (if available)

Thank you for contributing to gntplib! 🎉