Author: Ronan Lamy <[email protected]>
Branch: rffi-parser-2
Changeset: r89612:ce1401635012
Date: 2017-01-16 17:04 +0000
http://bitbucket.org/pypy/pypy/changeset/ce1401635012/
Log: Allow parsing multiple headers into the same cts
diff --git a/pypy/module/cpyext/cparser.py b/pypy/module/cpyext/cparser.py
--- a/pypy/module/cpyext/cparser.py
+++ b/pypy/module/cpyext/cparser.py
@@ -685,9 +685,9 @@
class CTypeSpace(object):
- def __init__(self, source, parser=None, definitions=None, macros=None,
+ def __init__(self, parser=None, definitions=None, macros=None,
headers=None, includes=None):
- self.source = source
+ self.sources = []
self.definitions = definitions if definitions is not None else {}
self.macros = macros if macros is not None else {}
self.structs = {}
@@ -697,6 +697,7 @@
self._TYPES = {}
self.includes = []
self.struct_typedefs = {}
+ self._handled = set()
if includes is not None:
for header in includes:
self.include(header)
@@ -706,6 +707,11 @@
self.structs.update(other.structs)
self.includes.append(other)
+ def parse_source(self, source):
+ self.sources.append(source)
+ self.ctx.parse(source)
+ self.configure_types()
+
def add_typedef(self, name, obj, quals):
assert name not in self.definitions
tp = self.convert_type(obj, quals)
@@ -746,7 +752,10 @@
return struct.TYPE
def build_eci(self):
- all_sources = [x.source for x in self.includes] + [self.source]
+ all_sources = []
+ for cts in self.includes:
+ all_sources.extend(cts.sources)
+ all_sources.extend(self.sources)
all_headers = self.headers
for x in self.includes:
for hdr in x.headers:
@@ -759,6 +768,9 @@
for name, (obj, quals) in self.ctx._declarations.iteritems():
if obj in self.ctx._included_declarations:
continue
+ if name in self._handled:
+ continue
+ self._handled.add(name)
if name.startswith('typedef '):
name = name[8:]
self.add_typedef(name, obj, quals)
@@ -771,6 +783,7 @@
del TYPE._hints['eci']
if name in self._TYPES:
self._TYPES[name].become(TYPE)
+ del self._TYPES[name]
def convert_type(self, obj, quals=0):
if isinstance(obj, model.PrimitiveType):
@@ -825,7 +838,6 @@
def parse_source(source, includes=None, headers=None, configure_now=True):
- src = CTypeSpace(source, headers=headers, includes=includes)
- src.ctx.parse(source)
- src.configure_types()
- return src
+ cts = CTypeSpace(headers=headers, includes=includes)
+ cts.parse_source(source)
+ return cts
diff --git a/pypy/module/cpyext/test/test_cparser.py
b/pypy/module/cpyext/test/test_cparser.py
--- a/pypy/module/cpyext/test/test_cparser.py
+++ b/pypy/module/cpyext/test/test_cparser.py
@@ -1,5 +1,5 @@
from rpython.rtyper.lltypesystem import rffi, lltype
-from pypy.module.cpyext.cparser import parse_source
+from pypy.module.cpyext.cparser import parse_source, CTypeSpace
def test_configure():
decl = """
@@ -67,6 +67,34 @@
Object = cts2.definitions['Object']
assert Object.c_type.TO is Type
+def test_multiple_sources():
+ cdef1 = """
+ typedef ssize_t Py_ssize_t;
+
+ #define PyObject_HEAD \
+ Py_ssize_t ob_refcnt; \
+ Py_ssize_t ob_pypy_link; \
+
+ typedef struct {
+ char *name;
+ } Type;
+ """
+ cdef2 = """
+ typedef struct {
+ PyObject_HEAD
+ Py_ssize_t ob_foo;
+ Type *type;
+ } Object;
+ """
+ cts = CTypeSpace()
+ cts.parse_source(cdef1)
+ Type = cts.definitions['Type']
+ assert isinstance(Type, lltype.Struct)
+ assert 'Object' not in cts.definitions
+ cts.parse_source(cdef2)
+ Object = cts.definitions['Object']
+ assert Object.c_type.TO is Type
+
def test_incomplete():
cdef = """
typedef ssize_t Py_ssize_t;
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit