endstone-papi 0.1.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 (105) hide show
  1. endstone_papi-0.1.0/.clang-format +43 -0
  2. endstone_papi-0.1.0/.clang-tidy +82 -0
  3. endstone_papi-0.1.0/.conan2/.gitignore +7 -0
  4. endstone_papi-0.1.0/.conan2/profiles/default +27 -0
  5. endstone_papi-0.1.0/.conan2/remotes.json +9 -0
  6. endstone_papi-0.1.0/.conanrc +1 -0
  7. endstone_papi-0.1.0/.github/workflows/build.yml +411 -0
  8. endstone_papi-0.1.0/.github/workflows/release.yml +540 -0
  9. endstone_papi-0.1.0/.gitignore +24 -0
  10. endstone_papi-0.1.0/CHANGELOG.md +55 -0
  11. endstone_papi-0.1.0/CLAUDE.md +519 -0
  12. endstone_papi-0.1.0/CMakeLists.txt +128 -0
  13. endstone_papi-0.1.0/CMakePresets.json +37 -0
  14. endstone_papi-0.1.0/LICENSE +21 -0
  15. endstone_papi-0.1.0/PKG-INFO +221 -0
  16. endstone_papi-0.1.0/README.md +194 -0
  17. endstone_papi-0.1.0/assets/screenshot.jpg +0 -0
  18. endstone_papi-0.1.0/cmake/toolchain_provenance.txt.in +4 -0
  19. endstone_papi-0.1.0/cmake/version.h.in +22 -0
  20. endstone_papi-0.1.0/conanfile.py +75 -0
  21. endstone_papi-0.1.0/endstone_papi/__init__.py +47 -0
  22. endstone_papi-0.1.0/endstone_papi/_native_loader.py +185 -0
  23. endstone_papi-0.1.0/endstone_papi/_papi.pyi +215 -0
  24. endstone_papi-0.1.0/endstone_papi/plugin.py +147 -0
  25. endstone_papi-0.1.0/examples/cpp/CMakeLists.txt +12 -0
  26. endstone_papi-0.1.0/examples/cpp/plugin.cpp +86 -0
  27. endstone_papi-0.1.0/examples/python/endstone_papi_pyexample/__init__.py +3 -0
  28. endstone_papi-0.1.0/examples/python/endstone_papi_pyexample/plugin.py +50 -0
  29. endstone_papi-0.1.0/examples/python/pyproject.toml +15 -0
  30. endstone_papi-0.1.0/include/endstone_papi/events.h +71 -0
  31. endstone_papi-0.1.0/include/endstone_papi/expansion_info.h +54 -0
  32. endstone_papi-0.1.0/include/endstone_papi/papi.h +8 -0
  33. endstone_papi-0.1.0/include/endstone_papi/placeholder_api.h +177 -0
  34. endstone_papi-0.1.0/include/endstone_papi/placeholder_expansion.h +168 -0
  35. endstone_papi-0.1.0/include/endstone_papi/unregister_reason.h +52 -0
  36. endstone_papi-0.1.0/papi_build_backend.py +78 -0
  37. endstone_papi-0.1.0/pyproject.toml +107 -0
  38. endstone_papi-0.1.0/src/CMakeLists.txt +33 -0
  39. endstone_papi-0.1.0/src/core/diagnostics/error_throttle.cpp +62 -0
  40. endstone_papi-0.1.0/src/core/diagnostics/error_throttle.h +154 -0
  41. endstone_papi-0.1.0/src/core/parser/bracket_replacer.cpp +61 -0
  42. endstone_papi-0.1.0/src/core/parser/bracket_replacer.h +45 -0
  43. endstone_papi-0.1.0/src/core/parser/identifier.cpp +53 -0
  44. endstone_papi-0.1.0/src/core/parser/identifier.h +23 -0
  45. endstone_papi-0.1.0/src/core/platform.h +29 -0
  46. endstone_papi-0.1.0/src/core/registry/expansion_manager.cpp +522 -0
  47. endstone_papi-0.1.0/src/core/registry/expansion_manager.h +339 -0
  48. endstone_papi-0.1.0/src/core/service/placeholder_api_impl.cpp +590 -0
  49. endstone_papi-0.1.0/src/core/service/placeholder_api_impl.h +86 -0
  50. endstone_papi-0.1.0/src/platform/endstone/bootstrap.cpp +86 -0
  51. endstone_papi-0.1.0/src/platform/endstone/bootstrap.h +62 -0
  52. endstone_papi-0.1.0/src/platform/endstone/server_platform.cpp +55 -0
  53. endstone_papi-0.1.0/src/platform/endstone/server_platform.h +38 -0
  54. endstone_papi-0.1.0/src/platform/endstone/service_publication.cpp +74 -0
  55. endstone_papi-0.1.0/src/platform/endstone/service_publication.h +26 -0
  56. endstone_papi-0.1.0/src/python/expansion_trampoline.cpp +296 -0
  57. endstone_papi-0.1.0/src/python/expansion_trampoline.h +51 -0
  58. endstone_papi-0.1.0/src/python/gil_safe_proxy.cpp +239 -0
  59. endstone_papi-0.1.0/src/python/gil_safe_proxy.h +86 -0
  60. endstone_papi-0.1.0/src/python/module.cpp +293 -0
  61. endstone_papi-0.1.0/tests/CMakeLists.txt +111 -0
  62. endstone_papi-0.1.0/tests/cpp/consumer_compile.cpp +81 -0
  63. endstone_papi-0.1.0/tests/cpp/fake_player.h +167 -0
  64. endstone_papi-0.1.0/tests/cpp/fakes.h +326 -0
  65. endstone_papi-0.1.0/tests/cpp/test_bracket_replacer.cpp +363 -0
  66. endstone_papi-0.1.0/tests/cpp/test_dot_syntax.cpp +101 -0
  67. endstone_papi-0.1.0/tests/cpp/test_error_throttle.cpp +165 -0
  68. endstone_papi-0.1.0/tests/cpp/test_events.cpp +221 -0
  69. endstone_papi-0.1.0/tests/cpp/test_expansion_manager.cpp +630 -0
  70. endstone_papi-0.1.0/tests/cpp/test_identifier.cpp +92 -0
  71. endstone_papi-0.1.0/tests/cpp/test_lifecycle.cpp +380 -0
  72. endstone_papi-0.1.0/tests/cpp/test_provider_dso.cpp +190 -0
  73. endstone_papi-0.1.0/tests/cpp/test_provider_shared_ptr_dso.cpp +151 -0
  74. endstone_papi-0.1.0/tests/cpp/test_public_api.cpp +168 -0
  75. endstone_papi-0.1.0/tests/cpp/test_relational.cpp +278 -0
  76. endstone_papi-0.1.0/tests/cpp/test_service.cpp +604 -0
  77. endstone_papi-0.1.0/tests/cpp/test_service_publication.cpp +183 -0
  78. endstone_papi-0.1.0/tests/cpp/test_version.cpp +10 -0
  79. endstone_papi-0.1.0/tests/fixtures/provider/provider_demo.cpp +73 -0
  80. endstone_papi-0.1.0/tests/fixtures/provider_shared/provider_shared_demo.cpp +62 -0
  81. endstone_papi-0.1.0/tests/python/conftest.py +47 -0
  82. endstone_papi-0.1.0/tests/python/test_commands.py +217 -0
  83. endstone_papi-0.1.0/tests/python/test_compatibility.py +113 -0
  84. endstone_papi-0.1.0/tests/python/test_dot_syntax.py +91 -0
  85. endstone_papi-0.1.0/tests/python/test_import.py +74 -0
  86. endstone_papi-0.1.0/tests/python/test_interop.py +415 -0
  87. endstone_papi-0.1.0/tests/python/test_module_lifetime.py +84 -0
  88. endstone_papi-0.1.0/tests/python/test_native_loader.py +250 -0
  89. endstone_papi-0.1.0/tests/python/test_parse_reentrancy.py +316 -0
  90. endstone_papi-0.1.0/tests/python/test_plugin_lifecycle.py +74 -0
  91. endstone_papi-0.1.0/tests/python/test_proxy_ownership.py +153 -0
  92. endstone_papi-0.1.0/tests/python/test_runtime_ownership.py +136 -0
  93. endstone_papi-0.1.0/tests/python/test_service_interop.py +360 -0
  94. endstone_papi-0.1.0/tests/python/test_trampoline_recursion.py +384 -0
  95. endstone_papi-0.1.0/tests/test_architecture_boundaries.py +409 -0
  96. endstone_papi-0.1.0/tools/build_linux_runtime.py +68 -0
  97. endstone_papi-0.1.0/tools/release_changelog.py +166 -0
  98. endstone_papi-0.1.0/tools/repair_wheel.py +199 -0
  99. endstone_papi-0.1.0/tools/run_clang_tidy.py +79 -0
  100. endstone_papi-0.1.0/tools/test_release_changelog.py +169 -0
  101. endstone_papi-0.1.0/tools/test_release_transaction.py +135 -0
  102. endstone_papi-0.1.0/tools/test_sdist_policy.py +178 -0
  103. endstone_papi-0.1.0/tools/test_toolchain_policy.py +360 -0
  104. endstone_papi-0.1.0/tools/verify_linux_wheel.py +225 -0
  105. endstone_papi-0.1.0/tools/wheel_smoke_test.py +105 -0
