[GRASS-SVN] r66990 - in grass/trunk/scripts: . g.search.module g.search.module/testsuite

svn_grass at osgeo.org svn_grass at osgeo.org
Mon Nov 30 13:09:22 PST 2015


Author: jachym
Date: 2015-11-30 13:09:22 -0800 (Mon, 30 Nov 2015)
New Revision: 66990

Added:
   grass/trunk/scripts/g.search.module/
   grass/trunk/scripts/g.search.module/Makefile
   grass/trunk/scripts/g.search.module/g.search.module.html
   grass/trunk/scripts/g.search.module/g.search.module.py
   grass/trunk/scripts/g.search.module/testsuite/
   grass/trunk/scripts/g.search.module/testsuite/test_g_search_module.py
Modified:
   grass/trunk/scripts/Makefile
Log:
Adding new g.search.module script

Modified: grass/trunk/scripts/Makefile
===================================================================
--- grass/trunk/scripts/Makefile	2015-11-30 17:57:27 UTC (rev 66989)
+++ grass/trunk/scripts/Makefile	2015-11-30 21:09:22 UTC (rev 66990)
@@ -21,6 +21,7 @@
 	g.extension \
 	g.extension.all \
 	g.manual \
+	g.search.module \
 	i.colors.enhance \
 	i.image.mosaic \
 	i.in.spotvgt \

Added: grass/trunk/scripts/g.search.module/Makefile
===================================================================
--- grass/trunk/scripts/g.search.module/Makefile	                        (rev 0)
+++ grass/trunk/scripts/g.search.module/Makefile	2015-11-30 21:09:22 UTC (rev 66990)
@@ -0,0 +1,7 @@
+MODULE_TOPDIR = ../..
+
+PGM = g.search.module
+
+include $(MODULE_TOPDIR)/include/Make/Script.make
+
+default: script

Added: grass/trunk/scripts/g.search.module/g.search.module.html
===================================================================
--- grass/trunk/scripts/g.search.module/g.search.module.html	                        (rev 0)
+++ grass/trunk/scripts/g.search.module/g.search.module.html	2015-11-30 21:09:22 UTC (rev 66990)
@@ -0,0 +1,69 @@
+<h2>DESCRIPTION</h2>
+
+<em>r.search.module</em> searches for given keyword in GRASS modules name,
+description, keywords and optionally manpages too.
+
+<h2>NOTES</h2>
+
+There can be more keywords, <em>g.search.module</em> will search for each of them
+
+<h2>EXAMPLE</h2>
+
+Search all modules, where keywords <em>buffer</em> OR <em>clip</em> can be found
+<div class="code"><pre>
+GRASS> g.search.module buffer,clip
+
+r.circle
+    keywords: raster,buffer,geometry,circle
+    description: Creates a raster map containing concentric rings around a
+                 given point.
+
+r.buffer.lowmem
+    keywords: raster,buffer
+    description: Creates a raster map showing buffer zones surrounding cells
+                 that contain non-NULL category values. This is the low-
+                 memory alternative to the classic r.buffer module.
+
+r.buffer
+    keywords: raster,buffer
+    description: Creates a raster map showing buffer zones surrounding cells
+                 that contain non-NULL category values.
+</pre></div>
+
+Search all modules, where keywords <em>overlay</em> AND <em>clip</em> can be
+found with some fancy terminal output
+<div class="code"><pre>
+GRASS> g.search.module clip,overlay -a -c
+
+v.overlay
+    keywords: vector,geometry,spatial query,intersection,union,clip
+    description: Overlays two vector maps.;
+</pre></div>
+
+Search in manual pages too 
+<div class="code"><pre>
+GRASS> g.search.module -m kapri
+
+db.execute
+    keywords: database,attribute table,SQL
+    description: Executes any SQL statement. For SELECT statements use
+                 'db.select'.
+
+db.select
+    keywords: database,attribute table,SQL
+    description: Selects data from attribute table. Performs SQL query
+                 statement(s).
+</pre></div>
+
+<h2>SEE ALSO</h2>
+
+<em>
+  <a href="g.manual.html">g.manual</a>,
+  <a href="g.search.map.html">g.search.map</a>,
+</em>
+
+<h2>AUTHORS</h2>
+
+Jachym Cepicky, OpenGeoLabs s.r.o., Czech Republic
+
+<p><i>Last changed: $Date: 2015-05-12 23:11:59 +0200 (Út, 12 kvě 2015) $</i>

