ksp-builder 0.0.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.
- ksp_builder-0.0.0/LICENSE +21 -0
- ksp_builder-0.0.0/PKG-INFO +264 -0
- ksp_builder-0.0.0/README.md +242 -0
- ksp_builder-0.0.0/ksp_builder/__init__.py +222 -0
- ksp_builder-0.0.0/ksp_builder/_build.py +250 -0
- ksp_builder-0.0.0/ksp_builder/_compile_kv.py +158 -0
- ksp_builder-0.0.0/ksp_builder/_cythonize.py +204 -0
- ksp_builder-0.0.0/ksp_builder/_gradle.py +102 -0
- ksp_builder-0.0.0/ksp_builder/_java.py +16 -0
- ksp_builder-0.0.0/ksp_builder/_kivy_school.py +43 -0
- ksp_builder-0.0.0/ksp_builder/_packages.py +225 -0
- ksp_builder-0.0.0/ksp_builder/_pre_post_build.py +128 -0
- ksp_builder-0.0.0/ksp_builder.egg-info/PKG-INFO +264 -0
- ksp_builder-0.0.0/ksp_builder.egg-info/SOURCES.txt +23 -0
- ksp_builder-0.0.0/ksp_builder.egg-info/dependency_links.txt +1 -0
- ksp_builder-0.0.0/ksp_builder.egg-info/requires.txt +4 -0
- ksp_builder-0.0.0/ksp_builder.egg-info/top_level.txt +1 -0
- ksp_builder-0.0.0/pyproject.toml +36 -0
- ksp_builder-0.0.0/setup.cfg +4 -0
- ksp_builder-0.0.0/tests/test_backend.py +84 -0
- ksp_builder-0.0.0/tests/test_compile_kv.py +263 -0
- ksp_builder-0.0.0/tests/test_cythonize.py +515 -0
- ksp_builder-0.0.0/tests/test_java.py +77 -0
- ksp_builder-0.0.0/tests/test_kivy_school_gradle.py +198 -0
- ksp_builder-0.0.0/tests/test_pre_post_build.py +181 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kivy School
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ksp-builder
|
|
3
|
+
Version: 0.0.0
|
|
4
|
+
Summary: PEP 517 build backend for KSProject-based packages
|
|
5
|
+
Author: ksp-builder contributors
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/kivy-school/ksp-builder
|
|
8
|
+
Project-URL: Repository, https://github.com/kivy-school/ksp-builder
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
14
|
+
Requires-Python: >=3.13
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Requires-Dist: compilekv
|
|
18
|
+
Requires-Dist: cython>=3.3.0
|
|
19
|
+
Requires-Dist: pyjnius-builder
|
|
20
|
+
Requires-Dist: setuptools>=84.0.0
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
|
|
23
|
+
# ksp-builder
|
|
24
|
+
A PEP 517 build backend for KSProject-based packages that combines Cython
|
|
25
|
+
compilation, Kivy KV compilation, Java source injection
|
|
26
|
+
([pyjnius-builder](https://github.com/kivy-school/pyjnius-builder) convention),
|
|
27
|
+
Swift build support
|
|
28
|
+
([pyswiftkit-builder](https://github.com/Py-Swift/pyswiftkit-builder)), and
|
|
29
|
+
Android Gradle configuration injection into a single backend.
|
|
30
|
+
|
|
31
|
+
**Requires Python ≥ 3.13** (uses `tomllib` from the standard library and aligns
|
|
32
|
+
with the minimum version requirements of pyswiftkit-builder and pyjnius-builder).
|
|
33
|
+
|
|
34
|
+
## Usage
|
|
35
|
+
|
|
36
|
+
```toml
|
|
37
|
+
[build-system]
|
|
38
|
+
requires = ["ksp-builder"]
|
|
39
|
+
build-backend = "ksp_builder"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Configuration
|
|
43
|
+
|
|
44
|
+
### Build scripts — `[tool.ksp-builder]`
|
|
45
|
+
|
|
46
|
+
Run your own scripts around the build. `before_build` runs before the artifact
|
|
47
|
+
is assembled, `after_build` runs once it exists on disk. Both keys are optional
|
|
48
|
+
and paths are relative to the project root.
|
|
49
|
+
|
|
50
|
+
```toml
|
|
51
|
+
[tool.ksp-builder]
|
|
52
|
+
before_build = "scripts/before_build.py"
|
|
53
|
+
after_build = "scripts/sign_wheel.sh"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The scripts do not have to be Python. A `.py` path is run with the interpreter
|
|
57
|
+
running the build; any other path is executed directly, so it needs its
|
|
58
|
+
executable bit set (`chmod +x`) and a shebang naming its interpreter:
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
#!/usr/bin/env bash
|
|
62
|
+
set -e
|
|
63
|
+
codesign --sign "$SIGNING_IDENTITY" "$KSP_BUILD_ARTIFACT"
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Scripts run with the project root as their working directory. `after_build`
|
|
67
|
+
receives the artifact path as its first argument. Both are given the
|
|
68
|
+
environment variables `KSP_BUILD_PROJECT_ROOT`, `KSP_BUILD_TARGET`
|
|
69
|
+
(`wheel`, `sdist` or `editable`), and — for `after_build` —
|
|
70
|
+
`KSP_BUILD_ARTIFACT`. A script that exits non-zero fails the build.
|
|
71
|
+
|
|
72
|
+
### Cython compilation — `[tool.ksp-builder]`
|
|
73
|
+
|
|
74
|
+
Compiles your package sources into extension modules, replacing the
|
|
75
|
+
`cythonized_app` `setup.py` (there is no `setup.py` with a PEP 517 backend, so
|
|
76
|
+
`ksp-builder` injects the `ext_modules` itself).
|
|
77
|
+
|
|
78
|
+
```toml
|
|
79
|
+
[tool.ksp-builder]
|
|
80
|
+
cythonize = true
|
|
81
|
+
py_to_pyx = true
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The two switches are separate on purpose:
|
|
85
|
+
|
|
86
|
+
| Setting | Effect |
|
|
87
|
+
| --- | --- |
|
|
88
|
+
| `cythonize = true` | Compiles the `.pyx` sources already in your packages. `.py` modules are untouched. |
|
|
89
|
+
| `py_to_pyx = true` | Also copies each `.py` module to `.dist_src/` as a `.pyx` and compiles it. **Requires `cythonize`** — on its own it does nothing. |
|
|
90
|
+
|
|
91
|
+
`__init__.py` and `__main__.py` are never converted — the first keeps the
|
|
92
|
+
package importable, the second keeps `python -m yourpackage` working, since
|
|
93
|
+
runpy needs a code object that a compiled extension cannot provide. Both are
|
|
94
|
+
still shipped, just as `.py`. Top-level modules (`py-modules`) are left alone
|
|
95
|
+
too. A converted module ships only as its
|
|
96
|
+
compiled extension: the original `.py` is dropped from the wheel. Generated
|
|
97
|
+
`.pyx` and C files are written to `.dist_src/` at the project root, which you
|
|
98
|
+
can add to `.gitignore`. Nothing is ever written back into your package: a
|
|
99
|
+
build leaves the source tree exactly as it found it.
|
|
100
|
+
|
|
101
|
+
#### `.kv` files and other assets
|
|
102
|
+
|
|
103
|
+
Plain setuptools ships only Python modules, so a cythonized Kivy app would build
|
|
104
|
+
fine and then fail at runtime with its `.kv` files missing. Whenever it is
|
|
105
|
+
compiling something (`cythonize` or `compile_kv`), `ksp-builder` therefore
|
|
106
|
+
ships **every file in your packages** as package data —
|
|
107
|
+
`.kv`, images, fonts, JSON, whatever is there — including files in nested data
|
|
108
|
+
directories such as `assets/images/`. No configuration needed.
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
kvapp/__init__.py -> kvapp/__init__.py
|
|
112
|
+
kvapp/app.py -> kvapp/app.cpython-313-darwin.so
|
|
113
|
+
kvapp/app.kv -> kvapp/app.kv
|
|
114
|
+
kvapp/data/images/logo.png -> kvapp/data/images/logo.png
|
|
115
|
+
kvapp/fonts/Roboto.ttf -> kvapp/fonts/Roboto.ttf
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Assets land next to the compiled extension, so `Path(__file__).parent` still
|
|
119
|
+
finds them. Directories containing an `__init__.py` are skipped here and
|
|
120
|
+
collected as the packages they are. (With `compile_kv = true` the `.kv` files
|
|
121
|
+
are the exception: they are compiled into their modules instead of shipped —
|
|
122
|
+
see below.)
|
|
123
|
+
|
|
124
|
+
Sources and build output are the one exception — `.py`, `.pyx`, `.pxd`, `.c`,
|
|
125
|
+
`.h`, `.o`, `.so`, `.pyd`, `.pyc` and `__pycache__` are never shipped as assets,
|
|
126
|
+
since that would hand back the very sources the compilation just removed. To
|
|
127
|
+
ship one of those deliberately (a prebuilt binary, say), name it explicitly in
|
|
128
|
+
`[tool.setuptools.package-data]`, which is merged with what is found here.
|
|
129
|
+
|
|
130
|
+
Set `include_assets = false` to turn the whole behaviour off and go back to
|
|
131
|
+
declaring package data yourself.
|
|
132
|
+
|
|
133
|
+
Package layout still comes from `[tool.setuptools]` — `packages`, `package-dir`
|
|
134
|
+
and `packages.find` are read as-is (with the same src/flat auto-discovery
|
|
135
|
+
setuptools does), so nothing is duplicated in this section. The remaining keys
|
|
136
|
+
only tune the Cython step:
|
|
137
|
+
|
|
138
|
+
```toml
|
|
139
|
+
[tool.ksp-builder]
|
|
140
|
+
cythonize = true
|
|
141
|
+
py_to_pyx = true
|
|
142
|
+
cythonize_exclude = ["main.py", "**/legacy/*.py"] # keep these as .py
|
|
143
|
+
cythonize_keep_py = true # ship the .py sources too
|
|
144
|
+
include_assets = false # stop auto-shipping assets
|
|
145
|
+
|
|
146
|
+
[tool.ksp-builder.cythonize_directives]
|
|
147
|
+
language_level = "3" # the default
|
|
148
|
+
boundscheck = false
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
A pattern in `cythonize_exclude` without a `/` matches that file name at any
|
|
152
|
+
depth; a pattern with one is matched against the whole project-relative path.
|
|
153
|
+
|
|
154
|
+
Editable installs (`pip install -e .`) compile real `.pyx` sources but never
|
|
155
|
+
convert `.py`, so your edits keep taking effect during development. Sdists are
|
|
156
|
+
never cythonized — compilation happens when a wheel is built from the sdist.
|
|
157
|
+
Note that setuptools does not add `.pyx` files to an sdist on its own, so if you
|
|
158
|
+
ship hand-written Cython sources, include them (`MANIFEST.in` with
|
|
159
|
+
`recursive-include <pkg> *.pyx *.pxd`) or a wheel built from the sdist will have
|
|
160
|
+
nothing to compile.
|
|
161
|
+
|
|
162
|
+
### Kivy KV compilation — `[tool.ksp-builder]`
|
|
163
|
+
|
|
164
|
+
```toml
|
|
165
|
+
[tool.ksp-builder]
|
|
166
|
+
compile_kv = true
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Turns every `.kv` file in your packages into a Python module using the
|
|
170
|
+
[`compilekv`](https://github.com/kivy-school/compilekv) library: the KV rules
|
|
171
|
+
become real widget classes, so nothing has to be parsed at startup and the
|
|
172
|
+
result can be compiled like any other module.
|
|
173
|
+
|
|
174
|
+
Each `.kv` is compiled together with the `.py` of the same name beside it, and
|
|
175
|
+
the module the two produce replaces that `.py` in the wheel. A `.kv` with no
|
|
176
|
+
`.py` beside it simply becomes a module of its own. The `.kv` itself is *not*
|
|
177
|
+
shipped — it has been compiled into the module, and shipping it too would only
|
|
178
|
+
invite a second, conflicting set of rules at runtime.
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
kvapp/app.py + kvapp/app.kv -> kvapp/app.py (the two, merged)
|
|
182
|
+
kvapp/theme.kv -> kvapp/theme.py (no .py of its own)
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Only `.kv` files sitting **directly in a package** are compiled, since a
|
|
186
|
+
compiled KV file becomes an importable module and there is no module name for
|
|
187
|
+
one in a plain data directory. A `.kv` under `kvapp/ui/` stays ordinary
|
|
188
|
+
package data.
|
|
189
|
+
|
|
190
|
+
#### All three switches together
|
|
191
|
+
|
|
192
|
+
`compile_kv` composes with the Cython switches. With all three on, the module
|
|
193
|
+
compiled out of the `.kv` is staged as a `.pyx` and compiled to an extension,
|
|
194
|
+
so neither the `.kv` nor the `.py` that fed it reaches the wheel:
|
|
195
|
+
|
|
196
|
+
```toml
|
|
197
|
+
[tool.ksp-builder]
|
|
198
|
+
cythonize = true
|
|
199
|
+
py_to_pyx = true
|
|
200
|
+
compile_kv = true
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
```
|
|
204
|
+
kvapp/__init__.py -> kvapp/__init__.py
|
|
205
|
+
kvapp/__main__.py -> kvapp/__main__.py
|
|
206
|
+
kvapp/app.py + kvapp/app.kv -> kvapp/app.cpython-313-darwin.so
|
|
207
|
+
kvapp/theme.kv -> kvapp/theme.cpython-313-darwin.so
|
|
208
|
+
kvapp/assets/logo.png -> kvapp/assets/logo.png
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
A module named by `cythonize_exclude` is still compiled out of its KV file, it
|
|
212
|
+
just stays a plain `.py`. `__init__` and `__main__` are never turned into
|
|
213
|
+
extensions here either.
|
|
214
|
+
|
|
215
|
+
Editable installs (`pip install -e .`) leave `.kv` files alone — the source
|
|
216
|
+
tree is what gets imported, so a generated module would never be used and your
|
|
217
|
+
`.kv` edits keep taking effect during development.
|
|
218
|
+
|
|
219
|
+
### Android Gradle config — `[tool.kivy-school.android]`
|
|
220
|
+
|
|
221
|
+
When present, `ksp-builder` generates a `.gradle/<package_name>.json` file and
|
|
222
|
+
injects it into the built wheel and sdist. `ksproject` can then discover and
|
|
223
|
+
merge these JSON files from all installed packages to assemble the final Gradle
|
|
224
|
+
build configuration (permissions, gradle dependencies, etc.).
|
|
225
|
+
|
|
226
|
+
```toml
|
|
227
|
+
[tool.kivy-school]
|
|
228
|
+
app_name = "MyApp"
|
|
229
|
+
|
|
230
|
+
[tool.kivy-school.android]
|
|
231
|
+
package_name = "org.example.myapp"
|
|
232
|
+
gradle_dependencies = [
|
|
233
|
+
"com.google.firebase:firebase-analytics:21.0.0",
|
|
234
|
+
]
|
|
235
|
+
permissions = [
|
|
236
|
+
"INTERNET",
|
|
237
|
+
"CAMERA",
|
|
238
|
+
]
|
|
239
|
+
[tool.kivy-school.android.meta_data]
|
|
240
|
+
"com.google.android.gms.ads.APPLICATION_ID" = "ca-app-pub-3940256099942544~3347511713"
|
|
241
|
+
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Java sources — `[tool.pyjnius]`
|
|
245
|
+
|
|
246
|
+
Java source files are injected into the wheel and sdist under `.java/`, following
|
|
247
|
+
the [pyjnius-builder](https://github.com/kivy-school/pyjnius-builder) convention.
|
|
248
|
+
|
|
249
|
+
```toml
|
|
250
|
+
[tool.pyjnius]
|
|
251
|
+
java-paths = ["java/"]
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Swift packages — `[tool.pyswiftkit]`
|
|
255
|
+
|
|
256
|
+
If `pyswiftkit-builder` is installed and `[tool.pyswiftkit]` is configured,
|
|
257
|
+
`swift build` runs automatically before the wheel is assembled and the compiled
|
|
258
|
+
artifacts are injected into the wheel.
|
|
259
|
+
|
|
260
|
+
```toml
|
|
261
|
+
[tool.pyswiftkit]
|
|
262
|
+
products = ["mymodule"]
|
|
263
|
+
```
|
|
264
|
+
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
# ksp-builder
|
|
2
|
+
A PEP 517 build backend for KSProject-based packages that combines Cython
|
|
3
|
+
compilation, Kivy KV compilation, Java source injection
|
|
4
|
+
([pyjnius-builder](https://github.com/kivy-school/pyjnius-builder) convention),
|
|
5
|
+
Swift build support
|
|
6
|
+
([pyswiftkit-builder](https://github.com/Py-Swift/pyswiftkit-builder)), and
|
|
7
|
+
Android Gradle configuration injection into a single backend.
|
|
8
|
+
|
|
9
|
+
**Requires Python ≥ 3.13** (uses `tomllib` from the standard library and aligns
|
|
10
|
+
with the minimum version requirements of pyswiftkit-builder and pyjnius-builder).
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
```toml
|
|
15
|
+
[build-system]
|
|
16
|
+
requires = ["ksp-builder"]
|
|
17
|
+
build-backend = "ksp_builder"
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Configuration
|
|
21
|
+
|
|
22
|
+
### Build scripts — `[tool.ksp-builder]`
|
|
23
|
+
|
|
24
|
+
Run your own scripts around the build. `before_build` runs before the artifact
|
|
25
|
+
is assembled, `after_build` runs once it exists on disk. Both keys are optional
|
|
26
|
+
and paths are relative to the project root.
|
|
27
|
+
|
|
28
|
+
```toml
|
|
29
|
+
[tool.ksp-builder]
|
|
30
|
+
before_build = "scripts/before_build.py"
|
|
31
|
+
after_build = "scripts/sign_wheel.sh"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The scripts do not have to be Python. A `.py` path is run with the interpreter
|
|
35
|
+
running the build; any other path is executed directly, so it needs its
|
|
36
|
+
executable bit set (`chmod +x`) and a shebang naming its interpreter:
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
#!/usr/bin/env bash
|
|
40
|
+
set -e
|
|
41
|
+
codesign --sign "$SIGNING_IDENTITY" "$KSP_BUILD_ARTIFACT"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Scripts run with the project root as their working directory. `after_build`
|
|
45
|
+
receives the artifact path as its first argument. Both are given the
|
|
46
|
+
environment variables `KSP_BUILD_PROJECT_ROOT`, `KSP_BUILD_TARGET`
|
|
47
|
+
(`wheel`, `sdist` or `editable`), and — for `after_build` —
|
|
48
|
+
`KSP_BUILD_ARTIFACT`. A script that exits non-zero fails the build.
|
|
49
|
+
|
|
50
|
+
### Cython compilation — `[tool.ksp-builder]`
|
|
51
|
+
|
|
52
|
+
Compiles your package sources into extension modules, replacing the
|
|
53
|
+
`cythonized_app` `setup.py` (there is no `setup.py` with a PEP 517 backend, so
|
|
54
|
+
`ksp-builder` injects the `ext_modules` itself).
|
|
55
|
+
|
|
56
|
+
```toml
|
|
57
|
+
[tool.ksp-builder]
|
|
58
|
+
cythonize = true
|
|
59
|
+
py_to_pyx = true
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The two switches are separate on purpose:
|
|
63
|
+
|
|
64
|
+
| Setting | Effect |
|
|
65
|
+
| --- | --- |
|
|
66
|
+
| `cythonize = true` | Compiles the `.pyx` sources already in your packages. `.py` modules are untouched. |
|
|
67
|
+
| `py_to_pyx = true` | Also copies each `.py` module to `.dist_src/` as a `.pyx` and compiles it. **Requires `cythonize`** — on its own it does nothing. |
|
|
68
|
+
|
|
69
|
+
`__init__.py` and `__main__.py` are never converted — the first keeps the
|
|
70
|
+
package importable, the second keeps `python -m yourpackage` working, since
|
|
71
|
+
runpy needs a code object that a compiled extension cannot provide. Both are
|
|
72
|
+
still shipped, just as `.py`. Top-level modules (`py-modules`) are left alone
|
|
73
|
+
too. A converted module ships only as its
|
|
74
|
+
compiled extension: the original `.py` is dropped from the wheel. Generated
|
|
75
|
+
`.pyx` and C files are written to `.dist_src/` at the project root, which you
|
|
76
|
+
can add to `.gitignore`. Nothing is ever written back into your package: a
|
|
77
|
+
build leaves the source tree exactly as it found it.
|
|
78
|
+
|
|
79
|
+
#### `.kv` files and other assets
|
|
80
|
+
|
|
81
|
+
Plain setuptools ships only Python modules, so a cythonized Kivy app would build
|
|
82
|
+
fine and then fail at runtime with its `.kv` files missing. Whenever it is
|
|
83
|
+
compiling something (`cythonize` or `compile_kv`), `ksp-builder` therefore
|
|
84
|
+
ships **every file in your packages** as package data —
|
|
85
|
+
`.kv`, images, fonts, JSON, whatever is there — including files in nested data
|
|
86
|
+
directories such as `assets/images/`. No configuration needed.
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
kvapp/__init__.py -> kvapp/__init__.py
|
|
90
|
+
kvapp/app.py -> kvapp/app.cpython-313-darwin.so
|
|
91
|
+
kvapp/app.kv -> kvapp/app.kv
|
|
92
|
+
kvapp/data/images/logo.png -> kvapp/data/images/logo.png
|
|
93
|
+
kvapp/fonts/Roboto.ttf -> kvapp/fonts/Roboto.ttf
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Assets land next to the compiled extension, so `Path(__file__).parent` still
|
|
97
|
+
finds them. Directories containing an `__init__.py` are skipped here and
|
|
98
|
+
collected as the packages they are. (With `compile_kv = true` the `.kv` files
|
|
99
|
+
are the exception: they are compiled into their modules instead of shipped —
|
|
100
|
+
see below.)
|
|
101
|
+
|
|
102
|
+
Sources and build output are the one exception — `.py`, `.pyx`, `.pxd`, `.c`,
|
|
103
|
+
`.h`, `.o`, `.so`, `.pyd`, `.pyc` and `__pycache__` are never shipped as assets,
|
|
104
|
+
since that would hand back the very sources the compilation just removed. To
|
|
105
|
+
ship one of those deliberately (a prebuilt binary, say), name it explicitly in
|
|
106
|
+
`[tool.setuptools.package-data]`, which is merged with what is found here.
|
|
107
|
+
|
|
108
|
+
Set `include_assets = false` to turn the whole behaviour off and go back to
|
|
109
|
+
declaring package data yourself.
|
|
110
|
+
|
|
111
|
+
Package layout still comes from `[tool.setuptools]` — `packages`, `package-dir`
|
|
112
|
+
and `packages.find` are read as-is (with the same src/flat auto-discovery
|
|
113
|
+
setuptools does), so nothing is duplicated in this section. The remaining keys
|
|
114
|
+
only tune the Cython step:
|
|
115
|
+
|
|
116
|
+
```toml
|
|
117
|
+
[tool.ksp-builder]
|
|
118
|
+
cythonize = true
|
|
119
|
+
py_to_pyx = true
|
|
120
|
+
cythonize_exclude = ["main.py", "**/legacy/*.py"] # keep these as .py
|
|
121
|
+
cythonize_keep_py = true # ship the .py sources too
|
|
122
|
+
include_assets = false # stop auto-shipping assets
|
|
123
|
+
|
|
124
|
+
[tool.ksp-builder.cythonize_directives]
|
|
125
|
+
language_level = "3" # the default
|
|
126
|
+
boundscheck = false
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
A pattern in `cythonize_exclude` without a `/` matches that file name at any
|
|
130
|
+
depth; a pattern with one is matched against the whole project-relative path.
|
|
131
|
+
|
|
132
|
+
Editable installs (`pip install -e .`) compile real `.pyx` sources but never
|
|
133
|
+
convert `.py`, so your edits keep taking effect during development. Sdists are
|
|
134
|
+
never cythonized — compilation happens when a wheel is built from the sdist.
|
|
135
|
+
Note that setuptools does not add `.pyx` files to an sdist on its own, so if you
|
|
136
|
+
ship hand-written Cython sources, include them (`MANIFEST.in` with
|
|
137
|
+
`recursive-include <pkg> *.pyx *.pxd`) or a wheel built from the sdist will have
|
|
138
|
+
nothing to compile.
|
|
139
|
+
|
|
140
|
+
### Kivy KV compilation — `[tool.ksp-builder]`
|
|
141
|
+
|
|
142
|
+
```toml
|
|
143
|
+
[tool.ksp-builder]
|
|
144
|
+
compile_kv = true
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Turns every `.kv` file in your packages into a Python module using the
|
|
148
|
+
[`compilekv`](https://github.com/kivy-school/compilekv) library: the KV rules
|
|
149
|
+
become real widget classes, so nothing has to be parsed at startup and the
|
|
150
|
+
result can be compiled like any other module.
|
|
151
|
+
|
|
152
|
+
Each `.kv` is compiled together with the `.py` of the same name beside it, and
|
|
153
|
+
the module the two produce replaces that `.py` in the wheel. A `.kv` with no
|
|
154
|
+
`.py` beside it simply becomes a module of its own. The `.kv` itself is *not*
|
|
155
|
+
shipped — it has been compiled into the module, and shipping it too would only
|
|
156
|
+
invite a second, conflicting set of rules at runtime.
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
kvapp/app.py + kvapp/app.kv -> kvapp/app.py (the two, merged)
|
|
160
|
+
kvapp/theme.kv -> kvapp/theme.py (no .py of its own)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Only `.kv` files sitting **directly in a package** are compiled, since a
|
|
164
|
+
compiled KV file becomes an importable module and there is no module name for
|
|
165
|
+
one in a plain data directory. A `.kv` under `kvapp/ui/` stays ordinary
|
|
166
|
+
package data.
|
|
167
|
+
|
|
168
|
+
#### All three switches together
|
|
169
|
+
|
|
170
|
+
`compile_kv` composes with the Cython switches. With all three on, the module
|
|
171
|
+
compiled out of the `.kv` is staged as a `.pyx` and compiled to an extension,
|
|
172
|
+
so neither the `.kv` nor the `.py` that fed it reaches the wheel:
|
|
173
|
+
|
|
174
|
+
```toml
|
|
175
|
+
[tool.ksp-builder]
|
|
176
|
+
cythonize = true
|
|
177
|
+
py_to_pyx = true
|
|
178
|
+
compile_kv = true
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
kvapp/__init__.py -> kvapp/__init__.py
|
|
183
|
+
kvapp/__main__.py -> kvapp/__main__.py
|
|
184
|
+
kvapp/app.py + kvapp/app.kv -> kvapp/app.cpython-313-darwin.so
|
|
185
|
+
kvapp/theme.kv -> kvapp/theme.cpython-313-darwin.so
|
|
186
|
+
kvapp/assets/logo.png -> kvapp/assets/logo.png
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
A module named by `cythonize_exclude` is still compiled out of its KV file, it
|
|
190
|
+
just stays a plain `.py`. `__init__` and `__main__` are never turned into
|
|
191
|
+
extensions here either.
|
|
192
|
+
|
|
193
|
+
Editable installs (`pip install -e .`) leave `.kv` files alone — the source
|
|
194
|
+
tree is what gets imported, so a generated module would never be used and your
|
|
195
|
+
`.kv` edits keep taking effect during development.
|
|
196
|
+
|
|
197
|
+
### Android Gradle config — `[tool.kivy-school.android]`
|
|
198
|
+
|
|
199
|
+
When present, `ksp-builder` generates a `.gradle/<package_name>.json` file and
|
|
200
|
+
injects it into the built wheel and sdist. `ksproject` can then discover and
|
|
201
|
+
merge these JSON files from all installed packages to assemble the final Gradle
|
|
202
|
+
build configuration (permissions, gradle dependencies, etc.).
|
|
203
|
+
|
|
204
|
+
```toml
|
|
205
|
+
[tool.kivy-school]
|
|
206
|
+
app_name = "MyApp"
|
|
207
|
+
|
|
208
|
+
[tool.kivy-school.android]
|
|
209
|
+
package_name = "org.example.myapp"
|
|
210
|
+
gradle_dependencies = [
|
|
211
|
+
"com.google.firebase:firebase-analytics:21.0.0",
|
|
212
|
+
]
|
|
213
|
+
permissions = [
|
|
214
|
+
"INTERNET",
|
|
215
|
+
"CAMERA",
|
|
216
|
+
]
|
|
217
|
+
[tool.kivy-school.android.meta_data]
|
|
218
|
+
"com.google.android.gms.ads.APPLICATION_ID" = "ca-app-pub-3940256099942544~3347511713"
|
|
219
|
+
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Java sources — `[tool.pyjnius]`
|
|
223
|
+
|
|
224
|
+
Java source files are injected into the wheel and sdist under `.java/`, following
|
|
225
|
+
the [pyjnius-builder](https://github.com/kivy-school/pyjnius-builder) convention.
|
|
226
|
+
|
|
227
|
+
```toml
|
|
228
|
+
[tool.pyjnius]
|
|
229
|
+
java-paths = ["java/"]
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Swift packages — `[tool.pyswiftkit]`
|
|
233
|
+
|
|
234
|
+
If `pyswiftkit-builder` is installed and `[tool.pyswiftkit]` is configured,
|
|
235
|
+
`swift build` runs automatically before the wheel is assembled and the compiled
|
|
236
|
+
artifacts are injected into the wheel.
|
|
237
|
+
|
|
238
|
+
```toml
|
|
239
|
+
[tool.pyswiftkit]
|
|
240
|
+
products = ["mymodule"]
|
|
241
|
+
```
|
|
242
|
+
|