- Introduced .copilot-instructions.md for GitHub Copilot usage guidelines. - Created DEVELOPMENT.md detailing environment setup, workflow, and common tasks. - Established STYLE_GUIDE.md as a quick reference for code style, formatting, and conventions.
8.5 KiB
8.5 KiB
GitHub Copilot Instructions for Elytra PIM Client
Project Overview
Elytra PIM Client is a fully Pythonic, Pydantic-driven client for the Elytra Product Information Management (PIM) API. It provides type-safe, validated interactions with the Elytra PIM API using modern Python practices.
Key Characteristics
- Python 3.9+ project with full type hints
- Pydantic v2 for data validation and serialization
- OpenAPI specification-driven API design
- Comprehensive error handling with custom exception classes
- Bearer token authentication
- Context manager support
- Fully tested with pytest
Code Style and Conventions
Language
- All code and documentation must be in English.
- No comments, docstrings, variable names, or documentation in other languages.
- Use clear, professional American English.
Formatting and Standards
- Code Style: Follow PEP 8 with line length of 100 characters
- Formatter: Black (configured in project)
- Import Order: Use isort with Black-compatible settings
- Linting: Flake8 for code quality checks
- Type Checking: mypy for static type checking
Type Hints
- Always include type hints for function parameters and return types
- Use
Optional[T]orT | Nonefor nullable types - Use
TypeVarfor generic functions - Use union types with
|operator (Python 3.10+) - For APIs returning multiple response types, use
TypeVarbound toBaseModel
Docstrings
- Use Google-style docstrings for all public modules, classes, and functions
- Format:
"""One-line summary. Longer description if needed. Args: param_name: Description of parameter Returns: Description of return value Raises: ExceptionType: When this exception is raised """
Imports
- Group imports: stdlib, third-party, local
- Use absolute imports
- Keep imports at module level unless lazy loading is necessary
Project Structure
elytra_client/
├── __init__.py # Package exports
├── client.py # Main ElytraClient class
├── config.py # Configuration handling
├── models.py # Pydantic models (auto-generated from OpenAPI)
└── exceptions.py # Custom exception classes
tests/
├── test_client.py # Client tests
└── ... # Other test files
examples/
└── ... # Example usage scripts
openapi.yaml # OpenAPI specification (source of truth)
pyproject.toml # Project metadata and dependencies
Core Patterns and Conventions
Exception Handling
- Use custom exception classes from
exceptions.py:ElytraAPIError: Base exception for all API errorsElytraAuthenticationError: Authentication failures (401, 403)ElytraNotFoundError: Resource not found (404)ElytraValidationError: Validation failures
- Always catch
requests.RequestExceptionin HTTP methods - Always catch
ValidationErrorwhen working with Pydantic models - Provide meaningful error messages with context
API Methods in ElytraClient
- Follow REST conventions:
get_*,create_*,update_*,delete_* - Return Pydantic models for single resources or dict with
itemslist for collections - Support pagination parameters:
page,limit,offset - Support language parameter:
lang(for multi-language support) - Use
_make_request()helper for all HTTP calls - Always validate responses with Pydantic models
Data Models (Pydantic)
- All models inherit from
pydantic.BaseModel - Use
Field()for validation and documentation - Use
field_validator()for custom validation - Model names follow pattern:
Single{Resource}{Operation}RequestBody,{Resource}Response, etc. - Use
exclude_none=Truewhen serializing to avoid sending null values
Configuration
- Use environment variables via
python-dotenv - Store sensitive data (API keys) in
.envfiles - Never commit
.envfiles - Provide
.env.exampleas template
Logging
- Use Python's
loggingmodule - Create loggers with
logger = logging.getLogger(__name__) - Log important operations and errors
- Avoid logging sensitive information (API keys, tokens)
Testing Requirements
Test Structure
- All tests in
tests/directory - Test file naming:
test_*.py - Test class naming:
Test* - Test function naming:
test_*
Coverage
- Aim for >80% code coverage
- Test both success and error paths
- Test Pydantic validation
- Use pytest fixtures for setup
Mocking
- Use
unittest.mockfor mocking requests - Mock external API calls
- Mock database calls if applicable
- Do not make real API calls in tests
Example Test Pattern
import pytest
from unittest.mock import Mock, patch
def test_get_products(client):
"""Test successful product retrieval."""
with patch.object(client.session, 'request') as mock_request:
# Setup mock
mock_request.return_value = Mock(status_code=200, json=lambda: {...})
# Execute
result = client.get_products()
# Assert
assert isinstance(result, dict)
Development Workflow
Before Committing
- Run tests:
pytest tests/ -v - Check coverage:
pytest --cov=elytra_client - Format code:
black elytra_client tests - Check imports:
isort elytra_client tests - Lint code:
flake8 elytra_client tests - Type check:
mypy elytra_client
Creating New Features
- Create a test first (TDD approach if possible)
- Implement the feature
- Ensure all tests pass
- Run formatters and linters
- Add documentation for public APIs
API Changes
- Update
openapi.yamlfirst (source of truth) - Regenerate/update Pydantic models in
models.py - Update client methods accordingly
- Update tests
Common Tasks and Expectations
When Adding API Methods
- Add method to
ElytraClientclass - Create corresponding Pydantic models for request/response
- Use
_make_request()helper - Add comprehensive docstrings
- Include type hints
- Error handling with custom exceptions
- Add tests with mocked responses
When Adding Pydantic Models
- Place in
models.py - Use descriptive names matching API structure
- Add field validators if needed
- Include docstrings for complex fields
- Use
ConfigDictfor model configuration if needed
When Fixing Bugs
- Add a failing test that reproduces the bug
- Fix the bug
- Verify the test now passes
- Check for similar issues in codebase
When Refactoring
- Ensure all tests pass before starting
- Make small, focused changes
- Run tests frequently
- Update documentation if interfaces change
- Commit atomic, logical changes
Performance Considerations
- Reuse
requests.Sessionfor connection pooling - Support pagination for large result sets
- Document timeout behavior
- Consider request/response sizes
- Log performance-critical operations
Documentation Requirements
README
- Keep up-to-date with current features
- Include installation and quick start
- Link to full API documentation
Code Comments
- Explain "why" not "what" - code should be self-explanatory for "what"
- Avoid obvious comments
- Use for complex algorithms or non-obvious decisions
- Keep comments synchronized with code
Docstrings
- Always provide docstrings for public APIs
- Include examples for complex usage patterns
- Multi-language support should be documented
What NOT to Do
- ❌ Don't mix English with other languages in code
- ❌ Don't commit
.envfiles or secrets - ❌ Don't make real API calls in tests
- ❌ Don't skip type hints
- ❌ Don't ignore linting or formatting errors
- ❌ Don't commit code that doesn't pass tests
- ❌ Don't use bare
except:clauses - ❌ Don't modify response models without updating tests
- ❌ Don't log sensitive information
- ❌ Don't hardcode API keys or credentials
Helpful Commands
# Install development dependencies
pip install -e ".[dev]"
# Run tests
pytest tests/ -v
# Run with coverage
pytest --cov=elytra_client --cov-report=html
# Format code
black elytra_client tests
isort elytra_client tests
# Lint
flake8 elytra_client tests
# Type check
mypy elytra_client
# Run all checks (recommended before commit)
black elytra_client tests && isort elytra_client tests && flake8 elytra_client tests && mypy elytra_client && pytest tests/ -v
Resources
- Pydantic v2 Docs: https://docs.pydantic.dev/latest/
- OpenAPI Specification: See
openapi.yamlin project root - Type Hints: https://docs.python.org/3/library/typing.html
- Pytest Documentation: https://docs.pytest.org/
- PEP 8 Style Guide: https://www.python.org/dev/peps/pep-0008/