zig-zon 0.2.1__tar.gz → 0.2.3__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.
Files changed (23) hide show
  1. {zig-zon-0.2.1 → zig-zon-0.2.3}/PKG-INFO +23 -2
  2. {zig-zon-0.2.1 → zig-zon-0.2.3}/build.zig +28 -36
  3. {zig-zon-0.2.1 → zig-zon-0.2.3}/build.zig.zon +4 -3
  4. zig-zon-0.2.3/pkg-info.zon +15 -0
  5. {zig-zon-0.2.1 → zig-zon-0.2.3}/setup.py +4 -2
  6. zig-zon-0.2.3/setup.zig.json +1 -0
  7. {zig-zon-0.2.1 → zig-zon-0.2.3}/src/zig_zon.zig +38 -27
  8. {zig-zon-0.2.1 → zig-zon-0.2.3}/zig-pkg/zig_python_sdist/build.zig +17 -26
  9. {zig-zon-0.2.1 → zig-zon-0.2.3}/zig-pkg/zig_python_sdist/build.zig.zon +2 -1
  10. zig-zon-0.2.3/zig-pkg/zig_python_sdist/pkg-info.zon +11 -0
  11. zig-zon-0.2.3/zig-pkg/zig_python_sdist/src/build/CPython.zig +125 -0
  12. {zig-zon-0.2.1 → zig-zon-0.2.3}/zig-pkg/zig_python_sdist/src/build/SDistStep.zig +26 -2
  13. {zig-zon-0.2.1 → zig-zon-0.2.3}/zig-pkg/zig_python_sdist/src/build/VenvInstallTest.zig +29 -4
  14. zig-zon-0.2.3/zig-pkg/zig_python_sdist/src/build/extract_link_info.py +84 -0
  15. {zig-zon-0.2.1 → zig-zon-0.2.3}/zig-pkg/zig_python_sdist/src/build/pkg_info.zig +0 -19
  16. zig-zon-0.2.3/zig-pkg/zig_python_sdist/src/build/python.zig +217 -0
  17. zig-zon-0.2.1/setup.zig.json +0 -1
  18. zig-zon-0.2.1/zig-pkg/zig_python_sdist/src/build/CPython.zig +0 -198
  19. zig-zon-0.2.1/zig-pkg/zig_python_sdist/src/build/extract_link_info.py +0 -72
  20. zig-zon-0.2.1/zig-pkg/zig_python_sdist/src/build/python.zig +0 -50
  21. {zig-zon-0.2.1 → zig-zon-0.2.3}/zig-pkg/zig_python_sdist/LICENSE +0 -0
  22. {zig-zon-0.2.1 → zig-zon-0.2.3}/zig-pkg/zig_python_sdist/README.md +0 -0
  23. {zig-zon-0.2.1 → zig-zon-0.2.3}/zig-pkg/zig_python_sdist/src/build/LowerDashStringFormatter.zig +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zig-zon
3
- Version: 0.2.1
3
+ Version: 0.2.3
4
4
  Summary: a native cpython extension to parse zig object notation strings
5
5
  Author-email: Tobias Simetsreiter <dasimmet@gmail.com>
6
6
  Maintainer-email: Tobias Simetsreiter <dasimmet@gmail.com>
@@ -10,6 +10,10 @@ Requires-Python: >=3.8
10
10
  Project-URL: Homepage, https://codeberg.org/dasimmet/python-zig-zon
11
11
  Project-URL: Issues, https://codeberg.org/dasimmet/python-zig-zon/issues
12
12
  Classifier: Development Status :: 4 - Beta
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Zig
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Topic :: Software Development :: Libraries
13
17
  Description-Content-Type: text/markdown
14
18
 
15
19
  # Python Zig Zon Parser
@@ -25,7 +29,7 @@ Depending on your OS, you may need the python development headers
25
29
 
26
30
  ## Usage
27
31
 
28
- install from source on pypi:
32
+ install from source on <https://pypi.org/project/zig-zon>:
29
33
 
