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

Commite46c960

Browse files
committed
Improve geninterop script to handle new case in 3.11
1 parent9412af9 commite46c960

File tree

1 file changed

+102
-71
lines changed

1 file changed

+102
-71
lines changed

‎tools/geninterop/geninterop.py

100644100755
Lines changed: 102 additions & 71 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,65 @@ 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

209206
defines= [
210-
"-D","__attribute__(x)=",
211-
"-D","__inline__=inline",
212-
"-D","__asm__=;#pragma asm",
213-
"-D","__int64=long long",
214-
"-D","_POSIX_THREADS"
207+
"-D",
208+
"__attribute__(x)=",
209+
"-D",
210+
"__inline__=inline",
211+
"-D",
212+
"__asm__=;#pragma asm",
213+
"-D",
214+
"__int64=long long",
215+
"-D",
216+
"_POSIX_THREADS",
215217
]
216218

217-
ifos.name=='nt':
218-
defines.extend([
219-
"-D","__inline=inline",
220-
"-D","__ptr32=",
221-
"-D","__ptr64=",
222-
"-D","__declspec(x)=",
223-
])
219+
ifos.name=="nt":
220+
defines.extend(
221+
[
222+
"-D",
223+
"__inline=inline",
224+
"-D",
225+
"__ptr32=",
226+
"-D",
227+
"__ptr64=",
228+
"-D",
229+
"__declspec(x)=",
230+
]
231+
)
224232

225233
ifhasattr(sys,"abiflags"):
226234
if"d"insys.abiflags:
227235
defines.extend(("-D","PYTHON_WITH_PYDEBUG"))
228236
if"u"insys.abiflags:
229237
defines.extend(("-D","PYTHON_WITH_WIDE_UNICODE"))
230238

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

234242
# normalize as the parser doesn't like windows line endings.
235243
lines= []
@@ -240,16 +248,13 @@ def preprocess_python_headers():
240248
return"\n".join(lines)
241249

242250

243-
244-
defgen_interop_head(writer):
251+
defgen_interop_head(writer,version,abi_flags):
245252
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.
253+
class_definition=f"""
254+
// Auto-generated by{filename}.
250255
// DO NOT MODIFY BY HAND.
251256
252-
// Python%s: ABI flags: '%s'
257+
// Python{".".join(version[:2])}: ABI flags: '{abi_flags}'
253258
254259
// ReSharper disable InconsistentNaming
255260
// ReSharper disable IdentifierTypo
@@ -261,7 +266,7 @@ def gen_interop_head(writer):
261266
using Python.Runtime.Native;
262267
263268
namespace Python.Runtime
264-
{"""% (filename,py_ver,abi_flags)
269+
{{"""
265270
writer.extend(class_definition)
266271

267272

@@ -271,25 +276,24 @@ def gen_interop_tail(writer):
271276
writer.extend(tail)
272277

273278

274-
defgen_heap_type_members(parser,writer,type_name=None):
279+
defgen_heap_type_members(parser,writer,type_name):
275280
"""Generate the TypeOffset C# class"""
276281
members=parser.get_struct_members("PyHeapTypeObject")
277-
type_name=type_nameor"TypeOffset{0}{1}".format(PY_MAJOR,PY_MINOR)
278-
class_definition="""
282+
class_definition=f"""
279283
[SuppressMessage("Style", "IDE1006:Naming Styles",
280284
Justification = "Following CPython",
281285
Scope = "type")]
282286
283287
[StructLayout(LayoutKind.Sequential)]
284-
internal class {0} : GeneratedTypeOffsets, ITypeOffsets
288+
internal class{type_name} : GeneratedTypeOffsets, ITypeOffsets
285289
{{
286-
public {0}() {{ }}
290+
public{type_name}() {{ }}
287291
// Auto-generated from PyHeapTypeObject in Python.h
288-
""".format(type_name)
292+
"""
289293

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

@@ -304,17 +308,18 @@ def gen_structure_code(parser, writer, type_name, indent):
304308
returnFalse
305309
out=writer.append
306310
out(indent,"[StructLayout(LayoutKind.Sequential)]")
307-
out(indent,"internal struct%s"%type_name)
311+
out(indent,f"internal struct{type_name}")
308312
out(indent,"{")
309-
forname,tpyinmembers:
310-
out(indent+1,"public IntPtr%s;"%name)
313+
forname,_typeinmembers:
314+
out(indent+1,f"public IntPtr{name};")
311315
out(indent,"}")
312316
out()
313317
returnTrue
314318

315-
defmain():
319+
320+
defmain(*,cc=None,include_py=None,version=None,out=None):
316321
# preprocess Python.h and build the AST
317-
python_h=preprocess_python_headers()
322+
python_h=preprocess_python_headers(cc=cc,include_py=include_py)
318323
parser=c_parser.CParser()
319324
ast=parser.parse(python_h)
320325

@@ -323,21 +328,47 @@ def main():
323328
ast_parser.visit(ast)
324329

325330
writer=Writer()
331+
332+
ifinclude_pyandnotversion:
333+
raiseRuntimeError("If the include path is overridden, version must be "
334+
"defined"
335+
)
336+
337+
ifversion:
338+
version=version.split('.')
339+
else:
340+
version=sys.version_info
341+
326342
# generate the C# code
327-
offsets_type_name="NativeTypeOffset"iflen(sys.argv)>1elseNone
328-
gen_interop_head(writer)
343+
abi_flags=getattr(sys,"abiflags","").replace("m","")
344+
gen_interop_head(writer,version,abi_flags)
329345

330-
gen_heap_type_members(ast_parser,writer,type_name=offsets_type_name)
346+
type_name=f"TypeOffset{version[0]}{version[1]}{abi_flags}"
347+
gen_heap_type_members(ast_parser,writer,type_name)
331348

332349
gen_interop_tail(writer)
333350

334351
interop_cs=writer.to_string()
335-
iflen(sys.argv)>1:
336-
withopen(sys.argv[1],"w")asfh:
337-
fh.write(interop_cs)
338-
else:
352+
ifnotoutorout=="-":
339353
print(interop_cs)
354+
else:
355+
withopen(out,"w")asfh:
356+
fh.write(interop_cs)
340357

341358

342359
if__name__=="__main__":
343-
sys.exit(main())
360+
importargparse
361+
362+
a=argparse.ArgumentParser("Interop file generator for Python.NET")
363+
a.add_argument("--cc",help="C compiler to use, either clang or gcc")
364+
a.add_argument("--include-py",help="Include path of Python")
365+
a.add_argument("--version",help="Python version")
366+
a.add_argument("--out",help="Output path",default="-")
367+
args=a.parse_args()
368+
369+
sys.exit(main(
370+
cc=args.cc,
371+
include_py=args.include_py,
372+
out=args.out,
373+
version=args.version
374+
))

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp