Skip to content

Contributing to FuzzyInfer

Thank you for your interest in contributing to FuzzyInfer! This document provides guidelines and instructions for contributing.

Getting Started

Prerequisites

  • Python 3.8 or higher
  • Git
  • Basic understanding of fuzzy logic (helpful but not required)

Development Setup

  1. Fork and clone the repository:
git clone https://github.com/YOUR_USERNAME/fuzzy-infer.git
cd fuzzy-infer
  1. Create a virtual environment:
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate
  1. Install development dependencies:
pip install -e ".[dev]"
  1. Install pre-commit hooks:
pre-commit install

Development Workflow

Creating a Branch

Create a feature branch for your work:

git checkout -b feature/your-feature-name
# or
git checkout -b fix/your-bugfix-name

Branch naming conventions: - feature/ - New features - fix/ - Bug fixes - docs/ - Documentation changes - refactor/ - Code refactoring - test/ - Test additions or updates

Making Changes

  1. Write your code following our style guidelines
  2. Add tests for new functionality
  3. Update documentation as needed
  4. Run the test suite
# Run all tests
pytest

# Run with coverage
pytest --cov=fuzzy_infer --cov-report=html

# Run specific test file
pytest tests/test_core.py

# Run specific test
pytest tests/test_core.py::test_fuzzy_or

Code Style

We use several tools to maintain code quality:

Black (Code Formatting)

black fuzzy_infer/ tests/

Ruff (Linting)

ruff check fuzzy_infer/ tests/

MyPy (Type Checking)

mypy fuzzy_infer/

Run All Quality Checks

make lint  # Runs black, ruff, and mypy

Writing Tests

  • Place tests in the tests/ directory
  • Name test files test_*.py
  • Name test functions test_*
  • Use descriptive test names
  • Aim for >90% code coverage

Example test:

def test_fact_creation():
    """Test that facts are created correctly."""
    fact = Fact("is-bird", ["tweety"], 0.9)

    assert fact.predicate == "is-bird"
    assert fact.args == ["tweety"]
    assert fact.degree == 0.9

Documentation

Docstrings

Use Google-style docstrings:

def add_fact(self, fact: Fact) -> 'FuzzyInfer':
    """
    Add a fact to the knowledge base.

    Args:
        fact: The fact to add

    Returns:
        Self for method chaining

    Raises:
        FactValidationError: If fact is invalid

    Examples:
        >>> inf = FuzzyInfer()
        >>> inf.add_fact(Fact("is-bird", ["tweety"], 0.9))
    """

Documentation Files

  • Place documentation in docs/
  • Use Markdown format
  • Include code examples
  • Build locally to test:
mkdocs serve

Then visit http://localhost:8000

Pull Request Process

Before Submitting

  1. Ensure all tests pass:

    pytest
    

  2. Ensure code is formatted:

    black fuzzy_infer/ tests/
    

  3. Ensure linting passes:

    ruff check fuzzy_infer/ tests/
    

  4. Ensure type checking passes:

    mypy fuzzy_infer/
    

  5. Update documentation if needed

  6. Add entry to CHANGELOG.md under "Unreleased"

Submitting a Pull Request

  1. Push your branch to your fork:
git push origin feature/your-feature-name
  1. Open a Pull Request on GitHub

  2. Fill out the PR template with:

  3. Clear description of changes
  4. Motivation and context
  5. How to test the changes
  6. Screenshots (if applicable)
  7. Related issues

  8. Wait for CI checks to pass

  9. Request review from maintainers

PR Review Process

  • Maintainers will review your PR
  • Address any requested changes
  • Once approved, maintainers will merge

Types of Contributions

Bug Reports

File bug reports as GitHub issues:

  • Use a clear, descriptive title
  • Describe expected vs actual behavior
  • Provide steps to reproduce
  • Include Python version, OS, and fuzzy-infer version
  • Add relevant code snippets or logs

Feature Requests

We welcome feature requests:

  • Check if feature already requested
  • Clearly describe the feature
  • Explain the use case
  • Provide examples if possible

