Skip to content

Commit

Permalink
Add more examples of implemented features (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
robert3005 authored Sep 4, 2023
1 parent c57300d commit 096f3f9
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 3 deletions.
6 changes: 5 additions & 1 deletion docs/guide/_2_functions.md
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
# Python Functions
# Python Functions

```zig title="src/functions.zig"
--8<-- "example/functions.zig"
```
6 changes: 5 additions & 1 deletion docs/guide/_3_classes.md
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
# Python Classes
# Python Classes

```zig title="src/classes.zig"
--8<-- "example/classes.zig"
```
38 changes: 38 additions & 0 deletions example/classes.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
const std = @import("std");
const py = @import("pydust");

pub const Animal = py.class("Animal", struct {
pub const __doc__ = "Animal docstring";
});

pub const Dog = py.subclass("Dog", &.{Animal}, struct {
pub const __doc__ = "Adorable animal docstring";
const Self = @This();

name: [:0]const u8,

pub fn __init__(self: *Self, args: *const extern struct { name: py.PyString }) !void {
args.name.incref();
self.name = try args.name.asSlice();
}

pub fn get_name(self: *const Self) !py.PyString {
return py.PyString.fromSlice(self.name);
}

pub fn make_noise() !py.PyString {
return py.PyString.fromSlice("Bark!");
}
});

pub const Owner = py.class("Owner", struct {
pub const __doc__ = "Takes care of an animal";

pub fn adopt_puppy(args: *const extern struct { name: py.PyString }) !py.PyObject {
return try py.init(Dog, .{ .name = args.name });
}
});

comptime {
py.module(@This());
}
9 changes: 9 additions & 0 deletions example/functions.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const py = @import("pydust");

pub fn double(args: *const extern struct { x: py.PyLong }) !i64 {
return try args.x.as(i64) * 2;
}

comptime {
py.module(@This());
}
2 changes: 1 addition & 1 deletion pydust/buildzig.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def generate_build_zig(build_zig_file):
f"""
// For each Python ext_module, generate a shared library and test runner.
const pyconf = b.addOptions();
pyconf.addOption([:0]const u8, "module_name", "{ext_module.libname}");
pyconf.addOption([:0]const u8, "module_name", "{ext_module.name}");
pyconf.addOption(bool, "limited_api", {str(ext_module.limited_api).lower()});
pyconf.addOption([:0]const u8, "hexversion", "{PYVER_HEX}");
Expand Down
8 changes: 8 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,11 @@ root = "example/modules.zig"
[[tool.pydust.ext_module]]
name = "example.result_types"
root = "example/result_types.zig"

[[tool.pydust.ext_module]]
name = "example.functions"
root = "example/functions.zig"

[[tool.pydust.ext_module]]
name = "example.classes"
root = "example/classes.zig"
21 changes: 21 additions & 0 deletions test/test_classes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import pytest

from example import classes


def test_hierarchy():
assert issubclass(classes.Dog, classes.Animal)
assert isinstance(classes.Dog("Pupper's name"), classes.Animal)


def test_make_noise():
with pytest.raises(AttributeError):
classes.Animal().make_noise()
assert classes.Dog("Pupper's name").make_noise() == "Bark!"


def test_adopt():
owner = classes.Owner()
adopted = owner.adopt_puppy("Cute pupper's name")
assert isinstance(adopted, classes.Dog)
assert adopted.get_name() == "Cute pupper's name"
17 changes: 17 additions & 0 deletions test/test_functions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import inspect

import pytest

from example import functions


def test_double():
assert functions.double(10) == 20
with pytest.raises(TypeError, match="'float' object cannot be interpreted as an integer"):
functions.double(0.1)


def test_text_signature():
assert inspect.signature(functions.double) == inspect.Signature(
[inspect.Parameter("x", kind=inspect._ParameterKind.POSITIONAL_ONLY)]
)

0 comments on commit 096f3f9

Please sign in to comment.