diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000000000000000000000000000000000000..e51656036d36266fcb2653c77777ee247783944d --- /dev/null +++ b/.flake8 @@ -0,0 +1,65 @@ +[flake8] +max-line-length = 100 +max-complexity = 10 +extend-ignore = + E203, # Whitespace before ':' + W503, # Line break before binary operator + D100, # Missing docstring in public module + D104, # Missing docstring in public package + D107, # Missing docstring in __init__ + B008 # Do not perform function calls in argument defaults +extend-select = + B950, # Line too long + B901, # Return statements in finally blocks + B902, # Invalid first argument names for methods + B903 # __slots__ efficiency + +exclude = + .git, + __pycache__, + build, + dist, + *.egg-info, + venv, + .env, + .venv, + .mypy_cache, + .pytest_cache + +per-file-ignores = + __init__.py: F401,F403 + tests/*: S101,D103,ANN + conftest.py: D103 + +# Plugin settings +docstring-convention = google +ignore-decorators = property|classmethod|staticmethod|validator|root_validator + +# Complexity settings +max-annotations-complexity = 4 +max-expression-complexity = 7 +max-cognitive-complexity = 12 + +# Additional settings +max-line-doc-length = 100 +max-doc-length = 100 +statistics = True +count = True +show-source = True + +# Error format +format = %(path)s:%(row)d:%(col)d: %(code)s %(text)s + +# Plugin configurations +[flake8:local-plugins] +extension = + B = flake8_bugbear:BugBearChecker + C = flake8_comprehensions:ComprehensionChecker + ANN = flake8_annotations:AnnotationChecker + CCR = flake8_cognitive_complexity:CognitiveComplexityChecker + ECE = flake8_expression_complexity:ExpressionComplexityChecker + DAR = flake8_darglint:DarglintChecker + +# Darglint configuration +strictness = short +docstring_style = google \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000000000000000000000000000000000000..3efcc29f7b430fe416776f2a066181bbdd3c1434 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,42 @@ +--- +name: Bug Report +about: Create a report to help us improve +title: '[BUG] ' +labels: bug +assignees: '' +--- + +## Bug Description + + +## Steps to Reproduce +1. +2. +3. + +## Expected Behavior + + +## Actual Behavior + + +## Screenshots/Logs + + +## Environment +- OS: [e.g., Ubuntu 22.04, Windows 11] +- Python Version: [e.g., 3.9.12] +- Package Version: [e.g., 0.1.0] +- Dependencies Versions: + ``` + Output of: pip freeze | grep -i ai-assistant + ``` + +## Additional Context + + +## Possible Solution + + +## Related Issues/PRs + \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000000000000000000000000000000000..a7c1f21d2c973a0c7ba200ec1847e9e6e868ea46 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,14 @@ +blank_issues_enabled: false +contact_links: + - name: Question or Discussion + url: https://github.com/yourusername/ai-assistant/discussions + about: Ask questions and discuss with other community members + - name: Documentation + url: https://yourusername.github.io/ai-assistant + about: Check out our documentation for answers + - name: Security Issue + url: https://github.com/yourusername/ai-assistant/security/policy + about: Please report security vulnerabilities here + +# Configure issue template chooser +# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#configuring-the-template-chooser \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/documentation.md b/.github/ISSUE_TEMPLATE/documentation.md new file mode 100644 index 0000000000000000000000000000000000000000..b6443f236c077e3be31527a0bb38299003cc60ac --- /dev/null +++ b/.github/ISSUE_TEMPLATE/documentation.md @@ -0,0 +1,36 @@ +--- +name: Documentation +about: Report an issue or suggest an improvement in documentation +title: '[DOCS] ' +labels: documentation +assignees: '' +--- + +## Documentation Location + + +## Current Documentation + + +## Issue/Suggested Improvement + + +## Proposed Changes + + +### Example + +```markdown +# Suggested documentation changes +``` + +## Additional Context + + +## Checklist +- [ ] I have checked that this is not already documented elsewhere +- [ ] I have checked the latest documentation in the main branch +- [ ] I have checked related issues/PRs + +## Related Issues/PRs + \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000000000000000000000000000000000000..f628e0183cace6c855bb26fcd04603858d1c8365 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,42 @@ +--- +name: Feature Request +about: Suggest an idea for this project +title: '[FEATURE] ' +labels: enhancement +assignees: '' +--- + +## Problem Statement + + +## Proposed Solution + + +## Alternative Solutions + + +## Example Use Case + +```python +# Example code showing how the feature might work +from ai_assistant import SomeFeature + +# Usage example +``` + +## Implementation Details + + +### Required Changes + +- [ ] Component 1 +- [ ] Component 2 + +### Potential Challenges + + +## Additional Context + + +## Related Issues/PRs + \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000000000000000000000000000000000000..7041d0a37249bfa8abc65e7f9bd41760a35009ec --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,62 @@ +## Description + + +## Type of Change + +- [ ] Bug fix (non-breaking change that fixes an issue) +- [ ] New feature (non-breaking change that adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] Documentation update +- [ ] Performance improvement +- [ ] Code cleanup or refactor +- [ ] Dependency update +- [ ] Other (please describe): + +## Motivation and Context + + +## Implementation Details + + +## How Has This Been Tested? + +- [ ] Unit tests added/updated +- [ ] Integration tests added/updated +- [ ] Manual testing performed + +### Test Configuration +- Python version: +- OS: +- Dependencies: + +## Breaking Changes + + +## Checklist + +- [ ] My code follows the project's style guidelines +- [ ] I have performed a self-review of my own code +- [ ] I have commented my code, particularly in hard-to-understand areas +- [ ] I have made corresponding changes to the documentation +- [ ] My changes generate no new warnings +- [ ] I have added tests that prove my fix is effective or that my feature works +- [ ] New and existing unit tests pass locally with my changes +- [ ] Any dependent changes have been merged and published +- [ ] I have updated the version number if necessary +- [ ] I have updated the changelog if necessary + +## Screenshots/Recordings + + +## Related Issues + +Closes # + +## Additional Notes + + +## Review Guidelines + + +## Deployment Notes + \ No newline at end of file diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000000000000000000000000000000000000..cd8aaea28829757111dfb995990028962201bfee --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,145 @@ +name: Deploy + +on: + push: + tags: + - 'v*' + workflow_dispatch: + inputs: + environment: + description: 'Environment to deploy to' + required: true + default: 'staging' + type: choice + options: + - staging + - production + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.12" + cache: 'pip' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install build twine + + - name: Build package + run: | + python -m build + + - name: Upload dist artifact + uses: actions/upload-artifact@v3 + with: + name: dist + path: dist/ + if-no-files-found: error + + test-package: + needs: build + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.9", "3.10", "3.11", "3.12"] + steps: + - uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + cache: 'pip' + + - name: Download dist + uses: actions/download-artifact@v3 + with: + name: dist + path: dist/ + + - name: Install package + run: | + python -m pip install --upgrade pip + pip install dist/*.whl + + - name: Test import + run: | + python -c "import tools; print(tools.__version__)" + + deploy-staging: + needs: [build, test-package] + runs-on: ubuntu-latest + if: github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'staging' + environment: + name: staging + url: ${{ steps.deploy.outputs.url }} + + steps: + - name: Download dist + uses: actions/download-artifact@v3 + with: + name: dist + path: dist/ + + - name: Deploy to Test PyPI + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.TEST_PYPI_TOKEN }} + run: | + python -m twine upload --repository testpypi dist/* + + - name: Set output URL + id: deploy + run: echo "url=https://test.pypi.org/project/ai-assistant/" >> $GITHUB_OUTPUT + + deploy-production: + needs: [build, test-package] + runs-on: ubuntu-latest + if: | + (github.event_name == 'workflow_dispatch' && github.event.inputs.environment == 'production') || + (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')) + environment: + name: production + url: ${{ steps.deploy.outputs.url }} + + steps: + - name: Download dist + uses: actions/download-artifact@v3 + with: + name: dist + path: dist/ + + - name: Deploy to PyPI + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} + run: | + python -m twine upload dist/* + + - name: Set output URL + id: deploy + run: echo "url=https://pypi.org/project/ai-assistant/" >> $GITHUB_OUTPUT + + - name: Create GitHub Release + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') + uses: softprops/action-gh-release@v1 + with: + files: dist/* + generate_release_notes: true + + cleanup: + needs: [deploy-staging, deploy-production] + if: always() + runs-on: ubuntu-latest + steps: + - name: Delete dist artifact + uses: geekyeggo/delete-artifact@v2 + with: + name: dist \ No newline at end of file diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000000000000000000000000000000000000..0563efa428a46885dd0cd431d095aa99e513049f --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,98 @@ +name: Lint + +on: + push: + branches: [ main, develop ] + pull_request: + branches: [ main, develop ] + +jobs: + lint: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.9"] + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + cache: 'pip' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements-dev.txt + + - name: Check formatting with black + run: black . --check --diff + + - name: Check import sorting with isort + run: isort . --check --diff + + - name: Run flake8 + run: flake8 . + + - name: Run pylint + run: pylint tools tests + + - name: Run mypy type checking + run: mypy . + + - name: Run bandit security checks + run: bandit -r . -c pyproject.toml + + - name: Run pyupgrade checks + run: | + find . -type f -name "*.py" -not -path "./venv/*" -not -path "./.env/*" -exec pyupgrade --py39-plus {} \; + + - name: Verify pre-commit hooks + run: | + pre-commit install + pre-commit run --all-files + + security: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.12" + cache: 'pip' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install bandit safety + + - name: Run bandit + run: | + bandit -r tools -ll -ii + + - name: Run safety check + run: | + safety check + + dependency-review: + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + steps: + - uses: actions/checkout@v4 + + - name: Dependency Review + uses: actions/dependency-review-action@v3 + with: + fail-on-severity: moderate + deny-licenses: | + GPL-1.0 + LGPL-2.0 + BSD-2-Clause + allow-licenses: | + MIT + Apache-2.0 + BSD-3-Clause \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000000000000000000000000000000000000..8b76fbde0ca45077333bce550d16c9e34c4800ee --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,102 @@ +name: Tests + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + workflow_dispatch: + +jobs: + test: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.9", "3.10", "3.11", "3.12"] + fail-fast: false + + steps: + - uses: actions/checkout@v4 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + cache: 'pip' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + pip install -r requirements-dev.txt + + - name: Run tests with coverage + run: | + python scripts/run_tests.py + env: + PYTHONPATH: ${{ github.workspace }} + + - name: Upload coverage reports + uses: codecov/codecov-action@v3 + with: + file: ./coverage.xml + flags: unittests + name: codecov-umbrella + fail_ci_if_error: true + if: success() + + - name: Upload coverage HTML report + uses: actions/upload-artifact@v3 + with: + name: coverage-report-${{ matrix.python-version }} + path: coverage_html/ + if-no-files-found: error + if: success() + + - name: Upload test results + uses: actions/upload-artifact@v3 + with: + name: pytest-results-${{ matrix.python-version }} + path: | + .coverage + coverage.xml + junit.xml + if-no-files-found: error + if: always() + + coverage-badge: + needs: test + runs-on: ubuntu-latest + if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request' + + steps: + - uses: actions/checkout@v4 + + - name: Download coverage data + uses: actions/download-artifact@v3 + with: + name: coverage-report-3.12 + path: coverage_html/ + + - name: Extract coverage percentage + run: | + COVERAGE=$(grep -o '[0-9]\+%' coverage_html/index.html | head -1 | tr -d '%') + echo "COVERAGE=$COVERAGE" >> $GITHUB_ENV + if [ "$COVERAGE" -ge 90 ]; then + echo "COVERAGE_COLOR=green" >> $GITHUB_ENV + elif [ "$COVERAGE" -ge 80 ]; then + echo "COVERAGE_COLOR=yellow" >> $GITHUB_ENV + else + echo "COVERAGE_COLOR=red" >> $GITHUB_ENV + fi + + - name: Create coverage badge + uses: schneegans/dynamic-badges-action@v1.6.0 + with: + auth: ${{ secrets.GIST_SECRET }} + gistID: ${{ secrets.COVERAGE_GIST_ID }} + filename: coverage.json + label: coverage + message: ${{ env.COVERAGE }}% + color: ${{ env.COVERAGE_COLOR }} + namedLogo: python \ No newline at end of file diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..df42e205ce24b67416a0d909ce31a31fda4250a2 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,170 @@ +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 + hooks: + - id: check-added-large-files + args: ['--maxkb=1024'] + - id: check-ast + - id: check-case-conflict + - id: check-docstring-first + - id: check-executables-have-shebangs + - id: check-json + - id: check-merge-conflict + - id: check-toml + - id: check-yaml + - id: debug-statements + - id: detect-private-key + - id: end-of-file-fixer + - id: trailing-whitespace + - id: mixed-line-ending + args: ['--fix=lf'] + +- repo: https://github.com/psf/black + rev: 24.2.0 + hooks: + - id: black + language_version: python3 + args: ['--config=pyproject.toml'] + +- repo: https://github.com/pycqa/isort + rev: 5.13.2 + hooks: + - id: isort + args: ['--settings-path=pyproject.toml'] + +- repo: https://github.com/pycqa/flake8 + rev: 7.0.0 + hooks: + - id: flake8 + additional_dependencies: + - flake8-docstrings + - flake8-bugbear + - flake8-comprehensions + - flake8-simplify + - flake8-pytest-style + - flake8-typing-imports + - pep8-naming + - flake8-cognitive-complexity + - flake8-expression-complexity + - mccabe + - flake8-functions + - flake8-annotations-complexity + +- repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.8.0 + hooks: + - id: mypy + additional_dependencies: + - types-requests + - types-PyYAML + - pydantic + - types-setuptools + - types-python-dateutil + - types-pytz + - types-urllib3 + - types-six + - types-protobuf + - types-mock + - types-toml + args: [ + '--config-file=pyproject.toml', + '--strict', + '--ignore-missing-imports', + '--python-version=3.9', + '--show-error-codes', + '--pretty', + '--warn-unused-ignores', + '--disallow-any-generics', + '--disallow-untyped-decorators', + '--no-implicit-optional' + ] + +- repo: https://github.com/microsoft/pyright + rev: 1.1.350 + hooks: + - id: pyright + additional_dependencies: + - pydantic + - requests + - PyYAML + args: [ + '--warnings', + '--pythonversion', '3.9', + '--typeCheckingMode', 'strict' + ] + +- repo: https://github.com/RobertCraigie/pyright-python + rev: v1.1.350 + hooks: + - id: pyright-python + name: pyright-strict + args: [ + '--warnings', + '--pythonversion', '3.9', + '--typeCheckingMode', 'strict', + '--ignoreexternal' + ] + +- repo: https://github.com/PyCQA/bandit + rev: 1.7.7 + hooks: + - id: bandit + args: ['-c', 'pyproject.toml'] + +- repo: https://github.com/asottile/pyupgrade + rev: v3.15.1 + hooks: + - id: pyupgrade + args: ['--py39-plus'] + +- repo: https://github.com/PyCQA/doc8 + rev: v1.1.1 + hooks: + - id: doc8 + args: ['--max-line-length=120'] + +- repo: https://github.com/pypa/safety + rev: 2.3.5 + hooks: + - id: safety + args: ['check'] + +- repo: local + hooks: + - id: pylint + name: pylint + entry: pylint + language: system + types: [python] + args: + - --rcfile=pyproject.toml + - --score=no + - --output-format=colorized + + - id: pytest-check + name: pytest-check + entry: pytest + language: system + pass_filenames: false + always_run: true + args: + - --cov + - --cov-report=term-missing + - -v + +- repo: https://github.com/rubik/radon + rev: v6.0.1 + hooks: + - id: radon + name: radon-complexity + entry: radon cc + args: [--min=C, --total-average, --show-complexity] + language: python + types: [python] + + - id: radon-maintainability + name: radon-maintainability + entry: radon mi + args: [--min=B, --show] + language: python + types: [python] diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000000000000000000000000000000000..d4c2dde703780d8924c78576277fa5a4723bc8dc --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,69 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added +- Initial project structure and setup +- Comprehensive code formatting standards + - Black configuration with 100 character line length + - isort for import sorting + - EditorConfig for consistent formatting +- Static type checking configuration + - MyPy with strict type checking + - Pyright integration + - Type stubs for common dependencies +- Code quality tools + - Flake8 with multiple plugins + - Radon for complexity checks + - Bandit for security scanning +- Testing framework + - Pytest configuration + - Coverage reporting setup + - Test helpers and fixtures +- Documentation + - Project README + - Contributing guidelines + - Code style guide + - Type checking guide +- CI/CD Pipeline + - GitHub Actions workflow + - Pre-commit hooks configuration + - Automated testing and linting +- Development tools + - Development requirements + - Virtual environment setup + - Local development guide + +### Changed +- None (initial release) + +### Deprecated +- None + +### Removed +- None + +### Fixed +- None + +### Security +- Added Bandit security checks +- Implemented Safety dependency scanning +- Configured security-focused pre-commit hooks +- Added checks for hardcoded secrets + +## [0.1.0] - YYYY-MM-DD +### Added +- First release of the project +- Basic project structure +- Core functionality implementation +- Initial test suite +- Basic documentation + +[Unreleased]: https://github.com/username/repository/compare/v0.1.0...HEAD +[0.1.0]: https://github.com/username/repository/releases/tag/v0.1.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000000000000000000000000000000000..f4ed5f17fdeecf21b0b27006d652204dbdb23d05 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,223 @@ +# Contributing Guidelines + +## Table of Contents +- [Development Setup](#development-setup) +- [Code Style](#code-style) +- [Type Checking](#type-checking) +- [Code Quality](#code-quality) +- [Testing](#testing) +- [Pull Request Process](#pull-request-process) +- [Commit Guidelines](#commit-guidelines) + +## Development Setup + +### Prerequisites +- Python 3.9+ +- pip +- git + +### Setting Up Development Environment +1. Clone the repository: + ```bash + git clone + cd + ``` + +2. Create and activate a virtual environment: + ```bash + python -m venv .venv + source .venv/bin/activate # Linux/macOS + .venv\Scripts\activate # Windows + ``` + +3. Install development dependencies: + ```bash + pip install -r requirements-dev.txt + ``` + +4. Install pre-commit hooks: + ```bash + pre-commit install + ``` + +## Code Style + +We follow a strict Python code style guide to maintain consistency across the project. Our code style is enforced through various tools: + +### Formatting +- **Black**: Code formatting with line length of 100 characters +- **isort**: Import sorting with three sections (stdlib, third-party, local) +- **EditorConfig**: Editor-agnostic formatting rules + +### Style Rules +- Use 4 spaces for indentation +- Use meaningful variable and function names +- Follow PEP 8 naming conventions +- Write descriptive docstrings in Google style +- Keep functions focused and concise + +Example: +```python +from typing import List, Optional + +def process_data(items: List[str], max_length: Optional[int] = None) -> List[str]: + """Process a list of string items with optional length limitation. + + Args: + items: List of strings to process. + max_length: Optional maximum length for each string. + + Returns: + List of processed strings. + + Raises: + ValueError: If any string is empty. + """ + if not items: + raise ValueError("Items list cannot be empty") + + return [item[:max_length] if max_length else item for item in items] +``` + +## Type Checking + +We use multiple type checking tools to ensure type safety: + +### MyPy +- Strict type checking enabled +- All functions must have type annotations +- Generic types must be fully specified +- No implicit Optional types + +### Pyright +- Strict mode enabled +- Reports missing type stubs +- Enforces strict collection type inference +- Checks for proper None handling + +Example of proper type usage: +```python +from typing import Dict, List, Optional, TypeVar + +T = TypeVar("T") + +def merge_lists(list1: List[T], list2: List[T]) -> List[T]: + """Merge two lists of the same type.""" + return list1 + list2 + +def get_config(path: str) -> Dict[str, Optional[str]]: + """Get configuration with optional values.""" + return {"key": "value", "optional_key": None} +``` + +## Code Quality + +We maintain high code quality standards through various tools: + +### Complexity Checks +- Maximum cyclomatic complexity: C grade (radon) +- Maximum cognitive complexity: 10 (flake8-cognitive-complexity) +- Maximum function length: 50 lines +- Maximum expression complexity: 3 (flake8-expression-complexity) + +### Security +- Bandit security checks +- Safety dependency checks +- No hardcoded secrets +- Proper error handling + +### Documentation +- All public APIs must be documented +- Complex algorithms need detailed explanations +- Update documentation when changing functionality +- Include examples in docstrings + +## Testing + +### Test Requirements +- All new code must have tests +- Maintain minimum 90% code coverage +- Test both success and error cases +- Use pytest fixtures for common setup + +### Running Tests +```bash +# Run all tests +pytest + +# Run with coverage +pytest --cov + +# Run specific test file +pytest tests/test_specific.py +``` + +## Pull Request Process + +1. **Branch Naming** + - feature/description-of-feature + - bugfix/description-of-bug + - hotfix/description-of-hotfix + +2. **Before Submitting** + - Run all pre-commit hooks + - Ensure all tests pass + - Update documentation if needed + - Add tests for new features + +3. **PR Description** + - Clear description of changes + - Link to related issues + - List of testing steps + - Screenshots (if UI changes) + +4. **Review Process** + - At least one approval required + - All comments must be resolved + - CI checks must pass + - No merge conflicts + +## Commit Guidelines + +### Commit Message Format +``` +(): + + + +