From 2c947c16cd2e77001257d40fd34a58fbedff800d Mon Sep 17 00:00:00 2001 From: kollivier Date: Sat, 14 Jul 2018 12:39:42 -0700 Subject: [PATCH] Initial tweaks for using ETG to generate bindings for projects other than wxPython. --- buildtools/config.py | 5 +++++ etgtools/__init__.py | 18 ++++++++++++++---- etgtools/extractors.py | 7 +++++-- etgtools/map_generator.py | 5 ++++- etgtools/sip_generator.py | 39 ++++++++++++++++++++++----------------- etgtools/tweaker_tools.py | 19 ++++++++++--------- 6 files changed, 60 insertions(+), 33 deletions(-) diff --git a/buildtools/config.py b/buildtools/config.py index c4acfc856..8b377d13f 100644 --- a/buildtools/config.py +++ b/buildtools/config.py @@ -84,6 +84,11 @@ class Configuration(object): PKGDIR = 'wx' # The name of the top-level package + COPYRIGHT_HOLDER = "Total Control Software" + COPYRIGHT_YEAR = "2017" + LICENSE_NAME = "wxWindows License" + # This information gets added to the top of each generated file. + # --------------------------------------------------------------- # Basic initialization and configuration code diff --git a/etgtools/__init__.py b/etgtools/__init__.py index eb5918d4f..01a1ca1d3 100644 --- a/etgtools/__init__.py +++ b/etgtools/__init__.py @@ -22,16 +22,20 @@ from .extractors import * #--------------------------------------------------------------------------- -cfg = Config(noWxConfig=True) - -phoenixRoot = cfg.ROOT_DIR -XMLSRC = cfg.DOXY_XML_DIR +CONFIG = None class DoxyXMLError(Exception): pass #--------------------------------------------------------------------------- +def setConfig(cfg): + global CONFIG + CONFIG = cfg + +def getConfig(): + return CONFIG + _filesparsed = set() def parseDoxyXML(module, class_or_filename_list): @@ -44,6 +48,12 @@ def parseDoxyXML(module, class_or_filename_list): Doxygen XML output folder. """ + global CONFIG + if not CONFIG: + CONFIG = Config(noWxConfig=True) + + XMLSRC = CONFIG.DOXY_XML_DIR + def _classToDoxyName(name, attempts, base='class'): import string filename = base diff --git a/etgtools/extractors.py b/etgtools/extractors.py index 5022a22a6..2bdfe93c5 100644 --- a/etgtools/extractors.py +++ b/etgtools/extractors.py @@ -22,6 +22,8 @@ textfile_open from sphinxtools.utilities import findDescendants +import etgtools + #--------------------------------------------------------------------------- # These classes simply hold various bits of information about the classes, # methods, functions and other items in the C/C++ API being wrapped. @@ -673,7 +675,7 @@ def renameClass(self, newName): def findHierarchy(self, element, all_classes, specials, read): - from etgtools import XMLSRC + XMLSRC = etgtools.getConfig().DOXY_XML_DIR if not read: fullname = self.name @@ -708,6 +710,8 @@ def findHierarchy(self, element, all_classes, specials, read): def extract(self, element): super(ClassDef, self).extract(element) + XMLSRC = etgtools.getConfig().DOXY_XML_DIR + self.nodeBases = self.findHierarchy(element, {}, [], False) for node in element.findall('basecompoundref'): @@ -724,7 +728,6 @@ def extract(self, element): for node in element.findall('innerclass'): if node.get('prot') == 'private': continue - from etgtools import XMLSRC ref = node.get('refid') fname = os.path.join(XMLSRC, ref+'.xml') root = et.parse(fname).getroot() diff --git a/etgtools/map_generator.py b/etgtools/map_generator.py index ffc7fbee5..6084cc343 100644 --- a/etgtools/map_generator.py +++ b/etgtools/map_generator.py @@ -30,7 +30,10 @@ def __init__(self): def generate(self, module): assert isinstance(module, extractors.ModuleDef) - realModuleName = MODULENAME_REPLACE[module.module] + try: + realModuleName = MODULENAME_REPLACE[module.module] + except KeyError: + realModuleName = module.module dispatchMap = { extractors.ClassDef : self.generateClass, diff --git a/etgtools/sip_generator.py b/etgtools/sip_generator.py index 6256db214..72b8773fc 100644 --- a/etgtools/sip_generator.py +++ b/etgtools/sip_generator.py @@ -13,16 +13,12 @@ """ import sys, os, re +import etgtools import etgtools.extractors as extractors import etgtools.generators as generators from etgtools.generators import nci, Utf8EncodingStream, textfile_open, wrapText - -from buildtools.config import Config -cfg = Config(noWxConfig=True) - divider = '//' + '-'*75 + '\n' -phoenixRoot = cfg.ROOT_DIR class SipGeneratorError(RuntimeError): pass @@ -41,13 +37,17 @@ class SipWrapperGenerator(generators.WrapperGeneratorBase): def generate(self, module, destFile=None): stream = Utf8EncodingStream() + cfg = etgtools.getConfig() # generate SIP code from the module and its objects self.generateModule(module, stream) # Write the contents of the stream to the destination file if not destFile: - destFile = os.path.join(phoenixRoot, 'sip/gen', module.name + '.sip') + destFile = os.path.join(cfg.ROOT_DIR, cfg.SIPGEN, module.name + '.sip') + destDir = os.path.dirname(destFile) + if not os.path.exists(destDir): + os.makedirs(destDir) f = textfile_open(destFile, 'wt') f.write(stream.getvalue()) f.close() @@ -57,13 +57,15 @@ def generate(self, module, destFile=None): def generateModule(self, module, stream): assert isinstance(module, extractors.ModuleDef) + cfg = etgtools.getConfig() + # write the file header stream.write(divider + """\ -// This file is generated by wxPython's SIP generator. Do not edit by hand. +// This file is generated by the ETG SIP generator. Do not edit by hand. // -// Copyright: (c) 2017 by Total Control Software -// License: wxWindows License -""") +// Copyright: (c) %s by %s +// License: %s +""" % (cfg.COPYRIGHT_YEAR, cfg.COPYRIGHT_HOLDER, cfg.LICENSE_NAME)) if module.name == module.module: stream.write(""" %%Module( name=%s.%s, @@ -76,13 +78,13 @@ def generateModule(self, module, stream): }; %%Copying - Copyright: (c) 2017 by Total Control Software - License: wxWindows License + Copyright: (c) %s by %s + License: %s %%End %%DefaultDocstringFormat(name="deindented") -""" % (module.package, module.name)) +""" % (module.package, module.name, cfg.COPYRIGHT_YEAR, cfg.COPYRIGHT_HOLDER, cfg.LICENSE_NAME)) if module.name.startswith('_'): doc = '' @@ -90,16 +92,16 @@ def generateModule(self, module, stream): doc = '\n"""\n%s"""\n' % module.docstring stream.write("""\ %%Extract(id=pycode%s, order=5) -# This file is generated by wxPython's SIP generator. Do not edit by hand. +# This file is generated by the ETG SIP generator. Do not edit by hand. # -# Copyright: (c) 2017 by Total Control Software -# License: wxWindows License +# Copyright: (c) %s by %s +# License: %s %s from .%s import * %%End -""" % ( module.name, doc, module.name)) +""" % ( module.name, doc, module.name, cfg.COPYRIGHT_YEAR, cfg.COPYRIGHT_HOLDER, cfg.LICENSE_NAME)) else: stream.write("//\n// This file will be included by %s.sip\n//\n" % module.module) @@ -226,6 +228,9 @@ def _lastParameter(idx): for idx, param in enumerate(parameters): if param.ignored: continue + # Handle FunctionName(void) parameter definitions + if param.type == 'void' and not param.name: + continue stream.write(indent) stream.write('%s %s' % (param.type, param.name)) stream.write(self.annotate(param)) diff --git a/etgtools/tweaker_tools.py b/etgtools/tweaker_tools.py index ba93f0f85..27ae03e96 100644 --- a/etgtools/tweaker_tools.py +++ b/etgtools/tweaker_tools.py @@ -121,15 +121,16 @@ def _processItem(item, names): names = list() filename = 'wx/core.pyi' - if PY3: - with open(filename, 'rt', encoding='utf-8') as f: - text = f.read() - else: - with open(filename, 'r') as f: - text = f.read() - parseTree = ast.parse(text, filename) - for item in parseTree.body: - _processItem(item, names) + if os.path.exists(filename): + if PY3: + with open(filename, 'rt', encoding='utf-8') as f: + text = f.read() + else: + with open(filename, 'r') as f: + text = f.read() + parseTree = ast.parse(text, filename) + for item in parseTree.body: + _processItem(item, names) FixWxPrefix._coreTopLevelNames = names