@@ -0,0 +1,43 @@
1
+ BasedOnStyle: Microsoft
2
+ AccessModifierOffset: -4
3
+ AlignConsecutiveMacros: Consecutive
4
+ AlignEscapedNewlines: Left
5
+ AlignOperands: AlignAfterOperator
6
+ AllowShortFunctionsOnASingleLine: Inline
7
+ AllowShortLambdasOnASingleLine: Inline
8
+ AlwaysBreakTemplateDeclarations: Yes
9
+ BreakBeforeBraces: Stroustrup
10
+ IncludeBlocks: Regroup
11
+ IncludeCategories:
12
+ - Regex: '^<[a-zA-Z0-9_]+\.h>' # C system headers
13
+ Priority: 1
14
+ SortPriority: 0
15
+ CaseSensitive: false
16
+ - Regex: '^<[^/]*>' # C++ standard library headers
17
+ Priority: 2
18
+ SortPriority: 0
19
+ CaseSensitive: false
20
+ - Regex: '^<endstone/' # Endstone API headers
21
+ Priority: 3
22
+ SortPriority: 0
23
+ CaseSensitive: false
24
+ - Regex: '^<pybind11/' # pybind11 headers
25
+ Priority: 3
26
+ SortPriority: 0
27
+ CaseSensitive: false
28
+ - Regex: '^<.*>' # Other libraries' .h files
29
+ Priority: 4
30
+ SortPriority: 0
31
+ CaseSensitive: false
32
+ - Regex: '^"endstone_papi/' # PAPI public headers
33
+ Priority: 5
34
+ SortPriority: 0
35
+ CaseSensitive: false
36
+ - Regex: '.*' # PAPI internal headers
37
+ Priority: 6
38
+ SortPriority: 0
39
+ CaseSensitive: false
40
+ InsertBraces: true
41
+ InsertNewlineAtEOF: true
42
+ MaxEmptyLinesToKeep: 1
43
+ SpacesBeforeTrailingComments: 2
@@ -0,0 +1,82 @@
1
+ ---
2
+ Checks: >
3
+ -*,
4
+ bugprone-*,
5
+ google-*,
6
+ misc-*,
7
+ modernize-*,
8
+ performance-*,
9
+ portability-*,
10
+ readability-*,
11
+ -misc-unused-using-decls,
12
+ -performance-unnecessary-value-param,
13
+ -misc-const-correctness,
14
+ -misc-non-private-member-variables-in-classes,
15
+ -misc-include-cleaner,
16
+ -modernize-use-trailing-return-type,
17
+ -modernize-avoid-c-arrays,
18
+ -modernize-use-designated-initializers,
19
+ -performance-enum-size,
20
+ -readability-identifier-length,
21
+ -readability-isolate-declaration,
22
+ -readability-function-cognitive-complexity,
23
+ -readability-magic-numbers,
24
+ -readability-math-missing-parentheses,
25
+ -readability-named-parameter,
26
+ -readability-simplify-boolean-expr,
27
+ -readability-use-anyofallof
28
+
29
+ WarningsAsErrors: "*"
30
+ HeaderFilterRegex: "(include/|src/).*"
31
+
32
+ CheckOptions:
33
+ misc-unused-parameters.IgnoreVirtual: true
34
+ modernize-type-traits.IgnoreMacros: true
35
+ readability-implicit-bool-conversion.AllowPointerConditions: true
36
+ readability-implicit-bool-conversion.AllowIntegerConditions: true
37
+ readability-identifier-naming.AbstractClassCase: CamelCase
38
+ readability-identifier-naming.ClassCase: CamelCase
39
+ readability-identifier-naming.ClassConstantCase: CamelCase
40
+ readability-identifier-naming.ClassMemberCase: lower_case
41
+ readability-identifier-naming.ClassMethodCase: camelBack
42
+ readability-identifier-naming.ConstantMemberCase: lower_case
43
+ readability-identifier-naming.ConstantParameterCase: lower_case
44
+ readability-identifier-naming.ConstantPointerParameterCase: lower_case
45
+ readability-identifier-naming.EnumCase: CamelCase
46
+ readability-identifier-naming.EnumConstantCase: CamelCase
47
+ readability-identifier-naming.FunctionCase: camelBack
48
+ readability-identifier-naming.GlobalConstantCase: CamelCase
49
+ readability-identifier-naming.GlobalVariableCase: lower_case
50
+ readability-identifier-naming.InlineNamespaceCase: aNy_CasE
51
+ readability-identifier-naming.LocalConstantCase: lower_case
52
+ readability-identifier-naming.LocalConstantPointerCase: lower_case
53
+ readability-identifier-naming.LocalPointerCase: lower_case
54
+ readability-identifier-naming.LocalVariableCase: lower_case
55
+ readability-identifier-naming.MacroDefinitionCase: UPPER_CASE
56
+ readability-identifier-naming.MemberCase: lower_case
57
+ readability-identifier-naming.MemberSuffix: '_'
58
+ readability-identifier-naming.MethodCase: camelBack
59
+ readability-identifier-naming.NamespaceCase: aNy_CasE
60
+ readability-identifier-naming.ParameterCase: lower_case
61
+ readability-identifier-naming.ParameterPackCase: lower_case
62
+ readability-identifier-naming.PointerParameterCase: lower_case
63
+ readability-identifier-naming.PrivateMemberCase: lower_case
64
+ readability-identifier-naming.PrivateMemberSuffix: '_'
65
+ readability-identifier-naming.PrivateMethodCase: camelBack
66
+ readability-identifier-naming.ProtectedMemberCase: lower_case
67
+ readability-identifier-naming.ProtectedMemberSuffix: '_'
68
+ readability-identifier-naming.ProtectedMethodCase: camelBack
69
+ readability-identifier-naming.PublicMemberCase: lower_case
70
+ readability-identifier-naming.PublicMethodCase: camelBack
71
+ readability-identifier-naming.StaticConstantCase: UPPER_CASE
72
+ readability-identifier-naming.StaticVariableCase: lower_case
73
+ readability-identifier-naming.StructCase: CamelCase
74
+ readability-identifier-naming.TemplateParameterCase: CamelCase
75
+ readability-identifier-naming.TemplateTemplateParameterCase: CamelCase
76
+ readability-identifier-naming.TypeAliasCase: CamelCase
77
+ readability-identifier-naming.TypedefCase: CamelCase
78
+ readability-identifier-naming.TypeTemplateParameterCase: CamelCase
79
+ readability-identifier-naming.UnionCase: CamelCase
80
+ readability-identifier-naming.ValueTemplateParameterCase: CamelCase
81
+ readability-identifier-naming.VariableCase: lower_case
82
+ readability-identifier-naming.VirtualMethodCase: camelBack
@@ -0,0 +1,7 @@
1
+ extensions/plugins/*
2
+ migrations/*
3
+ p/*
4
+ *.db
5
+ global.conf
6
+ settings.yml
7
+ version.txt
@@ -0,0 +1,27 @@
1
+ [settings]
2
+ os={{ detect_api.detect_os() }}
3
+ arch={{ detect_api.detect_arch() }}
4
+ build_type=Release
5
+ &:build_type=RelWithDebInfo
6
+ {% if platform.system() == "Windows" %}
7
+ {% set compiler, version, _ = detect_api.detect_msvc_compiler() %}
8
+ compiler={{ compiler }}
9
+ compiler.version={{ detect_api.default_compiler_version(compiler, version) }}
10
+ compiler.runtime=dynamic
11
+ {% else %}
12
+ {% set c_compiler = os.getenv("CC", "clang") %}
13
+ {% set cpp_compiler = os.getenv("CXX", "clang++") %}
14
+ {% set compiler, version, _ = detect_api.detect_clang_compiler(cpp_compiler) %}
15
+ compiler={{ compiler }}
16
+ compiler.version={{ detect_api.default_compiler_version(compiler, version) }}
17
+ compiler.libcxx=libc++
18
+ {% endif %}
19
+ compiler.cppstd=20
20
+
21
+ [conf]
22
+ tools.cmake.cmaketoolchain:generator=Ninja
23
+ {% if platform.system() == "Windows" %}
24
+ tools.build:compiler_executables={"c": "clang-cl", "cpp": "clang-cl"}
25
+ {% else %}
26
+ tools.build:compiler_executables={{ {"c": c_compiler, "cpp": cpp_compiler} | tojson }}
27
+ {% endif %}
@@ -0,0 +1,9 @@
1
+ {
2
+ "remotes": [
3
+ {
4
+ "name": "conancenter",
5
+ "url": "https://center2.conan.io",
6
+ "verify_ssl": true
7
+ }
8
+ ]
9
+ }
@@ -0,0 +1 @@
1
+ conan_home=./.conan2
@@ -0,0 +1,411 @@
1
+ name: Build
2
+
3
+ on:
4
+ push:
5
+ branches: [develop]
6
+ pull_request:
7
+ branches: [develop]
8
+ workflow_dispatch:
9
+ inputs:
10
+ ref:
11
+ description: "Git ref to build"
12
+ required: true
13
+ type: string
14
+
15
+ permissions:
16
+ contents: read
17
+
18
+ jobs:
19
+ native-linux:
20
+ name: Native (Linux)
21
+ runs-on: ubuntu-22.04
22
+ timeout-minutes: 30
23
+
24
+ steps:
25
+ - name: Checkout
26
+ uses: actions/checkout@v7
27
+ with:
28
+ ref: ${{ inputs.ref || github.sha }}
29
+
30
+ - name: Install Clang 20
31
+ run: |
32
+ wget -qO /tmp/llvm.sh https://apt.llvm.org/llvm.sh
33
+ chmod +x /tmp/llvm.sh
34
+ sudo /tmp/llvm.sh 20
35
+ sudo apt-get install -y clang-format-20 clang-tidy-20 libc++-20-dev libc++abi-20-dev
36
+ sudo ln -sf /usr/bin/clang-20 /usr/local/bin/clang
37
+ sudo ln -sf /usr/bin/clang++-20 /usr/local/bin/clang++
38
+ clang --version | grep -E "clang version 20\\."
39
+
40
+ - name: Set up Python
41
+ uses: actions/setup-python@v7
42
+ with:
43
+ python-version: "3.12"
44
+
45
+ - name: Install Conan
46
+ run: python -m pip install "conan==2.30.0"
47
+
48
+ - name: Cache Conan packages
49
+ uses: actions/cache@v6
50
+ with:
51
+ path: .conan2
52
+ key: ${{ runner.os }}-clang20-conan-${{ hashFiles('conanfile.py', '.conan2/profiles/default') }}
53
+
54
+ - name: Install dependencies
55
+ run: conan install . --build=missing
56
+
57
+ - name: Configure
58
+ run: cmake --preset papi-dev -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
59
+
60
+ - name: Build
61
+ run: cmake --build --preset papi-dev
62
+
63
+ - name: Run tests
64
+ run: ctest --preset papi-dev --output-on-failure
65
+
66
+ - name: Install Python test dependencies
67
+ run: python -m pip install "endstone==0.11.11" pytest
68
+
69
+ - name: Stage native module for Python tests
70
+ shell: bash
71
+ run: cp build/RelWithDebInfo/_papi*.so endstone_papi/ 2>/dev/null || true
72
+
73
+ - name: Run Python tests
74
+ run: python -m pytest -q
75
+
76
+ - name: Check formatting
77
+ run: git ls-files '*.cpp' '*.h' | xargs clang-format-20 --dry-run --Werror
78
+
79
+ - name: Run clang-tidy
80
+ run: python tools/run_clang_tidy.py --build-dir build/RelWithDebInfo --clang-tidy clang-tidy-20
81
+
82
+ - name: Architecture boundaries
83
+ run: python tests/test_architecture_boundaries.py
84
+
85
+ - name: Changelog tooling tests
86
+ run: |
87
+ python tools/test_release_changelog.py
88
+ python tools/test_release_transaction.py
89
+ python tools/test_toolchain_policy.py
90
+ python tools/test_sdist_policy.py
91
+
92
+ native-windows:
93
+ name: Native (Windows)
94
+ runs-on: windows-latest
95
+ timeout-minutes: 30
96
+
97
+ steps:
98
+ - name: Checkout
99
+ uses: actions/checkout@v7
100
+ with:
101
+ ref: ${{ inputs.ref || github.sha }}
102
+
103
+ - name: Set up MSVC environment
104
+ uses: TheMrMilchmann/setup-msvc-dev@v4
105
+ with:
106
+ arch: x64
107
+
108
+ - name: Select clang-cl 20
109
+ shell: pwsh
110
+ run: |
111
+ $llvmBin = "C:\Program Files\LLVM\bin"
112
+ $llvmBin | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
113
+ $version = & "$llvmBin\clang-cl.exe" --version
114
+ $version
115
+ if (-not ($version | Select-String "clang version 20\.")) {
116
+ throw "clang-cl 20 is required"
117
+ }
118
+
119
+ - name: Set up Python
120
+ uses: actions/setup-python@v7
121
+ with:
122
+ python-version: "3.12"
123
+
124
+ - name: Install Conan
125
+ run: python -m pip install "conan==2.30.0"
126
+
127
+ - name: Cache Conan packages
128
+ uses: actions/cache@v6
129
+ with:
130
+ path: .conan2
131
+ key: ${{ runner.os }}-clang20-conan-${{ hashFiles('conanfile.py', '.conan2/profiles/default') }}
132
+
133
+ - name: Install dependencies
134
+ run: conan install . --build=missing
135
+
136
+ - name: Configure
137
+ run: cmake --preset papi-dev -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
138
+
139
+ - name: Build
140
+ run: cmake --build --preset papi-dev
141
+
142
+ - name: Run tests
143
+ run: ctest --preset papi-dev --output-on-failure
144
+
145
+ - name: Install Python test dependencies
146
+ run: python -m pip install "endstone==0.11.11" pytest
147
+
148
+ - name: Stage native module for Python tests
149
+ shell: bash
150
+ run: cp build/RelWithDebInfo/_papi*.pyd endstone_papi/ 2>/dev/null || true
151
+
152
+ - name: Run Python tests
153
+ run: python -m pytest -q
154
+
155
+ - name: Check formatting
156
+ shell: pwsh
157
+ run: |
158
+ $files = git ls-files '*.cpp' '*.h'
159
+ & clang-format --dry-run --Werror $files
160
+ if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
161
+
162
+ - name: Run clang-tidy
163
+ run: python tools/run_clang_tidy.py --build-dir build/RelWithDebInfo --clang-tidy clang-tidy
164
+
165
+ - name: Architecture boundaries
166
+ run: python tests/test_architecture_boundaries.py
167
+
168
+ python:
169
+ name: Python
170
+ runs-on: ubuntu-22.04
171
+ timeout-minutes: 15
172
+
173
+ steps:
174
+ - name: Checkout
175
+ uses: actions/checkout@v7
176
+ with:
177
+ ref: ${{ inputs.ref || github.sha }}
178
+
179
+ - name: Set up Python
180
+ uses: actions/setup-python@v7
181
+ with:
182
+ python-version: "3.12"
183
+
184
+ - name: Install ruff
185
+ run: python -m pip install ruff
186
+
187
+ - name: Check formatting
188
+ run: python -m ruff format --check .
189
+
190
+ - name: Lint
191
+ run: python -m ruff check .
192
+
193
+ wheel:
194
+ name: Wheel (${{ matrix.python-tag }}-${{ matrix.platform }})
195
+ runs-on: ${{ matrix.os }}
196
+ timeout-minutes: 30
197
+ strategy:
198
+ fail-fast: false
199
+ matrix:
200
+ os: [ ubuntu-22.04, windows-latest ]
201
+ python-tag: [ "cp310", "cp311", "cp312", "cp313", "cp314" ]
202
+ include:
203
+ - os: ubuntu-22.04
204
+ platform: manylinux_x86_64
205
+ - os: windows-latest
206
+ platform: win_amd64
207
+ - python-tag: "cp310"
208
+ python-version: "3.10"
209
+ - python-tag: "cp311"
210
+ python-version: "3.11"
211
+ - python-tag: "cp312"
212
+ python-version: "3.12"
213
+ - python-tag: "cp313"
214
+ python-version: "3.13"
215
+ - python-tag: "cp314"
216
+ python-version: "3.14"
217
+
218
+ steps:
219
+ - name: Checkout
220
+ uses: actions/checkout@v7
221
+ with:
222
+ ref: ${{ inputs.ref || github.sha }}
223
+ fetch-depth: 0
224
+
225
+ - name: Set up MSVC (Windows)
226
+ if: runner.os == 'Windows'
227
+ uses: TheMrMilchmann/setup-msvc-dev@v4
228
+ with:
229
+ arch: x64
230
+
231
+ - name: Set up CMake and Ninja
232
+ uses: lukka/get-cmake@v4.4.2
233
+
234
+ - name: Build wheels
235
+ uses: pypa/cibuildwheel@v3.4.1
236
+ env:
237
+ CIBW_BUILD: ${{ matrix.python-tag }}-${{ matrix.platform }}
238
+ CIBW_BUILD_VERBOSITY: 1
239
+ CIBW_CONTAINER_ENGINE: "docker; create_args: --volume ${{ github.workspace }}/.conan2:/project/.conan2"
240
+
241
+ - name: Reclaim Conan home (Linux)
242
+ if: always() && runner.os == 'Linux'
243
+ run: sudo chown -R "$(id -u):$(id -g)" .conan2
244
+
245
+ - name: Verify wheel contents
246
+ shell: bash
247
+ run: |
248
+ python -c "
249
+ import zipfile, sys, pathlib
250
+ whl = list(pathlib.Path('wheelhouse').glob('*.whl'))[0]
251
+ z = zipfile.ZipFile(whl)
252
+ names = z.namelist()
253
+ assert any('_papi' in n for n in names), 'native module missing'
254
+ assert any(n.endswith('.pyi') for n in names), '.pyi missing'
255
+ assert any('include/endstone_papi' in n for n in names), 'headers missing'
256
+ assert any('LICENSE' in n for n in names), 'LICENSE missing'
257
+ provenance = z.read('endstone_papi/_toolchain_provenance.txt').decode()
258
+ assert 'compiler_id=Clang' in provenance, provenance
259
+ assert 'compiler_version=20.' in provenance, provenance
260
+ if sys.platform.startswith('linux'):
261
+ assert 'endstone_papi/libc++.so.1' in names, 'libc++ runtime bridge missing'
262
+ assert 'endstone_papi/libc++abi.so.1' in names, 'libc++abi runtime bridge missing'
263
+ assert 'endstone_papi/libunwind.so.1' in names, 'libunwind runtime bridge missing'
264
+ assert not any('endstone_papi.libs/' in n for n in names), 'duplicate C++ runtime bundled'
265
+ # Verify the Endstone runtime dependency is declared.
266
+ meta = [n for n in names if n.endswith('METADATA')][0]
267
+ content = z.read(meta).decode()
268
+ assert any(
269
+ line.lower().startswith('requires-dist: endstone')
270
+ for line in content.splitlines()
271
+ ), 'endstone dependency not declared in wheel METADATA'
272
+ print(f'OK: {len(names)} files in {whl.name}')
273
+ "
274
+ if [ "${{ runner.os }}" = "Linux" ]; then
275
+ docker run --rm \
276
+ -v "$GITHUB_WORKSPACE:/project" \
277
+ -w /project \
278
+ ghcr.io/endstonemc/manylinux_2_31_x86_64 \
279
+ bash -lc 'export PATH=/opt/python/cp312-cp312/bin:$PATH; python -m pip install "auditwheel==6.4.2" "endstone==0.11.11" "patchelf==0.17.2.4" && python tools/verify_linux_wheel.py wheelhouse/*.whl --auditwheel'
280
+ fi
281
+
282
+ - name: Set up Python for runtime test
283
+ uses: actions/setup-python@v7
284
+ with:
285
+ python-version: "${{ matrix.python-version }}"
286
+
287
+ - name: Runtime smoke test
288
+ shell: bash
289
+ env:
290
+ PYTHONFAULTHANDLER: "1"
291
+ run: |
292
+ python -m pip install endstone==0.11.11
293
+ whl="$(python -c 'import pathlib; print(list(pathlib.Path("wheelhouse").glob("*.whl"))[0])')"
294
+ python -m pip install "$whl"
295
+ python tools/wheel_smoke_test.py --official
296
+
297
+ - uses: actions/upload-artifact@v7
298
+ if: always()
299
+ with:
300
+ name: papi-${{ matrix.python-tag }}-${{ matrix.platform }}
301
+ path: ./wheelhouse/*.whl
302
+
303
+ sdist:
304
+ name: Sdist
305
+ runs-on: ubuntu-22.04
306
+ timeout-minutes: 30
307
+
308
+ steps:
309
+ - name: Checkout
310
+ uses: actions/checkout@v7
311
+ with:
312
+ ref: ${{ inputs.ref || github.sha }}
313
+ fetch-depth: 0
314
+
315
+ - name: Set up Python
316
+ uses: actions/setup-python@v7
317
+ with:
318
+ python-version: "3.12"
319
+
320
+ - name: Install build
321
+ run: python -m pip install build cibuildwheel==3.4.1
322
+
323
+ - name: Build sdist
324
+ run: python -m build --sdist
325
+
326
+ - name: Verify sdist contains native sources
327
+ shell: bash
328
+ run: |
329
+ python -c "
330
+ import tarfile, pathlib
331
+ sdist = list(pathlib.Path('dist').glob('*.tar.gz'))[0]
332
+ t = tarfile.open(sdist)
333
+ names = t.getnames()
334
+ for required in ['module.cpp', 'gil_safe_proxy.cpp', 'expansion_trampoline.cpp',
335
+ 'bootstrap.cpp', 'placeholder_api_impl.cpp', 'build_linux_runtime.py']:
336
+ assert any(required in n for n in names), f'{required} missing from sdist'
337
+ print(f'OK: sdist contains all native sources')
338
+ "
339
+
340
+ - name: Stage only the sdist archive
341
+ shell: bash
342
+ run: |
343
+ rm -rf /tmp/papi-sdist-input /tmp/papi-sdist-build /tmp/papi-sdist-smoke
344
+ mkdir /tmp/papi-sdist-input /tmp/papi-sdist-build /tmp/papi-sdist-smoke
345
+ cp dist/*.tar.gz /tmp/papi-sdist-input/
346
+ test "$(find /tmp/papi-sdist-input -maxdepth 1 -type f | wc -l)" -eq 1
347
+
348
+ - name: Extract isolated sdist archive
349
+ shell: bash
350
+ run: |
351
+ tar -xf /tmp/papi-sdist-input/*.tar.gz -C /tmp/papi-sdist-build --strip-components=1
352
+
353
+ - name: Build checkout and isolated sdist wheels at Endstone baseline
354
+ shell: bash
355
+ env:
356
+ CIBW_CONTAINER_ENGINE: "docker; create_args: --volume ${{ github.workspace }}/.conan2:/project/.conan2"
357
+ run: |
358
+ CIBW_BUILD=cp312-manylinux_x86_64 python -m cibuildwheel --platform linux \
359
+ --output-dir /tmp/papi-checkout-wheel .
360
+ cd /tmp/papi-sdist-build
361
+ CIBW_BUILD=cp312-manylinux_x86_64 python -m cibuildwheel --platform linux \
362
+ --output-dir "$GITHUB_WORKSPACE/wheelhouse" .
363
+
364
+ - name: Reclaim Conan home
365
+ if: always()
366
+ run: sudo chown -R "$(id -u):$(id -g)" .conan2
367
+
368
+ - name: Verify checkout and sdist wheel runtime contracts
369
+ shell: bash
370
+ run: |
371
+ sdist_wheel="$(find wheelhouse -maxdepth 1 -name '*.whl' -print -quit)"
372
+ checkout_wheel="$(find /tmp/papi-checkout-wheel -maxdepth 1 -name '*.whl' -print -quit)"
373
+ docker run --rm \
374
+ -v "$GITHUB_WORKSPACE:/project" \
375
+ -v /tmp/papi-checkout-wheel:/checkout-wheel:ro \
376
+ -w /project \
377
+ ghcr.io/endstonemc/manylinux_2_31_x86_64 \
378
+ bash -lc 'export PATH=/opt/python/cp312-cp312/bin:$PATH; python -m pip install "auditwheel==6.4.2" "endstone==0.11.11" "patchelf==0.17.2.4" && python tools/verify_linux_wheel.py wheelhouse/*.whl --compare /checkout-wheel/*.whl --auditwheel'
379
+
380
+ - name: Runtime smoke test from isolated sdist-built wheel
381
+ shell: bash
382
+ run: |
383
+ python -m venv /tmp/papi-sdist-smoke-env
384
+ /tmp/papi-sdist-smoke-env/bin/pip install wheelhouse/*.whl
385
+ cd /tmp/papi-sdist-smoke
386
+ /tmp/papi-sdist-smoke-env/bin/python "$GITHUB_WORKSPACE/tools/wheel_smoke_test.py" --official
387
+ module="$(find /tmp/papi-sdist-smoke-env -path '*site-packages/endstone_papi/_papi*.so' -print -quit)"
388
+ ldd "$module" | tee /tmp/papi-sdist-ldd.txt
389
+ grep -F 'endstone_papi/libc++.so.1' /tmp/papi-sdist-ldd.txt
390
+ grep -F 'endstone_papi/libc++abi.so.1' /tmp/papi-sdist-ldd.txt
391
+ grep -F 'endstone.libs/libunwind-' /tmp/papi-sdist-ldd.txt
392
+ python -c "
393
+ from pathlib import Path
394
+ lines = Path('/tmp/papi-sdist-ldd.txt').read_text().splitlines()
395
+ runtime = [line for line in lines if any(name in line for name in ('libc++.so', 'libc++abi.so', 'libunwind.so'))]
396
+ assert runtime, lines
397
+ assert not any('=> /usr/' in line for line in runtime), runtime
398
+ "
399
+ hashed="$(find /tmp/papi-sdist-smoke-env -path '*site-packages/endstone.libs/libc++-*.so.1.0' -print -quit)"
400
+ test -n "$hashed"
401
+ mv "$hashed" "$hashed.missing"
402
+ if /tmp/papi-sdist-smoke-env/bin/python -c 'import endstone_papi'; then
403
+ echo 'native import unexpectedly succeeded without Endstone libc++' >&2
404
+ exit 1
405
+ fi
406
+ mv "$hashed.missing" "$hashed"
407
+
408
+ - uses: actions/upload-artifact@v7
409
+ with:
410
+ name: papi-sdist
411
+ path: ./dist/*.tar.gz