Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc0b4eb2

Browse files
committed
Improve geninterop script to handle new case in 3.11
1 parent2b52910 commitc0b4eb2

File tree

1 file changed

+83
-61
lines changed

1 file changed

+83
-61
lines changed

‎tools/geninterop/geninterop.py

100644100755
Lines changed: 83 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -13,40 +13,26 @@
1313
- clang
1414
"""
1515

16-
from __future__importprint_function
17-
18-
importlogging
1916
importos
17+
importshutil
2018
importsys
2119
importsysconfig
2220
importsubprocess
2321

24-
ifsys.version_info.major>2:
25-
fromioimportStringIO
26-
else:
27-
fromStringIOimportStringIO
28-
22+
fromioimportStringIO
23+
frompathlibimportPath
2924
frompycparserimportc_ast,c_parser
3025

31-
_log=logging.getLogger()
32-
logging.basicConfig(level=logging.DEBUG)
33-
34-
PY_MAJOR=sys.version_info[0]
35-
PY_MINOR=sys.version_info[1]
36-
3726
# rename some members from their C name when generating the C#
3827
_typeoffset_member_renames= {
3928
"ht_name":"name",
40-
"ht_qualname":"qualname"
29+
"ht_qualname":"qualname",
30+
"getitem":"spec_cache_getitem",
4131
}
4232

4333

4434
def_check_output(*args,**kwargs):
45-
"""Check output wrapper for py2/py3 compatibility"""
46-
output=subprocess.check_output(*args,**kwargs)
47-
ifPY_MAJOR==2:
48-
returnoutput
49-
returnoutput.decode("ascii")
35+
returnsubprocess.check_output(*args,**kwargs,encoding="utf8")
5036

5137

5238
classAstParser(object):
@@ -92,7 +78,7 @@ def visit(self, node):
9278
self.visit_identifier(node)
9379

9480
defvisit_ast(self,ast):
95-
forname,nodeinast.children():
81+
for_name,nodeinast.children():
9682
self.visit(node)
9783

9884
defvisit_typedef(self,typedef):
@@ -113,7 +99,7 @@ def visit_struct(self, struct):
11399
self.visit(decl)
114100
self._struct_members_stack.pop(0)
115101
self._struct_stack.pop(0)
116-
elifself._ptr_decl_depth:
102+
elifself._ptr_decl_depthorself._struct_members_stack:
117103
# the struct is empty, but add it as a member to the current
118104
# struct as the current member maybe a pointer to it.
119105
self._add_struct_member(struct.name)
@@ -141,7 +127,8 @@ def _add_struct_member(self, type_name):
141127
current_struct=self._struct_stack[0]
142128
member_name=self._struct_members_stack[0]
143129
struct_members=self._struct_members.setdefault(
144-
self._get_struct_name(current_struct), [])
130+
self._get_struct_name(current_struct), []
131+
)
145132

146133
# get the node associated with this type
147134
node=None
@@ -179,7 +166,6 @@ def _get_struct_name(self, node):
179166

180167

181168
classWriter(object):
182-
183169
def__init__(self):
184170
self._stream=StringIO()
185171

@@ -193,43 +179,56 @@ def to_string(self):
193179
returnself._stream.getvalue()
194180

195181

196-
defpreprocess_python_headers():
182+
defpreprocess_python_headers(*,cc=None,include_py=None):
197183
"""Return Python.h pre-processed, ready for parsing.
198184
Requires clang.
199185
"""
200-
fake_libc_include=os.path.join(os.path.dirname(__file__),
201-
"fake_libc_include")
186+
this_path=Path(__file__).parent
187+
188+
fake_libc_include=this_path/"fake_libc_include"
202189
include_dirs= [fake_libc_include]
203190

204-
include_py=sysconfig.get_config_var("INCLUDEPY")
191+
ifccisNone:
192+
cc=shutil.which("clang")
193+
ifccisNone:
194+
cc=shutil.which("gcc")
195+
ifccisNone:
196+
raiseRuntimeError("No suitable C compiler found, need clang or gcc")
197+
198+
ifinclude_pyisNone:
199+
include_py=sysconfig.get_config_var("INCLUDEPY")
200+
include_py=Path(include_py)
201+
205202
include_dirs.append(include_py)
206203

207-
include_args= [cforpininclude_dirsforcin ["-I",p]]
204+
include_args= [cforpininclude_dirsforcin ["-I",str(p)]]
208205

206+
# fmt: off
209207
defines= [
210208
"-D","__attribute__(x)=",
211209
"-D","__inline__=inline",
212210
"-D","__asm__=;#pragma asm",
213211
"-D","__int64=long long",
214-
"-D","_POSIX_THREADS"
212+
"-D","_POSIX_THREADS",
215213
]
216214

217-
ifos.name=='nt':
215+
ifsys.platform=="win32":
218216
defines.extend([
219217
"-D","__inline=inline",
220218
"-D","__ptr32=",
221219
"-D","__ptr64=",
222220
"-D","__declspec(x)=",
223221
])
222+
#fmt: on
224223

225224
ifhasattr(sys,"abiflags"):
226225
if"d"insys.abiflags:
227226
defines.extend(("-D","PYTHON_WITH_PYDEBUG"))
228227
if"u"insys.abiflags:
229228
defines.extend(("-D","PYTHON_WITH_WIDE_UNICODE"))
230229

231-
python_h=os.path.join(include_py,"Python.h")
232-
cmd= ["clang","-pthread"]+include_args+defines+ ["-E",python_h]
230+
python_h=include_py/"Python.h"
231+
cmd= [cc,"-pthread"]+include_args+defines+ ["-E",str(python_h)]
233232

234233
# normalize as the parser doesn't like windows line endings.
235234
lines= []
@@ -240,16 +239,13 @@ def preprocess_python_headers():
240239
return"\n".join(lines)
241240

242241

243-
244-
defgen_interop_head(writer):
242+
defgen_interop_head(writer,version,abi_flags):
245243
filename=os.path.basename(__file__)
246-
abi_flags=getattr(sys,"abiflags","").replace("m","")
247-
py_ver="{0}.{1}".format(PY_MAJOR,PY_MINOR)
248-
class_definition="""
249-
// Auto-generated by %s.
244+
class_definition=f"""
245+
// Auto-generated by{filename}.
250246
// DO NOT MODIFY BY HAND.
251247
252-
// Python%s: ABI flags: '%s'
248+
// Python{".".join(version[:2])}: ABI flags: '{abi_flags}'
253249
254250
// ReSharper disable InconsistentNaming
255251
// ReSharper disable IdentifierTypo
@@ -261,7 +257,7 @@ def gen_interop_head(writer):
261257
using Python.Runtime.Native;
262258
263259
namespace Python.Runtime
264-
{"""% (filename,py_ver,abi_flags)
260+
{{"""
265261
writer.extend(class_definition)
266262

267263

@@ -271,25 +267,24 @@ def gen_interop_tail(writer):
271267
writer.extend(tail)
272268

273269

274-
defgen_heap_type_members(parser,writer,type_name=None):
270+
defgen_heap_type_members(parser,writer,type_name):
275271
"""Generate the TypeOffset C# class"""
276272
members=parser.get_struct_members("PyHeapTypeObject")
277-
type_name=type_nameor"TypeOffset{0}{1}".format(PY_MAJOR,PY_MINOR)
278-
class_definition="""
273+
class_definition=f"""
279274
[SuppressMessage("Style", "IDE1006:Naming Styles",
280275
Justification = "Following CPython",
281276
Scope = "type")]
282277
283278
[StructLayout(LayoutKind.Sequential)]
284-
internal class {0} : GeneratedTypeOffsets, ITypeOffsets
279+
internal class{type_name} : GeneratedTypeOffsets, ITypeOffsets
285280
{{
286-
public {0}() {{ }}
281+
public{type_name}() {{ }}
287282
// Auto-generated from PyHeapTypeObject in Python.h
288-
""".format(type_name)
283+
"""
289284

290285
# All the members are sizeof(void*) so we don't need to do any
291286
# extra work to determine the size based on the type.
292-
forname,tpyinmembers:
287+
forname,_typeinmembers:
293288
name=_typeoffset_member_renames.get(name,name)
294289
class_definition+=" public int %s { get; private set; }\n"%name
295290

@@ -304,17 +299,18 @@ def gen_structure_code(parser, writer, type_name, indent):
304299
returnFalse
305300
out=writer.append
306301
out(indent,"[StructLayout(LayoutKind.Sequential)]")
307-
out(indent,"internal struct%s"%type_name)
302+
out(indent,f"internal struct{type_name}")
308303
out(indent,"{")
309-
forname,tpyinmembers:
310-
out(indent+1,"public IntPtr%s;"%name)
304+
forname,_typeinmembers:
305+
out(indent+1,f"public IntPtr{name};")
311306
out(indent,"}")
312307
out()
313308
returnTrue
314309

315-
defmain():
310+
311+
defmain(*,cc=None,include_py=None,version=None,out=None):
316312
# preprocess Python.h and build the AST
317-
python_h=preprocess_python_headers()
313+
python_h=preprocess_python_headers(cc=cc,include_py=include_py)
318314
parser=c_parser.CParser()
319315
ast=parser.parse(python_h)
320316

@@ -323,21 +319,47 @@ def main():
323319
ast_parser.visit(ast)
324320

325321
writer=Writer()
322+
323+
ifinclude_pyandnotversion:
324+
raiseRuntimeError("If the include path is overridden, version must be "
325+
"defined"
326+
)
327+
328+
ifversion:
329+
version=version.split('.')
330+
else:
331+
version=sys.version_info
332+
326333
# generate the C# code
327-
offsets_type_name="NativeTypeOffset"iflen(sys.argv)>1elseNone
328-
gen_interop_head(writer)
334+
abi_flags=getattr(sys,"abiflags","").replace("m","")
335+
gen_interop_head(writer,version,abi_flags)
329336

330-
gen_heap_type_members(ast_parser,writer,type_name=offsets_type_name)
337+
type_name=f"TypeOffset{version[0]}{version[1]}{abi_flags}"
338+
gen_heap_type_members(ast_parser,writer,type_name)
331339

332340
gen_interop_tail(writer)
333341

334342
interop_cs=writer.to_string()
335-
iflen(sys.argv)>1:
336-
withopen(sys.argv[1],"w")asfh:
337-
fh.write(interop_cs)
338-
else:
343+
ifnotoutorout=="-":
339344
print(interop_cs)
345+
else:
346+
withopen(out,"w")asfh:
347+
fh.write(interop_cs)
340348

341349

342350
if__name__=="__main__":
343-
sys.exit(main())
351+
importargparse
352+
353+
a=argparse.ArgumentParser("Interop file generator for Python.NET")
354+
a.add_argument("--cc",help="C compiler to use, either clang or gcc")
355+
a.add_argument("--include-py",help="Include path of Python")
356+
a.add_argument("--version",help="Python version")
357+
a.add_argument("--out",help="Output path",default="-")
358+
args=a.parse_args()
359+
360+
sys.exit(main(
361+
cc=args.cc,
362+
include_py=args.include_py,
363+
out=args.out,
364+
version=args.version
365+
))

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp