Преглед на файлове

Merge branch 'master' of github.com:OSGeo/grass

Markus Neteler преди 6 години
родител
ревизия
2604e476c5
променени са 49 файла, в които са добавени 330 реда и са изтрити 297 реда
  1. 0 86
      README
  2. 92 0
      README.md
  3. 8 8
      gui/wxpython/core/toolboxes.py
  4. 13 13
      lib/gis/testsuite/gis_lib_env_test.py
  5. 4 3
      lib/gis/testsuite/test_parser_json.py
  6. 2 2
      lib/python/gunittest/case.py
  7. 1 1
      lib/python/gunittest/checkers.py
  8. 2 2
      lib/python/gunittest/gmodules.py
  9. 1 0
      lib/python/pygrass/gis/__init__.py
  10. 1 1
      lib/python/pygrass/gis/region.py
  11. 2 2
      lib/python/pygrass/messages/__init__.py
  12. 3 3
      lib/python/pygrass/modules/grid/grid.py
  13. 1 1
      lib/python/pygrass/modules/grid/testsuite/test_pygrass_modules_grid_doctests.py
  14. 11 11
      lib/python/pygrass/modules/interface/flag.py
  15. 35 35
      lib/python/pygrass/modules/interface/module.py
  16. 2 2
      lib/python/pygrass/modules/interface/parameter.py
  17. 1 5
      lib/python/pygrass/modules/interface/testsuite/test_pygrass_modules_interface_doctests.py
  18. 2 1
      lib/python/pygrass/modules/shortcuts.py
  19. 1 1
      lib/python/pygrass/modules/testsuite/test_pygrass_modules_doctests.py
  20. 4 4
      lib/python/pygrass/rpc/__init__.py
  21. 5 5
      lib/python/pygrass/shell/conversion.py
  22. 3 3
      lib/python/pygrass/utils.py
  23. 1 1
      lib/python/pygrass/vector/__init__.py
  24. 1 1
      lib/python/pygrass/vector/abstract.py
  25. 2 0
      lib/python/pygrass/vector/geometry.py
  26. 5 5
      lib/python/pygrass/vector/table.py
  27. 7 10
      lib/python/script/task.py
  28. 2 1
      lib/python/temporal/core.py
  29. 1 1
      lib/raster/testsuite/rast_parse_color_rule.py
  30. 20 10
      raster/r.contour/cont.c
  31. 18 0
      raster/r.contour/main.c
  32. 3 3
      raster/r.contour/testsuite/testrc.py
  33. 3 1
      scripts/g.extension/g.extension.py
  34. 2 3
      scripts/g.extension/testsuite/test_addons_toolboxes.py
  35. 6 6
      temporal/t.rast.accdetect/testsuite/data/test_1_temp_accumulation.ref
  36. 3 3
      temporal/t.rast.accdetect/testsuite/data/test_1_temp_indi.ref
  37. 3 3
      temporal/t.rast.accdetect/testsuite/data/test_1_temp_occ_a.ref
  38. 3 3
      temporal/t.rast.accdetect/testsuite/data/test_1_temp_occ_b.ref
  39. 6 6
      temporal/t.rast.accdetect/testsuite/data/test_2_temp_accumulation.ref
  40. 3 3
      temporal/t.rast.accdetect/testsuite/data/test_2_temp_indi.ref
  41. 3 3
      temporal/t.rast.accdetect/testsuite/data/test_2_temp_occ.ref
  42. 1 2
      temporal/t.rast.aggregate/testsuite/test_aggregation_absolute.py
  43. 8 8
      temporal/t.rast3d.univar/testsuite/test_t_rast3d_univar.py
  44. 7 7
      vector/v.db.select/testsuite/test_v_db_select.py
  45. 1 1
      vector/v.in.lidar/testsuite/decimation_test.py
  46. 1 1
      vector/v.in.lidar/testsuite/mask_test.py
  47. 10 10
      vector/v.profile/testsuite/test_v_profile.py
  48. 8 8
      vector/v.univar/testsuite/v_univar_test.py
  49. 8 8
      vector/v.what/testsuite/test_vwhat_ncspm.py

+ 0 - 86
README

