Coverage for packages/pyswig/src/pyswig/maininterfacefile.py: 95%
86 statements
« prev ^ index » next coverage.py v7.14.3, created at 2026-06-26 21:05 +0000
« prev ^ index » next coverage.py v7.14.3, created at 2026-06-26 21:05 +0000
1# Copyright (c) 2015-2020 Michel Gillet
2# SPDX-License-Identifier: MIT
4from __future__ import annotations
6from pathlib import Path
7from typing import TYPE_CHECKING, TextIO
9from pyswig.exceptions import PySwigError
10from pyswig.types import normalize_source_entry
12if TYPE_CHECKING:
13 from pyswig.pyswig import PySwig
16class MainInterfaceFile:
17 """Class generating the main interface file, input to Swig"""
19 def __init__(self, pyswig: PySwig | None = None) -> None:
20 self.m_pyswig = pyswig
21 self.m_fout: TextIO | None = None
23 def _get_pyswig(self) -> PySwig | None:
24 """Get the PySwig instance to use to generate the main interface file"""
25 return self.m_pyswig
27 def generate(self) -> None:
28 """Generate the Swig interface file, the main input file for Swig"""
29 output_path = self._output_path()
30 pyswig = self._get_pyswig()
31 assert pyswig is not None
32 pyswig.set_output_file(output_path.name)
33 with open(output_path, "w", encoding="utf-8") as fout:
34 self.m_fout = fout
35 self.write_header()
36 self.write_cpp_includes()
37 self.write_defines()
38 self.main_file_write_interface_files()
39 self.m_fout = None
41 def _output_path(self) -> Path:
42 pyswig = self._get_pyswig()
43 if pyswig is None:
44 raise PySwigError("PySwig instance is required to generate the main interface file")
46 src_output_dir = pyswig.get_src_output_dir()
47 module_name = pyswig.get_module_name()
48 if src_output_dir is None or module_name is None:
49 raise PySwigError("module name and source output directory must be configured")
51 return Path(src_output_dir) / f"{module_name}.hh"
53 def write_header(self) -> None:
54 """Write header of the the main interface file"""
55 pyswig = self._get_pyswig()
56 assert pyswig is not None
57 assert self.m_fout is not None
59 self.m_fout.write(f"// PySwig {pyswig.get_version()}\n\n")
60 if pyswig.get_use_director():
61 self.m_fout.write(f'%module(directors="1") {pyswig.get_module_name()}\n')
62 else:
63 self.m_fout.write(f"%module {pyswig.get_module_name()}\n")
65 self.m_fout.write("%include typemaps.i\n")
67 for type_map in pyswig.get_typemaps():
68 self.m_fout.write(f"%include {type_map}\n")
70 self.m_fout.write("\n")
71 imports = pyswig.get_imports()
72 if imports is not None:
73 for import_lib in imports:
74 self.m_fout.write(f"%import {import_lib}\n")
75 self.m_fout.write("\n")
77 def write_cpp_includes(self) -> None:
78 """Write the C/C++ includes to the main file"""
79 pyswig = self._get_pyswig()
80 assert pyswig is not None
81 assert self.m_fout is not None
83 self.m_fout.write("%{\n")
84 self.m_fout.write("\n")
85 for include in pyswig.get_includes(False):
86 self.m_fout.write(f"#include <{include}>\n")
87 self.m_fout.write("\n")
88 for include in pyswig.get_includes(True):
89 self.m_fout.write(f'#include "{include}"\n')
90 self.m_fout.write("\n")
91 self.m_fout.write("%}\n\n")
93 def write_defines(self) -> None:
94 """Write the defines in the main file"""
95 pyswig = self._get_pyswig()
96 assert pyswig is not None
97 assert self.m_fout is not None
99 for define in pyswig.get_defines():
100 if define.value:
101 self.m_fout.write(f"#define {define.name} {define.value}\n")
102 else:
103 self.m_fout.write(f"#define {define.name}\n")
104 self.m_fout.write("\n")
106 def main_file_write_interface_files(self) -> None:
107 """Write the insterface in the main file"""
108 pyswig = self._get_pyswig()
109 assert pyswig is not None
110 assert self.m_fout is not None
112 for file_config in pyswig.get_file_configs():
113 source_files = file_config.get_source_files()
114 if source_files is None:
115 continue
116 for source_file in source_files:
117 spec = normalize_source_entry(source_file)
118 rel = Path(spec.name)
119 if spec.wrap:
120 rel = rel.with_name(rel.stem + "_wrap" + rel.suffix)
121 out_interface = rel.with_suffix(".hh")
122 self.m_fout.write(f"%include {out_interface.as_posix()}\n")