span-panel-api 2.3.2__tar.gz → 2.4.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. span_panel_api-2.4.1/.codefactor +29 -0
  2. span_panel_api-2.4.1/.codefactor.yml +18 -0
  3. span_panel_api-2.4.1/.github/ISSUE_TEMPLATE/bug_report.md +37 -0
  4. span_panel_api-2.4.1/.github/ISSUE_TEMPLATE/feature_request.md +31 -0
  5. span_panel_api-2.4.1/.github/dependabot.yml +62 -0
  6. span_panel_api-2.4.1/.github/workflows/ci.yml +102 -0
  7. span_panel_api-2.4.1/.github/workflows/dependabot-auto-approve.yml +38 -0
  8. span_panel_api-2.4.1/.github/workflows/dependabot-auto-merge.yml +56 -0
  9. span_panel_api-2.4.1/.github/workflows/release.yml +42 -0
  10. span_panel_api-2.4.1/.gitignore +35 -0
  11. span_panel_api-2.4.1/.markdownlint-cli2.jsonc +49 -0
  12. span_panel_api-2.4.1/.markdownlint.json +11 -0
  13. span_panel_api-2.4.1/.pre-commit-config.yaml +136 -0
  14. span_panel_api-2.4.1/.prettierrc.json +25 -0
  15. span_panel_api-2.4.1/.vscode/extensions.json +5 -0
  16. span_panel_api-2.4.1/.vscode/tasks.json +131 -0
  17. span_panel_api-2.4.1/CHANGELOG.md +318 -0
  18. span_panel_api-2.4.1/DEVELOPMENT.md +79 -0
  19. span_panel_api-2.3.2/README.md → span_panel_api-2.4.1/PKG-INFO +17 -48
  20. span_panel_api-2.3.2/PKG-INFO → span_panel_api-2.4.1/README.md +2 -69
  21. span_panel_api-2.4.1/SECURITY.md +11 -0
  22. span_panel_api-2.4.1/conftest.py +18 -0
  23. span_panel_api-2.4.1/coverage_output.log +9 -0
  24. span_panel_api-2.4.1/debug_unmapped.py +0 -0
  25. span_panel_api-2.4.1/developer_attribute_readme.md +276 -0
  26. span_panel_api-2.4.1/openapi.json +1621 -0
  27. {span_panel_api-2.3.2 → span_panel_api-2.4.1}/pyproject.toml +27 -25
  28. span_panel_api-2.4.1/pytest.ini +2 -0
  29. span_panel_api-2.4.1/pytest_output.log +11 -0
  30. span_panel_api-2.4.1/scripts/__init__.py +1 -0
  31. span_panel_api-2.4.1/scripts/coverage.py +118 -0
  32. span_panel_api-2.4.1/scripts/format.sh +25 -0
  33. span_panel_api-2.4.1/scripts/format_markdown.py +39 -0
  34. span_panel_api-2.4.1/scripts/test_live_auth.py +311 -0
  35. span_panel_api-2.4.1/setup-hooks.sh +31 -0
  36. {span_panel_api-2.3.2 → span_panel_api-2.4.1}/src/span_panel_api/__init__.py +5 -1
  37. span_panel_api-2.4.1/src/span_panel_api/_http.py +27 -0
  38. {span_panel_api-2.3.2 → span_panel_api-2.4.1}/src/span_panel_api/auth.py +76 -32
  39. {span_panel_api-2.3.2 → span_panel_api-2.4.1}/src/span_panel_api/detection.py +29 -14
  40. {span_panel_api-2.3.2 → span_panel_api-2.4.1}/src/span_panel_api/models.py +7 -1
  41. {span_panel_api-2.3.2 → span_panel_api-2.4.1}/src/span_panel_api/mqtt/client.py +2 -2
  42. {span_panel_api-2.3.2 → span_panel_api-2.4.1}/src/span_panel_api/mqtt/connection.py +27 -23
  43. {span_panel_api-2.3.2 → span_panel_api-2.4.1}/src/span_panel_api/mqtt/field_metadata.py +5 -5
  44. span_panel_api-2.4.1/src/span_panel_api/py.typed +0 -0
  45. span_panel_api-2.4.1/tests/conftest.py +121 -0
  46. span_panel_api-2.4.1/tests/fixtures/configs/simulation_config_32_circuit.yaml +444 -0
  47. span_panel_api-2.4.1/tests/fixtures/configs/simulation_config_40_circuit_with_battery.yaml +325 -0
  48. span_panel_api-2.4.1/tests/fixtures/configs/simulation_config_8_tab_workshop.yaml +170 -0
  49. span_panel_api-2.4.1/tests/fixtures/v2/README.md +27 -0
  50. span_panel_api-2.4.1/tests/fixtures/v2/homie_schema.json +420 -0
  51. span_panel_api-2.4.1/tests/fixtures/v2/status.json +4 -0
  52. span_panel_api-2.4.1/tests/simulation_fixtures/circuits.response.txt +8 -0
  53. span_panel_api-2.4.1/tests/simulation_fixtures/panel.response.txt +7 -0
  54. span_panel_api-2.4.1/tests/simulation_fixtures/soe.response.txt +8 -0
  55. span_panel_api-2.4.1/tests/simulation_fixtures/status.response.txt +8 -0
  56. span_panel_api-2.4.1/tests/test_async_mqtt_client.py +54 -0
  57. span_panel_api-2.4.1/tests/test_auth_and_homie_helpers.py +177 -0
  58. span_panel_api-2.4.1/tests/test_detection_auth.py +837 -0
  59. span_panel_api-2.4.1/tests/test_field_metadata.py +280 -0
  60. span_panel_api-2.4.1/tests/test_mqtt_bridge.py +81 -0
  61. span_panel_api-2.4.1/tests/test_mqtt_connect_flow.py +387 -0
  62. span_panel_api-2.4.1/tests/test_mqtt_debounce.py +279 -0
  63. span_panel_api-2.4.1/tests/test_mqtt_homie.py +1449 -0
  64. span_panel_api-2.4.1/tests/test_phase_validation_configs.py +273 -0
  65. span_panel_api-2.4.1/tests/test_phase_validation_errors.py +206 -0
  66. span_panel_api-2.4.1/tests/test_protocol_conformance.py +48 -0
  67. span_panel_api-2.4.1/tests/test_protocol_models.py +101 -0
  68. span_panel_api-2.4.1/uv.lock +1518 -0
  69. /span_panel_api-2.3.2/src/span_panel_api/py.typed → /span_panel_api-2.4.1/.deps-installed +0 -0
  70. {span_panel_api-2.3.2 → span_panel_api-2.4.1}/LICENSE +0 -0
  71. {span_panel_api-2.3.2 → span_panel_api-2.4.1}/src/span_panel_api/const.py +0 -0
  72. {span_panel_api-2.3.2 → span_panel_api-2.4.1}/src/span_panel_api/exceptions.py +0 -0
  73. {span_panel_api-2.3.2 → span_panel_api-2.4.1}/src/span_panel_api/factory.py +0 -0
  74. {span_panel_api-2.3.2 → span_panel_api-2.4.1}/src/span_panel_api/mqtt/__init__.py +0 -0
  75. {span_panel_api-2.3.2 → span_panel_api-2.4.1}/src/span_panel_api/mqtt/async_client.py +0 -0
  76. {span_panel_api-2.3.2 → span_panel_api-2.4.1}/src/span_panel_api/mqtt/const.py +0 -0
  77. {span_panel_api-2.3.2 → span_panel_api-2.4.1}/src/span_panel_api/mqtt/homie.py +0 -0
  78. {span_panel_api-2.3.2 → span_panel_api-2.4.1}/src/span_panel_api/mqtt/models.py +0 -0
  79. {span_panel_api-2.3.2 → span_panel_api-2.4.1}/src/span_panel_api/phase_validation.py +0 -0
  80. {span_panel_api-2.3.2 → span_panel_api-2.4.1}/src/span_panel_api/protocol.py +0 -0