Code Contributions

We accept various types of code contributions:

  • Bug fixes: Fix existing issues
  • New features: Add new functionality
  • Performance improvements: Optimize code
  • Refactoring: Improve code structure
  • Tests: Increase test coverage
  • Documentation: Improve or add docs

Documentation Contributions

Documentation is crucial:

  • Fix typos or unclear explanations
  • Add examples
  • Improve API documentation
  • Write tutorials or guides
  • Translate documentation

Code Review Guidelines

For Contributors

  • Be open to feedback
  • Respond to comments promptly
  • Ask questions if unclear
  • Make requested changes
  • Keep PRs focused and small

For Reviewers

  • Be respectful and constructive
  • Explain the "why" behind suggestions
  • Appreciate the contribution
  • Review promptly
  • Test the changes locally

Testing Guidelines

Test Categories

  1. Unit Tests: Test individual functions/classes
  2. Integration Tests: Test component interactions
  3. End-to-End Tests: Test complete workflows

Writing Good Tests

# Good: Descriptive name, clear assertions
def test_fuzzy_or_takes_maximum_degree():
    """Fuzzy OR should select the maximum degree."""
    inf = FuzzyInfer()
    inf.add_fact(Fact("is-bird", ["tweety"], 0.8))
    inf.add_fact(Fact("is-bird", ["tweety"], 0.9))

    result = inf.query("is-bird", ["tweety"])
    assert result[0].degree == 0.9

# Bad: Unclear name, multiple assertions
def test_facts():
    inf = FuzzyInfer()
    inf.add_fact(Fact("a", ["b"], 0.5))
    assert len(inf.facts) == 1
    assert inf.facts[("a", ("b",))].degree == 0.5
    # ... many more assertions

Test Coverage

  • Aim for >90% coverage
  • Focus on critical paths
  • Test edge cases
  • Test error conditions

Check coverage:

pytest --cov=fuzzy_infer --cov-report=html
open htmlcov/index.html  # View coverage report

Project Structure

fuzzy-infer/
├── fuzzy_infer/          # Main package
│   ├── __init__.py       # Package exports
│   ├── core.py           # Inference engine
│   ├── models.py         # Data models
│   ├── fluent.py         # Fluent API
│   ├── jsonl.py          # JSONL serialization
│   ├── cli.py            # CLI interface
│   └── exceptions.py     # Custom exceptions
├── tests/                # Test suite
│   ├── test_core.py
│   ├── test_models.py
│   ├── test_fluent.py
│   └── ...
├── docs/                 # Documentation
│   ├── guide/            # User guides
│   ├── api/              # API reference
│   └── ...
├── examples/             # Example code
├── .github/              # GitHub workflows
│   └── workflows/
│       └── docs.yml      # Documentation deployment
├── pyproject.toml        # Project configuration
├── mkdocs.yml            # Documentation config
├── CHANGELOG.md          # Version history
└── README.md             # Project overview

Release Process

(For maintainers)

  1. Update version in pyproject.toml
  2. Update CHANGELOG.md
  3. Create git tag:
    git tag -a v2.0.0 -m "Release v2.0.0"
    git push origin v2.0.0
    
  4. Build and publish to PyPI:
    python -m build
    twine upload dist/*
    

Community

Code of Conduct

  • Be respectful and inclusive
  • Welcome newcomers
  • Focus on constructive feedback
  • Report unacceptable behavior

Getting Help

  • GitHub Issues: Bug reports and feature requests
  • GitHub Discussions: Questions and discussions
  • Documentation: https://fuzzy-infer.readthedocs.io

Recognition

Contributors are recognized in: - CHANGELOG.md - GitHub contributors page - Release notes

License

By contributing, you agree that your contributions will be licensed under the MIT License.

Questions?

If you have questions about contributing, feel free to: - Open a GitHub Discussion - Comment on relevant issues - Reach out to maintainers

Thank you for contributing to FuzzyInfer! 🎉