headerkit 0.4.0__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 (83) hide show
  1. headerkit-0.4.0/.github/dependabot.yml +25 -0
  2. headerkit-0.4.0/.github/workflows/check-llvm.yml +113 -0
  3. headerkit-0.4.0/.github/workflows/check-python.yml +161 -0
  4. headerkit-0.4.0/.github/workflows/ci.yml +27 -0
  5. headerkit-0.4.0/.github/workflows/docs.yml +67 -0
  6. headerkit-0.4.0/.github/workflows/release.yml +84 -0
  7. headerkit-0.4.0/.github/workflows/test-install-libclang.yml +52 -0
  8. headerkit-0.4.0/.github/workflows/test.yml +43 -0
  9. headerkit-0.4.0/.gitignore +73 -0
  10. headerkit-0.4.0/.pre-commit-config.yaml +29 -0
  11. headerkit-0.4.0/AGENTS.md +49 -0
  12. headerkit-0.4.0/CHANGELOG.md +109 -0
  13. headerkit-0.4.0/CLAUDE.md +5 -0
  14. headerkit-0.4.0/LICENSE +21 -0
  15. headerkit-0.4.0/PKG-INFO +121 -0
  16. headerkit-0.4.0/README.md +70 -0
  17. headerkit-0.4.0/docs/guides/architecture.md +275 -0
  18. headerkit-0.4.0/docs/guides/cffi.md +174 -0
  19. headerkit-0.4.0/docs/guides/custom-backends.md +229 -0
  20. headerkit-0.4.0/docs/guides/custom-writers.md +311 -0
  21. headerkit-0.4.0/docs/guides/install-libclang.md +93 -0
  22. headerkit-0.4.0/docs/guides/installation.md +94 -0
  23. headerkit-0.4.0/docs/guides/quickstart.md +151 -0
  24. headerkit-0.4.0/docs/index.md +88 -0
  25. headerkit-0.4.0/docs/reference/backends.md +47 -0
  26. headerkit-0.4.0/docs/reference/cffi.md +31 -0
  27. headerkit-0.4.0/docs/reference/index.md +48 -0
  28. headerkit-0.4.0/docs/reference/install-libclang.md +19 -0
  29. headerkit-0.4.0/docs/reference/ir.md +110 -0
  30. headerkit-0.4.0/docs/reference/json.md +20 -0
  31. headerkit-0.4.0/docs/reference/writers.md +49 -0
  32. headerkit-0.4.0/docs/tutorials/ctypes-writer.md +363 -0
  33. headerkit-0.4.0/docs/tutorials/header-cleanup.md +408 -0
  34. headerkit-0.4.0/docs/tutorials/json-export.md +294 -0
  35. headerkit-0.4.0/docs/tutorials/pxd-writer.md +319 -0
  36. headerkit-0.4.0/headerkit/__init__.py +74 -0
  37. headerkit-0.4.0/headerkit/_clang/LICENSE +278 -0
  38. headerkit-0.4.0/headerkit/_clang/__init__.py +137 -0
  39. headerkit-0.4.0/headerkit/_clang/_version.py +333 -0
  40. headerkit-0.4.0/headerkit/_clang/v18/PROVENANCE +5 -0
  41. headerkit-0.4.0/headerkit/_clang/v18/__init__.py +0 -0
  42. headerkit-0.4.0/headerkit/_clang/v18/cindex.py +3977 -0
  43. headerkit-0.4.0/headerkit/_clang/v18/enumerations.py +33 -0
  44. headerkit-0.4.0/headerkit/_clang/v19/PROVENANCE +5 -0
  45. headerkit-0.4.0/headerkit/_clang/v19/__init__.py +0 -0
  46. headerkit-0.4.0/headerkit/_clang/v19/cindex.py +4103 -0
  47. headerkit-0.4.0/headerkit/_clang/v20/PROVENANCE +5 -0
  48. headerkit-0.4.0/headerkit/_clang/v20/__init__.py +0 -0
  49. headerkit-0.4.0/headerkit/_clang/v20/cindex.py +4232 -0
  50. headerkit-0.4.0/headerkit/_clang/v21/PROVENANCE +5 -0
  51. headerkit-0.4.0/headerkit/_clang/v21/__init__.py +0 -0
  52. headerkit-0.4.0/headerkit/_clang/v21/cindex.py +4631 -0
  53. headerkit-0.4.0/headerkit/backends/__init__.py +228 -0
  54. headerkit-0.4.0/headerkit/backends/libclang.py +2061 -0
  55. headerkit-0.4.0/headerkit/install_libclang.py +204 -0
  56. headerkit-0.4.0/headerkit/ir.py +770 -0
  57. headerkit-0.4.0/headerkit/py.typed +0 -0
  58. headerkit-0.4.0/headerkit/writers/__init__.py +260 -0
  59. headerkit-0.4.0/headerkit/writers/cffi.py +529 -0
  60. headerkit-0.4.0/headerkit/writers/json.py +247 -0
  61. headerkit-0.4.0/mkdocs.yml +99 -0
  62. headerkit-0.4.0/pyproject.toml +77 -0
  63. headerkit-0.4.0/tests/__init__.py +0 -0
  64. headerkit-0.4.0/tests/test_backends/__init__.py +0 -0
  65. headerkit-0.4.0/tests/test_backends/test_libclang.py +882 -0
  66. headerkit-0.4.0/tests/test_backends/test_registry.py +172 -0
  67. headerkit-0.4.0/tests/test_clang/__init__.py +0 -0
  68. headerkit-0.4.0/tests/test_clang/test_loader.py +140 -0
  69. headerkit-0.4.0/tests/test_clang/test_pypy_compat.py +148 -0
  70. headerkit-0.4.0/tests/test_clang/test_version_detect.py +438 -0
  71. headerkit-0.4.0/tests/test_clang/test_windows_detection.py +267 -0
  72. headerkit-0.4.0/tests/test_install_libclang.py +204 -0
  73. headerkit-0.4.0/tests/test_integration/__init__.py +0 -0
  74. headerkit-0.4.0/tests/test_integration/conftest.py +225 -0
  75. headerkit-0.4.0/tests/test_integration/test_real_headers.py +322 -0
  76. headerkit-0.4.0/tests/test_integration/test_roundtrip.py +599 -0
  77. headerkit-0.4.0/tests/test_ir.py +359 -0
  78. headerkit-0.4.0/tests/test_public_api.py +100 -0
  79. headerkit-0.4.0/tests/test_writers/__init__.py +0 -0
  80. headerkit-0.4.0/tests/test_writers/test_cffi.py +314 -0
  81. headerkit-0.4.0/tests/test_writers/test_json.py +637 -0
  82. headerkit-0.4.0/tests/test_writers/test_registry.py +273 -0
  83. headerkit-0.4.0/uv.lock +1020 -0