@@ -1,86 +0,0 @@
-GRASS GIS Development Subversion repository
-
-##########################################################
-How to get write access here?
-
-Write access is only granted to developers who agree to abide by
-RFC2 - Legal aspects of code contributions
- http://trac.osgeo.org/grass/wiki/RFC/2_LegalAspectsOfCodeContributions
-and the code submission guidelines
- http://trac.osgeo.org/grass/wiki/Submitting
-
-This needs to be communicated to a GRASS developer. S/he will 
-then possibly propose you to the GRASS Project Steering committee
-after a period of evaluation. For details, see
- http://trac.osgeo.org/grass/wiki/RFC
-
-Once write access is granted, you, the new developer need to
-obtain an "osgeo_id" at http://www.osgeo.org/osgeo_userid
-If you already have an "osgeo_id" but forgot it, search for it at
-Search at http://www.osgeo.org/cgi-bin/ldap_web_search.py
-
-##########################################################
-How to compile GRASS:
-   See INSTALL file.
-
-Yes, you should really read INSTALL.
-
-##########################################################################
-How to generate the 'Programmer's Manual':
-
-This needs doxygen (http://www.doxygen.org) and optionally
-Graphviz dot (http://www.research.att.com/sw/tools/graphviz/).
-
-To build the GRASS programmer's documentation, run
-   make htmldocs
-or to generate documentation as single html file (recommended for simple reading)
-   make htmldocs-single
-here. This takes quite some time. The result is in lib/html/index.html
-which refers to further document repositories in
-   lib/vector/html/index.html
-   lib/db/html/index.html
-   lib/gis/html/index.html
-
-The master file is: ./grasslib.dox where all sub-documents have to
-be linked into.
-
-To generate the documents in PDF format, run
-   make pdfdocs
-
-An online version is available at:
-https://grass.osgeo.org/programming7/
-
-## Docker
-
-Build using the downloaded source code (in the directory with the
-source code):
-
-    docker build -t grassgis77 .
-
-A test run (assuming you have existing GRASS GIS location; it can be downloaded from
-https://grass.osgeo.org/sampledata/north_carolina/nc_basic_spm_grass7.zip)
-
-    # case 1: launching in the grassdata directory in which the location is stored:
-    docker run -it --rm --user=$(id -u):$(id -g) --volume $(pwd):/data --env HOME=/data/ grassgis77 \
-        grass --text nc_spm_08_grass7/user1 --exec g.region -p
-
-    # case 2: launching anywhere
-    docker run -it --rm --user=$(id -u):$(id -g) --volume /your/test/grassdata/:/data --env HOME=/data/ grassgis77 \
-        grass /data/nc_basic_spm/PERMANENT --exec g.region -p
-
-Note that the first `grassgis77` is the name of the image while the second
-`grass` is the name of the executable.
-
-To run the tests (again assuming local location):
-
-    docker run -it --rm --user=$(id -u):$(id -g) --volume /your/test/grassdata/:/data --env HOME=/data/ -w /code/grass \
-        grassgis77 grass /data/nc_basic_spm/PERMANENT --exec \
-            python -m grass.gunittest.main \
-                --location nc_basic_spm --location-type nc
-
-Note: If you compiled locally before building the Docker image, you may
-encounter problems as the local configuration and locally compiled file
-are copied to and used in the Docker image. To make sure you don't have
-this issue, clean all the compiled files from the source code:
-
-    make distclean

+ 92 - 0
README.md

@@ -0,0 +1,92 @@
+[![Build Status](https://travis-ci.com/OSGeo/grass.svg?branch=master)](https://travis-ci.com/OSGeo/grass)
+
+GRASS GIS Repository
+====================
+
+How to get write access here?
+-----------------------------
+
+See [Procedure for gaining Git write access](https://trac.osgeo.org/grass/wiki/HowToContribute#WriteaccesstotheGRASScorerepository)
+
+How to compile GRASS?
+---------------------
+
+> See INSTALL file.
+
+Yes, you should really read INSTALL.
+
+How to generate the 'Programmer's Manual'?
+------------------------------------------
+
+This needs doxygen (http://www.doxygen.org) and optionally
+Graphviz dot (http://www.research.att.com/sw/tools/graphviz/).
+
+To build the GRASS programmer's documentation, run
+```
+make htmldocs
+```
+or to generate documentation as single html file (recommended for simple reading)
+```
+make htmldocs-single
+```
+here. This takes quite some time. The result is in `lib/html/index.html`
+which refers to further document repositories in
+```
+   lib/vector/html/index.html
+   lib/db/html/index.html
+   lib/gis/html/index.html
+```
+
+The master file is: `./grasslib.dox` where all sub-documents have to
+be linked into.
+
+To generate the documents in PDF format, run
+
+```
+make pdfdocs
+```
+
+An online version is available [here](https://grass.osgeo.org/programming7/)
+
+## Docker
+
+Build using the downloaded source code (in the directory with the
+source code):
+
+```
+    docker build -t grassgis77 .
+```
+
+A test run (assuming you have existing GRASS GIS location; it can be downloaded from
+[here](https://grass.osgeo.org/sampledata/north_carolina/nc_basic_spm_grass7.zip))
+
+```
+# case 1: launching in the grassdata directory in which the location is stored:
+docker run -it --rm --user=$(id -u):$(id -g) --volume $(pwd):/data --env HOME=/data/ grassgis77 \
+    grass --text nc_spm_08_grass7/user1 --exec g.region -p
+
+# case 2: launching anywhere
+docker run -it --rm --user=$(id -u):$(id -g) --volume /your/test/grassdata/:/data --env HOME=/data/ grassgis77 \
+    grass /data/nc_basic_spm/PERMANENT --exec g.region -p
+```
+
+Note that the first `grassgis77` is the name of the image while the second
+`grass` is the name of the executable.
+
+To run the tests (again assuming local location):
+
+```
+    docker run -it --rm --user=$(id -u):$(id -g) --volume /your/test/grassdata/:/data --env HOME=/data/ -w /code/grass \
+        grassgis77 grass /data/nc_basic_spm/PERMANENT --exec \
+            python -m grass.gunittest.main \
+                --location nc_basic_spm --location-type nc
+```
+
+Note: If you compiled locally before building the Docker image, you may
+encounter problems as the local configuration and locally compiled file
+are copied to and used in the Docker image. To make sure you don't have
+this issue, clean all the compiled files from the source code:
+
+```
+make distclean
+```

+ 8 - 8
gui/wxpython/core/toolboxes.py

@@ -461,7 +461,7 @@ def _expandUserToolboxesItem(node, toolboxes):
     >>> toolboxes = etree.fromstring('<toolboxes><toolbox name="UserToolbox"><items><module-item name="g.region"/></items></toolbox></toolboxes>')
     >>> _expandUserToolboxesItem(tree, toolboxes)
     >>> etree.tostring(tree)
-    '<toolbox><items><toolbox name="GeneratedUserToolboxesList"><label>Custom toolboxes</label><items><toolbox name="UserToolbox"><items><module-item name="g.region" /></items></toolbox></items></toolbox></items></toolbox>'
+    b'<toolbox><items><toolbox name="GeneratedUserToolboxesList"><label>Custom toolboxes</label><items><toolbox name="UserToolbox"><items><module-item name="g.region" /></items></toolbox></items></toolbox></items></toolbox>'
     """
     tboxes = toolboxes.findall('.//toolbox')
 
@@ -486,7 +486,7 @@ def _removeUserToolboxesItem(root):
     >>> tree = etree.fromstring('<toolbox><items><user-toolboxes-list/></items></toolbox>')
     >>> _removeUserToolboxesItem(tree)
     >>> etree.tostring(tree)
-    '<toolbox><items /></toolbox>'
+    b'<toolbox><items /></toolbox>'
     """
     for n in root.findall('./items/user-toolboxes-list'):
         items = root.find('./items')
@@ -571,7 +571,7 @@ def _expandItems(node, items, itemTag):
     >>> items = etree.fromstring('<module-items><module-item name="g.region"><module>g.region</module><description>GRASS region management</description></module-item></module-items>')
     >>> _expandItems(tree, items, 'module-item')
     >>> etree.tostring(tree)
-    '<items><module-item name="g.region"><module>g.region</module><description>GRASS region management</description></module-item></items>'
+    b'<items><module-item name="g.region"><module>g.region</module><description>GRASS region management</description></module-item></items>'
     """
     for moduleItem in node.findall('.//' + itemTag):
         itemName = moduleItem.get('name')
@@ -605,13 +605,13 @@ def _expandRuntimeModules(node, loadMetadata=True):
     ...                         '</items>')
     >>> _expandRuntimeModules(tree)
     >>> etree.tostring(tree)
-    '<items><module-item name="g.region"><module>g.region</module><description>Manages the boundary definitions for the geographic region.</description><keywords>general,settings,computational region,extent,resolution,level1</keywords></module-item></items>'
+    b'<items><module-item name="g.region"><module>g.region</module><description>Manages the boundary definitions for the geographic region.</description><keywords>general,settings,computational region,extent,resolution,level1</keywords></module-item></items>'
     >>> tree = etree.fromstring('<items>'
     ...                         '<module-item name="m.proj"></module-item>'
     ...                         '</items>')
     >>> _expandRuntimeModules(tree)
     >>> etree.tostring(tree)
-    '<items><module-item name="m.proj"><module>m.proj</module><description>Converts coordinates from one projection to another (cs2cs frontend).</description><keywords>miscellaneous,projection,transformation</keywords></module-item></items>'
+    b'<items><module-item name="m.proj"><module>m.proj</module><description>Converts coordinates from one projection to another (cs2cs frontend).</description><keywords>miscellaneous,projection,transformation</keywords></module-item></items>'
     """
     hasErrors = False
     modules = node.findall('.//module-item')
@@ -690,7 +690,7 @@ def _convertTag(node, old, new):
     >>> _convertTag(tree, 'toolbox', 'menu')
     >>> _convertTag(tree, 'module-item', 'menuitem')
     >>> etree.tostring(tree)
-    '<toolboxes><menu><items><menuitem /></items></menu></toolboxes>'
+    b'<toolboxes><menu><items><menuitem /></items></menu></toolboxes>'
     """
     for n in node.findall('.//%s' % old):
         n.tag = new
@@ -703,7 +703,7 @@ def _convertTagAndRemoveAttrib(node, old, new):
     >>> _convertTagAndRemoveAttrib(tree, 'toolbox', 'menu')
     >>> _convertTagAndRemoveAttrib(tree, 'module-item', 'menuitem')
     >>> etree.tostring(tree)
-    '<toolboxes><menu><items><menuitem /></items></menu></toolboxes>'
+    b'<toolboxes><menu><items><menuitem /></items></menu></toolboxes>'
     """
     for n in node.findall('.//%s' % old):
         n.tag = new
@@ -716,7 +716,7 @@ def _convertTree(root):
     >>> tree = etree.fromstring('<toolbox name="MainMenu"><label>Main menu</label><items><toolbox><label>Raster</label><items><module-item name="g.region"><module>g.region</module></module-item></items></toolbox></items></toolbox>')
     >>> _convertTree(tree)
     >>> etree.tostring(tree)
-    '<menudata><menubar><menu><label>Raster</label><items><menuitem><command>g.region</command></menuitem></items></menu></menubar></menudata>'
+    b'<menudata><menubar><menu><label>Raster</label><items><menuitem><command>g.region</command></menuitem></items></menu></menubar></menudata>'
     """
     root.attrib = {}
     label = root.find('label')

+ 13 - 13
lib/gis/testsuite/gis_lib_env_test.py

@@ -16,23 +16,23 @@ class GisLibraryTestEnv(TestCase):
         libgis.G_setenv("TEST", "A");
 
         value = libgis.G_getenv("TEST")
-        self.assertEqual(value, "A")
+        self.assertEqual(value, b"A")
         value = libgis.G_getenv2("TEST", libgis.G_VAR_GISRC)
-        self.assertEqual(value, "A")
+        self.assertEqual(value, b"A")
         
         # In memory management
         libgis.G_setenv_nogisrc("TEST", "B");
 
         value = libgis.G_getenv_nofatal("TEST")
-        self.assertEqual(value, "B")
+        self.assertEqual(value, b"B")
         value = libgis.G_getenv_nofatal2("TEST", libgis.G_VAR_GISRC)
-        self.assertEqual(value, "B")
+        self.assertEqual(value, b"B")
         # Force reading
         libgis.G__read_gisrc_env()
         value = libgis.G_getenv("TEST")
-        self.assertEqual(value, "A")
+        self.assertEqual(value, b"A")
         value = libgis.G_getenv2("TEST", libgis.G_VAR_GISRC)
-        self.assertEqual(value, "A")
+        self.assertEqual(value, b"A")
 
     def test_switch_env(self):
         libgis.G_setenv_nogisrc("TEST", "SWITCH");
@@ -42,29 +42,29 @@ class GisLibraryTestEnv(TestCase):
         libgis.G_setenv_nogisrc("TEST", "TARGET");
         libgis.G_setenv_nogisrc2("TEST", "TARGET2", libgis.G_VAR_MAPSET);
         value = libgis.G_getenv("TEST")
-        self.assertEqual(value, "TARGET")
+        self.assertEqual(value, b"TARGET")
         value = libgis.G_getenv2("TEST", libgis.G_VAR_MAPSET)
-        self.assertEqual(value, "TARGET2")
+        self.assertEqual(value, b"TARGET2")
         # Switch back to orig env
         libgis.G_switch_env()
         value = libgis.G_getenv("TEST")
-        self.assertEqual(value, "SWITCH")
+        self.assertEqual(value, b"SWITCH")
         value = libgis.G_getenv2("TEST", libgis.G_VAR_MAPSET)
-        self.assertEqual(value, "SWITCH2")
+        self.assertEqual(value, b"SWITCH2")
 
     def test_mapset(self):
         # Mapset VAR file
         libgis.G_setenv2("TEST", "C", libgis.G_VAR_MAPSET);
         value = libgis.G_getenv2("TEST", libgis.G_VAR_MAPSET)
-        self.assertEqual(value, "C")
+        self.assertEqual(value, b"C")
  
         libgis.G_setenv_nogisrc2("TEST", "D", libgis.G_VAR_MAPSET);
         value = libgis.G_getenv_nofatal2("TEST", libgis.G_VAR_MAPSET)
-        self.assertEqual(value, "D")
+        self.assertEqual(value, b"D")
         # Force reading
         libgis.G__read_mapset_env()
         value = libgis.G_getenv2("TEST", libgis.G_VAR_MAPSET)
-        self.assertEqual(value, "C")
+        self.assertEqual(value, b"C")
         
 
 

+ 4 - 3
lib/gis/testsuite/test_parser_json.py

@@ -10,6 +10,7 @@ for details.
 
 import subprocess
 from grass.gunittest.case import TestCase
+from grass.script import decode
 import json
 
 
@@ -39,7 +40,7 @@ class TestParserJson(TestCase):
 
         stdout, stderr = subprocess.Popen(args, stdout=subprocess.PIPE).communicate()
         print(stdout)
-        json_code = json.loads(stdout)
+        json_code = json.loads(decode(stdout))
         self.assertEqual(json_code["module"], "r.slope.aspect")
         self.assertEqual(len(json_code["inputs"]), 5)
         self.assertEqual(json_code["inputs"], inputs)
@@ -67,7 +68,7 @@ class TestParserJson(TestCase):
 
         stdout, stderr = subprocess.Popen(args, stdout=subprocess.PIPE).communicate()
         print(stdout)
-        json_code = json.loads(stdout)
+        json_code = json.loads(decode(stdout))
         self.assertEqual(json_code["module"], "v.out.ascii")
         self.assertEqual(len(json_code["inputs"]), 6)
         self.assertEqual(json_code["inputs"], inputs)
@@ -86,7 +87,7 @@ class TestParserJson(TestCase):
 
         stdout, stderr = subprocess.Popen(args, stdout=subprocess.PIPE).communicate()
         print(stdout)
-        json_code = json.loads(stdout)
+        json_code = json.loads(decode(stdout))
         self.assertEqual(json_code["module"], "v.info")
         self.assertEqual(len(json_code["inputs"]), 2)
         self.assertEqual(json_code["inputs"], inputs)

+ 2 - 2
lib/python/gunittest/case.py

@@ -19,7 +19,7 @@ import unittest
 
 from grass.pygrass.modules import Module
 from grass.exceptions import CalledModuleError
-from grass.script import shutil_which, text_to_string
+from grass.script import shutil_which, text_to_string, encode
 
 from .gmodules import call_module, SimpleModule
 from .checkers import (check_text_ellipsis,
@@ -729,7 +729,7 @@ class TestCase(unittest.TestCase):
         # hash is the easiest way how to get a valid vector name
         # TODO: introduce some function which will make file valid
         hasher = hashlib.md5()
-        hasher.update(filename)
+        hasher.update(encode(filename))
         namehash = hasher.hexdigest()
         vector = self._get_unique_name('import_ascii_vector_' + name_part
                                        + '_' + namehash)

+ 1 - 1
lib/python/gunittest/checkers.py

@@ -67,7 +67,7 @@ def unify_units(dic):
 
     Example of British English spelling replaced by US English spelling::
 
-        >>> unify_units({'units': ['metres'], 'unit': ['metre']})
+        >>> unify_units({'units': ['metres'], 'unit': ['metre']})  # doctest: +SKIP
         {'units': ['meters'], 'unit': ['meter']}
 
     :param dic: The dictionary containing information about units

+ 2 - 2
lib/python/gunittest/gmodules.py

@@ -40,7 +40,7 @@ class SimpleModule(Module):
     >>> str(colors.outputs.stdout)
     ''
     >>> colors.outputs.stderr.strip()
-    u"Color table for raster map <test_a> set to 'rules'"
+    "Color table for raster map <test_a> set to 'rules'"
     """
     def __init__(self, cmd, *args, **kargs):
         for banned in ['stdout_', 'stderr_', 'finish_', 'run_']:
@@ -60,7 +60,7 @@ def call_module(module, stdin=None,
                 **kwargs):
     r"""Run module with parameters given in `kwargs` and return its output.
 
-    >>> print call_module('g.region', flags='pg')  # doctest: +ELLIPSIS
+    >>> print (call_module('g.region', flags='pg'))  # doctest: +ELLIPSIS
     projection=...
     zone=...
     n=...

+ 1 - 0
lib/python/pygrass/gis/__init__.py

@@ -14,6 +14,7 @@ import grass.lib.gis as libgis
 from grass.pygrass.errors import GrassError
 from grass.script.utils import encode, decode
 from grass.pygrass.utils import getenv
+from grass.pygrass.gis.region import Region
 
 test_vector_name = "Gis_test_vector"
 test_raster_name = "Gis_test_raster"

+ 1 - 1
lib/python/pygrass/gis/region.py

@@ -323,7 +323,7 @@ class Region(object):
 
             >>> reg = Region()
             >>> reg.keys()                               # doctest: +ELLIPSIS
-            [u'proj', u'zone', ..., u'cols', u'cells']
+            ['proj', 'zone', ..., 'cols', 'cells']
 
         ..
         """

+ 2 - 2
lib/python/pygrass/messages/__init__.py

@@ -148,7 +148,7 @@ class Messenger(object):
        Traceback (most recent call last):
          File "__init__.py", line 241, in fatal
            raise FatalError(message)
-       FatalError: Ohh no no no!
+       grass.exceptions.FatalError: Ohh no no no!
 
        >>> msgr = Messenger(raise_on_error=True)
        >>> msgr.set_raise_on_error(False)
@@ -164,7 +164,7 @@ class Messenger(object):
        Traceback (most recent call last):
          File "__init__.py", line 241, in fatal
            raise FatalError(message)
-       FatalError: Ohh no no no!
+       grass.exceptions.FatalError: Ohh no no no!
 
     """
     def __init__(self, raise_on_error=False):

+ 3 - 3
lib/python/pygrass/modules/grid/grid.py

@@ -83,9 +83,9 @@ def copy_mapset(mapset, path):
     >>> sorted(os.listdir(path))                          # doctest: +ELLIPSIS
     [...'PERMANENT'...]
     >>> sorted(os.listdir(os.path.join(path, 'PERMANENT')))
-    [u'DEFAULT_WIND', u'PROJ_INFO', u'PROJ_UNITS', u'VAR', u'WIND']
+    ['DEFAULT_WIND', 'PROJ_INFO', 'PROJ_UNITS', 'VAR', 'WIND']
     >>> sorted(os.listdir(os.path.join(path, mname)))   # doctest: +ELLIPSIS
-    [...u'SEARCH_PATH',...u'WIND']
+    [...'SEARCH_PATH',...'WIND']
     >>> import shutil
     >>> shutil.rmtree(path)
 
@@ -311,7 +311,7 @@ def get_cmd(cmdd):
     ...              elevation='ele', slope='slp', aspect='asp',
     ...              overwrite=True, run_=False)
     >>> get_cmd(slp.get_dict())  # doctest: +ELLIPSIS
-    ['r.slope.aspect', u'elevation=ele', u'format=degrees', ..., u'--o']
+    ['r.slope.aspect', 'elevation=ele', 'format=degrees', ..., '--o']
     """
     cmd = [cmdd['name'], ]
     cmd.extend(("%s=%s" % (k, v) for k, v in cmdd['inputs']

+ 1 - 1
lib/python/pygrass/modules/grid/testsuite/test_pygrass_modules_grid_doctests.py

@@ -31,7 +31,7 @@ def load_tests(loader, tests, ignore):
     # for now it is the only place where it works
     grass.gunittest.utils.do_doctest_gettext_workaround()
 
-    tests.addTests(doctest.DocTestSuite(gmodules.shortcuts))
+    #tests.addTests(doctest.DocTestSuite(gmodules.shortcuts))
     return tests
 
 

+ 11 - 11
lib/python/pygrass/modules/interface/flag.py

@@ -13,14 +13,14 @@ class Flag(object):
     >>> flag = Flag(diz=dict(name='a', description='Flag description',
     ...                      default=True))
     >>> flag.name
-    u'a'
+    'a'
     >>> flag.special
     False
     >>> flag.description
-    u'Flag description'
+    'Flag description'
     >>> flag = Flag(diz=dict(name='overwrite'))
     >>> flag.name
-    u'overwrite'
+    'overwrite'
     >>> flag.special
     True
     """
@@ -41,16 +41,16 @@ class Flag(object):
         >>> flag = Flag(diz=dict(name='a', description='Flag description',
         ...                      default=True))
         >>> flag.get_bash()
-        u''
+        ''
         >>> flag.value = True
         >>> flag.get_bash()
-        u'-a'
+        '-a'
         >>> flag = Flag(diz=dict(name='overwrite'))
         >>> flag.get_bash()
-        u''
+        ''
         >>> flag.value = True
         >>> flag.get_bash()
-        u'--o'
+        '--o'
         """
         if self.value:
             if self.special:
@@ -66,16 +66,16 @@ class Flag(object):
         >>> flag = Flag(diz=dict(name='a', description='Flag description',
         ...                      default=True))
         >>> flag.get_python()
-        u''
+        ''
         >>> flag.value = True
         >>> flag.get_python()
-        u'a'
+        'a'
         >>> flag = Flag(diz=dict(name='overwrite'))
         >>> flag.get_python()
-        u''
+        ''
         >>> flag.value = True
         >>> flag.get_python()
-        u'overwrite=True'
+        'overwrite=True'
         """
         if self.value:
             return '%s=True' % self.name if self.special else self.name

+ 35 - 35
lib/python/pygrass/modules/interface/module.py

@@ -325,11 +325,11 @@ class Module(object):
     >>> region.flags.u = True
     >>> region.flags["3"].value = True  # set numeric flags
     >>> region.get_bash()
-    u'g.region -p -3 -u'
+    'g.region -p -3 -u'
     >>> new_region = copy.deepcopy(region)
     >>> new_region.inputs.res = "10"
     >>> new_region.get_bash()
-    u'g.region res=10 -p -3 -u'
+    'g.region res=10 -p -3 -u'
 
     >>> neighbors = Module("r.neighbors")
     >>> neighbors.inputs.input = "mapA"
@@ -337,30 +337,30 @@ class Module(object):
     >>> neighbors.inputs.size = 5
     >>> neighbors.inputs.quantile = 0.5
     >>> neighbors.get_bash()
-    u'r.neighbors input=mapA method=average size=5 quantile=0.5 output=mapB'
+    'r.neighbors input=mapA method=average size=5 quantile=0.5 output=mapB'
 
     >>> new_neighbors1 = copy.deepcopy(neighbors)
     >>> new_neighbors1.inputs.input = "mapD"
     >>> new_neighbors1.inputs.size = 3
     >>> new_neighbors1.inputs.quantile = 0.5
     >>> new_neighbors1.get_bash()
-    u'r.neighbors input=mapD method=average size=3 quantile=0.5 output=mapB'
+    'r.neighbors input=mapD method=average size=3 quantile=0.5 output=mapB'
 
     >>> new_neighbors2 = copy.deepcopy(neighbors)
     >>> new_neighbors2(input="mapD", size=3, run_=False)
     Module('r.neighbors')
     >>> new_neighbors2.get_bash()
-    u'r.neighbors input=mapD method=average size=3 quantile=0.5 output=mapB'
+    'r.neighbors input=mapD method=average size=3 quantile=0.5 output=mapB'
 
     >>> neighbors = Module("r.neighbors")
     >>> neighbors.get_bash()
-    u'r.neighbors method=average size=3'
+    'r.neighbors method=average size=3'
 
     >>> new_neighbors3 = copy.deepcopy(neighbors)
     >>> new_neighbors3(input="mapA", size=3, output="mapB", run_=False)
     Module('r.neighbors')
     >>> new_neighbors3.get_bash()
-    u'r.neighbors input=mapA method=average size=3 output=mapB'
+    'r.neighbors input=mapA method=average size=3 output=mapB'
 
     >>> mapcalc = Module("r.mapcalc", expression="test_a = 1",
     ...                  overwrite=True, run_=False)
@@ -391,17 +391,17 @@ class Module(object):
     >>> p.popen.returncode
     0
     >>> colors.inputs["stdin"].value
-    u'1 red'
+    '1 red'
     >>> colors.outputs["stdout"].value
-    u''
+    ''
     >>> colors.outputs["stderr"].value.strip()
-    u"Color table for raster map <test_a> set to 'rules'"
+    "Color table for raster map <test_a> set to 'rules'"
 
     >>> colors = Module("r.colors", map="test_a", rules="-",
     ...                 run_=False, finish_=False, stdin_=PIPE)
     >>> colors.run()
     Module('r.colors')
-    >>> stdout, stderr = colors.popen.communicate(input="1 red")
+    >>> stdout, stderr = colors.popen.communicate(input=b"1 red")
     >>> colors.popen.returncode
     0
     >>> stdout
@@ -412,30 +412,30 @@ class Module(object):
     ...                 stdin_=PIPE, stderr_=PIPE)
     >>> colors.run()
     Module('r.colors')
-    >>> stdout, stderr = colors.popen.communicate(input="1 red")
+    >>> stdout, stderr = colors.popen.communicate(input=b"1 red")
     >>> colors.popen.returncode
     0
     >>> stdout
     >>> stderr.strip()
-    "Color table for raster map <test_a> set to 'rules'"
+    b"Color table for raster map <test_a> set to 'rules'"
 
     Run a second time
 
     >>> colors.run()
     Module('r.colors')
-    >>> stdout, stderr = colors.popen.communicate(input="1 blue")
+    >>> stdout, stderr = colors.popen.communicate(input=b"1 blue")
     >>> colors.popen.returncode
     0
     >>> stdout
     >>> stderr.strip()
-    "Color table for raster map <test_a> set to 'rules'"
+    b"Color table for raster map <test_a> set to 'rules'"
 
     Multiple run test
 
     >>> colors = Module("r.colors", map="test_a",
     ...                                            color="ryb", run_=False)
     >>> colors.get_bash()
-    u'r.colors map=test_a color=ryb'
+    'r.colors map=test_a color=ryb'
     >>> colors.run()
     Module('r.colors')
     >>> colors(color="gyr")
@@ -843,31 +843,31 @@ class MultiModule(object):
 
     Asynchronous module run, setting finish = False
 
-    >>> region_1 = Module("g.region", run_=False)
-    >>> region_1.flags.p = True
-    >>> region_2 = copy.deepcopy(region_1)
-    >>> region_2.flags.p = True
-    >>> region_3 = copy.deepcopy(region_1)
-    >>> region_3.flags.p = True
-    >>> region_4 = copy.deepcopy(region_1)
-    >>> region_4.flags.p = True
-    >>> region_5 = copy.deepcopy(region_1)
-    >>> region_5.flags.p = True
+    >>> region_1 = Module("g.region", run_=False)  # doctest: +SKIP
+    >>> region_1.flags.p = True  # doctest: +SKIP
+    >>> region_2 = copy.deepcopy(region_1)  # doctest: +SKIP
+    >>> region_2.flags.p = True  # doctest: +SKIP
+    >>> region_3 = copy.deepcopy(region_1)  # doctest: +SKIP
+    >>> region_3.flags.p = True  # doctest: +SKIP
+    >>> region_4 = copy.deepcopy(region_1)  # doctest: +SKIP
+    >>> region_4.flags.p = True  # doctest: +SKIP
+    >>> region_5 = copy.deepcopy(region_1)  # doctest: +SKIP
+    >>> region_5.flags.p = True  # doctest: +SKIP
     >>> mm = MultiModule(module_list=[region_1, region_2, region_3, region_4, region_5],
-    ...                  sync=False)
-    >>> t = mm.run()
-    >>> isinstance(t, Process)
+    ...                  sync=False)  # doctest: +SKIP
+    >>> t = mm.run()  # doctest: +SKIP
+    >>> isinstance(t, Process)  # doctest: +SKIP
     True
-    >>> m_list = mm.wait()
-    >>> m_list[0].popen.returncode
+    >>> m_list = mm.wait()  # doctest: +SKIP
+    >>> m_list[0].popen.returncode  # doctest: +SKIP
     0
-    >>> m_list[1].popen.returncode
+    >>> m_list[1].popen.returncode  # doctest: +SKIP
     0
-    >>> m_list[2].popen.returncode
+    >>> m_list[2].popen.returncode  # doctest: +SKIP
     0
-    >>> m_list[3].popen.returncode
+    >>> m_list[3].popen.returncode  # doctest: +SKIP
     0
-    >>> m_list[4].popen.returncode
+    >>> m_list[4].popen.returncode  # doctest: +SKIP
     0
 
     Asynchronous module run, setting finish = False and using temporary region

+ 2 - 2
lib/python/pygrass/modules/interface/parameter.py

@@ -200,7 +200,7 @@ class Parameter(object):
             ...                            multiple='no', type='integer',
             ...                            values=[2, 4, 6, 8], default=8))
             >>> param.get_bash()
-            u'int_number=8'
+            'int_number=8'
 
         ..
         """
@@ -220,7 +220,7 @@ class Parameter(object):
             ...                            multiple='no', type='integer',
             ...                            values=[2, 4, 6, 8], default=8))
             >>> param.get_python()
-            u'int_number=8'
+            'int_number=8'
 
         ..
         """

+ 1 - 5
lib/python/pygrass/modules/interface/testsuite/test_pygrass_modules_interface_doctests.py

@@ -39,8 +39,4 @@ def load_tests(loader, tests, ignore):
 
 
 if __name__ == '__main__':
-    # Temporarily skip test for Python 3
-    if sys.version_info[0] > 2:
-        pass
-    else:
-        grass.gunittest.main.test()
+    grass.gunittest.main.test()

+ 2 - 1
lib/python/pygrass/modules/shortcuts.py

@@ -26,7 +26,8 @@ class MetaModule(object):
        >>> g_list.run()
        Module('g.list')
        >>> g_list.outputs.stdout                         # doctest: +ELLIPSIS
-       u'...basin...elevation...'
+       '...basin...elevation...'
+
        >>> r = MetaModule('r')
        >>> what = r.what
        >>> what.description

+ 1 - 1
lib/python/pygrass/modules/testsuite/test_pygrass_modules_doctests.py

@@ -35,7 +35,7 @@ def load_tests(loader, tests, ignore):
     tests.addTests(doctest.DocTestSuite(grid.grid))
     tests.addTests(doctest.DocTestSuite(grid.patch))
     tests.addTests(doctest.DocTestSuite(grid.split))
-    tests.addTests(doctest.DocTestSuite(shortcuts))
+#    tests.addTests(doctest.DocTestSuite(shortcuts))
     return tests
 
 

+ 4 - 4
lib/python/pygrass/rpc/__init__.py

@@ -314,15 +314,15 @@ class DataProvider(RPCServerBase):
             >>> provider = DataProvider()
             >>> ret = provider.get_vector_table_as_dict(name=test_vector_name)
             >>> ret["table"]
-            {1: [1, u'point', 1.0], 2: [2, u'line', 2.0], 3: [3, u'centroid', 3.0]}
+            {1: [1, 'point', 1.0], 2: [2, 'line', 2.0], 3: [3, 'centroid', 3.0]}
             >>> ret["columns"]
-            Columns([(u'cat', u'INTEGER'), (u'name', u'varchar(50)'), (u'value', u'double precision')])
+            Columns([('cat', 'INTEGER'), ('name', 'varchar(50)'), ('value', 'double precision')])
             >>> ret = provider.get_vector_table_as_dict(name=test_vector_name,
             ...                                           where="value > 1")
             >>> ret["table"]
-            {2: [2, u'line', 2.0], 3: [3, u'centroid', 3.0]}
+            {2: [2, 'line', 2.0], 3: [3, 'centroid', 3.0]}
             >>> ret["columns"]
-            Columns([(u'cat', u'INTEGER'), (u'name', u'varchar(50)'), (u'value', u'double precision')])
+            Columns([('cat', 'INTEGER'), ('name', 'varchar(50)'), ('value', 'double precision')])
             >>> provider.get_vector_table_as_dict(name="no_map",
             ...                                   where="value > 1")
             >>> provider.stop()

+ 5 - 5
lib/python/pygrass/shell/conversion.py

@@ -26,7 +26,7 @@ def dict2html(dic, keys=None, border='',
     :param str vdec: string to decorate the value (i.e. "b", "i", etc.)
 
     >>> dic = {'key 0': 0, 'key 1': 1}
-    >>> print dict2html(dic)
+    >>> print (dict2html(dic))
     <table>
         <tr>
           <td>key 0</td>
@@ -37,7 +37,7 @@ def dict2html(dic, keys=None, border='',
           <td>1</td>
         </tr>
     </table>
-    >>> print dict2html(dic, border="1")
+    >>> print (dict2html(dic, border="1"))
     <table border='1'>
         <tr>
           <td>key 0</td>
@@ -48,7 +48,7 @@ def dict2html(dic, keys=None, border='',
           <td>1</td>
         </tr>
     </table>
-    >>> print dict2html(dic, kdec='b', vfmt='%05d', vdec='i')
+    >>> print (dict2html(dic, kdec='b', vfmt='%05d', vdec='i'))
     <table>
         <tr>
           <td><b>key 0</b></td>
@@ -60,8 +60,8 @@ def dict2html(dic, keys=None, border='',
         </tr>
     </table>
     >>> dic = {'key 0': (2, 3), 'key 1': (10, 5)}
-    >>> print dict2html(dic, kdec='b', vdec='i',
-    ...                 vfun=lambda x: "%d<sup>%.1f</sup>" % x)
+    >>> print (dict2html(dic, kdec='b', vdec='i',
+    ...                 vfun=lambda x: "%d<sup>%.1f</sup>" % x))
     <table>
         <tr>
           <td><b>key 0</b></td>

+ 3 - 3
lib/python/pygrass/utils.py

@@ -260,7 +260,7 @@ def get_raster_for_points(poi_vector, raster, column=None, region=None):
     >>> get_raster_for_points(vect, ele, column=test_raster_name, region=region)
     True
     >>> vect.table.filters.select('value', test_raster_name)
-    Filters(u'SELECT value, Utils_test_raster FROM test_vect_2;')
+    Filters('SELECT value, Utils_test_raster FROM test_vect_2;')
     >>> cur = vect.table.execute()
     >>> r = cur.fetchall()
     >>> r[0]                                        # doctest: +ELLIPSIS
@@ -348,11 +348,11 @@ def set_path(modulename, dirname=None, path='.'):
 def split_in_chunk(iterable, length=10):
     """Split a list in chunk.
 
-    >>> for chunk in split_in_chunk(range(25)): print chunk
+    >>> for chunk in split_in_chunk(range(25)): print (chunk)
     (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
     (10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
     (20, 21, 22, 23, 24)
-    >>> for chunk in split_in_chunk(range(25), 3): print chunk
+    >>> for chunk in split_in_chunk(range(25), 3): print (chunk)
     (0, 1, 2)
     (3, 4, 5)
     (6, 7, 8)

+ 1 - 1
lib/python/pygrass/vector/__init__.py

@@ -777,7 +777,7 @@ class VectorTopo(Vector):
             ...                                         feature_type="blub")
             Traceback (most recent call last):
             ...
-            GrassError: Unsupported feature type <blub>, supported are <point,line,boundary,centroid>
+            grass.exceptions.GrassError: Unsupported feature type <blub>, supported are <point,line,boundary,centroid>
 
             >>> test_vect.close()
 

+ 1 - 1
lib/python/pygrass/vector/abstract.py

@@ -92,7 +92,7 @@ class Info(object):
         return self._mode
 
     def _set_mode(self, mode):
-        if mode.upper() not in ('R', 'W'):
+        if mode.upper() not in 'RW':
             str_err = _("Mode type: {0} not supported ('r', 'w')")
             raise ValueError(str_err.format(mode))
         self._mode = mode

+ 2 - 0
lib/python/pygrass/vector/geometry.py

@@ -1304,6 +1304,8 @@ class Boundary(Line):
     def __init__(self, **kargs):
         super(Boundary, self).__init__(**kargs)
         v_id = kargs.get('v_id', 0)
+        # not sure what it means that v_id is None
+        v_id = 0 if v_id is None else v_id
         self.dir = libvect.GV_FORWARD if v_id > 0 else libvect.GV_BACKWARD
         self.c_left = ctypes.pointer(ctypes.c_int())
         self.c_right = ctypes.pointer(ctypes.c_int())

+ 5 - 5
lib/python/pygrass/vector/table.py

@@ -336,7 +336,7 @@ class Columns(object):
         ['INTEGER', 'varchar(50)', 'double precision']
 
         """
-        return self.odict.values()
+        return list(self.odict.values())
 
     def names(self, remove=None, unicod=True):
         """Return a list with the column names.
@@ -356,10 +356,10 @@ class Columns(object):
 
         """
         if remove:
-            nams = self.odict.keys()
+            nams = list(self.odict.keys())
             nams.remove(remove)
         else:
-            nams = self.odict.keys()
+            nams = list(self.odict.keys())
         if unicod:
             return nams
         else:
@@ -381,7 +381,7 @@ class Columns(object):
         [('cat', 'INTEGER'), ('name', 'varchar(50)'), ('value', 'double precision')]
 
         """
-        return self.odict.items()
+        return list(self.odict.items())
 
     def add(self, col_name, col_type):
         """Add a new column to the table.
@@ -509,7 +509,7 @@ class Columns(object):
         >>> cols_sqlite.cast('n_pizzas', 'float8')  # doctest: +ELLIPSIS
         Traceback (most recent call last):
           ...
-        DBError: SQLite does not support to cast columns.
+        grass.exceptions.DBError: SQLite does not support to cast columns.
         >>> import psycopg2 as pg                         # doctest: +SKIP
         >>> cols_pg = Columns(test_vector_name,
         ...                   pg.connect('host=localhost dbname=grassdb')) # doctest: +SKIP

+ 7 - 10
lib/python/script/task.py

@@ -445,21 +445,18 @@ def convert_xml_to_utf8(xml_text):
 
     # modify: fetch encoding from the interface description text(xml)
     # e.g. <?xml version="1.0" encoding="GBK"?>
-    pattern = re.compile(b'<\?xml[^>]*\Wencoding="([^"]*)"[^>]*\?>')
+    pattern = re.compile('<\?xml[^>]*\Wencoding="([^"]*)"[^>]*\?>')
     m = re.match(pattern, xml_text)
     if m is None:
-        return xml_text
+        return xml_text.encode("utf-8") if xml_text else None
     #
     enc = m.groups()[0]
-    # for Python 3
-    enc_decoded = enc.decode('ascii')
 
     # modify: change the encoding to "utf-8", for correct parsing
-    xml_text_utf8 = xml_text.decode(enc_decoded).encode("utf-8")
-    p = re.compile(b'encoding="' + enc + b'"', re.IGNORECASE)
-    xml_text_utf8 = p.sub(b'encoding="utf-8"', xml_text_utf8)
+    p = re.compile('encoding="' + enc + '"', re.IGNORECASE)
+    xml_text_utf8 = p.sub('encoding="utf-8"', xml_text)
 
-    return xml_text_utf8
+    return xml_text_utf8.encode("utf-8")
 
 
 def get_interface_description(cmd):
@@ -472,7 +469,7 @@ def get_interface_description(cmd):
     :param cmd: command (name of GRASS module)
     """
     try:
-        p = Popen([encode(cmd), b'--interface-description'], stdout=PIPE,
+        p = Popen([cmd, '--interface-description'], stdout=PIPE,
                   stderr=PIPE)
         cmdout, cmderr = p.communicate()
 
@@ -503,7 +500,7 @@ def get_interface_description(cmd):
         raise ScriptError(_("Unable to fetch interface description for command '<{cmd}>'."
                             "\n\nDetails: <{det}>".format(cmd=cmd, det=e)))
 
-    desc = convert_xml_to_utf8(cmdout)
+    desc = convert_xml_to_utf8(decode(cmdout))
     desc = desc.replace(b'grass-interface.dtd',
                         os.path.join(os.getenv('GISBASE'), 'gui', 'xml',
                                      'grass-interface.dtd').encode('utf-8'))

+ 2 - 1
lib/python/temporal/core.py

@@ -1233,7 +1233,7 @@ class DBConnection(object):
                         # objects too
                         statement = "%s\'%s\'%s" % (statement[0:pos],
                                                     str(args[count]),
-                                                    str(statement[pos + 1:]))
+                                                    statement[pos + 1:])
                     count += 1
 
                 return statement
@@ -1319,6 +1319,7 @@ class DBConnection(object):
 
            :param statement: The executable SQL statement or SQL script
         """
+        print (statement)
         connected = False
         if not self.connected:
             self.connect()

+ 1 - 1
lib/raster/testsuite/rast_parse_color_rule.py

@@ -45,7 +45,7 @@ class ParseSingleColorRuleColorsTestCase(TestCase):
         colors = ("{string} -> "
                   "{v.value}: {r.value}, {g.value}, {b.value}".format(**locals()))
         error_text = Rast_parse_color_rule_error(ret)
-        self.assertEqual(error_text, "",
+        self.assertEqual(error_text, b"",
                          msg=("Conversion not successful (%s): %s (%s)"
                               % (colors, error_text, ret)))
         self.assertEqual(v.value, value,

+ 20 - 10
raster/r.contour/cont.c

@@ -94,27 +94,29 @@ void contour(double levels[],
 	}
 
 	/* check each cell of top and bottom borders  */
-	for (startrow = 0; startrow < nrow; startrow += (nrow - 2)) {
+	for (startrow = 0; startrow <= nrow - 2; startrow += (nrow - 2)) {
 	    for (startcol = 0; startcol <= ncol - 2; startcol++) {
 
 		/* look for starting point of new line */
 		if (!hit[startrow][startcol]) {
 		    current.r = startrow;
 		    current.c = startcol;
-		    outside = getnewcell(&current, nrow, ncol, z);
 
 		    /* is this top or bottom? */
-		    if (startrow == 0)	/* top */
+		    if (startrow < nrow - 2)	/* top */
 			current.edge = 0;
 		    else	/* bottom edge */
 			current.edge = 2;
+
+		    outside = getnewcell(&current, nrow, ncol, z);
+
 		    p1 = current.edge;
 		    p2 = current.edge + 1;
 
 		    if (checkedge(current.z[p1], current.z[p2], level)) {
 			getpoint(&current, level, Cell, Points);
 			/* while not off an edge, follow line */
-			while (!outside && !hit[current.r][current.c]) {
+			while (!outside) {
 			    hit[current.r][current.c] |=
 				findcrossing(&current, level, Cell, Points,
 					     &ncrossing);
@@ -133,25 +135,27 @@ void contour(double levels[],
 	}			/* for rows */
 
 	/* check right and left borders (each row of first and last column) */
-	for (startcol = 0; startcol < ncol; startcol += (ncol - 2)) {
+	for (startcol = 0; startcol <= ncol - 2 ; startcol += (ncol - 2)) {
 	    for (startrow = 0; startrow <= nrow - 2; startrow++) {
 		/* look for starting point of new line */
 		if (!hit[startrow][startcol]) {
 		    current.r = startrow;
 		    current.c = startcol;
-		    outside = getnewcell(&current, nrow, ncol, z);
 
 		    /* is this left or right edge? */
-		    if (startcol == 0)	/* left */
+		    if (startcol < ncol - 2)	/* left */
 			current.edge = 3;
 		    else	/* right edge */
 			current.edge = 1;
+
+		    outside = getnewcell(&current, nrow, ncol, z);
+
 		    p1 = current.edge;
 		    p2 = (current.edge + 1) % 4;
 		    if (checkedge(current.z[p1], current.z[p2], level)) {
 			getpoint(&current, level, Cell, Points);
 			/* while not off an edge, follow line */
-			while (!outside && !hit[current.r][current.c]) {
+			while (!outside) {
 			    hit[current.r][current.c] |=
 				findcrossing(&current, level, Cell, Points,
 					     &ncrossing);
@@ -177,9 +181,12 @@ void contour(double levels[],
 		    current.r = startrow;
 		    current.c = startcol;
 		    current.edge = 0;
+		    p1 = current.edge;
+		    p2 = current.edge + 1;
+
 		    outside = getnewcell(&current, nrow, ncol, z);
 		    if (!outside &&
-			checkedge(current.z[0], current.z[1], level)) {
+			checkedge(current.z[p1], current.z[p2], level)) {
 			getpoint(&current, level, Cell, Points);
 			hit[current.r][current.c] |=
 			    findcrossing(&current, level, Cell, Points,
@@ -188,7 +195,7 @@ void contour(double levels[],
 			outside = getnewcell(&current, nrow, ncol, z);
 
 			/* while not back to starting point, follow line */
-			while (!outside && !hit[current.r][current.c] &&
+			while (!outside &&
 			       ((current.edge != 0) ||
 				((current.r != startrow) ||
 				 (current.c != startcol)))) {
@@ -236,6 +243,8 @@ static int getnewcell(struct cell *current, int nrow, int ncol, DCELL ** z)
 	current->z[2] = z[current->r + 1][current->c + 1];
 	current->z[3] = z[current->r + 1][current->c];
 
+	/* testing for NULL values here does not work */
+
 	return 0;
     }
     return 1;
@@ -328,6 +337,7 @@ static int findcrossing(struct cell *current, double level,
 
 	cellhit = 1;
     }
+
     return cellhit;
 }
 

+ 18 - 0
raster/r.contour/main.c

@@ -72,6 +72,7 @@ int main(int argc, char *argv[])
     struct FPRange range;
     int fd;
     double *lev;
+    double snap;
     int nlevels;
     int n_cut;
 
@@ -221,6 +222,23 @@ int main(int argc, char *argv[])
         db_close_database_shutdown_driver(Driver);
     }
     Vect_build(&Map);
+
+    /* if a contour line hits a border of NULL cells, it traces 
+     * itself back until it hits a border of NULL cells again,
+     * then goes back to the starting point
+     * -> cleaning is needed */
+    snap = (Wind.ns_res + Wind.ew_res) / 2000.0;
+    G_message(_("Snap lines"));
+    Vect_snap_lines(&Map, GV_LINE, snap, NULL);
+    G_message(_("Break lines at intersections"));
+    Vect_break_lines(&Map, GV_LINE, NULL);
+    G_message(_("Remove duplicates"));
+    Vect_remove_duplicates(&Map, GV_LINE, NULL);
+    G_message(_("Merge lines"));
+    Vect_merge_lines(&Map, GV_LINE, NULL, NULL);
+    Vect_build_partial(&Map, GV_BUILD_NONE);
+    Vect_build(&Map);
+    
     Vect_close(&Map);
 
     exit(EXIT_SUCCESS);

+ 3 - 3
raster/r.contour/testsuite/testrc.py

@@ -12,7 +12,7 @@ from grass.gunittest.case import TestCase
 from grass.gunittest.main import test
 from grass.gunittest.gmodules import SimpleModule
 
-out_where = """cat|level
+out_where = u"""cat|level
 1|56
 2|58
 3|60
@@ -86,7 +86,7 @@ class Testrr(TestCase):
 
     def test_flag_t(self):
         """Testing flag t"""
-        string="""min=1
+        string=u"""min=1
         max=6"""
         self.assertModule('r.contour', input=self.input, output=self.output, levels=1, step=1, flags='t')
         self.assertRasterFitsUnivar(self.output,
@@ -104,7 +104,7 @@ class Testrr(TestCase):
         self.assertModule('r.contour', input=self.input, output=self.output, step=2)
         v_db_select = SimpleModule('v.db.select', map=self.output)
         v_db_select.run()
-        self.assertLooksLike(reference=out_where, actual=v_db_select.outputs.stdout.encode('utf8'))
+        self.assertLooksLike(reference=out_where, actual=v_db_select.outputs.stdout)
 
 if __name__ == '__main__':
     from grass.gunittest.main import test

+ 3 - 1
scripts/g.extension/g.extension.py

@@ -324,7 +324,9 @@ def list_available_extensions(url):
     if flags['t']:
         grass.message(_("List of available extensions (toolboxes):"))
         tlist = get_available_toolboxes(url)
-        for toolbox_code, toolbox_data in tlist.items():
+        tkeys = sorted(tlist.keys())
+        for toolbox_code in tkeys:
+            toolbox_data = tlist[toolbox_code]
             if flags['g']:
                 print('toolbox_name=' + toolbox_data['name'])
                 print('toolbox_code=' + toolbox_code)

+ 2 - 3
scripts/g.extension/testsuite/test_addons_toolboxes.py

@@ -15,11 +15,10 @@ COPYRIGHT: (C) 2015 Vaclav Petras, and by the GRASS Development Team
 from grass.gunittest.case import TestCase
 from grass.gunittest.main import test
 from grass.gunittest.gmodules import SimpleModule
-from grass.script.utils import decode
 
 import os
 
-FULL_TOOLBOXES_OUTPUT = """\
+FULL_TOOLBOXES_OUTPUT = u"""\
 Hydrology (HY)
 * r.stream.basins
 * r.stream.channel
@@ -45,7 +44,7 @@ class TestToolboxesMetadata(TestCase):
         """List toolboxes and their content"""
         module = SimpleModule('g.extension', flags='lt', url=self.url)
         self.assertModule(module)
-        stdout = decode(module.outputs.stdout)
+        stdout = module.outputs.stdout
         self.assertMultiLineEqual(stdout, FULL_TOOLBOXES_OUTPUT)
 
 

+ 6 - 6
temporal/t.rast.accdetect/testsuite/data/test_1_temp_accumulation.ref

@@ -1,7 +1,7 @@
 name|start_time|min|max
-temp_acc_1|2001-01-01 00:00:00|5.0|5.0
-temp_acc_2|2001-03-01 00:00:00|15.0|15.0
-temp_acc_3|2001-05-01 00:00:00|30.0|30.0
-temp_acc_4|2001-07-01 00:00:00|50.0|50.0
-temp_acc_5|2001-09-01 00:00:00|75.0|75.0
-temp_acc_6|2001-11-01 00:00:00|105.0|105.0
+temp_acc_001|2001-01-01 00:00:00|5.0|5.0
+temp_acc_002|2001-03-01 00:00:00|15.0|15.0
+temp_acc_003|2001-05-01 00:00:00|30.0|30.0
+temp_acc_004|2001-07-01 00:00:00|50.0|50.0
+temp_acc_005|2001-09-01 00:00:00|75.0|75.0
+temp_acc_006|2001-11-01 00:00:00|105.0|105.0

+ 3 - 3
temporal/t.rast.accdetect/testsuite/data/test_1_temp_indi.ref

@@ -1,4 +1,4 @@
 name|start_time|min|max
-temp_occ_indicator_3|2001-05-01 00:00:00|1.0|1.0
-temp_occ_indicator_4|2001-07-01 00:00:00|2.0|2.0
-temp_occ_indicator_5|2001-09-01 00:00:00|3.0|3.0
+temp_occ_indicator_003|2001-05-01 00:00:00|1.0|1.0
+temp_occ_indicator_004|2001-07-01 00:00:00|2.0|2.0
+temp_occ_indicator_005|2001-09-01 00:00:00|3.0|3.0

+ 3 - 3
temporal/t.rast.accdetect/testsuite/data/test_1_temp_occ_a.ref

@@ -1,4 +1,4 @@
 name|start_time|min|max
-temp_occ_3|2001-05-01 00:00:00|120.0|120.0
-temp_occ_4|2001-07-01 00:00:00|181.0|181.0
-temp_occ_5|2001-09-01 00:00:00|243.0|243.0
+temp_occ_003|2001-05-01 00:00:00|120.0|120.0
+temp_occ_004|2001-07-01 00:00:00|181.0|181.0
+temp_occ_005|2001-09-01 00:00:00|243.0|243.0

+ 3 - 3
temporal/t.rast.accdetect/testsuite/data/test_1_temp_occ_b.ref

@@ -1,4 +1,4 @@
 name|start_time|min|max
-temp_occ_3|2001-05-01 00:00:00|120.0|120.0
-temp_occ_4|2001-07-01 00:00:00|181.0|181.0
-temp_occ_5|2001-09-01 00:00:00|243.0|243.0
+temp_occ_003|2001-05-01 00:00:00|120.0|120.0
+temp_occ_004|2001-07-01 00:00:00|181.0|181.0
+temp_occ_005|2001-09-01 00:00:00|243.0|243.0

+ 6 - 6
temporal/t.rast.accdetect/testsuite/data/test_2_temp_accumulation.ref

@@ -1,7 +1,7 @@
 name|start_time|min|max
-temp_acc_6|2001-01-01 00:00:00|105.0|105.0
-temp_acc_5|2001-03-01 00:00:00|75.0|75.0
-temp_acc_4|2001-05-01 00:00:00|50.0|50.0
-temp_acc_3|2001-07-01 00:00:00|30.0|30.0
-temp_acc_2|2001-09-01 00:00:00|15.0|15.0
-temp_acc_1|2001-11-01 00:00:00|5.0|5.0
+temp_acc_006|2001-01-01 00:00:00|105.0|105.0
+temp_acc_005|2001-03-01 00:00:00|75.0|75.0
+temp_acc_004|2001-05-01 00:00:00|50.0|50.0
+temp_acc_003|2001-07-01 00:00:00|30.0|30.0
+temp_acc_002|2001-09-01 00:00:00|15.0|15.0
+temp_acc_001|2001-11-01 00:00:00|5.0|5.0

+ 3 - 3
temporal/t.rast.accdetect/testsuite/data/test_2_temp_indi.ref

@@ -1,4 +1,4 @@
 name|start_time|min|max
-temp_occ_indicator_5|2001-03-01 00:00:00|3.0|3.0
-temp_occ_indicator_4|2001-05-01 00:00:00|2.0|2.0
-temp_occ_indicator_3|2001-07-01 00:00:00|1.0|1.0
+temp_occ_indicator_005|2001-03-01 00:00:00|3.0|3.0
+temp_occ_indicator_004|2001-05-01 00:00:00|2.0|2.0
+temp_occ_indicator_003|2001-07-01 00:00:00|1.0|1.0

+ 3 - 3
temporal/t.rast.accdetect/testsuite/data/test_2_temp_occ.ref

@@ -1,4 +1,4 @@
 name|start_time|min|max
-temp_occ_5|2001-03-01 00:00:00|59.0|59.0
-temp_occ_4|2001-05-01 00:00:00|120.0|120.0
-temp_occ_3|2001-07-01 00:00:00|181.0|181.0
+temp_occ_005|2001-03-01 00:00:00|59.0|59.0
+temp_occ_004|2001-05-01 00:00:00|120.0|120.0
+temp_occ_003|2001-07-01 00:00:00|181.0|181.0

+ 1 - 2
temporal/t.rast.aggregate/testsuite/test_aggregation_absolute.py

@@ -116,8 +116,7 @@ class TestAggregationAbsolute(TestCase):
                           basename="b", granularity="1 months",
                           method="maximum", sampling=["contains"],
                           file_limit=0, nprocs=3, suffix='time')
-        #self.assertRasterExists('b_2001_01_01T00_00_00')
-        self.assertRasterExists('b_2001_01_01_00')
+        self.assertRasterExists('b_2001_01_01T00_00_00')
 
     def test_aggregation_2months(self):
         """Aggregation two month"""

+ 8 - 8
temporal/t.rast3d.univar/testsuite/test_t_rast3d_univar.py

@@ -48,13 +48,13 @@ class TestRasterUnivar(TestCase):
                                                           overwrite=True, verbose=True)
         self.assertModule(t_rast3d_univar)
 
-        univar_text="""id|start|end|mean|min|max|mean_of_abs|stddev|variance|coeff_var|sum|null_cells|cells|non_null_cells
+        univar_text=u"""id|start|end|mean|min|max|mean_of_abs|stddev|variance|coeff_var|sum|null_cells|cells|non_null_cells
 a_1@testing|2001-01-01 00:00:00|2001-04-01 00:00:00|100|100|100|100|0|0|0|48000000|0|480000|480000
 a_2@testing|2001-04-01 00:00:00|2001-07-01 00:00:00|200|200|200|200|0|0|0|96000000|0|480000|480000
 a_3@testing|2001-07-01 00:00:00|2001-10-01 00:00:00|300|300|300|300|0|0|0|144000000|0|480000|480000
 a_4@testing|2001-10-01 00:00:00|2002-01-01 00:00:00|400|400|400|400|0|0|0|192000000|0|480000|480000
 """
-        for ref, res in zip(univar_text.split("\n"), t_rast3d_univar.outputs.stdout.encode('utf8').split("\n")):
+        for ref, res in zip(univar_text.split("\n"), t_rast3d_univar.outputs.stdout.split("\n")):
             if ref and res:
                 ref_line = ref.split("|", 1)[1]
                 res_line = res.split("|", 1)[1]
@@ -67,12 +67,12 @@ a_4@testing|2001-10-01 00:00:00|2002-01-01 00:00:00|400|400|400|400|0|0|0|192000
                                                           overwrite=True, verbose=True)
         self.assertModule(t_rast3d_univar)
 
-        univar_text="""id|start|end|mean|min|max|mean_of_abs|stddev|variance|coeff_var|sum|null_cells|cells|non_null_cells
+        univar_text=u"""id|start|end|mean|min|max|mean_of_abs|stddev|variance|coeff_var|sum|null_cells|cells|non_null_cells
 a_2@testing|2001-04-01 00:00:00|2001-07-01 00:00:00|200|200|200|200|0|0|0|96000000|0|480000|480000
 a_3@testing|2001-07-01 00:00:00|2001-10-01 00:00:00|300|300|300|300|0|0|0|144000000|0|480000|480000
 a_4@testing|2001-10-01 00:00:00|2002-01-01 00:00:00|400|400|400|400|0|0|0|192000000|0|480000|480000
 """
-        for ref, res in zip(univar_text.split("\n"), t_rast3d_univar.outputs.stdout.encode('utf8').split("\n")):
+        for ref, res in zip(univar_text.split("\n"), t_rast3d_univar.outputs.stdout.split("\n")):
             if ref and res:
                 ref_line = ref.split("|", 1)[1]
                 res_line = res.split("|", 1)[1]
@@ -85,14 +85,14 @@ a_4@testing|2001-10-01 00:00:00|2002-01-01 00:00:00|400|400|400|400|0|0|0|192000
                                              where="start_time >= '2001-03-01'",
                                              overwrite=True, verbose=True)
 
-        univar_text="""id|start|end|mean|min|max|mean_of_abs|stddev|variance|coeff_var|sum|null_cells|cells|non_null_cells
+        univar_text=u"""id|start|end|mean|min|max|mean_of_abs|stddev|variance|coeff_var|sum|null_cells|cells|non_null_cells
 a_2@testing|2001-04-01 00:00:00|2001-07-01 00:00:00|200|200|200|200|0|0|0|96000000|0|480000|480000
 a_3@testing|2001-07-01 00:00:00|2001-10-01 00:00:00|300|300|300|300|0|0|0|144000000|0|480000|480000
 a_4@testing|2001-10-01 00:00:00|2002-01-01 00:00:00|400|400|400|400|0|0|0|192000000|0|480000|480000
 """
         univar_output = open("univar_output.txt", "r").read()
 
-        for ref, res in zip(univar_text.split("\n"), univar_output.encode('utf8').split("\n")):
+        for ref, res in zip(univar_text.split("\n"), univar_output.split("\n")):
             if ref and res:
                 ref_line = ref.split("|", 1)[1]
                 res_line = res.split("|", 1)[1]
@@ -105,13 +105,13 @@ a_4@testing|2001-10-01 00:00:00|2002-01-01 00:00:00|400|400|400|400|0|0|0|192000
                                              where="start_time >= '2001-03-01'",
                                              overwrite=True, verbose=True)
 
-        univar_text="""a_2@testing|2001-04-01 00:00:00|2001-07-01 00:00:00|200|200|200|200|0|0|0|96000000|0|480000|480000
+        univar_text=u"""a_2@testing|2001-04-01 00:00:00|2001-07-01 00:00:00|200|200|200|200|0|0|0|96000000|0|480000|480000
 a_3@testing|2001-07-01 00:00:00|2001-10-01 00:00:00|300|300|300|300|0|0|0|144000000|0|480000|480000
 a_4@testing|2001-10-01 00:00:00|2002-01-01 00:00:00|400|400|400|400|0|0|0|192000000|0|480000|480000
 """
         univar_output = open("univar_output.txt", "r").read()
 
-        for ref, res in zip(univar_text.split("\n"), univar_output.encode('utf8').split("\n")):
+        for ref, res in zip(univar_text.split("\n"), univar_output.split("\n")):
             if ref and res:
                 ref_line = ref.split("|", 1)[1]
                 res_line = res.split("|", 1)[1]

+ 7 - 7
vector/v.db.select/testsuite/test_v_db_select.py

@@ -14,7 +14,7 @@ from grass.gunittest.case import TestCase
 from grass.gunittest.main import test
 from grass.gunittest.gmodules import SimpleModule
 
-out_group = """CZab
+out_group = u"""CZab
 CZam
 CZba
 CZbb
@@ -153,12 +153,12 @@ Zwe
 bz
 """
 
-out_where = """1076|366545504|324050.96875|1077|1076|Zwe|366545512.376|324050.97237
+out_where = u"""1076|366545504|324050.96875|1077|1076|Zwe|366545512.376|324050.97237
 1123|1288.555298|254.393951|1124|1123|Zwe|1288.546525|254.393964
 1290|63600420|109186.835938|1291|1290|Zwe|63600422.4739|109186.832069
 """
 
-out_sep = """1076,366545504,324050.96875,1077,1076,Zwe,366545512.376,324050.97237
+out_sep = u"""1076,366545504,324050.96875,1077,1076,Zwe,366545512.376,324050.97237
 1123,1288.555298,254.393951,1124,1123,Zwe,1288.546525,254.393964
 1290,63600420,109186.835938,1291,1290,Zwe,63600422.4739,109186.832069
 """
@@ -188,7 +188,7 @@ class SelectTest(TestCase):
         sel = SimpleModule('v.db.select', flags='c', map=self.invect,
                            columns=self.col, group=self.col)
         sel.run()
-        self.assertLooksLike(reference=out_group, actual=sel.outputs.stdout.encode('utf8'))
+        self.assertLooksLike(reference=out_group, actual=sel.outputs.stdout)
 
     def testWhere(self):
         """Testing v.db.select with where option"""
@@ -196,7 +196,7 @@ class SelectTest(TestCase):
                            where="{col}='{val}'".format(col=self.col,
                                                         val=self.val))
         sel.run()
-        self.assertLooksLike(reference=out_where, actual=sel.outputs.stdout.encode('utf8'))
+        self.assertLooksLike(reference=out_where, actual=sel.outputs.stdout)
 
     def testSeparator(self):
         sel = SimpleModule('v.db.select', flags='c', map=self.invect,
@@ -204,7 +204,7 @@ class SelectTest(TestCase):
                                                         val=self.val),
                            separator='comma')
         sel.run()
-        self.assertLooksLike(reference=out_sep, actual=sel.outputs.stdout.encode('utf8'))
+        self.assertLooksLike(reference=out_sep, actual=sel.outputs.stdout)
 
     def testComma(self):
         sel = SimpleModule('v.db.select', flags='c', map=self.invect,
@@ -212,7 +212,7 @@ class SelectTest(TestCase):
                                                         val=self.val),
                            separator=',')
         sel.run()
-        self.assertLooksLike(reference=out_sep, actual=sel.outputs.stdout.encode('utf8'))
+        self.assertLooksLike(reference=out_sep, actual=sel.outputs.stdout)
 
 if __name__ == '__main__':
     test()

+ 1 - 1
vector/v.in.lidar/testsuite/decimation_test.py

@@ -134,7 +134,7 @@ class TestCountBasedDecimation(TestCase):
         self.assertVectorExists(self.imported_points)
         self.assertVectorFitsTopoInfo(
             vector=self.imported_points,
-            reference=dict(points=(self.npoints - 105) / 10))
+            reference=dict(points=int((self.npoints - 105) / 10)))
 
     def test_limit_skip(self):
         """Test to see if the outputs are created"""

+ 1 - 1
vector/v.in.lidar/testsuite/mask_test.py

@@ -145,7 +145,7 @@ class VectorMaskTest(TestCase):
     def test_inverted_mask(self):
         """Test to see if the standard outputs are created"""
         self.assertModule('v.in.lidar', input=self.las_file,
-            output=self.imported_points, flags='bti',
+            output=self.imported_points, flags='btu',
             mask=self.areas)
         self.assertVectorExists(self.imported_points)
         self.assertVectorFitsTopoInfo(

+ 10 - 10
vector/v.profile/testsuite/test_v_profile.py

@@ -18,30 +18,30 @@ from grass.gunittest.case import TestCase
 from grass.gunittest.main import test
 from grass.gunittest.gmodules import SimpleModule
 
-output_full = """Number|Distance|cat|feature_id|featurenam|class|st_alpha|st_num|county|county_num|primlat_dm|primlon_dm|primlatdec|primlondec|srclat_dms|srclon_dms|srclatdec|srclondec|elev_m|map_name
+output_full = u"""Number|Distance|cat|feature_id|featurenam|class|st_alpha|st_num|county|county_num|primlat_dm|primlon_dm|primlatdec|primlondec|srclat_dms|srclon_dms|srclatdec|srclondec|elev_m|map_name
 1|19537.97|572|986138|"Greshams Lake"|"Reservoir"|"NC"|37|"Wake"|183|"078:34:31W"|"35:52:43N"|35.878484|-78.57528|""|""|""|""|77|"Wake Forest"
 2|19537.97|1029|999647|"Greshams Lake Dam"|"Dam"|"NC"|37|"Wake"|183|"078:34:31W"|"35:52:43N"|35.878484|-78.57528|""|""|""|""|77|"Wake Forest"
 """
 
-output_nocols = """1|19537.97|572|986138|"Greshams Lake"|"Reservoir"|"NC"|37|"Wake"|183|"078:34:31W"|"35:52:43N"|35.878484|-78.57528|""|""|""|""|77|"Wake Forest"
+output_nocols = u"""1|19537.97|572|986138|"Greshams Lake"|"Reservoir"|"NC"|37|"Wake"|183|"078:34:31W"|"35:52:43N"|35.878484|-78.57528|""|""|""|""|77|"Wake Forest"
 2|19537.97|1029|999647|"Greshams Lake Dam"|"Dam"|"NC"|37|"Wake"|183|"078:34:31W"|"35:52:43N"|35.878484|-78.57528|""|""|""|""|77|"Wake Forest"
 """
 
-output_filtered = """Number|Distance|cat|feature_id|featurenam|class|st_alpha|st_num|county|county_num|primlat_dm|primlon_dm|primlatdec|primlondec|srclat_dms|srclon_dms|srclatdec|srclondec|elev_m|map_name
+output_filtered = u"""Number|Distance|cat|feature_id|featurenam|class|st_alpha|st_num|county|county_num|primlat_dm|primlon_dm|primlatdec|primlondec|srclat_dms|srclon_dms|srclatdec|srclondec|elev_m|map_name
 1|19537.97|1029|999647|"Greshams Lake Dam"|"Dam"|"NC"|37|"Wake"|183|"078:34:31W"|"35:52:43N"|35.878484|-78.57528|""|""|""|""|77|"Wake Forest"
 """
 
-output_coords = """Number|Distance|cat|feature_id|featurenam|class|st_alpha|st_num|county|county_num|primlat_dm|primlon_dm|primlatdec|primlondec|srclat_dms|srclon_dms|srclatdec|srclondec|elev_m|map_name
+output_coords = u"""Number|Distance|cat|feature_id|featurenam|class|st_alpha|st_num|county|county_num|primlat_dm|primlon_dm|primlatdec|primlondec|srclat_dms|srclon_dms|srclatdec|srclondec|elev_m|map_name
 1|24.34|572|986138|"Greshams Lake"|"Reservoir"|"NC"|37|"Wake"|183|"078:34:31W"|"35:52:43N"|35.878484|-78.57528|""|""|""|""|77|"Wake Forest"
 2|24.34|1029|999647|"Greshams Lake Dam"|"Dam"|"NC"|37|"Wake"|183|"078:34:31W"|"35:52:43N"|35.878484|-78.57528|""|""|""|""|77|"Wake Forest"
 """
 
-buf_points = """\
+buf_points = u"""\
 626382.68026139|228917.44816672|1
 626643.91393428|228738.2879083|2
 626907.14939778|228529.10079092|3
 """
-buf_output = """\
+buf_output = u"""\
 Number,Distance,cat,dbl_1,dbl_2,int_1
 1,2102.114,3,626907.14939778,228529.10079092,3
 2,2854.300,2,626643.91393428,228738.2879083,2
@@ -111,21 +111,21 @@ class TestProfiling(TestCase):
         vpro = SimpleModule('v.profile', input=self.in_points, profile_map=self.in_map, buffer=200,
             profile_where=self.where)
         vpro.run()
-        self.assertLooksLike(reference=output_full, actual=vpro.outputs.stdout.encode('utf8'))
+        self.assertLooksLike(reference=output_full, actual=vpro.outputs.stdout)
         # Without column names
         vpro = SimpleModule('v.profile', input=self.in_points, profile_map=self.in_map, buffer=200,
             profile_where=self.where, c=True)
         vpro.run()
-        self.assertLooksLike(reference=output_nocols, actual=vpro.outputs.stdout.encode('utf8'))
+        self.assertLooksLike(reference=output_nocols, actual=vpro.outputs.stdout)
         # Filtering input points
         vpro = SimpleModule('v.profile', input=self.in_points, profile_map=self.in_map, buffer=200,
             where="class='Dam'", profile_where=self.where)
         vpro.run()
-        self.assertLooksLike(reference=output_filtered, actual=vpro.outputs.stdout.encode('utf8'))
+        self.assertLooksLike(reference=output_filtered, actual=vpro.outputs.stdout)
         # Providing profiling line from coordinates
         vpro = SimpleModule('v.profile', input=self.in_points, coordinates=self.prof_ponts, buffer=200)
         vpro.run()
-        self.assertLooksLike(reference=output_coords, actual=vpro.outputs.stdout.encode('utf8'))
+        self.assertLooksLike(reference=output_coords, actual=vpro.outputs.stdout)
     
     def testBuffering(self):
         """Test against errors in buffering implementation"""

+ 8 - 8
vector/v.univar/testsuite/v_univar_test.py

@@ -16,7 +16,7 @@ class TestProfiling(TestCase):
 
     def test_flagg(self):
         """Testing flag g with map lakes"""
-        output_str = """n=15279
+        output_str = u"""n=15279
 nmissing=0
 nnull=0
 min=1
@@ -34,12 +34,12 @@ kurtosis=-1.20024
 skewness=-2.41826e-14"""
         v_univar = SimpleModule("v.univar", flags="g", map='lakes', column='cat')
         v_univar.run()
-        self.assertLooksLike(actual=v_univar.outputs.stdout.encode('utf8'),
+        self.assertLooksLike(actual=v_univar.outputs.stdout,
                              reference=output_str)
 
     def test_flage(self):
         """Testing flag e with map geology"""
-        output_str = """number of features with non NULL attribute: 1832
+        output_str = u"""number of features with non NULL attribute: 1832
 number of missing attributes: 0
 number of NULL attributes: 0
 minimum: 166.947
@@ -61,12 +61,12 @@ median (even number of cells): 10308.4
 90th percentile: 86449.7"""
         v_univar = SimpleModule('v.univar', map='geology', column='PERIMETER', flags='e')
         v_univar.run()
-        self.assertLooksLike(actual=v_univar.outputs.stdout.encode('utf8'),
+        self.assertLooksLike(actual=v_univar.outputs.stdout,
                              reference=output_str)
  
     def test_flagw(self):
         """Testing flag w with map lakes"""
-        output_str = """number of features with non NULL attribute: 15279
+        output_str = u"""number of features with non NULL attribute: 15279
 number of missing attributes: 0
 number of NULL attributes: 0
 minimum: 2
@@ -77,12 +77,12 @@ mean: 6190.76
 mean of absolute values: 6190.76"""
         v_univar = SimpleModule('v.univar', map='lakes', column='FULL_HYDRO', flags='w')
         v_univar.run()
-        self.assertLooksLike(actual=v_univar.outputs.stdout.encode('utf8'),
+        self.assertLooksLike(actual=v_univar.outputs.stdout,
                              reference=output_str)
 
     def test_flagd(self):
         """Testing flag d with map hospitals"""
-        univar_string = """number of primitives: 160
+        univar_string = u"""number of primitives: 160
 number of non zero distances: 12561
 number of zero distances: 0
 minimum: 9.16773
@@ -100,7 +100,7 @@ kurtosis: 0.277564
 skewness: 0.801646"""
         v_univar = SimpleModule('v.univar', map='hospitals', column='CITY', flags='d')
         v_univar.run()
-        self.assertLooksLike(actual=v_univar.outputs.stdout.encode('utf8'),
+        self.assertLooksLike(actual=v_univar.outputs.stdout,
                              reference=univar_string)
 		
     def test_output(self):

+ 8 - 8
vector/v.what/testsuite/test_vwhat_ncspm.py

@@ -7,7 +7,7 @@ from grass.gunittest.gmodules import SimpleModule
 
 
 # v.what map=schools,roadsmajor,elev_points,geology layer=-1,-1,-1,-1 coordinates=636661,226489 distance=1000
-out1 = """East: 636661
+out1 = u"""East: 636661
 North: 226489
 ------------------------------------------------------------------
 Map: schools 
@@ -38,7 +38,7 @@ Category: 217
 """
 
 # v.what map=schools,roadsmajor,elev_points,geology layer=-1,-1,-1,-1 coordinates=636661,226489 distance=1000 -ag
-out2 = """East: 636661
+out2 = u"""East: 636661
 North: 226489
 ------------------------------------------------------------------
 Map: schools 
@@ -94,7 +94,7 @@ SHAPE_len : 198808.723525
 """
 
 # v.what map=schools,roadsmajor,elev_points,geology layer=-1,-1,-1,-1 coordinates=636661,226489 distance=1000 -ag
-out3 = """East=636661
+out3 = u"""East=636661
 North=226489
 
 Map=schools
@@ -146,7 +146,7 @@ SHAPE_len=198808.723525
 """
 
 # v.what map=schools,roadsmajor,elev_points,geology layer=-1,-1,-1,-1 coordinates=636661,226489 distance=100
-out4 = """East: 636661
+out4 = u"""East: 636661
 North: 226489
 ------------------------------------------------------------------
 Map: schools 
@@ -182,21 +182,21 @@ class TestNCMaps(TestCase):
 
     def test_multiple_maps(self):
         self.assertModule(self.vwhat)
-        self.assertMultiLineEqual(first=out1, second=self.vwhat.outputs.stdout.encode('utf8'))
+        self.assertMultiLineEqual(first=out1, second=self.vwhat.outputs.stdout)
 
     def test_print_options(self):
         self.vwhat.flags['a'].value = True
         self.assertModule(self.vwhat)
-        self.assertLooksLike(reference=out2, actual=self.vwhat.outputs.stdout.encode('utf8'))
+        self.assertLooksLike(reference=out2, actual=self.vwhat.outputs.stdout)
 
         self.vwhat.flags['g'].value = True
         self.assertModule(self.vwhat)
-        self.assertLooksLike(reference=out3, actual=self.vwhat.outputs.stdout.encode('utf8'))
+        self.assertLooksLike(reference=out3, actual=self.vwhat.outputs.stdout)
 
     def test_threshold(self):
         self.vwhat.inputs['distance'].value = 100
         self.assertModule(self.vwhat)
-        self.assertLooksLike(reference=out4, actual=self.vwhat.outputs.stdout.encode('utf8'))
+        self.assertLooksLike(reference=out4, actual=self.vwhat.outputs.stdout)
 
     def test_print_options_json(self):
         import json