Skip to content

Commit

Permalink
PySlice (#152)
Browse files Browse the repository at this point in the history
  • Loading branch information
gatesn authored Sep 28, 2023
1 parent febac87 commit 5b40c58
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 6 deletions.
15 changes: 13 additions & 2 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ pub fn build(b: *std.Build) void {

const pythonInc = getPythonIncludePath(python_exe, b.allocator) catch @panic("Missing python");
const pythonLib = getPythonLibraryPath(python_exe, b.allocator) catch @panic("Missing python");
const pythonVer = getPythonLDVersion(python_exe, b.allocator) catch @panic("Missing python");
const pythonLibName = std.fmt.allocPrint(b.allocator, "python{s}", .{pythonVer}) catch @panic("Missing python");

const test_step = b.step("test", "Run library tests");
const docs_step = b.step("docs", "Generate docs");
Expand Down Expand Up @@ -52,7 +54,7 @@ pub fn build(b: *std.Build) void {
main_tests.linkLibC();
main_tests.addIncludePath(.{ .path = pythonInc });
main_tests.addLibraryPath(.{ .path = pythonLib });
main_tests.linkSystemLibrary("python3.11");
main_tests.linkSystemLibrary(pythonLibName);
main_tests.addAnonymousModule("pyconf", .{ .source_file = .{ .path = "./pyconf.dummy.zig" } });

const run_main_tests = b.addRunArtifact(main_tests);
Expand All @@ -69,7 +71,7 @@ pub fn build(b: *std.Build) void {
example_lib.linkLibC();
main_tests.addIncludePath(.{ .path = pythonInc });
main_tests.addLibraryPath(.{ .path = pythonLib });
main_tests.linkSystemLibrary("python3.11");
main_tests.linkSystemLibrary(pythonLibName);
main_tests.addAnonymousModule("pydust", .{ .source_file = .{ .path = "pydust/src/pydust.zig" } });
main_tests.addAnonymousModule("pyconf", .{ .source_file = .{ .path = "./pyconf.dummy.zig" } });

Expand Down Expand Up @@ -103,3 +105,12 @@ fn getPythonLibraryPath(python_exe: []const u8, allocator: std.mem.Allocator) ![
defer allocator.free(includeResult.stderr);
return includeResult.stdout;
}

fn getPythonLDVersion(python_exe: []const u8, allocator: std.mem.Allocator) ![]const u8 {
const includeResult = try std.process.Child.exec(.{
.allocator = allocator,
.argv = &.{ python_exe, "-c", "import sysconfig; print(sysconfig.get_config_var('LDVERSION'), end='')" },
});
defer allocator.free(includeResult.stderr);
return includeResult.stdout;
}
2 changes: 1 addition & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pydust/src/trampoline.zig
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ pub fn Trampoline(comptime T: type) type {
// Early return to handle optionals
if (typeInfo == .Optional) {
const value = object orelse return null;
if (py.is_none(value)) return null;
return @as(T, try Trampoline(typeInfo.Optional.child).unwrap(value));
}

Expand Down
1 change: 1 addition & 0 deletions pydust/src/types.zig
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub usingnamespace @import("types/list.zig");
pub usingnamespace @import("types/long.zig");
pub usingnamespace @import("types/module.zig");
pub usingnamespace @import("types/obj.zig");
pub usingnamespace @import("types/slice.zig");
pub usingnamespace @import("types/str.zig");
pub usingnamespace @import("types/tuple.zig");
pub usingnamespace @import("types/type.zig");
3 changes: 2 additions & 1 deletion pydust/src/types/dict.zig
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,8 @@ test "PyDict set and get" {
defer pd.decref();

const bar = try py.PyString.create("bar");
try pd.setOwnedItem("foo", bar);
defer bar.decref();
try pd.setItem("foo", bar);

try testing.expect(try pd.contains("foo"));
try testing.expectEqual(@as(usize, 1), pd.length());
Expand Down
60 changes: 60 additions & 0 deletions pydust/src/types/slice.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

const std = @import("std");
const py = @import("../pydust.zig");
const PyObjectMixin = @import("./obj.zig").PyObjectMixin;
const ffi = py.ffi;
const PyError = @import("../errors.zig").PyError;

/// Wrapper for Python PySlice.
pub const PySlice = extern struct {
obj: py.PyObject,

pub usingnamespace PyObjectMixin("slice", "PySlice", @This());

pub fn create(start: anytype, stop: anytype, step: anytype) !PySlice {
// TODO(ngates): think about how to improve comptime optional handling?
const pystart = if (@typeInfo(@TypeOf(start)) == .Null) null else (try py.create(start)).py;
defer if (@typeInfo(@TypeOf(start)) != .Null) py.decref(pystart);
const pystop = if (@typeInfo(@TypeOf(stop)) == .Null) null else (try py.create(stop)).py;
defer if (@typeInfo(@TypeOf(stop)) != .Null) py.decref(pystop);
const pystep = if (@typeInfo(@TypeOf(step)) == .Null) null else (try py.create(step)).py;
defer if (@typeInfo(@TypeOf(step)) != .Null) py.decref(pystep);

const pyslice = ffi.PySlice_New(pystart, pystop, pystep) orelse return PyError.PyRaised;
return .{ .obj = .{ .py = pyslice } };
}

pub fn getStart(self: PySlice, comptime T: type) !T {
return try py.as(T, try self.obj.get("start"));
}

pub fn getStop(self: PySlice, comptime T: type) !T {
return try py.as(T, try self.obj.get("stop"));
}

pub fn getStep(self: PySlice, comptime T: type) !T {
return try py.as(T, try self.obj.get("step"));
}
};

test "PySlice" {
py.initialize();
defer py.finalize();

const range = try PySlice.create(0, 100, null);
defer range.decref();

try std.testing.expectEqual(@as(u64, 0), try range.getStart(u64));
try std.testing.expectEqual(@as(?u64, null), try range.getStep(?u64));
}
2 changes: 0 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ black = "^23.9.1"
[tool.poetry.group.dev.dependencies]
pytest = "^7.4.0"
ruff = "^0.0.291"
black = "^23.9.1"

[tool.poetry.group.docs.dependencies]
# For generating docs
Expand All @@ -31,7 +30,6 @@ mkdocs-material = "^9.2.6"
mkdocs-include-markdown-plugin = { version = "^6.0.1", python = "<3.13" }
mike = "^1.1.2"


[tool.poetry.group.test.dependencies]
numpy = "^1.25.2"

Expand Down

0 comments on commit 5b40c58

Please sign in to comment.