30
34
  ```bash
31
35
  pip install zig-zon
@@ -41,6 +45,23 @@ print(parsed)
41
45
 
42
46
  or, look at the [test file](https://codeberg.org/dasimmet/python-zig-zon/src/branch/main/src/test_zig_zon.py)
43
47
 
48
+ ## Supported values and their python type
49
+
50
+ - `structs` -> `dict`
51
+ - `tuples` -> `list`
52
+ - `integer literals` -> `int`
53
+ - `hex literals` -> `int`
54
+ - `float literals` -> `float`
55
+ - `booleans` -> `bool`
56
+ - `null` -> `None`
57
+ - `string literals` -> `str`
58
+ - `bare enum literals` -> `str`
59
+ - `quoted enum literals` -> `str`
60
+
61
+ ## Not supported values
62
+
63
+ - `bigint`
64
+
44
65
  ## How it works
45
66
 
46
67
  The `zig build` commands produces a python source distribution archive ready
@@ -2,35 +2,13 @@ const std = @import("std");
2
2
  const Build = std.Build;
3
3
  const zig_python_sdist = @import("zig_python_sdist");
4
4
  const zon = @import("build.zig.zon");
5
- const CPython = @import("setuptools_zig_build").CPython;
6
5
 
7
6
  pub fn build(b: *Build) void {
8
7
  const target = b.standardTargetOptions(.{});
9
8
  const optimize = b.standardOptimizeOption(.{});
10
9
 
11
10
  // this target and section of our build is used at pip install time
12
- const ext_install_step = b.step("pyext", "build python extension module");
13
- {
14
- const cpython = zig_python_sdist.CPython.find(b);
15
-
16
- const lib = b.addLibrary(.{
17
- .name = "zig_zon",
18
- .root_module = b.addModule("zig_zon", .{
19
- .root_source_file = b.path("src/zig_zon.zig"),
20
- .target = target,
21
- .optimize = optimize,
22
- }),
23
- .linkage = .dynamic,
24
- });
25
- cpython.link(b, .{
26
- .lib = lib,
27
- .version = zon.version,
28
- .optimize = .ReleaseSmall,
29
- });
30
- const ext_install = zig_python_sdist.CPython.installExtLib(b, lib);
31
-
32
- ext_install_step.dependOn(&ext_install.step);
33
- }
11
+ const ext_install_step = b.step("bdist-wheel", "build python extension module");
34
12
 
35
13
  // this generates a python sdist archive
36
14
  const sdist = zig_python_sdist.create(b, .{
@@ -38,21 +16,14 @@ pub fn build(b: *Build) void {
38
16
  .version = zon.version,
39
17
  .description = b.path("README.md"),
40
18
  .build = .{
41
- .args = &.{ ext_install_step.name, b.fmt("-Doptimize={s}", .{@tagName(optimize)}) },
42
- },
43
- .extra_pkg_info = &.{
44
- .{ .key = "Summary", .value = "a native cpython extension to parse zig object notation strings" },
45
- .{ .key = "Author-email", .value = "Tobias Simetsreiter <dasimmet@gmail.com>" },
46
- .{ .key = "Maintainer-email", .value = "Tobias Simetsreiter <dasimmet@gmail.com>" },
47
- .{ .key = "License-Expression", .value = "MIT" },
48
- .{ .key = "Keywords", .value = "zig,ziglang,cpython,native,sdist,zon" },
49
- .{ .key = "Requires-Python", .value = ">=3.8" },
50
- .{ .key = "Project-URL", .value = "Homepage, https://codeberg.org/dasimmet/python-zig-zon" },
51
- .{ .key = "Project-URL", .value = "Issues, https://codeberg.org/dasimmet/python-zig-zon/issues" },
52
- // .{ .key = "Requires-Python", .value = ">=3.8" },
53
- .{ .key = "Classifier", .value = "Development Status :: 4 - Beta" },
19
+ .args = &.{
20
+ ext_install_step.name,
21
+ b.fmt("-Doptimize={s}", .{@tagName(optimize)}),
22
+ },
54
23
  },
24
+ .extra_pkg_info = @import("pkg-info.zon"),
55
25
  .files = &.{
26
+ .{ .src = b.path("pkg-info.zon"), .dest = "pkg-info.zon" },
56
27
  .{ .src = b.path("build.zig.zon"), .dest = "build.zig.zon" },
57
28
  .{ .src = b.path("build.zig"), .dest = "build.zig" },
58
29
  .{ .src = b.path("src/zig_zon.zig"), .dest = "src/zig_zon.zig" },
@@ -73,8 +44,29 @@ pub fn build(b: *Build) void {
73
44
  .{
74
45
  .sdist = sdist.getEmittedArchive(),
75
46
  .test_py = b.path("src/test_zig_zon.py"),
47
+ .twine_check = true,
76
48
  .no_clean = b.option(bool, "pip-no-clean", "dont cleanup pip temp dirs") orelse false,
77
49
  },
78
50
  );
79
51
  b.step("test-pip-install", "").dependOn(test_pip_install.step);
52
+
53
+ {
54
+ const lib = b.addLibrary(.{
55
+ .name = "zig_zon",
56
+ .root_module = b.addModule("zig_zon", .{
57
+ .root_source_file = b.path("src/zig_zon.zig"),
58
+ .target = target,
59
+ .optimize = optimize,
60
+ }),
61
+ .linkage = .dynamic,
62
+ });
63
+ zig_python_sdist.linkCPython(b, .{
64
+ .lib = lib,
65
+ .version = zon.version,
66
+ .optimize = .ReleaseSmall,
67
+ });
68
+ const ext_install = zig_python_sdist.installExtLib(b, lib);
69
+
70
+ ext_install_step.dependOn(&ext_install.step);
71
+ }
80
72
  }
@@ -1,18 +1,19 @@
1
1
  .{
2
2
  .name = .python_zig_zon,
3
3
  .fingerprint = 0x3d332656a3644fc9,
4
- .version = "0.2.1",
4
+ .version = "0.2.3",
5
5
  .minimum_zig_version = "0.16.0",
6
6
  .dependencies = .{
7
7
  .zig_python_sdist = .{
8
- .url = "git+https://codeberg.org/dasimmet/zig-python-sdist.git#d3b3de8f114f891e0d62c923441bb925eb8014ae",
9
- .hash = "zig_python_sdist-0.0.1-wjgdOg-SAACQzg1tSdozTV7Tg11rIzVRDlx-8XIzOFee",
8
+ .url = "git+https://codeberg.org/dasimmet/zig-python-sdist.git?ref=0.0.2#3dd2c2eaf62a7007d6c257c357ded7911537621a",
9
+ .hash = "zig_python_sdist-0.0.2-wjgdOpyrAADPCiUfh4LoKFNZkHstj4a1bIyEuwnNKkcc",
10
10
  },
11
11
  },
12
12
  .paths = .{
13
13
  "src",
14
14
  "build.zig",
15
15
  "build.zig.zon",
16
+ "pkg-info.zon",
16
17
  "LICENSE",
17
18
  "README.md",
18
19
  "setup.py",
@@ -0,0 +1,15 @@
1
+ .{
2
+ .{ .key = "Summary", .value = "a native cpython extension to parse zig object notation strings" },
3
+ .{ .key = "Author-email", .value = "Tobias Simetsreiter <dasimmet@gmail.com>" },
4
+ .{ .key = "Maintainer-email", .value = "Tobias Simetsreiter <dasimmet@gmail.com>" },
5
+ .{ .key = "License-Expression", .value = "MIT" },
6
+ .{ .key = "Keywords", .value = "zig,ziglang,cpython,native,sdist,zon" },
7
+ .{ .key = "Requires-Python", .value = ">=3.8" },
8
+ .{ .key = "Project-URL", .value = "Homepage, https://codeberg.org/dasimmet/python-zig-zon" },
9
+ .{ .key = "Project-URL", .value = "Issues, https://codeberg.org/dasimmet/python-zig-zon/issues" },
10
+ .{ .key = "Classifier", .value = "Development Status :: 4 - Beta" },
11
+ .{ .key = "Classifier", .value = "Programming Language :: Python :: 3" },
12
+ .{ .key = "Classifier", .value = "Programming Language :: Zig" },
13
+ .{ .key = "Classifier", .value = "Intended Audience :: Developers" },
14
+ .{ .key = "Classifier", .value = "Topic :: Software Development :: Libraries" },
15
+ }
@@ -39,10 +39,11 @@ class ZigBuildWheel(bdist_wheel):
39
39
  subprocess.check_call(build_cmd)
40
40
 
41
41
  os.makedirs(self.bdist_dir, exist_ok=True)
42
- artifacts = glob.glob("zig-out/lib/*")
42
+ copy_pattern = "zig-out/{}".format(setup_json['build']['copy_pattern'])
43
+ artifacts = glob.glob(copy_pattern)
43
44
  if len(artifacts) == 0:
44
45
  raise Exception(
45
- 'no zig artifacts found in {}/zig-out/lib/*'.format(cwd))
46
+ 'no zig artifacts found in {}/{}'.format(cwd, copy_pattern))
46
47
 
47
48
  for it in artifacts:
48
49
  shutil.copyfile(it, os.path.join(
@@ -55,6 +56,7 @@ setup(
55
56
  name=setup_json['name'],
56
57
  version=mkversion(setup_json['version']),
57
58
  cmdclass={'bdist_wheel': ZigBuildWheel},
59
+ install_requires=setup_json['install_requires'],
58
60
  setup_requires=[
59
61
  "setuptools",
60
62
  "wheel",
@@ -0,0 +1 @@
1
+ {"name":"zig_zon","version":{"major":0,"minor":2,"patch":3,"pre":null,"build":null},"zig_version":{"major":0,"minor":16,"patch":0,"pre":null,"build":null},"build":{"args":["bdist-wheel","-Doptimize=Debug","--fork=zig-pkg/zig_python_sdist"],"requires":[],"copy_pattern":"lib/*"},"install_requires":[]}
@@ -26,20 +26,23 @@ pub var zigmodule = c.PyModuleDef{
26
26
  pub export fn PyInit_zig_zon() [*c]c.PyObject {
27
27
  const mod = c.PyModule_Create(&zigmodule);
28
28
  cpython.addVersion(mod);
29
- cpython.addZigTargetTriple(mod);
29
+ cpython.addZigBuiltin(mod);
30
30
  return mod;
31
31
  }
32
32
 
33
33
  pub fn parse(self: [*]PyObject, args: [*]PyObject) callconv(.c) [*c]PyObject {
34
34
  _ = self;
35
- var zon_txt: [*c]u8 = undefined;
36
- if (!(c.PyArg_ParseTuple(args, "s", &zon_txt) != 0)) return null;
35
+ const zon_slice: [:0]u8 = zon_slice: {
36
+ var zon_txt: [*c]u8 = undefined;
37
+ if (!(c.PyArg_ParseTuple(args, "s", &zon_txt) != 0)) return null;
38
+ break :zon_slice std.mem.sliceTo(zon_txt, 0);
39
+ };
37
40
 
38
41
  var arena_instance = std.heap.ArenaAllocator.init(std.heap.c_allocator);
39
42
  defer arena_instance.deinit();
40
43
  const arena = arena_instance.allocator();
41
44
 
42
- const ast = Ast.parse(arena, std.mem.sliceTo(zon_txt, 0), .zon) catch |err| {
45
+ const ast = Ast.parse(arena, zon_slice, .zon) catch |err| {
43
46
  const errstr = std.fmt.allocPrintSentinel(
44
47
  arena,
45
48
  "zig-zon ast error: {s}",
@@ -50,23 +53,25 @@ pub fn parse(self: [*]PyObject, args: [*]PyObject) callconv(.c) [*c]PyObject {
50
53
  return null;
51
54
  };
52
55
 
53
- // TODO: use zoir instead of AST maybe?
54
- // this is unused for now and instead i walk the AST, but i keep it in as a sanity check for now.
55
- var zoir = ZonGen.generate(arena, ast, .{ .parse_str_lits = false }) catch |err| {
56
- const errstr = std.fmt.allocPrintSentinel(
57
- arena,
58
- "zig-zon zoir error: {s}",
59
- .{@errorName(err)},
60
- 0,
61
- ) catch "";
62
- c.PyErr_SetString(c.PyExc_Exception, errstr.ptr);
63
- return null;
64
- };
65
- defer zoir.deinit(arena);
56
+ {
57
+ // TODO: use zoir instead of AST maybe?
58
+ // this is unused for now and instead i walk the AST myself, but i keep it in as a sanity check.
59
+ var zoir = ZonGen.generate(arena, ast, .{ .parse_str_lits = false }) catch |err| {
60
+ const errstr = std.fmt.allocPrintSentinel(
61
+ arena,
62
+ "zig-zon zoir error: {s}",
63
+ .{@errorName(err)},
64
+ 0,
65
+ ) catch "";
66
+ c.PyErr_SetString(c.PyExc_Exception, errstr.ptr);
67
+ return null;
68
+ };
69
+ defer zoir.deinit(arena);
70
+ }
66
71
 
67
72
  const main_node_index = ast.nodeData(.root).node;
68
73
 
69
- return parseZon(arena, ast, main_node_index) catch |err| {
74
+ return parseZonAst(arena, ast, main_node_index) catch |err| {
70
75
  const errstr = std.fmt.allocPrintSentinel(
71
76
  arena,
72
77
  "zig-zon parse error: {s}",
@@ -86,10 +91,11 @@ const ZonError = error{
86
91
  StructExpected,
87
92
  StructIdentifierExpected,
88
93
  NotImplemented,
89
- ZonArrayError,
94
+ ZonArrayInitFailed,
95
+ InvalidLiteral, // from quoted enum literal parse function
90
96
  } || IdentifierError || NumberLiteralError;
91
97
 
92
- fn parseZon(arena: Allocator, tree: Ast, node: Ast.Node.Index) ZonError!*c.PyObject {
98
+ fn parseZonAst(arena: Allocator, tree: Ast, node: Ast.Node.Index) ZonError!*c.PyObject {
93
99
  const node_tag = tree.nodeTag(node);
94
100
  switch (node_tag) {
95
101
  .struct_init_comma,
@@ -114,8 +120,13 @@ fn parseZon(arena: Allocator, tree: Ast, node: Ast.Node.Index) ZonError!*c.PyObj
114
120
  const name_token = tree.firstToken(node);
115
121
  const enum_name = tree.tokenSlice(name_token + 1);
116
122
  if (std.mem.startsWith(u8, enum_name, "@")) {
117
- std.log.err("non bare enum literals not implemented: {s}", .{enum_name});
118
- return error.NotImplemented;
123
+ assert(std.mem.startsWith(u8, enum_name, "@\""));
124
+ assert(std.mem.endsWith(u8, enum_name, "\""));
125
+ const enum_parsed_name = try std.zig.string_literal.parseAlloc(
126
+ arena,
127
+ enum_name[1..enum_name.len],
128
+ );
129
+ return c.Py_BuildValue("s#", enum_parsed_name.ptr, enum_parsed_name.len);
119
130
  }
120
131
 
121
132
  return c.Py_BuildValue("s#", enum_name.ptr, enum_name.len);
@@ -208,7 +219,7 @@ fn parseZonStruct(arena: Allocator, tree: Ast, node: Ast.Node.Index) ZonError!*c
208
219
  for (struct_init.ast.fields) |field_init| {
209
220
  const name_token = tree.firstToken(field_init) - 2;
210
221
  const field_name = try identifierTokenString(arena, tree, name_token);
211
- const field_obj = try parseZon(arena, tree, field_init);
222
+ const field_obj = try parseZonAst(arena, tree, field_init);
212
223
  const set_result = c.PyDict_SetItemString(ret, field_name, field_obj);
213
224
  assert(set_result >= 0);
214
225
  }
@@ -221,13 +232,13 @@ fn parseZonArray(arena: Allocator, tree: Ast, node: Ast.Node.Index) !*c.PyObject
221
232
  const array_init = tree.fullArrayInit(&buf, node) orelse {
222
233
  const tok = tree.nodeMainToken(node);
223
234
  std.log.err("expected paths expression to be a list of strings, got: {d}", .{tok});
224
- return error.ZonArrayError;
235
+ return error.ZonArrayInitFailed;
225
236
  };
226
237
 
227
238
  const ret = c.PyList_New(0);
228
239
 
229
240
  for (array_init.ast.elements) |elem_node| {
230
- const field_ret = try parseZon(arena, tree, elem_node);
241
+ const field_ret = try parseZonAst(arena, tree, elem_node);
231
242
  assert(c.PyList_Append(ret, field_ret) >= 0);
232
243
  }
233
244
  return ret;
@@ -236,10 +247,10 @@ fn parseZonArray(arena: Allocator, tree: Ast, node: Ast.Node.Index) !*c.PyObject
236
247
  const IdentifierError = error{OutOfMemory} || StringLiteralError;
237
248
 
238
249
  fn identifierTokenString(arena: Allocator, ast: Ast, token: Ast.TokenIndex) IdentifierError![:0]const u8 {
239
- std.debug.assert(ast.tokenTag(token) == .identifier);
250
+ assert(ast.tokenTag(token) == .identifier);
240
251
  const ident_name = ast.tokenSlice(token);
241
252
  if (!std.mem.startsWith(u8, ident_name, "@")) {
242
- return try arena.dupeZ(u8, ident_name);
253
+ return try arena.dupeSentinel(u8, ident_name, 0);
243
254
  }
244
255
 
245
256
  var buf = std.ArrayListUnmanaged(u8).empty;
@@ -24,8 +24,6 @@ pub fn build(b: *Build) void {
24
24
 
25
25
  b.installArtifact(exe);
26
26
 
27
- const cpython = CPython.find(b);
28
-
29
27
  const sdist_dummy = b.addLibrary(.{
30
28
  .name = "sdist_dummy",
31
29
  .root_module = b.createModule(.{
@@ -35,13 +33,14 @@ pub fn build(b: *Build) void {
35
33
  }),
36
34
  .linkage = .dynamic,
37
35
  });
38
- cpython.link(b, .{
36
+
37
+ linkCPython(b, .{
39
38
  .lib = sdist_dummy,
40
39
  .version = zon.version,
41
40
  });
42
- const install_ext = CPython.installExtLib(b, sdist_dummy);
41
+ const install_ext = installExtLib(b, sdist_dummy);
43
42
 
44
- const build_ext_step = b.step("build-ext", "build the sdist dummy python module");
43
+ const build_ext_step = b.step("bdist-wheel", "build the sdist dummy python module");
45
44
  build_ext_step.dependOn(&install_ext.step);
46
45
 
47
46
  const sdist = SDistStep.createInternal(b, .{
@@ -50,54 +49,46 @@ pub fn build(b: *Build) void {
50
49
  .version = zon.version,
51
50
  .description = b.path("README.md"),
52
51
  .build = .{
53
- .args = &.{build_ext_step.name},
54
- },
55
- .extra_pkg_info = &.{
56
- .{ .key = "Summary", .value = "Just a Test" },
57
- .{ .key = "Author-email", .value = "Tobias Simetsreiter <dasimmet@gmail.com>" },
58
- .{ .key = "Maintainer-email", .value = "Tobias Simetsreiter <dasimmet@gmail.com>" },
59
- .{ .key = "License-Expression", .value = "MIT" },
60
- .{ .key = "Keywords", .value = "zig,ziglang,cpython,native,sdist" },
61
- .{ .key = "Requires-Python", .value = ">=3.8" },
62
- .{ .key = "Project-URL", .value = "Homepage, https://codeberg.org/dasimmet/zig-python-sdist" },
63
- .{ .key = "Project-URL", .value = "Issues, https://codeberg.org/dasimmet/zig-python-sdist/issues" },
64
- .{ .key = "Classifier", .value = "Development Status :: 4 - Beta" },
52
+ .args = &.{ build_ext_step.name, b.fmt("-Doptimize={s}", .{@tagName(optimize)}) },
65
53
  },
54
+ .extra_pkg_info = @import("pkg-info.zon"),
66
55
  .files = &.{
67
56
  .{ .src = b.path("build.zig.zon"), .dest = "build.zig.zon" },
68
57
  .{ .src = b.path("build.zig"), .dest = "build.zig" },
58
+ .{ .src = b.path("pkg-info.zon"), .dest = "pkg-info.zon" },
69
59
  .{ .src = b.path("example/sdist_dummy.zig"), .dest = "example/sdist_dummy.zig" },
70
60
  },
71
61
  .directories = &.{
72
62
  .{ .src = b.path("src"), .dest = "src" },
73
63
  .{ .src = b.path("src/build"), .dest = "src/build" },
74
64
  },
65
+ .install_requires = &.{"ruamel.yaml.clibz"},
75
66
  .zig_version = std.SemanticVersion.parse("0.16.0") catch unreachable,
76
67
  });
77
-
78
- const sdistfile = b.addInstallFileWithDir(
79
- sdist.getEmittedArchive(),
80
- .{ .custom = "src" },
81
- sdist.basename,
82
- );
83
- b.getInstallStep().dependOn(&sdistfile.step);
68
+ const sdist_install = sdist.install();
69
+ b.getInstallStep().dependOn(&sdist_install.step);
70
+ b.step("sdist", "only build and install sdist").dependOn(&sdist_install.step);
84
71
 
85
72
  const test_pip_install = VenvInstallTest.create(
86
73
  b,
87
74
  .{
88
75
  .sdist = sdist.getEmittedArchive(),
89
76
  .test_py = b.path("example/test_ext.py"),
77
+ .twine_check = true,
90
78
  .no_clean = b.option(bool, "pip-no-clean", "cleanup pip temp dirs") orelse false,
91
79
  },
92
80
  );
93
81
  b.step("test-pip-install", "").dependOn(test_pip_install.step);
94
82
  }
95
83
 
84
+ pub const linkCPython = CPython.link;
85
+ pub const installExtLib = CPython.installExtLib;
86
+
96
87
  pub fn create(b: *Build, options: SDistStep.Options) *SDistStep {
97
88
  var opt = options;
98
89
  const sdist = b.dependencyFromBuildZig(@This(), .{
99
90
  .target = b.graph.host,
100
- .optimize = .Debug,
91
+ .optimize = .ReleaseFast,
101
92
  });
102
93
  opt.sdist_builder = opt.sdist_builder orelse sdist.artifact("sdist-builder");
103
94
 
@@ -106,6 +97,7 @@ pub fn create(b: *Build, options: SDistStep.Options) *SDistStep {
106
97
  const extra_files: []const SDistStep.Content = &.{
107
98
  .{ .src = sdist.path("build.zig.zon"), .dest = "zig-pkg/zig_python_sdist/build.zig.zon" },
108
99
  .{ .src = sdist.path("build.zig"), .dest = "zig-pkg/zig_python_sdist/build.zig" },
100
+ .{ .src = sdist.path("pkg-info.zon"), .dest = "zig-pkg/zig_python_sdist/pkg-info.zon" },
109
101
  .{ .src = sdist.path("README.md"), .dest = "zig-pkg/zig_python_sdist/README.md" },
110
102
  .{ .src = sdist.path("LICENSE"), .dest = "zig-pkg/zig_python_sdist/LICENSE" },
111
103
  };
@@ -121,7 +113,6 @@ pub fn create(b: *Build, options: SDistStep.Options) *SDistStep {
121
113
  {
122
114
  var dirs: std.ArrayList(SDistStep.Content) = .empty;
123
115
  const extra_dirs: []const SDistStep.Content = &.{
124
- // .{ .src = sdist.path("src"), .dest = "zig-pkg/zig_python_sdist/src" },
125
116
  .{ .src = sdist.path("src/build"), .dest = "zig-pkg/zig_python_sdist/src/build" },
126
117
  };
127
118
  dirs.ensureTotalCapacity(
@@ -1,10 +1,11 @@
1
1
  .{
2
2
  .name = .zig_python_sdist,
3
- .version = "0.0.1",
3
+ .version = "0.0.2",
4
4
  .minimum_zig_version = "0.17.0-dev.947+36069a2a7",
5
5
  .paths = .{
6
6
  "build.zig",
7
7
  "build.zig.zon",
8
+ "pkg-info.zon",
8
9
  "README.md",
9
10
  "LICENSE",
10
11
  "src",
@@ -0,0 +1,11 @@
1
+ .{
2
+ .{ .key = "Summary", .value = "Just a Test" },
3
+ .{ .key = "Author-email", .value = "Tobias Simetsreiter <dasimmet@gmail.com>" },
4
+ .{ .key = "Maintainer-email", .value = "Tobias Simetsreiter <dasimmet@gmail.com>" },
5
+ .{ .key = "License-Expression", .value = "MIT" },
6
+ .{ .key = "Keywords", .value = "zig,ziglang,cpython,native,sdist" },
7
+ .{ .key = "Requires-Python", .value = ">=3.8" },
8
+ .{ .key = "Project-URL", .value = "Homepage, https://codeberg.org/dasimmet/zig-python-sdist" },
9
+ .{ .key = "Project-URL", .value = "Issues, https://codeberg.org/dasimmet/zig-python-sdist/issues" },
10
+ .{ .key = "Classifier", .value = "Development Status :: 4 - Beta" },
11
+ }
@@ -0,0 +1,125 @@
1
+ const std = @import("std");
2
+ const builtin = @import("builtin");
3
+ const Build = std.Build;
4
+ const LazyPath = Build.LazyPath;
5
+ const mem = std.mem;
6
+
7
+ /// a module for building cpython extension libraries,
8
+ /// linking them with system python headers and libs
9
+ pub const CPython = @This();
10
+
11
+ exe: LazyPath,
12
+
13
+ pub fn find(b: *Build) *CPython {
14
+ const self = b.allocator.create(CPython) catch @panic("OOM");
15
+ self.* = .{
16
+ .exe = findProgramCompat(b, &.{
17
+ "python",
18
+ "python3",
19
+ }) orelse {
20
+ const err_wf = b.addWriteFiles();
21
+ const err_step = b.addFail("finding python failed. please provide a path to the exe using -Dpython=");
22
+ err_wf.step.dependOn(&err_step.step);
23
+ self.* = .{ .exe = err_wf.getDirectory() };
24
+ return self;
25
+ },
26
+ };
27
+ return self;
28
+ }
29
+
30
+ pub const LinkOptions = struct {
31
+ /// library to link against libpython
32
+ lib: *std.Build.Step.Compile,
33
+ version: ?[]const u8 = null,
34
+ python_exe: ?LazyPath = null,
35
+ /// optimize mode for the c module. will fall back to lib's optimize mode.
36
+ optimize: ?std.builtin.OptimizeMode = null,
37
+ macros: []const [2][]const u8 = &default_macros,
38
+ pub const default_macros = .{
39
+ .{ "Py_LIMITED_API", "0x03060500" }, // use the limited api from 3.6.5
40
+ };
41
+ };
42
+
43
+ pub fn link(b: *Build, options: LinkOptions) void {
44
+ const self: *const CPython = if (options.python_exe) |python_exe|
45
+ &.{ .exe = python_exe }
46
+ else
47
+ CPython.find(b);
48
+
49
+ const target = Build.ResolvedTarget{
50
+ .query = .{},
51
+ .result = options.lib.rootModuleTarget(),
52
+ };
53
+
54
+ const python_inc = self.generateIncludeDir(b);
55
+
56
+ const cpython = b.addTranslateC(.{
57
+ .root_source_file = python_inc.path(b, "zig_python_include.h"),
58
+ .optimize = options.optimize orelse options.lib.root_module.optimize orelse .ReleaseSafe,
59
+ .target = target,
60
+ });
61
+ cpython.addIncludePath(python_inc);
62
+
63
+ const wf = b.addWriteFiles();
64
+
65
+ const pymod = b.createModule(.{
66
+ .root_source_file = wf.add("python.zig", @embedFile("python.zig")),
67
+ .imports = &.{
68
+ .{ .name = "c", .module = cpython.createModule() },
69
+ },
70
+ });
71
+
72
+ if (options.version) |version| {
73
+ pymod.addImport("version", b.createModule(.{
74
+ .root_source_file = wf.add("version.txt", version),
75
+ }));
76
+ } else {
77
+ pymod.addImport("version", b.createModule(.{
78
+ .root_source_file = wf.add("version.txt", "version not provided at configure time!"),
79
+ }));
80
+ }
81
+
82
+ for (options.macros) |macro| {
83
+ cpython.defineCMacro(macro[0], macro[1]);
84
+ }
85
+
86
+ if (target.result.os.tag == .windows) {
87
+ options.lib.root_module.addLibraryPath(python_inc);
88
+ options.lib.root_module.linkSystemLibrary("python", .{});
89
+ }
90
+ options.lib.root_module.addImport(
91
+ "cpython",
92
+ pymod,
93
+ );
94
+ }
95
+
96
+ pub fn generateIncludeDir(self: CPython, b: *Build) LazyPath {
97
+ const extract_link_info = Build.Step.Run.create(b, "python header extraction run");
98
+ extract_link_info.addFileArg(self.exe);
99
+ const wf = b.addWriteFiles();
100
+ extract_link_info.addFileArg(wf.add("extract_link_info.py", @embedFile("extract_link_info.py")));
101
+ return extract_link_info.addOutputDirectoryArg("pyinclude");
102
+ }
103
+
104
+ pub fn installExtLib(b: *Build, lib: *Build.Step.Compile) *Build.Step.InstallFile {
105
+ const ext_lib_name = lib_ext_name(b, lib);
106
+ return b.addInstallLibFile(lib.getEmittedBin(), ext_lib_name);
107
+ }
108
+
109
+ pub fn lib_ext_name(b: *Build, lib: *Build.Step.Compile) []const u8 {
110
+ const target = lib.rootModuleTarget();
111
+ return if (target.os.tag == .windows)
112
+ b.fmt("{s}.pyd", .{lib.name})
113
+ else
114
+ b.fmt("{s}.so", .{lib.name});
115
+ }
116
+
117
+ // compat for 0.16.0 and 0.17.0
118
+ pub fn findProgramCompat(b: *std.Build, names: []const []const u8) ?LazyPath {
119
+ if (comptime (@import("builtin").zig_version.order(std.SemanticVersion.parse("0.16.0") catch unreachable) == .gt)) {
120
+ return b.findProgramLazy(.{ .names = names });
121
+ }
122
+ return .{
123
+ .cwd_relative = b.findProgram(names, &.{}) catch return null,
124
+ };
125
+ }