Skip to content

Commit b8b55e8

Browse files
whitewhite
authored andcommitted
fix: add includeMsgpack flag and per-module CHANGELOGs
- Add includeMsgpack to VenvConfig (defaults to true) so users who don't need python-embed-runtime can opt out of msgpack installation - Add includeBuild 'python-embed-build-common' to root settings.gradle so publish-build-common.yml resolves correctly - Create python-embed-build-common/CHANGELOG.md (1.0.2) - Create python-embed-maven-plugin/CHANGELOG.md (1.0.2) - Update root CHANGELOG.md with 1.0.4 entry for new modules - Update VenvManagerTest and VenvTaskTest for includeMsgpack changes
1 parent cb59f0c commit b8b55e8

7 files changed

Lines changed: 89 additions & 8 deletions

File tree

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Changelog
2+
3+
## [1.0.2] - 2026-06-26
4+
5+
### Added
6+
- `VenvManager` — shared venv setup logic extracted from Gradle plugin
7+
- `VenvConfig` — configuration record for venv setup
8+
- `PythonDownloader` — downloads python-build-standalone releases from GitHub
9+
- `PythonResolver` — detects system Python and resolves python executable paths
10+
- `FingerprintManager` — incremental rebuild via package hash fingerprinting
11+
- `TarGzExtractor` — custom tar.gz extractor with path traversal protection
12+
- `RequirementsParser` — parses pip requirements.txt files
13+
14+
[build-common-v1.0.2]: https://github.com/howtis/python-embed/releases/tag/build-common-v1.0.2