Added: grass/trunk/scripts/g.search.module/g.search.module.py
===================================================================
--- grass/trunk/scripts/g.search.module/g.search.module.py	                        (rev 0)
+++ grass/trunk/scripts/g.search.module/g.search.module.py	2015-11-30 21:09:22 UTC (rev 66990)
@@ -0,0 +1,235 @@
+#!/usr/bin/env python
+############################################################################
+#
+# MODULE:	g.search.module
+# AUTHOR(S):	Jachym Cepicky <jachym.cepicky gmail.com>
+# PURPOSE:	g.search.module in grass modules using keywords
+# COPYRIGHT:	(C) 2015-2016 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.
+#
+#############################################################################
+
+#%module
+#% description: Search in GRASS modules using keywords
+#% keyword: general
+#% keyword: modules
+#% keyword: search
+#%end
+#%option
+#% key: keyword
+#% multiple: yes
+#% type: string
+#% description: Keyword to be searched
+#% required : yes
+#%end
+#%flag
+#% key: a
+#% description: Display only modules where all keywords are available (AND), default: OR
+#% guisection: Output
+#%end
+#%flag
+#% key: m
+#% description: Search in manual pages too (can be slow)
+#% guisection: Output
+#%end
+#%flag
+#% key: c
+#% description: Use colorized (more readable) output to terminal
+#% guisection: Output
+#%end
+#%flag
+#% key: g
+#% description: Shell script format
+#% guisection: Output
+#%end
+#%flag
+#% key: j
+#% description: JSON format
+#% guisection: Output
+#%end
+
+import os
+import sys
+
+from grass.script.utils import diff_files, try_rmdir
+from grass.script import core as grass
+
+try:
+    import xml.etree.ElementTree   as etree
+except ImportError:
+    import elementtree.ElementTree as etree # Python <= 2.4
+
+COLORIZE=False
+
+def main():
+    global COLORIZE
+    keywords = options['keyword'].lower().split(',')
+    AND = flags['a']
+    manpages = flags['m']
+    out_format = None
+    if flags['g']:
+        out_format = 'shell'
+    elif flags['j']:
+        out_format = 'json'
+    else:
+        COLORIZE = flags['c']
+
+    modules = _search_module(keywords, AND, manpages)
+
+    print_results(modules, out_format) 
+
+def print_results(data, out_format=None):
+    """
+    Print result of the searching method
+
+    each data item should have
+
+    {
+        'name': name of the item,
+        'attributes': {
+            # list of attributes to be shown too
+        }
+    }
+
+    :param list.<dict> data: input list of found data items
+    :param str out_format: output format 'shell', 'json', None
+    """
+
+    if not out_format:
+        _print_results(data)
+
+    elif out_format == 'shell':
+        _print_results_shell(data)
+
+    elif out_format == 'json':
+        _print_results_json(data)
+
+def _print_results_shell(data):
+    """Print just the name attribute"""
+
+    for item in data:
+        print item['name']
+
+def _print_results_json(data):
+    """Print JSON output"""
+
+    import json
+    print json.dumps(data, sort_keys=True, indent=4, separators=(',', ': '))
+
+def _print_results(data):
+
+    import textwrap
+
+    for item in data:
+        print '\n{}'.format(colorize(item['name'], attrs=['bold']))
+        for attr in item['attributes']:
+            out = '{}: {}'.format(attr, item['attributes'][attr])
+            out = textwrap.wrap(out, width=79, initial_indent=4*' ',
+                    subsequent_indent=4*' '+len(attr)*' '+'  ')
+            for line in out:
+                print line
+
+def colorize(text, attrs=None, pattern=None):
+    """Colorize given text input
+
+    :param string text: input text to be colored
+    :param list.<string> attrs: list of attributes as defined in termcolor package
+    :param string pattern: text to be highlighted in input text
+    :return: colored string
+    """
+    
+
+    if COLORIZE:
+        from termcolor import colored
+    else:
+        def colored(pattern, attrs):
+            return pattern
+
+    if pattern:
+        return text.replace(pattern, colored(pattern, attrs=attrs))
+    else:
+        return colored(text, attrs=attrs)
+
+def _search_module(keywords, logical_and=False, manpages=False):
+    """Search modules by given keywords
+
+    :param list.<str> keywords: list of keywords
+    :param boolean logical_and: use AND (default OR)
+    :param boolean manpages: search in manpages too
+    :return dict: modules
+    """
+
+    WXGUIDIR = os.path.join(os.getenv("GISBASE"), "gui", "wxpython")
+    filename = os.path.join(WXGUIDIR, 'xml', 'module_items.xml')
+    menudata_file = open(filename, 'r')
+
+    menudata = etree.parse(menudata_file)
+    menudata_file.close()
+
+    items = menudata.findall('module-item')
+
+    found_modules = []
+    for item in items:
+        name = item.attrib['name']
+        description = item.find('description').text
+        module_keywords = item.find('keywords').text
+
+        found = [False]
+        if logical_and:
+            found = [False] * len(keywords)
+
+        for idx in range(len(keywords)):
+            keyword = keywords[idx]
+            keyword_found = False
+
+            keyword_found = _basic_search(keyword, name, description, module_keywords)
+
+            if not keyword_found and manpages:
+                keyword_found = _manpage_search(keyword, name)
+
+            if keyword_found:
+                if logical_and:
+                    found[idx] = True
+                else:
+                    found = [True]
+
+                description = colorize(description,
+                                        attrs=['underline'],
+                                        pattern=keyword)
+                module_keywords = colorize(module_keywords,
+                                            attrs=['underline'],
+                                            pattern=keyword)
+
+        if False not in found:
+            found_modules.append({
+                'name': name,
+                'attributes': {
+                    'keywords': module_keywords,
+                    'description': description
+                }
+            })
+
+    return found_modules
+
+def _basic_search(pattern, name, description, module_keywords):
+    
+    if name.lower().find(pattern) > -1 or\
+       description.lower().find(pattern) > -1 or\
+       module_keywords.lower().find(pattern) > -1:
+
+        return True
+    else:
+        return False
+
+def _manpage_search(pattern, name):
+
+    manpage = grass.read_command('g.manual', flags='m', entry=name)
+
+    return manpage.lower().find(pattern) > -1
+
+if __name__ == "__main__":
+    options, flags = grass.parser()
+    sys.exit(main())


