Skip to content

Commit 33a6b37

Browse files
authored
Merge pull request #33 from pyozig/dev
fix: deduplicate test/bench logic for pip package Windows support
2 parents f6d6972 + 33ae6cd commit 33a6b37

7 files changed

Lines changed: 22 additions & 133 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ All notable changes to PyOZ will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.11.3] - 2026-02-10
9+
10+
### Fixed
11+
- **pip-installed pyoz test/bench on Windows** - Deduplicated test/bench runner logic in the pip package (`pypi/src/lib.zig`) by delegating to `commands.runTests`/`commands.runBench` instead of maintaining a separate copy. The previous duplicate code had hardcoded `zig-out/lib/` paths and no package mode support, causing test failures on Windows.
12+
813
## [0.11.2] - 2026-02-10
914

1015
### Fixed

build.zig.zon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.{
22
.name = .PyOZ,
3-
.version = "0.11.2",
3+
.version = "0.11.3",
44
.fingerprint = 0x4d3668413e69d99e,
55
.dependencies = .{},
66
.paths = .{

pypi/build.zig.zon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.{
22
.name = .pyoz,
3-
.version = "0.11.2",
3+
.version = "0.11.3",
44
.fingerprint = 0x43eec3150282fd1f,
55
.dependencies = .{
66
.PyOZ = .{

pypi/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "pyoz"
7-
version = "0.11.2"
7+
version = "0.11.3"
88
description = "Python extension modules in Zig, made easy"
99
readme = "README.md"
1010
license = "MIT"

pypi/setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[metadata]
22
name = pyoz
3-
version = 0.11.2
3+
version = 0.11.3
44

55
[options]
66
packages = pyoz

pypi/src/lib.zig

Lines changed: 12 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
const std = @import("std");
2-
const builtin = @import("builtin");
32
const pyoz = @import("PyOZ");
43
const version = @import("version");
54

65
const project = @import("project.zig");
76
const builder = @import("builder.zig");
7+
const commands = @import("commands.zig");
88
const wheel = @import("wheel.zig");
9-
const symreader = @import("symreader.zig");
109

1110
fn init_project(name: ?[]const u8, in_current_dir: ?bool, local_pyoz_path: ?[]const u8, package_layout: ?bool) !void {
1211
try project.create(std.heap.page_allocator, name, in_current_dir orelse false, local_pyoz_path, package_layout orelse false);
@@ -29,137 +28,22 @@ fn publish_wheels(test_pypi: ?bool) !void {
2928
}
3029

3130
fn run_tests(release: ?bool, verbose: ?bool) !void {
32-
const alloc = std.heap.page_allocator;
33-
const rel = release orelse false;
34-
const verb = verbose orelse false;
35-
36-
// Build the module
37-
var build_result = try builder.buildModule(alloc, rel);
38-
defer build_result.deinit(alloc);
39-
40-
// Extract tests from the compiled module
41-
const test_content = try symreader.extractTests(alloc, build_result.module_path);
42-
if (test_content == null or test_content.?.len == 0) {
43-
std.debug.print("\nNo tests found in module.\n", .{});
44-
std.debug.print("Add .tests to your pyoz.module() config:\n\n", .{});
45-
std.debug.print(" .tests = &.{{\n", .{});
46-
std.debug.print(" pyoz.@\"test\"(\"my test\",\n", .{});
47-
std.debug.print(" \\\\assert mymod.add(2, 3) == 5\n", .{});
48-
std.debug.print(" ),\n", .{});
49-
std.debug.print(" }},\n", .{});
50-
return;
51-
}
52-
defer alloc.free(test_content.?);
53-
54-
// Write test file
55-
const test_file = "zig-out/lib/__pyoz_test.py";
56-
{
57-
const f = try std.fs.cwd().createFile(test_file, .{});
58-
defer f.close();
59-
try f.writeAll(test_content.?);
60-
}
61-
62-
std.debug.print("\nRunning tests...\n\n", .{});
63-
64-
const python_cmd = builder.getPythonCommand();
65-
const path_sep = if (builtin.os.tag == .windows) ";" else ":";
66-
67-
const existing_pp = std.process.getEnvVarOwned(alloc, "PYTHONPATH") catch "";
68-
defer if (existing_pp.len > 0) alloc.free(existing_pp);
69-
70-
const new_pp = if (existing_pp.len > 0)
71-
try std.fmt.allocPrint(alloc, "zig-out/lib{s}{s}", .{ path_sep, existing_pp })
72-
else
73-
try alloc.dupe(u8, "zig-out/lib");
74-
defer alloc.free(new_pp);
75-
76-
var argv_buf: [6][]const u8 = undefined;
77-
var argc: usize = 0;
78-
argv_buf[argc] = python_cmd;
79-
argc += 1;
80-
argv_buf[argc] = "-m";
81-
argc += 1;
82-
argv_buf[argc] = "unittest";
83-
argc += 1;
84-
argv_buf[argc] = test_file;
85-
argc += 1;
86-
if (verb) {
87-
argv_buf[argc] = "-v";
88-
argc += 1;
31+
var args_buf: [2][]const u8 = undefined;
32+
var args_len: usize = 0;
33+
if (release orelse false) {
34+
args_buf[args_len] = "--release";
35+
args_len += 1;
8936
}
90-
91-
var env_map = try std.process.getEnvMap(alloc);
92-
defer env_map.deinit();
93-
try env_map.put("PYTHONPATH", new_pp);
94-
95-
var child = std.process.Child.init(argv_buf[0..argc], alloc);
96-
child.env_map = &env_map;
97-
child.stderr_behavior = .Inherit;
98-
child.stdout_behavior = .Inherit;
99-
100-
const term = try child.spawnAndWait();
101-
if (term.Exited != 0) {
102-
std.process.exit(1);
37+
if (verbose orelse false) {
38+
args_buf[args_len] = "--verbose";
39+
args_len += 1;
10340
}
41+
try commands.runTests(std.heap.page_allocator, args_buf[0..args_len]);
10442
}
10543

10644
fn run_bench() !void {
107-
const alloc = std.heap.page_allocator;
108-
109-
// Always build in release mode for benchmarks
110-
var build_result = try builder.buildModule(alloc, true);
111-
defer build_result.deinit(alloc);
112-
113-
// Extract benchmarks from the compiled module
114-
const bench_content = try symreader.extractBenchmarks(alloc, build_result.module_path);
115-
if (bench_content == null or bench_content.?.len == 0) {
116-
std.debug.print("\nNo benchmarks found in module.\n", .{});
117-
std.debug.print("Add .benchmarks to your pyoz.module() config:\n\n", .{});
118-
std.debug.print(" .benchmarks = &.{{\n", .{});
119-
std.debug.print(" pyoz.bench(\"my benchmark\",\n", .{});
120-
std.debug.print(" \\\\mymod.add(100, 200)\n", .{});
121-
std.debug.print(" ),\n", .{});
122-
std.debug.print(" }},\n", .{});
123-
return;
124-
}
125-
defer alloc.free(bench_content.?);
126-
127-
// Write benchmark file
128-
const bench_file = "zig-out/lib/__pyoz_bench.py";
129-
{
130-
const f = try std.fs.cwd().createFile(bench_file, .{});
131-
defer f.close();
132-
try f.writeAll(bench_content.?);
133-
}
134-
135-
std.debug.print("\nRunning benchmarks...\n", .{});
136-
137-
const python_cmd = builder.getPythonCommand();
138-
const path_sep = if (builtin.os.tag == .windows) ";" else ":";
139-
140-
const existing_pp = std.process.getEnvVarOwned(alloc, "PYTHONPATH") catch "";
141-
defer if (existing_pp.len > 0) alloc.free(existing_pp);
142-
143-
const new_pp = if (existing_pp.len > 0)
144-
try std.fmt.allocPrint(alloc, "zig-out/lib{s}{s}", .{ path_sep, existing_pp })
145-
else
146-
try alloc.dupe(u8, "zig-out/lib");
147-
defer alloc.free(new_pp);
148-
149-
var env_map = try std.process.getEnvMap(alloc);
150-
defer env_map.deinit();
151-
try env_map.put("PYTHONPATH", new_pp);
152-
153-
const argv = [_][]const u8{ python_cmd, bench_file };
154-
var child = std.process.Child.init(&argv, alloc);
155-
child.env_map = &env_map;
156-
child.stderr_behavior = .Inherit;
157-
child.stdout_behavior = .Inherit;
158-
159-
const term = try child.spawnAndWait();
160-
if (term.Exited != 0) {
161-
std.process.exit(1);
162-
}
45+
const args = [_][]const u8{};
46+
try commands.runBench(std.heap.page_allocator, &args);
16347
}
16448

16549
fn get_version() []const u8 {

src/version.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
pub const major: u8 = 0;
55
pub const minor: u8 = 11;
6-
pub const patch: u8 = 2;
6+
pub const patch: u8 = 3;
77

88
/// Pre-release identifier (e.g., "alpha", "beta", "rc1", or null for release)
99
pub const pre_release: ?[]const u8 = null;

0 commit comments

Comments
 (0)