@@ -0,0 +1,29 @@
1
+ {
2
+ "version": "1.0.0",
3
+ "exclude": [
4
+ "scripts/**/*",
5
+ "examples/**/*",
6
+ "tests/**/*",
7
+ "src/span_panel_api/generated_client/**/*",
8
+ "generate_client.py",
9
+ "*.pyc",
10
+ "__pycache__/**/*",
11
+ ".venv/**/*",
12
+ "venv/**/*",
13
+ "dist/**/*",
14
+ "build/**/*",
15
+ ".git/**/*",
16
+ ".mypy_cache/**/*",
17
+ ".pytest_cache/**/*",
18
+ ".ruff_cache/**/*"
19
+ ],
20
+ "rules": {
21
+ "ComplexMethod": {
22
+ "enabled": true,
23
+ "exclude": [
24
+ "scripts/**/*",
25
+ "examples/**/*"
26
+ ]
27
+ }
28
+ }
29
+ }
@@ -0,0 +1,18 @@
1
+ version: 1.0
2
+
3
+ # Exclude noisy or generated directories from CodeFactor analysis
4
+ exclude_patterns:
5
+ - scripts/**
6
+ - examples/**
7
+ - tests/**
8
+ - src/span_panel_api/generated_client/**
9
+ - generate_client.py
10
+ - __pycache__/**
11
+ - .venv/**
12
+ - venv/**
13
+ - dist/**
14
+ - build/**
15
+ - .git/**
16
+ - .mypy_cache/**
17
+ - .pytest_cache/**
18
+ - .ruff_cache/**
@@ -0,0 +1,37 @@
1
+ # Bug Report
2
+
3
+ ---
4
+
5
+ name: Bug report
6
+
7
+ about: Create a report to help us improve
8
+
9
+ title: ''
10
+
11
+ labels: ''
12
+
13
+ assignees: ''
14
+
15
+ ---
16
+
17
+ ## Python Version Used
18
+
19
+ ## Describe the bug
20
+
21
+ A clear and concise description of what the bug is.
22
+
23
+ ## To Reproduce
24
+
25
+ Steps to reproduce the behavior:
26
+
27
+ ## Expected behavior
28
+
29
+ A clear and concise description of what you expected to happen.
30
+
31
+ ## Screenshots
32
+
33
+ If applicable, add screenshots to help explain your problem.
34
+
35
+ ## Additional context
36
+
37
+ Add any other context about the problem here.
@@ -0,0 +1,31 @@
1
+ # Feature Request
2
+
3
+ ---
4
+
5
+ name: Feature request
6
+
7
+ about: Suggest an idea for this project
8
+
9
+ title: ''
10
+
11
+ labels: ''
12
+
13
+ assignees: ''
14
+
15
+ ---
16
+
17
+ ## Is your feature request related to a problem? Please describe
18
+
19
+ A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
20
+
21
+ ## Describe the solution you'd like
22
+
23
+ A clear and concise description of what you want to happen.
24
+
25
+ ## Describe alternatives you've considered
26
+
27
+ A clear and concise description of any alternative solutions or features you've considered.
28
+
29
+ ## Additional context
30
+
31
+ Add any other context or screenshots about the feature request here.
@@ -0,0 +1,62 @@
1
+ version: 2
2
+ updates:
3
+ # Enable version updates for Python dependencies
4
+ - package-ecosystem: "pip"
5
+ directory: "/"
6
+ schedule:
7
+ interval: "weekly"
8
+ open-pull-requests-limit: 1
9
+ allow:
10
+ - dependency-type: "all"
11
+ groups:
12
+ # Group development dependencies together
13
+ dev-dependencies:
14
+ patterns:
15
+ - "pytest*"
16
+ - "mypy"
17
+ - "ruff"
18
+ - "bandit"
19
+ - "pre-commit"
20
+ - "twine"
21
+ - "*-cov"
22
+ - "types-*"
23
+ # Group documentation dependencies
24
+ docs-dependencies:
25
+ patterns:
26
+ - "mkdocs*"
27
+ - "mkdocstrings"
28
+ # Group core runtime dependencies for span-panel-api
29
+ runtime-dependencies:
30
+ patterns:
31
+ - "httpx"
32
+ - "attrs"
33
+ - "python-dateutil"
34
+ - "click"
35
+ reviewers:
36
+ - "cayossarian"
37
+ assignees:
38
+ - "cayossarian"
39
+
40
+ # Enable version updates for Python dependencies (generated client)
41
+ - package-ecosystem: "pip"
42
+ directory: "/generated_client"
43
+ schedule:
44
+ interval: "weekly"
45
+ open-pull-requests-limit: 5
46
+ allow:
47
+ - dependency-type: "all"
48
+ reviewers:
49
+ - "cayossarian"
50
+ assignees:
51
+ - "cayossarian"
52
+
53
+ # Enable version updates for GitHub Actions
54
+ - package-ecosystem: "github-actions"
55
+ directory: "/"
56
+ schedule:
57
+ interval: "weekly"
58
+ open-pull-requests-limit: 5
59
+ reviewers:
60
+ - "cayossarian"
61
+ assignees:
62
+ - "cayossarian"
@@ -0,0 +1,102 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ main, develop ]
6
+ pull_request:
7
+ branches: [ main, develop ]
8
+
9
+ jobs:
10
+ lint-and-test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ["3.13", "3.14"]
15
+
16
+ steps:
17
+ - name: Checkout code
18
+ uses: actions/checkout@v6
19
+
20
+ - name: Set up Python ${{ matrix.python-version }}
21
+ uses: actions/setup-python@v6
22
+ with:
23
+ python-version: ${{ matrix.python-version }}
24
+ allow-prereleases: true
25
+
26
+ - name: Install uv
27
+ uses: astral-sh/setup-uv@v5
28
+ with:
29
+ enable-cache: true
30
+
31
+ - name: Install dependencies
32
+ run: uv sync
33
+
34
+ - name: Run pre-commit hooks
35
+ run: |
36
+ uv run pre-commit run --all-files
37
+
38
+ - name: Run tests with pytest
39
+ run: |
40
+ uv run pytest tests/ -v --cov=src/span_panel_api --cov-report=xml --cov-report=term-missing
41
+
42
+
43
+
44
+ security-scan:
45
+ runs-on: ubuntu-latest
46
+ steps:
47
+ - name: Checkout code
48
+ uses: actions/checkout@v6
49
+
50
+ - name: Set up Python
51
+ uses: actions/setup-python@v6
52
+ with:
53
+ python-version: "3.13"
54
+
55
+ - name: Install uv
56
+ uses: astral-sh/setup-uv@v5
57
+ with:
58
+ enable-cache: true
59
+
60
+ - name: Install dependencies
61
+ run: uv sync
62
+
63
+ - name: Run Bandit security scan
64
+ run: |
65
+ uv run bandit -r src/ -f json -o bandit-report.json || true
66
+
67
+ - name: Upload Bandit scan results
68
+ uses: actions/upload-artifact@v7
69
+ with:
70
+ name: bandit-report
71
+ path: bandit-report.json
72
+
73
+ build-check:
74
+ runs-on: ubuntu-latest
75
+ steps:
76
+ - name: Checkout code
77
+ uses: actions/checkout@v6
78
+
79
+ - name: Set up Python
80
+ uses: actions/setup-python@v6
81
+ with:
82
+ python-version: "3.13"
83
+
84
+ - name: Install uv
85
+ uses: astral-sh/setup-uv@v5
86
+ with:
87
+ enable-cache: true
88
+
89
+ - name: Install dependencies
90
+ run: uv sync
91
+
92
+ - name: Build package
93
+ run: uv build
94
+
95
+ - name: Check package
96
+ run: uv run twine check dist/*
97
+
98
+ - name: Upload build artifacts
99
+ uses: actions/upload-artifact@v7
100
+ with:
101
+ name: dist
102
+ path: dist/
@@ -0,0 +1,38 @@
1
+ name: Dependabot Auto-Approve
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize, reopened]
6
+
7
+ permissions:
8
+ contents: read
9
+ pull-requests: write
10
+
11
+ jobs:
12
+ auto-approve:
13
+ runs-on: ubuntu-latest
14
+ if: github.actor == 'dependabot[bot]'
15
+ steps:
16
+ - name: Dependabot metadata
17
+ id: metadata
18
+ uses: dependabot/fetch-metadata@v2.5.0
19
+ with:
20
+ github-token: "${{ secrets.GITHUB_TOKEN }}"
21
+
22
+ - name: Auto-approve patch and minor updates
23
+ if: ${{ steps.metadata.outputs.update-type == 'version-update:semver-patch' || steps.metadata.outputs.update-type == 'version-update:semver-minor' }}
24
+ run: |
25
+ echo "Auto-approving ${{ steps.metadata.outputs.dependency-names }}"
26
+ gh pr review --approve "$PR_URL"
27
+ env:
28
+ PR_URL: ${{ github.event.pull_request.html_url }}
29
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
30
+
31
+ - name: Auto-approve GitHub Actions updates
32
+ if: ${{ steps.metadata.outputs.package-ecosystem == 'github_actions' }}
33
+ run: |
34
+ echo "Auto-approving GitHub Actions update for ${{ steps.metadata.outputs.dependency-names }}"
35
+ gh pr review --approve "$PR_URL"
36
+ env:
37
+ PR_URL: ${{ github.event.pull_request.html_url }}
38
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,56 @@
1
+ name: Dependabot Auto-Merge
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize, reopened]
6
+
7
+ permissions:
8
+ contents: write
9
+ pull-requests: write
10
+
11
+ jobs:
12
+ auto-merge:
13
+ runs-on: ubuntu-latest
14
+ if: github.actor == 'dependabot[bot]'
15
+ steps:
16
+ - name: Dependabot metadata
17
+ id: metadata
18
+ uses: dependabot/fetch-metadata@v2.5.0
19
+ with:
20
+ github-token: "${{ secrets.GITHUB_TOKEN }}"
21
+
22
+ - name: Auto-merge for patch and minor updates
23
+ if: ${{ steps.metadata.outputs.update-type == 'version-update:semver-patch' || steps.metadata.outputs.update-type == 'version-update:semver-minor' }}
24
+ run: |
25
+ echo "Auto-merging ${{ steps.metadata.outputs.dependency-names }}"
26
+ gh pr merge --auto --merge "$PR_URL"
27
+ env:
28
+ PR_URL: ${{ github.event.pull_request.html_url }}
29
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
30
+
31
+ - name: Enable auto-merge for GitHub Actions updates
32
+ if: ${{ steps.metadata.outputs.package-ecosystem == 'github_actions' }}
33
+ run: |
34
+ echo "Auto-merging GitHub Actions update for ${{ steps.metadata.outputs.dependency-names }}"
35
+ gh pr merge --auto --merge "$PR_URL"
36
+ env:
37
+ PR_URL: ${{ github.event.pull_request.html_url }}
38
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
39
+
40
+ - name: Comment on major version updates
41
+ if: ${{ steps.metadata.outputs.update-type == 'version-update:semver-major' }}
42
+ run: |
43
+ gh pr comment "$PR_URL" --body "🚨 **Major version update detected!**
44
+
45
+ This PR contains major version updates that may include breaking changes:
46
+ - **${{ steps.metadata.outputs.dependency-names }}**
47
+
48
+ Please review carefully before merging. Consider:
49
+ - Reading the changelog/release notes
50
+ - Testing locally
51
+ - Checking for breaking changes
52
+
53
+ This PR will **NOT** be auto-merged due to the major version change."
54
+ env:
55
+ PR_URL: ${{ github.event.pull_request.html_url }}
56
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,42 @@
1
+ name: Release
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ deploy:
9
+ runs-on: ubuntu-latest
10
+ environment: release
11
+ permissions:
12
+ id-token: write # For trusted publishing to PyPI
13
+
14
+ steps:
15
+ - name: Checkout code
16
+ uses: actions/checkout@v6
17
+
18
+ - name: Set up Python
19
+ uses: actions/setup-python@v6
20
+ with:
21
+ python-version: "3.13"
22
+
23
+ - name: Install uv
24
+ uses: astral-sh/setup-uv@v5
25
+ with:
26
+ enable-cache: true
27
+
28
+ - name: Update version from tag
29
+ run: |
30
+ # Extract version from git tag (remove 'v' prefix if present)
31
+ VERSION=${GITHUB_REF#refs/tags/}
32
+ VERSION=${VERSION#v}
33
+ echo "Setting version to $VERSION"
34
+ sed -i "s/^version = \".*\"/version = \"$VERSION\"/" pyproject.toml
35
+
36
+ - name: Build package
37
+ run: uv build
38
+
39
+ - name: Publish to PyPI
40
+ uses: pypa/gh-action-pypi-publish@release/v1
41
+ with:
42
+ print-hash: true
@@ -0,0 +1,35 @@
1
+ __pycache__/
2
+ build/
3
+ dist/
4
+ *.egg-info/
5
+ .pytest_cache/
6
+ .cursor/
7
+ .cursorignore
8
+ .cursor
9
+ .cursorindexingignore
10
+ xnotes/*
11
+
12
+ # pyenv
13
+ .python-version
14
+
15
+ # Environments
16
+ .env
17
+ .envrc
18
+ .venv
19
+ .vscode/settings.json
20
+
21
+ # mypy
22
+ .mypy_cache/
23
+ .dmypy.json
24
+ dmypy.json
25
+
26
+ # ruff
27
+ .ruff_cache/
28
+
29
+ # JetBrains
30
+ .idea/
31
+
32
+ /coverage.xml
33
+ /.coverage
34
+ **/.DS_Store
35
+ .local_coverage_data
@@ -0,0 +1,49 @@
1
+ {
2
+ "config": {
3
+ "default": true,
4
+ "MD013": {
5
+ "line_length": 256,
6
+ "heading_line_length": 256,
7
+ "code_block_line_length": 256,
8
+ "tables": false
9
+ },
10
+ "MD025": false,
11
+ "MD033": {
12
+ "allowed_elements": ["br", "details", "summary"]
13
+ },
14
+ "MD046": {
15
+ "style": "fenced"
16
+ },
17
+ "MD024": {
18
+ "siblings_only": true
19
+ },
20
+ "MD022": {
21
+ "lines_above": 1,
22
+ "lines_below": 1
23
+ },
24
+ "MD026": {
25
+ "punctuation": ".,;:!"
26
+ },
27
+ "MD031": {
28
+ "list_items": true
29
+ },
30
+ "MD032": true,
31
+ "MD036": false,
32
+ "MD040": {
33
+ "allowed_languages": ["yaml", "python", "bash", "shell", "json", "toml", "markdown", "text", "console", "diff"],
34
+ "language_only": false
35
+ }
36
+ },
37
+ "globs": ["**/*.md"],
38
+ "ignores": [
39
+ ".venv/**",
40
+ "venv/**",
41
+ "node_modules/**",
42
+ "__pycache__/**",
43
+ "htmlcov/**",
44
+ ".mypy_cache/**",
45
+ ".pytest_cache/**",
46
+ "dist/**",
47
+ "build/**"
48
+ ]
49
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "default": true,
3
+ "MD013": {
4
+ "line_length": 256
5
+ },
6
+ "MD024": {
7
+ "siblings_only": true
8
+ },
9
+ "MD033": false,
10
+ "MD041": false
11
+ }
@@ -0,0 +1,136 @@
1
+ repos:
2
+ # Pre-commit hooks for basic checks
3
+ - repo: https://github.com/pre-commit/pre-commit-hooks
4
+ rev: v5.0.0
5
+ hooks:
6
+ - id: trailing-whitespace
7
+ exclude: '^src/span_panel_api/generated_client/.*|\..*_cache/.*|dist/.*|venv/.*|\.venv/.*'
8
+ - id: end-of-file-fixer
9
+ exclude: '^src/span_panel_api/generated_client/.*|\..*_cache/.*|dist/.*|venv/.*|\.venv/.*'
10
+ - id: check-yaml
11
+ exclude: '^src/span_panel_api/generated_client/.*|\..*_cache/.*|dist/.*|venv/.*|\.venv/.*'
12
+ - id: check-toml
13
+ exclude: '^src/span_panel_api/generated_client/.*|\..*_cache/.*|dist/.*|venv/.*|\.venv/.*'
14
+ - id: check-json
15
+ exclude: '^src/span_panel_api/generated_client/.*|\..*_cache/.*|dist/.*|venv/.*|\.venv/.*'
16
+ - id: check-added-large-files
17
+ - id: check-merge-conflict
18
+ exclude: '^src/span_panel_api/generated_client/.*|\..*_cache/.*|dist/.*|venv/.*|\.venv/.*'
19
+ - id: debug-statements
20
+ exclude: '^src/span_panel_api/generated_client/.*|generate_client\.py|scripts/.*|tests/.*|\..*_cache/.*|dist/.*|venv/.*|\.venv/.*|^examples/.*'
21
+ - id: mixed-line-ending
22
+ args: ['--fix=lf']
23
+ exclude: '^src/span_panel_api/generated_client/.*|\..*_cache/.*|dist/.*|venv/.*|\.venv/.*'
24
+
25
+ # Ruff for formatting and linting
26
+ - repo: https://github.com/astral-sh/ruff-pre-commit
27
+ rev: v0.11.13
28
+ hooks:
29
+ # Run formatter first - exclude tests to avoid conflicts with black
30
+ - id: ruff-format
31
+ exclude: '^src/span_panel_api/generated_client/.*|generate_client\.py|scripts/.*|tests/.*|\..*_cache/.*|dist/.*|venv/.*|\.venv/.*|^examples/.*'
32
+ # Then linter - exclude tests and scripts from strict linting
33
+ - id: ruff-check
34
+ args: ['--fix']
35
+ exclude: '^src/span_panel_api/generated_client/.*|generate_client\.py|scripts/.*|tests/.*|\..*_cache/.*|dist/.*|venv/.*|\.venv/.*|^examples/.*'
36
+
37
+ # Black for line length handling and test file formatting
38
+ - repo: https://github.com/psf/black
39
+ rev: 25.1.0
40
+ hooks:
41
+ - id: black
42
+ language_version: python3
43
+ args: [
44
+ '--line-length=125',
45
+ '--skip-string-normalization',
46
+ '--target-version=py312',
47
+ '--extend-exclude=src/span_panel_api/generated_client|generate_client\.py|scripts|\.venv|venv'
48
+ ]
49
+ exclude: '^src/span_panel_api/generated_client/.*|generate_client\.py|scripts/.*|\..*_cache/.*|dist/.*|venv/.*|\.venv/.*|^examples/.*'
50
+
51
+ # Prettier for markdown formatting
52
+ - repo: https://github.com/pre-commit/mirrors-prettier
53
+ rev: v3.1.0
54
+ hooks:
55
+ - id: prettier
56
+ types: [markdown]
57
+ args: ['--config', '.prettierrc.json']
58
+ exclude: '^src/span_panel_api/generated_client/.*|\..*_cache/.*|dist/.*|venv/.*|\.venv/.*|node_modules/.*|htmlcov/.*'
59
+
60
+ # Markdownlint for markdown files (after Prettier formatting)
61
+ - repo: https://github.com/DavidAnson/markdownlint-cli2
62
+ rev: v0.15.0
63
+ hooks:
64
+ - id: markdownlint-cli2
65
+ args: ['--config', '.markdownlint-cli2.jsonc']
66
+ exclude: '^src/span_panel_api/generated_client/.*|\..*_cache/.*|dist/.*|venv/.*|\.venv/.*|node_modules/.*|htmlcov/.*'
67
+
68
+ # MyPy for type checking
69
+ - repo: https://github.com/pre-commit/mirrors-mypy
70
+ rev: v1.16.0
71
+ hooks:
72
+ - id: mypy
73
+ additional_dependencies:
74
+ - httpx
75
+ - click
76
+ - typing-extensions
77
+ - pytest
78
+ - types-PyYAML
79
+ - paho-mqtt
80
+ args: ['--config-file=pyproject.toml']
81
+ exclude: '^src/span_panel_api/generated_client/.*|scripts/.*|tests/.*|docs/.*|examples/.*|\..*_cache/.*|dist/.*|venv/.*'
82
+
83
+ # Pylint for code quality
84
+ - repo: https://github.com/pycqa/pylint
85
+ rev: v3.3.3
86
+ hooks:
87
+ - id: pylint
88
+ additional_dependencies:
89
+ - httpx
90
+ - click
91
+ - typing-extensions
92
+ - pytest
93
+ - pyyaml
94
+ - paho-mqtt
95
+ exclude: '^src/span_panel_api/generated_client/.*|tests/.*|generate_client\.py|scripts/.*|\..*_cache/.*|dist/.*|venv/.*|\.venv/.*|^examples/.*'
96
+
97
+ # Check for common security issues
98
+ - repo: https://github.com/PyCQA/bandit
99
+ rev: 1.8.3
100
+ hooks:
101
+ - id: bandit
102
+ args: ['-c', 'pyproject.toml']
103
+ additional_dependencies: ['bandit[toml]']
104
+ exclude: '^tests/.*|^scripts/.*|^src/span_panel_api/generated_client/.*|\..*_cache/.*|dist/.*|venv/.*|\.venv/.*|^examples/.*'
105
+
106
+ # Vulture for dead code detection
107
+ - repo: local
108
+ hooks:
109
+ - id: vulture
110
+ name: vulture
111
+ entry: bash -c 'uv run vulture src/span_panel_api/ --min-confidence 80'
112
+ language: system
113
+ types: [python]
114
+ pass_filenames: false
115
+ exclude: '^src/span_panel_api/generated_client/.*|\..*_cache/.*|dist/.*|venv/.*|\.venv/.*|^examples/.*'
116
+
117
+ # uv lock check for lockfile validation
118
+ - repo: local
119
+ hooks:
120
+ - id: uv-lock-check
121
+ name: uv lock check
122
+ entry: uv lock --check
123
+ language: system
124
+ pass_filenames: false
125
+ files: ^pyproject\.toml$|^uv\.lock$
126
+
127
+ # Quick coverage check (total only, no details)
128
+ - repo: local
129
+ hooks:
130
+ - id: pytest-cov-summary
131
+ name: coverage summary
132
+ entry: bash
133
+ language: system
134
+ args: ['-c', 'output=$(uv run pytest tests/ --cov=src/span_panel_api --cov-config=pyproject.toml --cov-fail-under=85 -q 2>&1); status=$?; echo "$output"; exit "$status"']
135
+ pass_filenames: false
136
+ verbose: true
@@ -0,0 +1,25 @@
1
+ {
2
+ "printWidth": 256,
3
+ "tabWidth": 2,
4
+ "useTabs": false,
5
+ "semi": true,
6
+ "singleQuote": false,
7
+ "quoteProps": "as-needed",
8
+ "jsxSingleQuote": false,
9
+ "trailingComma": "es5",
10
+ "bracketSpacing": true,
11
+ "bracketSameLine": false,
12
+ "arrowParens": "always",
13
+ "endOfLine": "lf",
14
+ "overrides": [
15
+ {
16
+ "files": "*.md",
17
+ "options": {
18
+ "printWidth": 256,
19
+ "proseWrap": "always",
20
+ "tabWidth": 2,
21
+ "useTabs": false
22
+ }
23
+ }
24
+ ]
25
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "recommendations": [
3
+ "ms-python.vscode-pylance"
4
+ ]
5
+ }