def generate(self, code_sink): """ Generate the getset table, return the table C name or '0' if the table is empty """ if not self.attributes: return '0' getsets = collections.OrderedDict() # attrname -> (getter, setter) for name, getter, setter, custom_name in self.attributes: getter_name = 'NULL' if getter is not None: # getter.generate(code_sink) try: utils.call_with_error_handling(getter.generate, (code_sink,), {}, getter) except utils.SkipWrapper: pass else: getter_name = getter.c_function_name setter_name = 'NULL' if setter is not None: #setter.generate(code_sink) try: utils.call_with_error_handling(setter.generate, (code_sink,), {}, setter) except utils.SkipWrapper: pass else: setter_name = setter.c_function_name assert name not in getsets getsets[name] = (getter_name, setter_name, custom_name) code_sink.writeln("static PyGetSetDef %s[] = {" % self.cname) code_sink.indent() for name, (getter_c_name, setter_c_name, custom_name) in getsets.items(): code_sink.writeln('{') code_sink.indent() code_sink.writeln('(char*) "%s", /* attribute name */' % (custom_name or name)) ## getter code_sink.writeln( '(getter) %s, /* C function to get the attribute */' % getter_c_name) ## setter code_sink.writeln( '(setter) %s, /* C function to set the attribute */' % setter_c_name) code_sink.writeln('NULL, /* optional doc string */') code_sink.writeln('NULL /* optional additional data ' 'for getter and setter */') code_sink.unindent() code_sink.writeln('},') code_sink.writeln('{ NULL, NULL, NULL, NULL, NULL }') code_sink.unindent() code_sink.writeln('};') return self.cname
def generate(self, code_sink): """ Generate the getset table, return the table C name or '0' if the table is empty """ if not self.attributes: return '0' getsets = {} # attrname -> (getter, setter) for name, getter, setter in self.attributes: getter_name = 'NULL' if getter is not None: # getter.generate(code_sink) try: utils.call_with_error_handling(getter.generate, (code_sink,), {}, getter) except utils.SkipWrapper: pass else: getter_name = getter.c_function_name setter_name = 'NULL' if setter is not None: #setter.generate(code_sink) try: utils.call_with_error_handling(setter.generate, (code_sink,), {}, setter) except utils.SkipWrapper: pass else: setter_name = setter.c_function_name assert name not in getsets getsets[name] = (getter_name, setter_name) code_sink.writeln("static PyGetSetDef %s[] = {" % self.cname) code_sink.indent() for name, (getter_c_name, setter_c_name) in getsets.items(): code_sink.writeln('{') code_sink.indent() code_sink.writeln('(char*) "%s", /* attribute name */' % name) ## getter code_sink.writeln( '(getter) %s, /* C function to get the attribute */' % getter_c_name) ## setter code_sink.writeln( '(setter) %s, /* C function to set the attribute */' % setter_c_name) code_sink.writeln('NULL, /* optional doc string */') code_sink.writeln('NULL /* optional additional data ' 'for getter and setter */') code_sink.unindent() code_sink.writeln('},') code_sink.writeln('{ NULL, NULL, NULL, NULL, NULL }') code_sink.unindent() code_sink.writeln('};') return self.cname
def do_generate(self, out, module_file_base_name=None): """(internal) Generates the module.""" assert isinstance(out, _SinkManager) if self.parent is None: ## generate the include directives (only the root module) forward_declarations_sink = MemoryCodeSink() if not self._forward_declarations_declared: self.generate_forward_declarations(forward_declarations_sink) self.after_forward_declarations.flush_to(forward_declarations_sink) if self.parent is None: for include in self.includes: out.get_includes_code_sink().writeln("#include %s" % include) self.includes = None forward_declarations_sink.flush_to(out.get_includes_code_sink()) else: assert module_file_base_name is None, "only root modules can generate with alternate module_file_base_name" ## generate the submodules for submodule in self.submodules: submodule.do_generate(out) m = self.declarations.declare_variable('PyObject*', 'm') assert m == 'm' if module_file_base_name is None: mod_init_name = '.'.join(self.get_module_path()) else: mod_init_name = module_file_base_name self.before_init.write_code('#if PY_VERSION_HEX >= 0x03000000') self.before_init.write_code( "m = PyModule_Create(&%s_moduledef);" % (self.name)) self.before_init.write_code('#else') self.before_init.write_code( "m = Py_InitModule3((char *) \"%s\", %s_functions, %s);" % (mod_init_name, self.prefix, self.docstring and '"'+self.docstring+'"' or 'NULL')) self.before_init.write_code('#endif') self.before_init.write_error_check("m == NULL") main_sink = out.get_main_code_sink() ## generate the function wrappers py_method_defs = [] if self.functions: main_sink.writeln('/* --- module functions --- */') main_sink.writeln() for func_name, overload in self.functions.items(): sink, header_sink = out.get_code_sink_for_wrapper(overload) sink.writeln() try: utils.call_with_error_handling(overload.generate, (sink,), {}, overload) except utils.SkipWrapper: continue try: utils.call_with_error_handling(overload.generate_declaration, (main_sink,), {}, overload) except utils.SkipWrapper: continue sink.writeln() py_method_defs.append(overload.get_py_method_def(func_name)) del sink ## generate the function table main_sink.writeln("static PyMethodDef %s_functions[] = {" % (self.prefix,)) main_sink.indent() for py_method_def in py_method_defs: main_sink.writeln(py_method_def) main_sink.writeln("{NULL, NULL, 0, NULL}") main_sink.unindent() main_sink.writeln("};") ## generate the classes if self.classes: main_sink.writeln('/* --- classes --- */') main_sink.writeln() for class_ in [c for c in self.classes if c.import_from_module]: sink, header_sink = out.get_code_sink_for_wrapper(class_) sink.writeln() class_.generate(sink, self) sink.writeln() for class_ in [c for c in self.classes if not c.import_from_module]: sink, header_sink = out.get_code_sink_for_wrapper(class_) sink.writeln() class_.generate(sink, self) sink.writeln() ## generate the containers if self.containers: main_sink.writeln('/* --- containers --- */') main_sink.writeln() for container in self.containers: sink, header_sink = out.get_code_sink_for_wrapper(container) sink.writeln() container.generate(sink, self) sink.writeln() ## generate the exceptions if self.exceptions: main_sink.writeln('/* --- exceptions --- */') main_sink.writeln() for exc in self.exceptions: sink, header_sink = out.get_code_sink_for_wrapper(exc) sink.writeln() exc.generate(sink, self) sink.writeln() # typedefs for (wrapper, alias) in self.typedefs: if isinstance(wrapper, CppClass): cls = wrapper cls.generate_typedef(self, alias) ## generate the enums if self.enums: main_sink.writeln('/* --- enumerations --- */') main_sink.writeln() for enum in self.enums: sink, header_sink = out.get_code_sink_for_wrapper(enum) sink.writeln() enum.generate(sink) enum.generate_declaration(header_sink, self) sink.writeln() ## register the submodules if self.submodules: submodule_var = self.declarations.declare_variable('PyObject*', 'submodule') for submodule in self.submodules: self.after_init.write_code('%s = %s();' % ( submodule_var, submodule.init_function_name)) self.after_init.write_error_check('%s == NULL' % submodule_var) self.after_init.write_code('Py_INCREF(%s);' % (submodule_var,)) self.after_init.write_code('PyModule_AddObject(m, (char *) "%s", %s);' % (submodule.name, submodule_var,)) ## flush the header section self.header.flush_to(out.get_includes_code_sink()) ## flush the body section self.body.flush_to(main_sink) ## now generate the module init function itself main_sink.writeln('#if PY_VERSION_HEX >= 0x03000000\n' 'static struct PyModuleDef %s_moduledef = {\n' ' PyModuleDef_HEAD_INIT,\n' ' "%s",\n' ' %s,\n' ' -1,\n' ' %s_functions,\n' '};\n' '#endif' % (self.name, mod_init_name, self.docstring and '"'+self.docstring+'"' or 'NULL', self.prefix)) main_sink.writeln() if self.parent is None: main_sink.writeln(''' #if PY_VERSION_HEX >= 0x03000000 #define MOD_ERROR NULL #define MOD_INIT(name) PyObject* PyInit_##name(void) #define MOD_RETURN(val) val #else #define MOD_ERROR #define MOD_INIT(name) void init##name(void) #define MOD_RETURN(val) #endif #if defined(__cplusplus) extern "C" #endif #if defined(__GNUC__) && __GNUC__ >= 4 __attribute__ ((visibility("default"))) #endif ''') else: main_sink.writeln("static PyObject *") if self.parent is None: main_sink.writeln("MOD_INIT(%s)" % (self.name,)) elif module_file_base_name is None: main_sink.writeln("%s(void)" % (self.init_function_name,)) else: main_sink.writeln("init%s(void)" % (module_file_base_name,)) main_sink.writeln('{') main_sink.indent() self.declarations.get_code_sink().flush_to(main_sink) self.before_init.sink.flush_to(main_sink) self.after_init.write_cleanup() self.after_init.sink.flush_to(main_sink) if self.parent is not None: main_sink.writeln("return m;") else: main_sink.writeln("return MOD_RETURN(m);") main_sink.unindent() main_sink.writeln('}')
def do_generate(self, out, module_file_base_name=None): """(internal) Generates the module.""" assert isinstance(out, _SinkManager) if self.parent is None: ## generate the include directives (only the root module) forward_declarations_sink = MemoryCodeSink() if not self._forward_declarations_declared: self.generate_forward_declarations(forward_declarations_sink) self.after_forward_declarations.flush_to(forward_declarations_sink) if self.parent is None: for include in self.includes: out.get_includes_code_sink().writeln("#include %s" % include) self.includes = None forward_declarations_sink.flush_to(out.get_includes_code_sink()) else: assert module_file_base_name is None, "only root modules can generate with alternate module_file_base_name" ## generate the submodules for submodule in self.submodules: submodule.do_generate(out) m = self.declarations.declare_variable('PyObject*', 'm') assert m == 'm' if module_file_base_name is None: mod_init_name = '.'.join(self.get_module_path()) else: mod_init_name = module_file_base_name self.before_init.write_code('#if PY_VERSION_HEX >= 0x03000000') self.before_init.write_code( "m = PyModule_Create(&%s_moduledef);" % (self.prefix)) self.before_init.write_code('#else') self.before_init.write_code( "m = Py_InitModule3((char *) \"%s\", %s_functions, %s);" % (mod_init_name, self.prefix, self.docstring and '"'+self.docstring+'"' or 'NULL')) self.before_init.write_code('#endif') self.before_init.write_error_check("m == NULL") main_sink = out.get_main_code_sink() ## generate the function wrappers py_method_defs = [] if self.functions: main_sink.writeln('/* --- module functions --- */') main_sink.writeln() for func_name, overload in self.functions.items(): sink, header_sink = out.get_code_sink_for_wrapper(overload) sink.writeln() try: utils.call_with_error_handling(overload.generate, (sink,), {}, overload) except utils.SkipWrapper: continue try: utils.call_with_error_handling(overload.generate_declaration, (main_sink,), {}, overload) except utils.SkipWrapper: continue sink.writeln() py_method_defs.append(overload.get_py_method_def(func_name)) del sink ## generate the function table main_sink.writeln("static PyMethodDef %s_functions[] = {" % (self.prefix,)) main_sink.indent() for py_method_def in py_method_defs: main_sink.writeln(py_method_def) main_sink.writeln("{NULL, NULL, 0, NULL}") main_sink.unindent() main_sink.writeln("};") ## generate the classes if self.classes: main_sink.writeln('/* --- classes --- */') main_sink.writeln() for class_ in [c for c in self.classes if c.import_from_module]: sink, header_sink = out.get_code_sink_for_wrapper(class_) sink.writeln() class_.generate(sink, self) sink.writeln() for class_ in [c for c in self.classes if not c.import_from_module]: sink, header_sink = out.get_code_sink_for_wrapper(class_) sink.writeln() class_.generate(sink, self) sink.writeln() ## generate the containers if self.containers: main_sink.writeln('/* --- containers --- */') main_sink.writeln() for container in self.containers: sink, header_sink = out.get_code_sink_for_wrapper(container) sink.writeln() container.generate(sink, self) sink.writeln() ## generate the exceptions if self.exceptions: main_sink.writeln('/* --- exceptions --- */') main_sink.writeln() for exc in self.exceptions: sink, header_sink = out.get_code_sink_for_wrapper(exc) sink.writeln() exc.generate(sink, self) sink.writeln() # typedefs for (wrapper, alias) in self.typedefs: if isinstance(wrapper, CppClass): cls = wrapper cls.generate_typedef(self, alias) ## generate the enums if self.enums: main_sink.writeln('/* --- enumerations --- */') main_sink.writeln() for enum in self.enums: sink, header_sink = out.get_code_sink_for_wrapper(enum) sink.writeln() enum.generate(sink) enum.generate_declaration(header_sink, self) sink.writeln() ## register the submodules if self.submodules: submodule_var = self.declarations.declare_variable('PyObject*', 'submodule') for submodule in self.submodules: self.after_init.write_code('%s = %s();' % ( submodule_var, submodule.init_function_name)) self.after_init.write_error_check('%s == NULL' % submodule_var) self.after_init.write_code('Py_INCREF(%s);' % (submodule_var,)) self.after_init.write_code('PyModule_AddObject(m, (char *) "%s", %s);' % (submodule.name, submodule_var,)) ## flush the header section self.header.flush_to(out.get_includes_code_sink()) ## flush the body section self.body.flush_to(main_sink) ## now generate the module init function itself main_sink.writeln('#if PY_VERSION_HEX >= 0x03000000\n' 'static struct PyModuleDef %s_moduledef = {\n' ' PyModuleDef_HEAD_INIT,\n' ' "%s",\n' ' %s,\n' ' -1,\n' ' %s_functions,\n' '};\n' '#endif' % (self.prefix, mod_init_name, self.docstring and '"'+self.docstring+'"' or 'NULL', self.prefix)) main_sink.writeln() if self.parent is None: main_sink.writeln(''' #if PY_VERSION_HEX >= 0x03000000 #define MOD_ERROR NULL #define MOD_INIT(name) PyObject* PyInit_##name(void) #define MOD_RETURN(val) val #else #define MOD_ERROR #define MOD_INIT(name) void init##name(void) #define MOD_RETURN(val) #endif #if defined(__cplusplus) extern "C" #endif #if defined(__GNUC__) && __GNUC__ >= 4 __attribute__ ((visibility("default"))) #endif ''') else: main_sink.writeln("static PyObject *") if self.parent is None: main_sink.writeln("MOD_INIT(%s)" % (self.name,)) elif module_file_base_name is None: main_sink.writeln("%s(void)" % (self.init_function_name,)) else: main_sink.writeln("init%s(void)" % (module_file_base_name,)) main_sink.writeln('{') main_sink.indent() self.declarations.get_code_sink().flush_to(main_sink) self.before_init.sink.flush_to(main_sink) self.after_init.write_cleanup() self.after_init.sink.flush_to(main_sink) if self.parent is not None: main_sink.writeln("return m;") else: main_sink.writeln("return MOD_RETURN(m);") main_sink.unindent() main_sink.writeln('}')