Contributing to Nukat
Thank you for your interest in contributing to Nukat! This document provides guidelines and instructions for contributing.
Code of Conduct
Be respectful, inclusive, and considerate of others. We want to maintain a welcoming environment for all contributors.
Getting Started
1. Fork and Clone
# Fork the repository on GitHub, then:
git clone https://github.com/YOUR_USERNAME/nukat.git
cd nukat
2. Set Up Development Environment
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install in development mode
pip install -e ".[dev,docs]"
3. Create a Branch
Development Workflow
Running Tests
# Run all tests
pytest
# Run with coverage
pytest --cov=nukat --cov-report=html
# Run specific test file
pytest tests/test_client.py
# Run specific test
pytest tests/test_client.py::TestNukat::test_search_by_author
Code Quality
We use several tools to maintain code quality:
Black (Code Formatting)
Ruff (Linting)
MyPy (Type Checking)
Pre-commit Checks
Before committing, run:
Coding Standards
Python Style
- Follow PEP 8
- Use Black for formatting (line length: 100)
- Write docstrings for all public functions/classes (Google style)
- Use type hints where appropriate
Example
from typing import List, Dict, Optional
def search_records(
query: str,
limit: int = 20,
year_from: Optional[int] = None
) -> List[Dict[str, str]]:
"""Search for catalog records.
Args:
query: Search query string
limit: Maximum number of results to return
year_from: Minimum publication year filter
Returns:
List of record dictionaries containing bibliographic data
Raises:
NukatError: If the search request fails
Example:
>>> results = search_records("Python", limit=10)
>>> len(results)
10
"""
# Implementation here
pass
Documentation
- Write clear docstrings using Google style
- Add examples in docstrings where helpful
- Update documentation in
docs/when adding features - Keep README.md up to date
Testing
- Write tests for new features
- Maintain or improve code coverage
- Use meaningful test names
- Mock external dependencies (HTTP requests)
Example test:
def test_search_with_year_filter():
"""Test searching with year range filter."""
client = Nukat()
with patch.object(client.session, 'get') as mock_get:
mock_get.return_value.content = b"<html>...</html>"
results = client.search("Python", year_from=2020, year_to=2024)
# Verify parameters
call_args = mock_get.call_args
assert 'year' in call_args[1]['params']
Contributing Guidelines
Adding a Feature
- Check existing issues or create one to discuss the feature
- Write tests for the new functionality
- Implement the feature following coding standards
- Update documentation in docstrings and
docs/ - Run tests and quality checks
- Submit a pull request
Fixing a Bug
- Create an issue describing the bug (if not already exists)
- Write a test that reproduces the bug
- Fix the bug
- Verify the test passes
- Submit a pull request referencing the issue
Improving Documentation
Documentation improvements are always welcome!
- Fix typos or unclear explanations
- Add examples
- Improve API documentation
- Translate content (if applicable)
Pull Request Process
- Update CHANGELOG.md with your changes
- Ensure all tests pass:
pytest - Ensure code is formatted:
black nukat tests - Ensure linting passes:
ruff check nukat tests - Update documentation if needed
- Write a clear PR description:
- What problem does it solve?
- How does it solve it?
- Any breaking changes?
PR Title Format
Use conventional commit style:
feat: Add search by publication datefix: Handle missing author field gracefullydocs: Add examples for advanced filteringtest: Add tests for ISBN searchrefactor: Simplify result parsing logicchore: Update dependencies
Development Tips
Debugging
# Enable verbose logging
import logging
logging.basicConfig(level=logging.DEBUG)
# Inspect raw HTML response
client = Nukat()
response = client.session.get(url, params=params)
print(response.content.decode('utf-8'))
Testing Against Live API
# tests/test_live.py (not committed)
from nukat import Nukat
def test_live_search():
"""Test against live NUKAT API."""
client = Nukat()
results = client.search("Python", limit=5)
assert len(results) > 0
Local Documentation
# Install docs dependencies
pip install -e ".[docs]"
# Serve docs locally
mkdocs serve
# View at http://127.0.0.1:8000
Project Structure
nukat/
├── nukat/ # Source code
│ ├── __init__.py # Package initialization
│ ├── client.py # Main Nukat client
│ └── main.py # CLI entry point
├── tests/ # Test suite
│ ├── test_client.py # Client tests
│ └── test_main.py # CLI tests
├── docs/ # Documentation
│ ├── index.md
│ ├── getting-started/
│ ├── usage/
│ └── ...
├── .github/ # GitHub Actions
│ └── workflows/
│ └── ci.yml
├── pyproject.toml # Project metadata and dependencies
├── mkdocs.yml # Documentation config
├── README.md
├── LICENSE
└── CHANGELOG.md
Release Process
(For maintainers)
- Update version in
pyproject.toml - Update
CHANGELOG.md - Create a git tag:
git tag v0.2.0 - Push tag:
git push origin v0.2.0 - GitHub Actions will build and publish to PyPI
Questions?
- 💬 Open a discussion
- 🐛 Report a bug
- 📧 Contact maintainers
License
By contributing, you agree that your contributions will be licensed under the MIT License.
Thank you for contributing to Nukat! 🎉