1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
"""
@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 <wenzeslaus gmail.com>
@author Anna Petrasova <kratochanna gmail.com>
"""
import sys
import grass.script.core as gcore
import grass.script.task as gtask
from grass.exceptions import ScriptError
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 builtins
builtins.__dict__["_"] = 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<module-item name="%s">\n' % (" " * indent, m))
indent += 4
fd.write("%s<module>%s</module>\n" % (" " * indent, m))
fd.write("%s<description>%s</description>\n" % (" " * indent, escapeXML(desc)))
fd.write(
"%s<keywords>%s</keywords>\n" % (" " * indent, escapeXML(",".join(keyw)))
)
indent -= 4
fd.write("%s</module-item>\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'])
""" # noqa: E501
try:
task = gtask.parse_interface(name)
except ScriptError as exc:
sys.stderr.write(
"Cannot parse interface for module %s. Empty strings"
" will be placed instead of description and keywords."
" Reason: %s\n" % (name, str(exc))
)
return "", ""
return task.get_description(full=True), task.get_keywords()
def header(fd):
fd.write('<?xml version="1.0" encoding="UTF-8"?>\n')
fd.write('<!DOCTYPE module-items SYSTEM "module_items.dtd">\n')
fd.write("<!--This file is automatically generated using %s-->\n" % sys.argv[0])
# g.version -r is crashing, commenting this block for now
# vInfo = gcore.version()
# fd.write('<!--version="%s" revision="%s" date="%s"-->\n' % \
# (vInfo['version'].split('.')[0],
# vInfo['revision'],
# datetime.now()))
fd.write("<module-items>\n")
def footer(fd):
fd.write("</module-items>\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())
|