Skip to content

Commit 3a54a5a

Browse files
committed
Tests pass
1 parent adbdea9 commit 3a54a5a

File tree

14 files changed

+175
-108
lines changed

14 files changed

+175
-108
lines changed

src/semiwrap/autowrap/cxxparser.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
Variable,
5959
)
6060

61+
from ..casters import CastersData
6162
from ..config.autowrap_yml import (
6263
AutowrapConfigYaml,
6364
BufferData,
@@ -329,7 +330,7 @@ def __init__(
329330
self,
330331
hctx: HeaderContext,
331332
gendata: GeneratorData,
332-
casters: typing.Dict[str, typing.Dict[str, typing.Any]],
333+
casters: CastersData,
333334
report_only: bool,
334335
) -> None:
335336
self.hctx = hctx
@@ -1898,8 +1899,8 @@ def _add_default_arg_cast(
18981899
typename = _fmt_nameonly(ntype.typename)
18991900
if typename:
19001901
ccfg = self.casters.get(typename)
1901-
if ccfg and ccfg.get("darg"):
1902-
found_typename = ccfg["typename"]
1902+
if ccfg and ccfg.default_arg_cast:
1903+
found_typename = ccfg.typename
19031904
name = f"({found_typename}){name}"
19041905

19051906
return name
@@ -1975,7 +1976,7 @@ def _set_type_caster_includes(self):
19751976
for typename in self.types:
19761977
ccfg = casters.get(typename)
19771978
if ccfg:
1978-
includes.add(ccfg["hdr"])
1979+
includes.add(ccfg.header)
19791980

19801981
self.hctx.type_caster_includes = sorted(includes)
19811982

@@ -1986,7 +1987,7 @@ def parse_header(
19861987
header_root: pathlib.Path,
19871988
gendata: GeneratorData,
19881989
parser_options: ParserOptions,
1989-
casters: typing.Dict[str, typing.Dict[str, typing.Any]],
1990+
casters: CastersData,
19901991
report_only: bool,
19911992
) -> HeaderContext:
19921993
user_cfg = gendata.data

src/semiwrap/casters.py

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,29 +7,49 @@
77

88
PKGCONF_CASTER_EXT = ".pybind11.json"
99

10+
#
11+
# JSON caster data
12+
#
13+
1014

1115
@dataclasses.dataclass
12-
class TypeCasterHeader:
16+
class TypeCasterJsonHeader:
1317
header: str
1418
types: T.List[str]
1519
default_arg_cast: bool = False
1620

1721

1822
#: content of .pybind11.json
1923
@dataclasses.dataclass
20-
class TypeCasterData:
21-
headers: T.List[TypeCasterHeader] = dataclasses.field(default_factory=list)
24+
class TypeCasterJsonData:
25+
"""
26+
Stored in *.pybind11.json
27+
"""
28+
29+
headers: T.List[TypeCasterJsonHeader] = dataclasses.field(default_factory=list)
2230

2331

24-
def load_typecaster_data(fname) -> TypeCasterData:
32+
def load_typecaster_json_data(fname) -> TypeCasterJsonData:
2533
with open(fname) as fp:
26-
return parse_input(json.load(fp), TypeCasterData, fname)
34+
return parse_input(json.load(fp), TypeCasterJsonData, fname)
2735

2836

29-
def save_typecaster_data(fname: pathlib.Path, data: TypeCasterData):
37+
def save_typecaster_json_data(fname: pathlib.Path, data: TypeCasterJsonData):
3038
with open(fname, "w") as fp:
3139
json.dump(dataclasses.asdict(data), fp)
3240

3341

34-
#: content of pickle file
35-
CastersData = T.Dict[str, T.Dict[str, T.Any]]
42+
#
43+
# Pickled caster lookup as stored by resolve_casters
44+
#
45+
46+
47+
@dataclasses.dataclass
48+
class TypeData:
49+
header: pathlib.Path
50+
typename: str
51+
default_arg_cast: bool
52+
53+
54+
#: content of pickle file used internally
55+
CastersData = T.Dict[str, TypeData]

src/semiwrap/cmd_dat2cpp.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ def _write_wrapper_cpp(input_dat: pathlib.Path, output_cpp: pathlib.Path):
2020
content = render_wrapped_cpp(hctx)
2121
output_cpp.write_text(content)
2222

23+
2324
def main():
2425
try:
2526
_, input_dat, output_cpp = sys.argv

src/semiwrap/cmd_dat2tmplcpp.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@
1111
from .autowrap.render_tmpl_inst import render_template_inst_cpp
1212

1313

14-
def _write_wrapper_cpp(
15-
input_dat: pathlib.Path, py_name: str, output_cpp: pathlib.Path
16-
):
14+
def _write_wrapper_cpp(input_dat: pathlib.Path, py_name: str, output_cpp: pathlib.Path):
1715
with open(input_dat, "rb") as fp:
1816
hctx = pickle.load(fp)
1917

src/semiwrap/cmd_dat2trampoline.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@ def _get_child_classes(c: ClassContext):
2222
yield from _get_child_classes(cls)
2323

2424

25-
def _write_wrapper_cpp(
26-
input_dat: pathlib.Path, yml_id: str, output_hpp: pathlib.Path
27-
):
25+
def _write_wrapper_cpp(input_dat: pathlib.Path, yml_id: str, output_hpp: pathlib.Path):
2826
with open(input_dat, "rb") as fp:
2927
hctx = pickle.load(fp)
3028

src/semiwrap/cmd_make_pyi.py

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
"""
2-
Creates an output .pyi file from a given python module
2+
Creates an output .pyi file from a given python module.
3+
4+
Arguments are:
5+
package outpath [subpackage outpath...] -- package mapped_file
36
"""
47

58
import importlib.util
@@ -29,8 +32,11 @@ def find_spec(cls, fullname, path, target=None):
2932
return importlib.util.spec_from_file_location(fullname, m)
3033

3134

32-
def _write_pyi(package_name: str, output_pyi: str):
35+
def _write_pyi(package_name, generated_pyi: T.Dict[pathlib.PurePath, pathlib.Path]):
3336

37+
# We can't control where stubgen writes files, so tell it to output
38+
# to a temporary directory and then we copy the files from there to
39+
# our desired location
3440
with tempfile.TemporaryDirectory() as tmpdir:
3541
# Call pybind11-stubgen
3642
sys.argv = [
@@ -45,28 +51,40 @@ def _write_pyi(package_name: str, output_pyi: str):
4551

4652
pybind11_stubgen.main()
4753

48-
import os
49-
os.system(f"find {tmpdir}")
50-
5154
# stubgen doesn't take a direct output filename, so move the file
5255
# to our desired location
53-
elems = package_name.split(".")
54-
elems[-1] = f"{elems[-1]}.pyi"
55-
pathlib.Path(tmpdir, *elems).rename(output_pyi)
56+
tmpdir_pth = pathlib.Path(tmpdir)
57+
for infile, output in generated_pyi.items():
58+
(tmpdir_pth / infile).rename(output)
5659

5760

5861
def main():
59-
try:
60-
_, package_name, output_pyi = sys.argv[:3]
61-
except ValueError:
62+
63+
generated_pyi: T.Dict[pathlib.PurePath, pathlib.Path] = {}
64+
argv = sys.argv
65+
66+
if len(argv) < 3:
6267
print(inspect.cleandoc(__doc__ or ""), file=sys.stderr)
6368
sys.exit(1)
6469

70+
# Package name first
71+
package_name = argv[1]
72+
73+
# Output file map: input output
74+
idx = 2
75+
while idx < len(argv):
76+
if argv[idx] == "--":
77+
idx += 1
78+
break
79+
80+
generated_pyi[pathlib.PurePath(argv[idx])] = pathlib.Path(argv[idx + 1])
81+
idx += 2
82+
6583
# Arguments are used to set up the package map
6684
package_map = _PackageFinder.mapping
67-
for i in range(3, len(sys.argv), 2):
68-
package_map[sys.argv[i]] = sys.argv[i + 1]
69-
85+
for i in range(idx, len(argv), 2):
86+
package_map[argv[i]] = argv[i + 1]
87+
7088
# Add parent packages too
7189
# .. assuming there are __init__.py in each package
7290
for pkg in list(package_map.keys()):
@@ -76,15 +94,14 @@ def main():
7694
break
7795
ppkg = pkg[:idx]
7896
if ppkg not in package_map:
79-
package_map[ppkg] = join(dirname(dirname(package_map[pkg])), "__init__.py")
97+
package_map[ppkg] = join(
98+
dirname(dirname(package_map[pkg])), "__init__.py"
99+
)
80100
pkg = ppkg
81101

82-
import pprint
83-
pprint.pprint(package_map)
84-
85102
sys.meta_path.insert(0, _PackageFinder)
86103

87-
_write_pyi(package_name, output_pyi)
104+
_write_pyi(package_name, generated_pyi)
88105

89106

90107
if __name__ == "__main__":

src/semiwrap/cmd_publish_casters.py

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,13 @@
55
Generates a FOO.pc file and a FOO.pybind11.json file
66
"""
77

8-
import json
98
import pathlib
109
import sys
11-
import typing as T
1210

13-
from .casters import TypeCasterData, TypeCasterHeader, save_typecaster_data
11+
from .casters import TypeCasterJsonData, TypeCasterJsonHeader, save_typecaster_json_data
1412
from .pyproject import PyProject
1513

1614

17-
from .config.pyproject_toml import ExtensionModuleConfig
18-
19-
2015
def main():
2116
try:
2217
_, pyproject_toml, caster_name, output_json, output_pc = sys.argv
@@ -53,7 +48,7 @@ def main():
5348
"",
5449
f"Name: {caster_name}",
5550
"Description: pybind11 type casters",
56-
"Version:", # TODO put in correct version
51+
"Version:", # TODO put in correct version
5752
"Cflags: -I${includedir}",
5853
]
5954

@@ -68,7 +63,7 @@ def main():
6863
# Gather the data and write it next to the pc file
6964
#
7065

71-
data = TypeCasterData()
66+
data = TypeCasterJsonData()
7267
for hdr in cfg.headers:
7368

7469
# Ensure the published header actually exists
@@ -82,14 +77,14 @@ def main():
8277
sys.exit(1)
8378

8479
data.headers.append(
85-
TypeCasterHeader(
80+
TypeCasterJsonHeader(
8681
header=hdr.header,
8782
types=hdr.types,
8883
default_arg_cast=hdr.default_arg_cast,
8984
)
9085
)
9186

92-
save_typecaster_data(pathlib.Path(output_json), data)
87+
save_typecaster_json_data(pathlib.Path(output_json), data)
9388

9489

9590
if __name__ == "__main__":

src/semiwrap/cmd_resolve_casters.py

Lines changed: 5 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,45 +3,17 @@
33
pybind11 type caster implementations.
44
"""
55

6-
import dataclasses
76
import inspect
87
import pathlib
98
import pickle
109
import sys
11-
import typing as T
1210

13-
from .casters import CastersData, load_typecaster_data
11+
from .casters import CastersData, load_typecaster_json_data, TypeData
1412
from .depfile import Depfile
1513

16-
# @dataclasses.dataclass
17-
# class TypeCasterJson:
18-
# pass
19-
20-
21-
# def _all_casters():
22-
# casters = {}
23-
# for dep in wrapper.all_deps():
24-
# dep.get_type_casters_cfg(casters)
25-
# self.pkgcfg.get_pkg("robotpy-build").get_type_casters_cfg(casters)
26-
# self.get_type_casters_cfg(casters)
27-
28-
# # make each configuration unique
29-
# for k, v in list(casters.items()):
30-
# v = v.copy()
31-
# v["typename"] = k
32-
# casters[k] = v
33-
34-
# # add non-namespaced versions of all casters
35-
# # -> in theory this could lead to a conflict, but
36-
# # let's see how it works in practice?
37-
# for k, v in list(casters.items()):
38-
# k = k.split("::")[-1]
39-
# casters[k] = v
40-
# return casters
41-
4214

4315
def _update_all_casters(type_caster_cfg: pathlib.Path, all_casters: CastersData):
44-
data = load_typecaster_data(type_caster_cfg)
16+
data = load_typecaster_json_data(type_caster_cfg)
4517

4618
# flatten it
4719
for item in data.headers:
@@ -53,10 +25,9 @@ def _update_all_casters(type_caster_cfg: pathlib.Path, all_casters: CastersData)
5325

5426
for typ in item.types:
5527
if typ not in all_casters:
56-
all_casters[typ] = {
57-
"hdr": str(header),
58-
"dcast": item.default_arg_cast,
59-
}
28+
all_casters[typ] = TypeData(
29+
header=header, typename=typ, default_arg_cast=item.default_arg_cast
30+
)
6031

6132

6233
def main():

0 commit comments

Comments
 (0)