""" @package tools.build_modules_xml @brief Builds XML metadata of GRASS modules. Runs only during compilation. (C) 2013 by the GRASS Development Team This program is free software under the GNU General Public License (>=v2). Read the file COPYING that comes with GRASS for details. @author Vaclav Petras @author Anna Petrasova """ from __future__ import print_function import sys import grass.script.core as gcore import grass.script.task as gtask def escapeXML(text): """This is a duplicate of function in core/toolboxes. >>> escapeXML('<>&') '&lt;>&' """ return text.replace("<", "<").replace("&", "&").replace(">", ">") def do_doctest_gettext_workaround(): """This is a duplicate of function in core/toolboxes.""" def new_displayhook(string): """A replacement for default `sys.displayhook`""" if string is not None: sys.stdout.write("%r\n" % (string,)) def new_translator(string): """A fake gettext underscore function.""" return string sys.displayhook = new_displayhook sys.__displayhook__ = new_displayhook import __builtin__ __builtin__._ = new_translator def parse_modules(fd): """Writes metadata to xml file.""" # TODO: what about ms windows? does gtask handle this? mlist = list(gcore.get_commands()[0]) indent = 4 for m in sorted(mlist): # TODO: get rid of g.mapsets_picker.py if m == "g.mapsets_picker.py" or m == "g.parser": continue desc, keyw = get_module_metadata(m) fd.write('%s\n' % (" " * indent, m)) indent += 4 fd.write("%s%s\n" % (" " * indent, m)) fd.write("%s%s\n" % (" " * indent, escapeXML(desc))) fd.write( "%s%s\n" % (" " * indent, escapeXML(",".join(keyw))) ) indent -= 4 fd.write("%s\n" % (" " * indent)) def get_module_metadata(name): """ >>> get_module_metadata('g.region') ('Manages the boundary definitions for the geographic region.', ['general', 'settings']) >>> get_module_metadata('m.proj') ('Converts coordinates from one projection to another (cs2cs frontend).', ['miscellaneous', 'projection']) """ try: task = gtask.parse_interface(name) except: sys.stderr.write( "Cannot parse interface for module %s. Empty strings" " will be placed instead of description and keywords." "\n" % name ) return "", "" return task.get_description(full=True), task.get_keywords() def header(fd): fd.write('\n') fd.write('\n') fd.write("\n" % sys.argv[0]) # g.version -r is crashing, commenting this block for now # vInfo = gcore.version() # fd.write('\n' % \ # (vInfo['version'].split('.')[0], # vInfo['revision'], # datetime.now())) fd.write("\n") def footer(fd): fd.write("\n") def doc_test(): """Tests the module using doctest :return: a number of failed tests """ import doctest do_doctest_gettext_workaround() return doctest.testmod().failed def module_test(): grass_commands = gcore.get_commands()[0] if "g.region" not in grass_commands: print("No g.region") return 1 if "m.proj" not in grass_commands: print("No m.proj") return 1 if "t.rast.univar" not in grass_commands: print("No t.rast.univar") return 1 print(get_module_metadata("g.region")) print(get_module_metadata("m.proj")) print(get_module_metadata("t.rast.univar")) def main(): fh = sys.stdout header(fh) parse_modules(fh) footer(fh) return 0 if __name__ == "__main__": if len(sys.argv) > 1: if sys.argv[1] == "doctest": sys.exit(doc_test()) elif sys.argv[1] == "test": sys.exit(module_test()) else: gcore.fatal("Unrecognized parameter.") sys.exit(main())