Property changes on: grass/trunk/scripts/g.search.module/g.search.module.py
___________________________________________________________________
Added: svn:executable
   + *

Added: grass/trunk/scripts/g.search.module/testsuite/test_g_search_module.py
===================================================================
--- grass/trunk/scripts/g.search.module/testsuite/test_g_search_module.py	                        (rev 0)
+++ grass/trunk/scripts/g.search.module/testsuite/test_g_search_module.py	2015-11-30 21:09:22 UTC (rev 66990)
@@ -0,0 +1,64 @@
+"""
+TEST:      test_g_search_module.py
+
+AUTHOR(S): Jachym Cepicky <jachym.cepicky gmail com>
+
+PURPOSE:   Test g.search.module script outputs
+
+COPYRIGHT: (C) 2015 Jachym Ceppicky, and 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.
+"""
+
+from grass.gunittest.case import TestCase
+from grass.gunittest.main import test
+from grass.gunittest.gmodules import SimpleModule
+
+import termcolor
+
+import os
+
+
+class TestSearchModule(TestCase):
+
+    def test_terminal_output(self):
+        """ """
+        module = SimpleModule('g.search.module', keyword="water")
+        self.assertModule(module)
+        stdout = module.outputs.stdout
+        self.assertEqual(stdout.split()[0], 'r.watershed')
+
+    def test_json_output(self):
+        import json
+        module = SimpleModule('g.search.module', keyword="water", flags="j")
+        self.assertModule(module)
+        stdout = json.loads(module.outputs.stdout)
+        self.assertEqual(len(stdout), 6, 'Six modules found')
+        self.assertEqual(stdout[3]['name'], 'r.basins.fill', 'r.basins.fill')
+        self.assertTrue('keywords' in stdout[3]['attributes'])
+
+    def test_shell_outout(self):
+        module = SimpleModule('g.search.module', keyword="water", flags="g")
+        self.assertModule(module)
+        stdout = module.outputs.stdout.split()
+        self.assertEqual(len(stdout), 6)
+        self.assertEqual(stdout[3], 'r.basins.fill')
+
+    def test_colored_terminal(self):
+        module = SimpleModule('g.search.module', keyword="water", flags="c")
+        self.assertModule(module)
+        stdout = module.outputs.stdout.split()
+        self.assertEqual(stdout[0],
+                         termcolor.colored('r.watershed',
+                         attrs=['bold']))
+
+    def test_manual_pages(self):
+        module = SimpleModule('g.search.module', keyword="kapri", flags="gm")
+        self.assertModule(module)
+        stdout = module.outputs.stdout.split()
+        self.assertEqual(len(stdout), 2)
+
+if __name__ == '__main__':
+    test()



More information about the grass-commit mailing list