Development¶
Resources for contributing to the WFRMLS Python client and following development best practices.
๐ ๏ธ Development Resources¶
-
Contributing
Guidelines for contributing code, reporting bugs, and requesting features
-
Testing
Running tests, writing test cases, and ensuring code quality
-
Release Process
How releases are managed and versioned
-
Style Guide
Code formatting, naming conventions, and best practices
๐ Quick Start for Contributors¶
Setting Up Development Environment¶
# Clone the repository
git clone https://github.com/theperrygroup/wfrmls.git
cd wfrmls
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install development dependencies
pip install -e ".[dev]"
# Install pre-commit hooks
pre-commit install
Running Tests¶
# Run all tests
pytest
# Run with coverage
pytest --cov=wfrmls --cov-report=html
# Run specific test file
pytest tests/test_client.py
# Run with verbose output
pytest -v
Code Quality Checks¶
# Format code
black wfrmls/ tests/
# Check linting
flake8 wfrmls/ tests/
# Type checking
mypy wfrmls/
# Run all quality checks
make quality
๐ Development Workflow¶
1. Issue Creation¶
Before starting work:
- Check existing issues and discussions
- Create detailed issue with use case
- Wait for feedback from maintainers
- Get issue assigned before starting work
2. Branch Strategy¶
# Create feature branch
git checkout -b feature/add-new-endpoint
# Create bugfix branch
git checkout -b bugfix/fix-authentication-error
# Create documentation branch
git checkout -b docs/update-api-reference
3. Development Process¶
- Write Tests First - Follow TDD when possible
- Implement Feature - Keep changes focused and small
- Update Documentation - Include docstrings and guides
- Run Quality Checks - Ensure all checks pass
- Manual Testing - Test with real API calls
4. Pull Request Process¶
- Commit Changes - Use conventional commit messages
- Push Branch - Push to your fork
- Create PR - Use provided template
- Address Feedback - Respond to review comments
- Merge - Maintainer will merge when ready
๐งช Testing Strategy¶
Test Categories¶
| Type | Location | Purpose | Coverage |
|---|---|---|---|
| Unit Tests | tests/unit/ | Test individual functions | >95% |
| Integration Tests | tests/integration/ | Test API interactions | Key workflows |
| End-to-End Tests | tests/e2e/ | Test complete scenarios | Critical paths |
Writing Tests¶
import pytest
from wfrmls import WFRMLSClient
from wfrmls.exceptions import ValidationError
class TestPropertyAPI:
"""Test property API functionality."""
def test_get_properties_success(self, mock_client):
"""Test successful property retrieval."""
# Arrange
expected_properties = [{"ListingId": "12345678"}]
mock_client.property.get_properties.return_value = expected_properties
# Act
result = mock_client.property.get_properties(top=1)
# Assert
assert result == expected_properties
mock_client.property.get_properties.assert_called_once_with(top=1)
def test_get_properties_validation_error(self, mock_client):
"""Test validation error handling."""
# Act & Assert
with pytest.raises(ValidationError):
mock_client.property.get_properties(top=-1)
Test Configuration¶
# conftest.py
import pytest
from unittest.mock import Mock
@pytest.fixture
def mock_client():
"""Create mock WFRMLS client for testing."""
client = Mock(spec=WFRMLSClient)
client.property = Mock()
client.member = Mock()
client.office = Mock()
return client
@pytest.fixture
def sample_property():
"""Sample property data for testing."""
return {
"ListingId": "12345678",
"ListPrice": 450000,
"StandardStatus": "Active",
"City": "Salt Lake City"
}
๐ Documentation Standards¶
Code Documentation¶
def get_properties(
self,
top: Optional[int] = None,
skip: Optional[int] = None,
filter_query: Optional[str] = None,
select: Optional[List[str]] = None,
orderby: Optional[str] = None,
count: bool = False
) -> List[Dict[str, Any]]:
"""Retrieve property listings from WFRMLS.
This method fetches property data with optional filtering, sorting,
and pagination. All parameters follow OData v4 conventions.
Args:
top: Maximum number of results to return. Defaults to API limit.
skip: Number of results to skip for pagination. Defaults to 0.
filter_query: OData filter expression for filtering results.
Example: "StandardStatus eq 'Active' and ListPrice gt 500000"
select: List of specific fields to include in response.
Example: ["ListingId", "ListPrice", "City"]
orderby: Field(s) to sort by with optional direction.
Example: "ListPrice desc" or "City asc, ListPrice desc"
count: Whether to include total count in response metadata.
Returns:
List of property dictionaries matching the query criteria.
Each dictionary contains the requested fields or all available
fields if select parameter is not specified.
Raises:
ValidationError: If query parameters are invalid.
AuthenticationError: If API credentials are invalid.
RateLimitError: If API rate limits are exceeded.
NotFoundError: If no results match the query (rare).
WFRMLSError: For other API-related errors.
Examples:
Basic usage:
>>> client = WFRMLSClient()
>>> properties = client.property.get_properties(top=10)
>>> len(properties)
10
With filtering:
>>> active_properties = client.property.get_properties(
... filter_query="StandardStatus eq 'Active'",
... select=["ListingId", "ListPrice"],
... orderby="ListPrice desc"
... )
With pagination:
>>> page_1 = client.property.get_properties(top=50, skip=0)
>>> page_2 = client.property.get_properties(top=50, skip=50)
Note:
Large result sets are automatically paginated by the API.
Consider using the skip parameter for manual pagination
when processing large datasets.
"""
README Updates¶
When adding new features, update:
- Installation instructions - If new dependencies
- Usage examples - Show new functionality
- API documentation - Link to detailed docs
- Contributing guide - If new development requirements
๐ง Build & Release¶
Local Development Build¶
# Install in development mode
pip install -e .
# Build source distribution
python -m build --sdist
# Build wheel
python -m build --wheel
# Check package
twine check dist/*
Version Management¶
We follow Semantic Versioning:
- MAJOR (1.0.0) - Breaking changes
- MINOR (1.1.0) - New features, backward compatible
- PATCH (1.1.1) - Bug fixes, backward compatible
Release Checklist¶
- All tests pass
- Documentation updated
- Version number bumped
- CHANGELOG.md updated
- Release notes prepared
- Tagged in git
- Published to PyPI
๐จ Code Style¶
Python Code Standards¶
# Good: Clear, descriptive names
def get_active_properties_by_city(city_name: str) -> List[Dict[str, Any]]:
"""Get active properties in a specific city."""
pass
# Bad: Unclear abbreviations
def get_act_props_by_c(c: str) -> List[Dict]:
pass
# Good: Type hints and docstrings
from typing import Optional, List, Dict, Any
def search_properties(
min_price: Optional[int] = None,
max_price: Optional[int] = None
) -> List[Dict[str, Any]]:
"""Search properties within a price range.
Args:
min_price: Minimum listing price filter.
max_price: Maximum listing price filter.
Returns:
List of property dictionaries matching criteria.
"""
pass
# Good: Error handling
try:
properties = client.property.get_properties()
except WFRMLSError as e:
logger.error(f"Failed to fetch properties: {e}")
raise
Import Organization¶
# Standard library imports
import os
import logging
from datetime import datetime
from typing import Optional, List, Dict, Any
# Third-party imports
import requests
from requests.adapters import HTTPAdapter
# Local imports
from wfrmls.exceptions import WFRMLSError, ValidationError
from wfrmls.utils import validate_parameters
๐ Additional Resources¶
Contributing¶
- Contributing Guide - Detailed contribution process
- Code of Conduct - Community standards
- Issue Templates - Bug reports and feature requests
Quality Assurance¶
- Testing Guide - Comprehensive testing documentation
- Style Guide - Code formatting and conventions
- Security Policy - Vulnerability reporting
Project Management¶
- Release Process - How releases are managed
- Roadmap - Future development plans
- Discussions - Community conversations
๐ค Getting Help¶
For Contributors¶
- GitHub Discussions - Ask development questions
- Discord Community - Real-time chat (if available)
- Office Hours - Weekly maintainer availability
For Maintainers¶
- Release Automation - CI/CD processes and scripts
- Review Guidelines - Code review best practices
- Triage Process - Issue classification and prioritization
Ready to contribute? Start with our Contributing Guide or explore the Testing Documentation.