python-embed-build-common/src/main/java/io/github/howtis/pythonembed/build/VenvConfig.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public final class VenvConfig {
2222
private final Path venvDir;
2323
private final String targetOs;
2424
private final Consumer<String> logger;
25+
private final boolean includeMsgpack;
2526

2627
private VenvConfig(Builder builder) {
2728
this.packages = Collections.unmodifiableList(new ArrayList<>(builder.packages));
@@ -33,6 +34,7 @@ private VenvConfig(Builder builder) {
3334
this.venvDir = Objects.requireNonNull(builder.venvDir, "venvDir must not be null");
3435
this.targetOs = builder.targetOs;
3536
this.logger = builder.logger;
37+
this.includeMsgpack = builder.includeMsgpack;
3638
}
3739

3840
public List<String> packages() { return packages; }
@@ -45,6 +47,15 @@ private VenvConfig(Builder builder) {
4547
public String targetOs() { return targetOs; }
4648
public Consumer<String> logger() { return logger; }
4749

50+
/**
51+
* Whether to include {@code msgpack} in the installed packages.
52+
* Defaults to {@code true} because {@code msgpack} is required by
53+
* {@code python-embed-runtime}'s bridge protocol.
54+
*
55+
* @return true if msgpack should be included
56+
*/
57+
public boolean includeMsgpack() { return includeMsgpack; }
58+
4859
public static Builder builder() {
4960
return new Builder();
5061
}
@@ -59,6 +70,7 @@ public static final class Builder {
5970
private Path venvDir;
6071
private String targetOs;
6172
private Consumer<String> logger = s -> {};
73+
private boolean includeMsgpack = true;
6274

6375
private Builder() {}
6476

@@ -107,6 +119,11 @@ public Builder logger(Consumer<String> logger) {
107119
return this;
108120
}
109121

122+
public Builder includeMsgpack(boolean includeMsgpack) {
123+
this.includeMsgpack = includeMsgpack;
124+
return this;
125+
}
126+
110127
public VenvConfig build() {
111128
return new VenvConfig(this);
112129
}

python-embed-build-common/src/main/java/io/github/howtis/pythonembed/build/VenvManager.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ public static PythonEnvironment setup(VenvConfig config) throws IOException {
3636

3737
// Collect packages
3838
List<String> packages = new ArrayList<>(config.packages());
39-
if (!packages.contains("msgpack")) {
39+
40+
// Include msgpack by default (required by python-embed-runtime bridge protocol).
41+
// Users who do not need the runtime can opt out via VenvConfig.includeMsgpack(false).
42+
if (config.includeMsgpack() && !packages.contains("msgpack")) {
4043
packages.add("msgpack");
4144
}
4245

python-embed-build-common/src/test/java/io/github/howtis/pythonembed/build/VenvManagerTest.java

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,7 @@ void setup_upToDate_skipsSetup(@TempDir Path tempDir) throws IOException {
6666
Files.createFile(pythonExe);
6767

6868
// Write a fingerprint matching the expected configuration.
69-
// VenvManager.setup() always adds "msgpack" to the packages list,
70-
// so the fingerprint must include it.
69+
// includeMsgpack defaults to true, so msgpack is added to the packages list.
7170
String pythonVersion = "3.12";
7271
String packageHash = FingerprintManager.computePackageHash(
7372
List.of("msgpack"), null, List.of(), null);
@@ -83,4 +82,37 @@ void setup_upToDate_skipsSetup(@TempDir Path tempDir) throws IOException {
8382
assertEquals(venvDir, result.venvDir());
8483
assertEquals("system", result.source());
8584
}
85+
86+
@Test
87+
void setup_upToDate_withoutMsgpack(@TempDir Path tempDir) throws IOException {
88+
Path venvDir = tempDir.resolve("venv");
89+
Files.createDirectories(venvDir);
90+
91+
// Create a mock Python executable
92+
Path pythonExe;
93+
if (PythonResolver.isWindows()) {
94+
pythonExe = venvDir.resolve("python.exe");
95+
} else {
96+
pythonExe = venvDir.resolve("bin").resolve("python3");
97+
Files.createDirectories(pythonExe.getParent());
98+
}
99+
Files.createFile(pythonExe);
100+
101+
// Write a fingerprint matching empty packages (msgpack excluded).
102+
String pythonVersion = "3.12";
103+
String packageHash = FingerprintManager.computePackageHash(
104+
List.of(), null, List.of(), null);
105+
FingerprintManager.write(venvDir, "system", pythonVersion, packageHash);
106+
107+
VenvConfig config = VenvConfig.builder()
108+
.venvDir(venvDir)
109+
.includeMsgpack(false)
110+
.build();
111+
112+
PythonEnvironment result = VenvManager.setup(config);
113+
114+
assertNotNull(result);
115+
assertEquals(venvDir, result.venvDir());
116+
assertEquals("system", result.source());
117+
}
86118
}

python-embed-gradle-plugin/src/test/java/io/github/howtis/pythonembed/gradle/VenvTaskTest.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,8 @@ void createVenv_fingerprintMatchSkipsSetup(@TempDir Path tempDir) throws IOExcep
149149
// Create fake python executable in OS-appropriate location
150150
createPrimaryPythonExe(venvPath);
151151

152-
// Set packages and compute expected fingerprint
153-
// msgpack is auto-added by VenvTask, so include it in the expected hash
152+
// Set packages and compute expected fingerprint.
153+
// includeMsgpack defaults to true in VenvConfig, so msgpack is auto-added.
154154
List<String> packages = List.of("numpy==1.26.4");
155155
task.getPackages().set(packages);
156156
String expectedHash = task.computePackageHash(List.of("numpy==1.26.4", "msgpack"), null, List.of(), null);
@@ -231,7 +231,8 @@ void createVenv_nullPythonSourceForcesFullSetup(@TempDir Path tempDir) throws IO
231231
// Create fake python executable in OS-appropriate location
232232
createPrimaryPythonExe(venvPath);
233233

234-
// Set packages matching the fingerprint
234+
// Set packages matching the fingerprint.
235+
// includeMsgpack defaults to true in VenvConfig, so msgpack is auto-added.
235236
List<String> packages = List.of("numpy==1.26.4");
236237
task.getPackages().set(packages);
237238
String expectedHash = task.computePackageHash(List.of("numpy==1.26.4", "msgpack"), null, List.of(), null);
@@ -278,7 +279,8 @@ void createVenv_pythonVersionMismatchForcesFullSetup(@TempDir Path tempDir) thro
278279
// Create fake python executable
279280
createPrimaryPythonExe(venvPath);
280281

281-
// Set packages matching the fingerprint
282+
// Set packages matching the fingerprint.
283+
// includeMsgpack defaults to true in VenvConfig, so msgpack is auto-added.
282284
List<String> packages = List.of("numpy==1.26.4");
283285
task.getPackages().set(packages);
284286
String expectedHash = task.computePackageHash(List.of("numpy==1.26.4", "msgpack"), null, List.of(), null);
@@ -314,7 +316,8 @@ void createVenv_pythonMissingForcesFullSetup(@TempDir Path tempDir) throws IOExc
314316
// Do NOT create python executable (simulates deleted venv)
315317
Files.createDirectories(venvPath);
316318

317-
// Set packages matching the fingerprint
319+
// Set packages matching the fingerprint.
320+
// includeMsgpack defaults to true in VenvConfig, so msgpack is auto-added.
318321
List<String> packages = List.of("numpy==1.26.4");
319322
task.getPackages().set(packages);
320323
String expectedHash = task.computePackageHash(List.of("numpy==1.26.4", "msgpack"), null, List.of(), null);
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Changelog
2+
3+
## [1.0.2] - 2026-06-26
4+
5+
### Added
6+
- `SetupMojo``python-embed:setup` goal for venv creation and package installation
7+
- `PropertiesMojo``python-embed:properties` goal to expose Python environment properties
8+
- `HelpMojo``python-embed:help` goal with plugin documentation
9+
- Maven plugin descriptor (`plugin.xml`) for `io.github.howtis:python-embed-maven-plugin`
10+
11+
[maven-plugin-v1.0.2]: https://github.com/howtis/python-embed/releases/tag/maven-plugin-v1.0.2

settings.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
rootProject.name = 'python-embed'
22

3+
includeBuild 'python-embed-build-common'
34
includeBuild 'python-embed-gradle-plugin'
45
includeBuild 'python-embed-maven-plugin'
56
include 'python-embed-runtime'

0 commit comments

Comments
 (0)