@@ -0,0 +1,25 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "github-actions"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
7
+ labels:
8
+ - "dependencies"
9
+ groups:
10
+ minor-and-patch:
11
+ update-types:
12
+ - "minor"
13
+ - "patch"
14
+
15
+ - package-ecosystem: "pip"
16
+ directory: "/"
17
+ schedule:
18
+ interval: "weekly"
19
+ labels:
20
+ - "dependencies"
21
+ groups:
22
+ minor-and-patch:
23
+ update-types:
24
+ - "minor"
25
+ - "patch"
@@ -0,0 +1,113 @@
1
+ name: Check LLVM Releases
2
+
3
+ # Detect new stable LLVM major versions that aren't yet vendored in headerkit/_clang/
4
+ # and open an issue with vendoring instructions.
5
+
6
+ on:
7
+ schedule:
8
+ - cron: "0 10 * * 1" # Mondays at 10 AM UTC
9
+ workflow_dispatch:
10
+
11
+ permissions:
12
+ issues: write
13
+
14
+ jobs:
15
+ check:
16
+ runs-on: ubuntu-latest
17
+ timeout-minutes: 10
18
+ steps:
19
+ - uses: actions/checkout@v6
20
+
21
+ - name: Detect new LLVM versions
22
+ id: detect
23
+ run: |
24
+ # Fetch all LLVM tags once and cache for reuse
25
+ all_tags=$(
26
+ git -c 'versionsort.suffix=-' \
27
+ ls-remote --exit-code --refs --sort='version:refname' --tags \
28
+ https://github.com/llvm/llvm-project 'llvmorg-*.*.*' \
29
+ | sed 's/.*llvmorg-//' \
30
+ | grep -v '-'
31
+ )
32
+
33
+ # Get all stable LLVM major versions with releases (>= 18)
34
+ released_majors=$(
35
+ echo "$all_tags" \
36
+ | awk -F. '$1 >= 18 { print $1 }' \
37
+ | sort -un
38
+ )
39
+
40
+ # Get vendored major versions
41
+ vendored_majors=$(
42
+ ls -d headerkit/_clang/v*/ 2>/dev/null \
43
+ | sed 's|headerkit/_clang/v||; s|/||' \
44
+ | sort -n
45
+ )
46
+
47
+ echo "Released LLVM majors: $released_majors"
48
+ echo "Vendored majors: $vendored_majors"
49
+
50
+ # Find missing versions
51
+ missing=""
52
+ for major in $released_majors; do
53
+ if ! echo "$vendored_majors" | grep -qx "$major"; then
54
+ missing="$missing $major"
55
+ fi
56
+ done
57
+ missing=$(echo "$missing" | xargs)
58
+
59
+ echo "Missing: ${missing:-none}"
60
+ echo "missing=$missing" >> "$GITHUB_OUTPUT"
61
+
62
+ # Save tag list for reuse in the next step
63
+ {
64
+ echo "all_tags<<TAGS_EOF"
65
+ echo "$all_tags"
66
+ echo "TAGS_EOF"
67
+ } >> "$GITHUB_OUTPUT"
68
+
69
+ - name: Open issues for missing versions
70
+ if: steps.detect.outputs.missing != ''
71
+ env:
72
+ GH_TOKEN: ${{ github.token }}
73
+ MISSING: ${{ steps.detect.outputs.missing }}
74
+ ALL_TAGS: ${{ steps.detect.outputs.all_tags }}
75
+ run: |
76
+ for major in $MISSING; do
77
+ title="Vendor clang Python bindings for LLVM $major"
78
+
79
+ # Skip if issue already exists (open or closed)
80
+ existing=$(gh issue list --search "\"$title\" in:title" --state all --json number --jq 'length')
81
+ if [ "$existing" -gt 0 ]; then
82
+ echo "Issue already exists for LLVM $major, skipping"
83
+ continue
84
+ fi
85
+
86
+ # Get latest patch version for this major from cached tags
87
+ latest=$(
88
+ echo "$ALL_TAGS" \
89
+ | grep "^${major}\." \
90
+ | sort -t. -k1,1n -k2,2n -k3,3n \
91
+ | tail -1
92
+ )
93
+
94
+ body="A new LLVM major version ($major) has stable releases (latest: $latest) but no vendored bindings in \`headerkit/_clang/\`.
95
+
96
+ ## Steps to vendor
97
+
98
+ 1. Download the clang Python bindings from the LLVM $latest source:
99
+ \`\`\`
100
+ https://github.com/llvm/llvm-project/tree/llvmorg-$latest/clang/bindings/python/clang
101
+ \`\`\`
102
+ 2. Create \`headerkit/_clang/v$major/\` with:
103
+ - \`__init__.py\`
104
+ - \`cindex.py\` (from the LLVM source)
105
+ - \`PROVENANCE\` (source URL, SHA256, license)
106
+ 3. Update \`headerkit/_clang/__init__.py\` if the loader needs changes for the new version.
107
+ 4. Add tests and verify with \`pytest\`.
108
+
109
+ *This issue was automatically created by the check-llvm workflow.*"
110
+
111
+ gh issue create --title "$title" --body "$body"
112
+ echo "Created issue for LLVM $major"
113
+ done
@@ -0,0 +1,161 @@
1
+ # Check for Python version support updates
2
+ #
3
+ # Runs weekly to detect:
4
+ # - New stable Python releases that should be added to the test matrix
5
+ # - Python versions reaching end-of-life that should be dropped
6
+ #
7
+ # Creates GitHub issues when action is needed.
8
+ #
9
+ # Manual trigger:
10
+ # Go to Actions -> Check Python Versions -> Run workflow
11
+
12
+ name: Check Python Versions
13
+
14
+ on:
15
+ workflow_dispatch:
16
+ schedule:
17
+ - cron: '0 10 * * 1' # Weekly on Monday
18
+
19
+ jobs:
20
+ check:
21
+ runs-on: ubuntu-latest
22
+ permissions:
23
+ issues: write
24
+
25
+ steps:
26
+ - uses: actions/checkout@v6
27
+
28
+ - name: Setup python
29
+ uses: actions/setup-python@v6
30
+ with:
31
+ python-version: '3.13'
32
+
33
+ - name: Check Python versions
34
+ id: check
35
+ env:
36
+ GH_TOKEN: ${{ github.token }}
37
+ run: |
38
+ # Extract supported versions from pyproject.toml
39
+ supported=$(grep 'Programming Language :: Python :: 3\.' pyproject.toml \
40
+ | sed 's/.*Python :: //' | sed 's/".*//' | tr '\n' ' ')
41
+ min_python=$(grep 'requires-python' pyproject.toml \
42
+ | sed 's/.*>=\([0-9.]*\).*/\1/')
43
+ echo "supported=$supported" >> $GITHUB_OUTPUT
44
+ echo "min_python=$min_python" >> $GITHUB_OUTPUT
45
+ echo "Currently supported: $supported"
46
+ echo "Minimum Python: $min_python"
47
+
48
+ # Fetch Python release cycle data from endoflife.date API
49
+ curl -s https://endoflife.date/api/python.json > /tmp/python_versions.json
50
+
51
+ # Find stable versions we DON'T support yet
52
+ python3 -c "
53
+ import json, sys
54
+ with open('/tmp/python_versions.json') as f:
55
+ versions = json.load(f)
56
+ supported = '$supported'.split()
57
+ for v in versions:
58
+ cycle = v['cycle']
59
+ # Only consider 3.x versions
60
+ if not cycle.startswith('3.'):
61
+ continue
62
+ minor = int(cycle.split('.')[1])
63
+ # Only consider versions >= our minimum
64
+ min_minor = int('$min_python'.split('.')[1])
65
+ if minor < min_minor:
66
+ continue
67
+ # Check if this is a stable release (not pre-release)
68
+ if v.get('lts', False) or v.get('latest', ''):
69
+ if cycle not in supported:
70
+ print(f'NEW:{cycle}')
71
+ # Check for EOL versions we still support
72
+ eol = v.get('eol', '')
73
+ if eol and eol != 'false' and eol <= '$(date +%Y-%m-%d)':
74
+ if cycle in supported:
75
+ print(f'EOL:{cycle}:{eol}')
76
+ " > /tmp/version_actions.txt
77
+
78
+ cat /tmp/version_actions.txt
79
+
80
+ new=$(grep '^NEW:' /tmp/version_actions.txt | sed 's/NEW://' | tr '\n' ' ' || true)
81
+ eol=$(grep '^EOL:' /tmp/version_actions.txt || true)
82
+
83
+ echo "new_versions=$new" >> $GITHUB_OUTPUT
84
+ echo "eol_versions=$eol" >> $GITHUB_OUTPUT
85
+
86
+ - name: Create issue for new Python versions
87
+ if: steps.check.outputs.new_versions != ''
88
+ env:
89
+ GH_TOKEN: ${{ github.token }}
90
+ NEW_VERSIONS: ${{ steps.check.outputs.new_versions }}
91
+ SUPPORTED: ${{ steps.check.outputs.supported }}
92
+ run: |
93
+ for version in $NEW_VERSIONS; do
94
+ title="Add Python $version to test matrix"
95
+
96
+ # Check if issue already exists
97
+ existing=$(gh issue list --state open --search "$title" --json number,title \
98
+ --jq ".[] | select(.title == \"$title\") | .number")
99
+ if [ -n "$existing" ]; then
100
+ echo "Issue #$existing already open for Python $version, skipping"
101
+ continue
102
+ fi
103
+
104
+ run_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
105
+
106
+ body=$(cat <<EOF
107
+ Python $version is now available as a stable release but is not in our test matrix.
108
+
109
+ ## Currently Supported
110
+ $SUPPORTED
111
+
112
+ ## Action Required
113
+ 1. Add \`"Programming Language :: Python :: $version"\` to \`pyproject.toml\` classifiers
114
+ 2. Add \`"$version"\` to the matrix in \`.github/workflows/test.yml\`
115
+ 3. Verify all tests pass on Python $version
116
+
117
+ **Workflow run:** $run_url
118
+ EOF
119
+ )
120
+
121
+ gh issue create --title "$title" --body "$body" --label "dependencies"
122
+ done
123
+
124
+ - name: Create issue for EOL Python versions
125
+ if: steps.check.outputs.eol_versions != ''
126
+ env:
127
+ GH_TOKEN: ${{ github.token }}
128
+ EOL_VERSIONS: ${{ steps.check.outputs.eol_versions }}
129
+ SUPPORTED: ${{ steps.check.outputs.supported }}
130
+ run: |
131
+ echo "$EOL_VERSIONS" | grep '^EOL:' | while IFS=: read -r _ version eol_date; do
132
+ title="Drop Python $version (EOL $eol_date)"
133
+
134
+ # Check if issue already exists
135
+ existing=$(gh issue list --state open --search "$title" --json number,title \
136
+ --jq ".[] | select(.title == \"$title\") | .number")
137
+ if [ -n "$existing" ]; then
138
+ echo "Issue #$existing already open for Python $version EOL, skipping"
139
+ continue
140
+ fi
141
+
142
+ run_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
143
+
144
+ body=$(cat <<EOF
145
+ Python $version reached end-of-life on $eol_date and no longer receives security patches.
146
+
147
+ ## Currently Supported
148
+ $SUPPORTED
149
+
150
+ ## Action Required
151
+ 1. Remove \`"Programming Language :: Python :: $version"\` from \`pyproject.toml\` classifiers
152
+ 2. Remove \`"$version"\` from the matrix in \`.github/workflows/test.yml\`
153
+ 3. Update \`requires-python\` in \`pyproject.toml\` if this was the minimum version
154
+ 4. Remove any version-specific workarounds for Python $version
155
+
156
+ **Workflow run:** $run_url
157
+ EOF
158
+ )
159
+
160
+ gh issue create --title "$title" --body "$body" --label "dependencies"
161
+ done
@@ -0,0 +1,27 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ concurrency:
10
+ group: ${{ github.workflow }}-${{ github.ref }}
11
+ cancel-in-progress: true
12
+
13
+ jobs:
14
+ lint:
15
+ runs-on: ubuntu-latest
16
+ timeout-minutes: 10
17
+ steps:
18
+ - uses: actions/checkout@v6
19
+ - uses: actions/setup-python@v6
20
+ with:
21
+ python-version: "3.12"
22
+ cache: 'pip'
23
+ - run: pip install -e '.[lint]'
24
+ - uses: pre-commit/action@v3.0.1
25
+
26
+ test:
27
+ uses: ./.github/workflows/test.yml
@@ -0,0 +1,67 @@
1
+ name: Documentation
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+ workflow_dispatch:
8
+ inputs:
9
+ version:
10
+ description: 'Version to deploy (e.g., 0.3)'
11
+ required: true
12
+ set_latest:
13
+ description: 'Set as latest?'
14
+ type: boolean
15
+ default: true
16
+
17
+ permissions:
18
+ contents: write
19
+
20
+ jobs:
21
+ deploy:
22
+ runs-on: ubuntu-latest
23
+ timeout-minutes: 10
24
+ steps:
25
+ - uses: actions/checkout@v4
26
+ with:
27
+ fetch-depth: 0
28
+
29
+ - uses: actions/setup-python@v6
30
+ with:
31
+ python-version: '3.12'
32
+ cache: 'pip'
33
+
34
+ - name: Install dependencies
35
+ run: pip install -e '.[docs]'
36
+
37
+ - name: Configure Git
38
+ run: |
39
+ git config user.name "github-actions[bot]"
40
+ git config user.email "github-actions[bot]@users.noreply.github.com"
41
+
42
+ - name: Extract version from tag
43
+ if: github.event_name == 'push'
44
+ id: version
45
+ run: |
46
+ TAG="${GITHUB_REF#refs/tags/v}"
47
+ MINOR="${TAG%.*}"
48
+ echo "version=$MINOR" >> "$GITHUB_OUTPUT"
49
+ echo "Deploying docs for version: $MINOR"
50
+
51
+ - name: Deploy versioned docs (tag push)
52
+ if: github.event_name == 'push'
53
+ run: |
54
+ mike deploy --push --update-aliases "${{ steps.version.outputs.version }}" latest
55
+
56
+ - name: Deploy versioned docs (manual)
57
+ if: github.event_name == 'workflow_dispatch'
58
+ run: |
59
+ if [ "${{ inputs.set_latest }}" = "true" ]; then
60
+ mike deploy --push --update-aliases "${{ inputs.version }}" latest
61
+ else
62
+ mike deploy --push "${{ inputs.version }}"
63
+ fi
64
+
65
+ - name: Set default version
66
+ if: github.event_name == 'push'
67
+ run: mike set-default --push latest
@@ -0,0 +1,84 @@
1
+ name: Release
2
+
3
+ # Publish to PyPI when a version tag is pushed.
4
+ #
5
+ # Prerequisites (one-time setup):
6
+ # 1. Go to https://pypi.org/manage/account/publishing/
7
+ # 2. Add a pending publisher:
8
+ # - Owner: axiomantic
9
+ # - Repository: headerkit
10
+ # - Workflow: release.yml
11
+ # - Environment: pypi
12
+
13
+ on:
14
+ push:
15
+ tags: ["v*"]
16
+
17
+ permissions: {}
18
+
19
+ jobs:
20
+ test:
21
+ uses: ./.github/workflows/test.yml
22
+
23
+ build:
24
+ needs: test
25
+ runs-on: ubuntu-latest
26
+ timeout-minutes: 10
27
+ steps:
28
+ - uses: actions/checkout@v6
29
+ - uses: actions/setup-python@v6
30
+ with:
31
+ python-version: "3.12"
32
+ cache: 'pip'
33
+ - run: pip install build
34
+ - run: python -m build
35
+ - name: Verify version matches tag
36
+ run: |
37
+ TAG="${{ github.ref_name }}"
38
+ EXPECTED="${TAG#v}"
39
+ VERSION=$(python -c "
40
+ import tomllib
41
+ with open('pyproject.toml', 'rb') as f:
42
+ print(tomllib.load(f)['project']['version'])
43
+ ")
44
+ if [ "$VERSION" != "$EXPECTED" ]; then
45
+ echo "::error::Version mismatch: tag=$EXPECTED, pyproject.toml=$VERSION"
46
+ exit 1
47
+ fi
48
+ - uses: actions/upload-artifact@v7
49
+ with:
50
+ name: dist
51
+ path: dist/
52
+ retention-days: 5
53
+
54
+ publish:
55
+ needs: build
56
+ runs-on: ubuntu-latest
57
+ timeout-minutes: 10
58
+ environment: pypi
59
+ permissions:
60
+ id-token: write
61
+ steps:
62
+ - uses: actions/download-artifact@v8
63
+ with:
64
+ name: dist
65
+ path: dist/
66
+ - uses: pypa/gh-action-pypi-publish@release/v1
67
+
68
+ github-release:
69
+ needs: [build, publish]
70
+ runs-on: ubuntu-latest
71
+ timeout-minutes: 10
72
+ permissions:
73
+ contents: write
74
+ steps:
75
+ - uses: actions/download-artifact@v8
76
+ with:
77
+ name: dist
78
+ path: dist/
79
+ - name: Create GitHub Release
80
+ env:
81
+ GH_TOKEN: ${{ github.token }}
82
+ TAG: ${{ github.ref_name }}
83
+ REPO: ${{ github.repository }}
84
+ run: gh release create "$TAG" dist/* --repo "$REPO" --generate-notes
@@ -0,0 +1,52 @@
1
+ name: Test install_libclang
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ concurrency:
10
+ group: ${{ github.workflow }}-${{ github.ref }}
11
+ cancel-in-progress: true
12
+
13
+ jobs:
14
+ install-libclang:
15
+ runs-on: ${{ matrix.os }}
16
+ timeout-minutes: 15
17
+ strategy:
18
+ fail-fast: false
19
+ matrix:
20
+ os: [ubuntu-latest, macos-latest, windows-latest]
21
+ steps:
22
+ - uses: actions/checkout@v6
23
+ - uses: actions/setup-python@v6
24
+ with:
25
+ python-version: "3.10"
26
+ cache: 'pip'
27
+
28
+ - name: Install package
29
+ shell: bash
30
+ run: pip install -e .
31
+
32
+ - name: Run install_libclang
33
+ shell: bash
34
+ run: |
35
+ if [ "$RUNNER_OS" = "Linux" ]; then
36
+ sudo python -m headerkit.install_libclang --skip-verify
37
+ else
38
+ python -m headerkit.install_libclang --skip-verify
39
+ fi
40
+
41
+ - name: Refresh PATH (Windows)
42
+ if: runner.os == 'Windows'
43
+ shell: pwsh
44
+ run: |
45
+ $machinePath = [Environment]::GetEnvironmentVariable("Path", "Machine")
46
+ $userPath = [Environment]::GetEnvironmentVariable("Path", "User")
47
+ $env:Path = "$machinePath;$userPath"
48
+ echo "Path=$env:Path" >> $env:GITHUB_ENV
49
+
50
+ - name: Verify libclang is usable
51
+ shell: bash
52
+ run: python -c "from headerkit.backends.libclang import is_system_libclang_available; assert is_system_libclang_available(), 'libclang not available after install'"
@@ -0,0 +1,43 @@
1
+ name: Tests
2
+
3
+ on:
4
+ workflow_call:
5
+
6
+ jobs:
7
+ test:
8
+ runs-on: ${{ matrix.os }}
9
+ timeout-minutes: 20
10
+ strategy:
11
+ fail-fast: false
12
+ matrix:
13
+ python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
14
+ os: [ubuntu-latest, macos-latest, windows-latest]
15
+ steps:
16
+ - uses: actions/checkout@v6
17
+ - uses: actions/setup-python@v6
18
+ with:
19
+ python-version: ${{ matrix.python-version }}
20
+ cache: 'pip'
21
+ - name: Install libclang (Ubuntu)
22
+ if: runner.os == 'Linux'
23
+ run: sudo apt-get update && sudo apt-get install -y libclang-dev
24
+ - name: Install libclang (macOS)
25
+ if: runner.os == 'macOS'
26
+ run: brew install llvm
27
+ - name: Verify LLVM (Windows)
28
+ if: runner.os == 'Windows'
29
+ shell: bash
30
+ run: |
31
+ clang --version
32
+ which clang || true
33
+ - name: Install package
34
+ shell: bash
35
+ run: pip install -e '.[test]'
36
+ - name: Cache test header downloads
37
+ uses: actions/cache@v4
38
+ with:
39
+ path: ~/.cache/headerkit-test-headers
40
+ key: test-headers-v1
41
+ - name: Run tests
42
+ shell: bash
43
+ run: pytest
@@ -0,0 +1,73 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ *.egg-info/
24
+ *.egg
25
+ MANIFEST
26
+
27
+ # Installer logs
28
+ pip-log.txt
29
+ pip-delete-this-directory.txt
30
+
31
+ # Unit test / coverage
32
+ htmlcov/
33
+ .tox/
34
+ .nox/
35
+ .coverage
36
+ .coverage.*
37
+ .cache
38
+ nosetests.xml
39
+ coverage.xml
40
+ *.cover
41
+ *.py,cover
42
+ .hypothesis/
43
+ .pytest_cache/
44
+
45
+ # Environments
46
+ .env
47
+ .venv/
48
+ env/
49
+ venv/
50
+ ENV/
51
+
52
+ # IDE
53
+ .vscode/
54
+ .idea/
55
+ *.swp
56
+ *.swo
57
+ *~
58
+
59
+ # mypy
60
+ .mypy_cache/
61
+
62
+ # ruff
63
+ .ruff_cache/
64
+
65
+ # OS
66
+ .DS_Store
67
+ Thumbs.db
68
+
69
+ # Project
70
+ logs/
71
+
72
+ # MkDocs
73
+ site/
@@ -0,0 +1,29 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v5.0.0
4
+ hooks:
5
+ - id: trailing-whitespace
6
+ - id: end-of-file-fixer
7
+ - id: check-yaml
8
+ args: [--unsafe]
9
+ - id: check-toml
10
+ - id: check-merge-conflict
11
+ - id: check-added-large-files
12
+ args: [--maxkb=500]
13
+ - id: debug-statements
14
+
15
+ - repo: https://github.com/astral-sh/ruff-pre-commit
16
+ rev: v0.9.10
17
+ hooks:
18
+ - id: ruff
19
+ args: [--fix]
20
+ - id: ruff-format
21
+
22
+ - repo: https://github.com/pre-commit/mirrors-mypy
23
+ rev: v1.15.0
24
+ hooks:
25
+ - id: mypy
26
+ args: [--strict]
27
+ additional_dependencies: []
28
+ pass_filenames: false
29
+ entry: mypy headerkit/