def generate_setting_id_impl(settings): ns = cpp.Namespace('faint') for setting_id in sorted(settings.keys()): item = settings[setting_id] ns += 'const %s %s;' % (item.cpp_type, item.cpp_name) ns += '' ns += setting_name_impl(settings, pretty=True) ns += setting_name_impl(settings, pretty=False) for setting_id in sorted(settings.keys()): item = settings[setting_id] if item.get_type() == 'stringtoint': ns += cpp_int_to_enum_impl(item) ns += cpp_enum_to_int_impl(item) ns += cpp_valid_impl(item) ns += cpp_value_string_impl(settings) comment = cpp.Comment('Generated by %s' % os.path.basename(__file__)) return (comment + cpp.Include('<sstream>') + cpp.Include('"cpp-setting-id.hh"') + ns)
def generate_setting_id_header(settings): ns = cpp.Namespace('faint') for setting_id in sorted(settings.keys()): item = settings[setting_id] if item.get_type() == 'stringtoint': enum = item.cpp_enum entries = list(enum.entries) entries.append("MIN=%s" % enum.entries[0]) entries.append("MAX=%s" % enum.entries[-1]) entries.append("DEFAULT=%s" % enum.entries[0]) ns += 'enum class %s{' % enum.name for entry in entries[:-1]: ns += entry + ',' ns += entries[-1] ns += '};' ns += '' ns += 'extern const %s %s;' % (item.cpp_type, item.cpp_name) ns += '%s to_%s(int);' % (enum.name, item.py_name) ns += 'bool valid_%s(int);' % (item.py_name) ns += 'int to_int(%s);' % (enum.name) ns += '' else: ns += 'extern const %s %s;' % (item.cpp_type, item.cpp_name) ns += 'utf8_string setting_name(const UntypedSetting&);' ns += 'utf8_string setting_name_pretty(const UntypedSetting&);' ns += '' ns += '// Returns the name for this value if the IntSetting has names for values' ns += '// otherwise, just returns the value as a string' ns += 'utf8_string value_string(const IntSetting&, int value);' ns += '' comment = cpp.Comment('Generated by %s' % os.path.basename(__file__)) return comment + cpp.IncludeGuard('CPP_SETTING_ID_HH', cpp.Include('"util/settings.hh"') + ns)
def run(root_dir, force=False): """Generate C++-Python code using the templates under the root-dir, and the Faint settings defined in set_and_get.py """ oldDir = os.getcwd() os.chdir(root_dir) sys.path.append(os.getcwd()) template_files = [ os.path.join("templates", f) for f in os.listdir("templates") ] out_dir = '../../generated/python/settings' up_to_date = not _should_generate("set_and_get.py", template_files, out_dir) # Fixme: Also check e.g. py-something-properties if not force and up_to_date: print("* Python-C++ interface up to date.") os.chdir(oldDir) return print("* Generating Python-C++ interface.") import set_and_get setters_and_getters = set_and_get.setters_and_getters settings_declarations = cpp.Code() settings_cc = cpp.Code() smth_declarations = cpp.Code() smth_cc = cpp.Code() functions_cc = cpp.Code() function_method_def = cpp.Code() # List of property-name to property-docs tuples properties = [] for setting in setters_and_getters: item = setters_and_getters[setting] setting_type = item.get_type() properties.append((None, item.py_name, item.doc_str)) if setting_type == 'bool': replacements = common_replacements(setting, item) generate_function(functions_cc, function_method_def, TEMPLATES.function_bool, TEMPLATES.function_method_def, replacements) generate_property(settings_declarations, settings_cc, TEMPLATES.settings_property, TEMPLATES.settings_bool, replacements) generate_property(smth_declarations, smth_cc, TEMPLATES.object_property, TEMPLATES.object_bool, replacements) elif setting_type == 'color': replacements = common_replacements(setting, item) generate_function(functions_cc, function_method_def, TEMPLATES.function_color, TEMPLATES.function_method_def, replacements) generate_property(settings_declarations, settings_cc, TEMPLATES.settings_property, TEMPLATES.settings_color, replacements) generate_property(smth_declarations, smth_cc, TEMPLATES.object_property, TEMPLATES.object_color, replacements) elif setting_type == 'float': replacements = numeric_replacements(setting, item) generate_function(functions_cc, function_method_def, TEMPLATES.function_float, TEMPLATES.function_method_def, replacements) generate_property(settings_declarations, settings_cc, TEMPLATES.settings_property, TEMPLATES.settings_float, replacements) generate_property(smth_declarations, smth_cc, TEMPLATES.object_property, TEMPLATES.object_float, replacements) elif setting_type == 'int': replacements = numeric_replacements(setting, item) generate_function(functions_cc, function_method_def, TEMPLATES.function_int, TEMPLATES.function_method_def, replacements) generate_property(settings_declarations, settings_cc, TEMPLATES.settings_property, TEMPLATES.settings_int, replacements) generate_property(smth_declarations, smth_cc, TEMPLATES.object_property, TEMPLATES.object_int, replacements) elif setting_type == 'string': replacements = common_replacements(setting, item) generate_function(functions_cc, function_method_def, TEMPLATES.function_string, TEMPLATES.function_method_def, replacements) generate_property(settings_declarations, settings_cc, TEMPLATES.settings_property, TEMPLATES.settings_string, replacements) generate_property(smth_declarations, smth_cc, TEMPLATES.object_property, TEMPLATES.object_string, replacements) elif setting_type == 'stringtoint': replacements = string_to_int_replacements(setting, item, for_property=False) generate_function(functions_cc, function_method_def, TEMPLATES.function_string_to_int, TEMPLATES.function_method_def, replacements) replacements = string_to_int_replacements(setting, item, for_property=True) generate_property(settings_declarations, settings_cc, TEMPLATES.settings_property, TEMPLATES.settings_string_to_int, replacements) generate_property(smth_declarations, smth_cc, TEMPLATES.object_property, TEMPLATES.object_string_to_int, replacements) else: print(setting_type) assert (False) property_doc_dir = '../../help/source/generated/' if not os.path.exists(property_doc_dir): os.mkdir(property_doc_dir) gen_method_def.write_property_doc( os.path.join(property_doc_dir, 'py-settings-properties.txt'), properties) comment = cpp.Comment('Generated by %s' % os.path.basename(__file__)) interface_cc = (comment + cpp.Include('"python/py-include.hh"') + cpp.Include('"app/canvas.hh"') + cpp.Include('"app/get-app-context.hh"') + cpp.Include('"util/settings.hh"') + cpp.Include('"util/setting-id.hh"') + cpp.Include('"python/py-util.hh"') + cpp.Include('"text/formatting.hh"') + cpp.Include('"python/py-function-error.hh"') + cpp.Namespace('faint', functions_cc)) if not os.path.exists(out_dir): os.makedirs(out_dir) with open(os.path.join(out_dir, 'setting-functions.hh'), 'w') as f: f.write(interface_cc.get_text()) with open(os.path.join(out_dir, 'cpp-setting-id.hh'), 'w') as f: f.write(generate_setting_id_header(setters_and_getters).get_text()) with open(os.path.join(out_dir, 'cpp-setting-id.cpp'), 'w') as f: f.write(generate_setting_id_impl(setters_and_getters).get_text()) with open(os.path.join(out_dir, 'py-settings-properties.hh'), 'w') as f: getset = cpp.Code() getset += 'static PyGetSetDef settings_properties[] ={' getset += settings_declarations getset += '{0,0,0,0,0}' getset += '};' content = comment + cpp.IncludeGuard( 'FAINT_PY_SETTINGS_PROPERTIES_HH', cpp.Namespace('faint', settings_cc + getset)) f.write(content.get_text()) # Fixme: Add hand-written properties in a less ugly way cpp_properties = gen_method_def.parse_file( os.path.abspath( os.path.join(root_dir, "../", "../", "py-something-properties.hh")))[1] getset = cpp.Code() getset += 'static PyGetSetDef smth_properties[] ={' getset += smth_declarations for item in cpp_properties: getset += gen_method_def.to_PyGetSetDef_entry(*item) + "," getset += '{0,0,0,0,0}' getset += '};' content = (comment + cpp.IncludeGuard('FAINT_PY_SMTH_SETTING_PROPERTIES_HH', cpp.Namespace('faint', smth_cc + getset))) with open(os.path.join(out_dir, 'py-smth-setting-properties.hh'), 'w') as f: f.write(content.get_text()) gen_method_def.write_property_doc( os.path.join(property_doc_dir, 'py-something-properties.txt'), cpp_properties) with open(os.path.join(out_dir, 'setting-function-defs.hh'), 'w') as f: content = comment + cpp.IncludeGuard('FAINT_SETTING_FUNCTION_DEFS_HH', function_method_def) f.write(content.get_text()) os.chdir(oldDir)