From 774d7aa3d84cdf5e89db464c4d291ed174de583d Mon Sep 17 00:00:00 2001 From: Candoran2 <45334438+Candoran2@users.noreply.github.com> Date: Sat, 18 Sep 2021 19:20:19 +0200 Subject: [PATCH] Pulled module paths up (i.e. module/enum and module/struct instead of struct/module) and applied them to all tags. Codegen adds __init__.py file to this path where the module attributes are set. --- codegen.py | 30 ++++++++++++++++++++---------- codegen/Module.py | 24 ++++++++++++++++++++++++ codegen/naming_conventions.py | 13 ++++++++++++- 3 files changed, 56 insertions(+), 11 deletions(-) create mode 100644 codegen/Module.py diff --git a/codegen.py b/codegen.py index cb931da30..721ae5488 100644 --- a/codegen.py +++ b/codegen.py @@ -10,6 +10,7 @@ from codegen.Enum import Enum from codegen.Bitfield import Bitfield from codegen.Versions import Versions +from codegen.Module import Module from codegen.naming_conventions import clean_comment_str logging.basicConfig(level=logging.DEBUG) @@ -47,14 +48,21 @@ def generate_module_paths(self, root): """preprocessing - generate module paths for imports relative to the output dir""" for child in root: # only check stuff that has a name - ignore version tags - if child.tag not in ("version", "module", "token"): - class_name = convention.name_class(child.attrib["name"]) - out_segments = ["formats", self.format_name,] - if child.attrib.get("module"): - out_segments.append(child.attrib["module"]) - out_segments.extend([child.tag, class_name, ]) + if child.tag not in ("version", "token"): + base_segments = os.path.join("formats", self.format_name) + if child.tag == "module": + # for modules, set the path to base/module_name + class_name = convention.name_module(child.attrib["name"]) + class_segments = [class_name] + else: + # for classes, set the path to module_path/tag/class_name or + # base/tag/class_name if it's not part of a module + class_name = convention.name_class(child.attrib["name"]) + if child.attrib.get("module"): + base_segments = self.path_dict[convention.name_module(child.attrib["module"])] + class_segments = [child.tag, class_name, ] # store the final relative module path for this class - self.path_dict[class_name] = os.path.join(*out_segments) + self.path_dict[class_name] = os.path.join(base_segments, *class_segments) self.tag_dict[class_name.lower()] = child.tag self.path_dict["Array"] = "array" @@ -76,7 +84,7 @@ def load_xml(self, xml_file): for child in root: self.replace_tokens(child) - if child.tag != 'version': + if child.tag not in ('version', 'module'): self.apply_conventions(child) try: if child.tag in self.struct_types: @@ -87,8 +95,8 @@ def load_xml(self, xml_file): # self.write_basic(child) elif child.tag == "enum": Enum(self, child) - # elif child.tag == "module": - # self.read_module(child) + elif child.tag == "module": + Module(self, child) elif child.tag == "version": versions.read(child) elif child.tag == "token": @@ -122,6 +130,8 @@ def apply_conventions(self, struct): self.apply_convention(field, convention.name_class, ("type",)) self.apply_convention(field, convention.name_class, ("onlyT",)) self.apply_convention(field, convention.name_class, ("excludeT",)) + for default in field: + self.apply_convention(field, convention.name_class, ("onlyT",)) # filter comment str struct.text = clean_comment_str(struct.text, indent="\t", class_comment='"""') diff --git a/codegen/Module.py b/codegen/Module.py new file mode 100644 index 000000000..11c151bc4 --- /dev/null +++ b/codegen/Module.py @@ -0,0 +1,24 @@ +import os +from codegen.naming_conventions import clean_comment_str, name_module + +class Module: + + def __init__(self, parser, element): + self.parser = parser + self.element = element + self.read(element) + self.write(parser.path_dict[name_module(element.attrib["name"])]) + + def read(self, element): + self.comment_str = clean_comment_str(element.text, indent="", class_comment='"""')[2:] + self.priority = int(element.attrib.get("priority","")) + self.depends = [name_module(module) for module in element.attrib.get("depends","").split(" ")] + self.custom = bool(eval(element.attrib.get("custom","true").replace("true","True").replace("false","False"),{})) + + def write(self, rel_path): + file = open(os.path.join(os.getcwd(), "generated", rel_path, "__init__.py"), "w", encoding=self.parser.encoding) + file.write(self.comment_str) + file.write(f'\n\n__priority__ = {repr(self.priority)}') + file.write(f'\n__depends__ = {repr(self.depends)}') + file.write(f'\n__custom__ = {repr(self.custom)}') + file.write(f'\n') \ No newline at end of file diff --git a/codegen/naming_conventions.py b/codegen/naming_conventions.py index 35fa9bdd1..306ddea2d 100644 --- a/codegen/naming_conventions.py +++ b/codegen/naming_conventions.py @@ -123,4 +123,15 @@ def clean_comment_str(comment_str="", indent="", class_comment=""): lines = [f"\n{indent}{class_comment}",] + [f"\n{indent}{line.strip()}" for line in comment_str.strip().split("\n")] + [f"\n{indent}{class_comment}",] else: lines = [f"\n{indent}# {line.strip()}" for line in comment_str.strip().split("\n")] - return "\n" + "".join(lines) \ No newline at end of file + return "\n" + "".join(lines) + + +def name_module(name): + """Converts a module name into a name suitable for a python module + :param name: the module name + :type name: str + :return: Reformatted module name + >>> name_module('BSHavok') + 'bshavok' + """ + return name.lower()