source: grass/trunk/lib/python/gunittest/gmodules.py

Last change on this file was 74416, checked in by sbl, 5 years ago

make multirunner pass with Py 2 and 3

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-python
File size: 5.0 KB
Line 
1# -*- coding: utf-8 -*-
2"""Specialized interfaces for invoking modules for testing framework
3
4Copyright (C) 2014 by the GRASS Development Team
5This program is free software under the GNU General Public
6License (>=v2). Read the file COPYING that comes with GRASS GIS
7for details.
8
9:authors: Vaclav Petras, Soeren Gebbert
10"""
11
12import subprocess
13from grass.script.core import start_command
14from grass.script.utils import encode, decode
15from grass.exceptions import CalledModuleError
16from grass.pygrass.modules import Module
17
18from .utils import do_doctest_gettext_workaround
19
20
21class SimpleModule(Module):
22 """Simple wrapper around pygrass.modules.Module to make sure that
23 run\_, finish\_, stdout and stderr are set correctly.
24
25 >>> mapcalc = SimpleModule('r.mapcalc', expression='test_a = 1',
26 ... overwrite=True)
27 >>> mapcalc.run()
28 Module('r.mapcalc')
29 >>> mapcalc.popen.returncode
30 0
31
32 >>> colors = SimpleModule('r.colors',
33 ... map='test_a', rules='-', stdin_='1 red')
34 >>> colors.run()
35 Module('r.colors')
36 >>> colors.popen.returncode
37 0
38 >>> str(colors.inputs.stdin)
39 '1 red'
40 >>> str(colors.outputs.stdout)
41 ''
42 >>> colors.outputs.stderr.strip()
43 u"Color table for raster map <test_a> set to 'rules'"
44 """
45 def __init__(self, cmd, *args, **kargs):
46 for banned in ['stdout_', 'stderr_', 'finish_', 'run_']:
47 if banned in kargs:
48 raise ValueError('Do not set %s parameter'
49 ', it would be overriden' % banned)
50 kargs['stdout_'] = subprocess.PIPE
51 kargs['stderr_'] = subprocess.PIPE
52 kargs['finish_'] = True
53 kargs['run_'] = False
54
55 Module.__init__(self, cmd, *args, **kargs)
56
57
58def call_module(module, stdin=None,
59 merge_stderr=False, capture_stdout=True, capture_stderr=True,
60 **kwargs):
61 r"""Run module with parameters given in `kwargs` and return its output.
62
63 >>> print call_module('g.region', flags='pg') # doctest: +ELLIPSIS
64 projection=...
65 zone=...
66 n=...
67 s=...
68 w=...
69 >>> call_module('m.proj', flags='i', input='-', stdin="50.0 41.5")
70 '8642890.65|6965155.61|0.00\n'
71 >>> call_module('g.region', aabbbccc='notexist') # doctest: +IGNORE_EXCEPTION_DETAIL
72 Traceback (most recent call last):
73 ...
74 CalledModuleError: Module run g.region ... ended with error
75
76 If `stdin` is not set and `kwargs` contains ``input`` with value set
77 to ``-`` (dash), the function raises an error.
78
79 Note that ``input`` nor ``output`` parameters are used by this
80 function itself, these are usually module parameters which this
81 function just passes to it. However, when ``input`` is in parameters
82 the function checks if its values is correct considering value of
83 ``stdin`` parameter.
84
85 :param str module: module name
86 :param stdin: string to be used as module standard input (stdin) or `None`
87 :param merge_stderr: if the standard error output should be merged with stdout
88 :param kwargs: module parameters
89
90 :returns: module standard output (stdout) as string or None if apture_stdout is False
91
92 :raises CalledModuleError: if module return code is non-zero
93 :raises ValueError: if the parameters are not correct
94
95 .. note::
96 The data read is buffered in memory, so do not use this method
97 if the data size is large or unlimited.
98 """
99 # TODO: remove this:
100 do_doctest_gettext_workaround()
101 # implementation inspired by subprocess.check_output() function
102 if stdin:
103 if 'input' in kwargs and kwargs['input'] != '-':
104 raise ValueError(_("input='-' must be used when stdin is specified"))
105 if stdin == subprocess.PIPE:
106 raise ValueError(_("stdin must be string or buffer, not PIPE"))
107 kwargs['stdin'] = subprocess.PIPE # to be able to send data to stdin
108 elif 'input' in kwargs and kwargs['input'] == '-':
109 raise ValueError(_("stdin must be used when input='-'"))
110 if merge_stderr and not (capture_stdout and capture_stderr):
111 raise ValueError(_("You cannot merge stdout and stderr and not capture them"))
112 if 'stdout' in kwargs:
113 raise TypeError(_("stdout argument not allowed, it could be overridden"))
114 if 'stderr' in kwargs:
115 raise TypeError(_("stderr argument not allowed, it could be overridden"))
116
117 if capture_stdout:
118 kwargs['stdout'] = subprocess.PIPE
119 if capture_stderr:
120 if merge_stderr:
121 kwargs['stderr'] = subprocess.STDOUT
122 else:
123 kwargs['stderr'] = subprocess.PIPE
124 process = start_command(module, **kwargs)
125 # input=None means no stdin (our default)
126 # for no stdout, output is None which is out interface
127 # for stderr=STDOUT or no stderr, errors is None
128 # which is fine for CalledModuleError
129 output, errors = process.communicate(input=encode(decode(stdin)) if stdin else None)
130 returncode = process.poll()
131 if returncode:
132 raise CalledModuleError(returncode, module, kwargs, errors)
133 return decode(output) if output else None
Note: See TracBrowser for help on using the repository browser.