소스 검색

pygrass update from trunk: backport documentation improvements (thanks: Luca, MarkusN and Martin) and recent fix on modules/interface/parameter and vector 3D

git-svn-id: https://svn.osgeo.org/grass/grass/branches/releasebranch_7_0@60913 15284696-431f-4ddb-bdfa-cd5b030d7da7
Pietro Zambelli 11 년 전
부모
커밋
d8428e295a
39개의 변경된 파일2018개의 추가작업 그리고 1270개의 파일을 삭제
  1. 10 87
      lib/python/pygrass/docs/Makefile
  2. 74 0
      lib/python/pygrass/docs/_static/pygrass.css
  3. 9 0
      lib/python/pygrass/docs/_templates/layout.html.template
  4. 25 4
      lib/python/pygrass/docs/conf.py
  5. 30 0
      lib/python/pygrass/docs/gis.rst
  6. 25 15
      lib/python/pygrass/docs/index.rst
  7. 3 3
      lib/python/pygrass/docs/intro.rst
  8. 15 0
      lib/python/pygrass/docs/messages.rst
  9. 15 11
      lib/python/pygrass/docs/modules.rst
  10. 25 0
      lib/python/pygrass/docs/modules_grid.rst
  11. 11 147
      lib/python/pygrass/docs/raster.rst
  12. 136 0
      lib/python/pygrass/docs/raster_elements.rst
  13. 9 74
      lib/python/pygrass/docs/vector.rst
  14. 21 15
      lib/python/pygrass/docs/attributes.rst
  15. 41 0
      lib/python/pygrass/docs/vector_features.rst
  16. 27 0
      lib/python/pygrass/docs/vector_utils.rst
  17. 77 26
      lib/python/pygrass/gis/__init__.py
  18. 81 44
      lib/python/pygrass/gis/region.py
  19. 72 42
      lib/python/pygrass/messages/__init__.py
  20. 164 234
      lib/python/pygrass/modules/grid/grid.py
  21. 33 2
      lib/python/pygrass/modules/grid/patch.py
  22. 51 37
      lib/python/pygrass/modules/grid/split.py
  23. 7 1
      lib/python/pygrass/modules/interface/flag.py
  24. 48 44
      lib/python/pygrass/modules/interface/module.py
  25. 9 2
      lib/python/pygrass/modules/interface/parameter.py
  26. 1 1
      lib/python/pygrass/modules/shortcuts.py
  27. 24 7
      lib/python/pygrass/pygrasslib.dox
  28. 85 71
      lib/python/pygrass/raster/__init__.py
  29. 22 6
      lib/python/pygrass/raster/category.py
  30. 42 35
      lib/python/pygrass/raster/history.py
  31. 76 53
      lib/python/pygrass/vector/__init__.py
  32. 72 46
      lib/python/pygrass/vector/abstract.py
  33. 112 59
      lib/python/pygrass/vector/basic.py
  34. 7 2
      lib/python/pygrass/vector/find.py
  35. 169 136
      lib/python/pygrass/vector/geometry.py
  36. 1 6
      lib/python/pygrass/vector/sql.py
  37. 192 60
      lib/python/pygrass/vector/table.py
  38. 130 0
      lib/python/pygrass/vector/testsuite/test_geometry.py
  39. 67 0
      lib/python/pygrass/vector/testsuite/test_vector3d.py

+ 10 - 87
lib/python/pygrass/docs/Makefile

@@ -14,6 +14,7 @@ SPHINXBUILD   = sphinx-build
 endif
 PAPER         =
 BUILDDIR      = _build
+BUILDDIR_HTML = $(HTMLDIR)/pygrass
 
 MYGISBASE = $(GISBASE)
 
@@ -33,74 +34,30 @@ help:
 	@echo "  html       to make standalone HTML files"
 	@echo "  dirhtml    to make HTML files named index.html in directories"
 	@echo "  singlehtml to make a single large HTML file"
-	@echo "  pickle     to make pickle files"
-	@echo "  json       to make JSON files"
-	@echo "  htmlhelp   to make HTML files and a HTML help project"
-	@echo "  qthelp     to make HTML files and a qthelp project"
-	@echo "  devhelp    to make HTML files and a Devhelp project"
 	@echo "  epub       to make an epub"
 	@echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
 	@echo "  latexpdf   to make LaTeX files and run them through pdflatex"
-	@echo "  text       to make text files"
 	@echo "  man        to make manual pages"
-	@echo "  texinfo    to make Texinfo files"
-	@echo "  info       to make Texinfo files and run them through makeinfo"
-	@echo "  gettext    to make PO message catalogs"
-	@echo "  changes    to make an overview of all changed/added/deprecated items"
-	@echo "  linkcheck  to check all external links for integrity"
 	@echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
 
 clean:
 	-rm -rf $(BUILDDIR)/*
+	-rm -f _templates/layout.html
 
 html:
-	$(call run_grass,$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html)
+	$(call run_grass,$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR_HTML))
 	@echo
-	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html/"
+	@echo "Build finished. The HTML pages are in $(BUILDDIR_HTML)"
 
 dirhtml:
-	$(call run_grass,$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml)
+	$(call run_grass,$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR_HTML))
 	@echo
-	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml/"
+	@echo "Build finished. The HTML pages are in $(BUILDDIR_HTML)"
 
 singlehtml:
-	$(call run_grass,$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml)
+	$(call run_grass,$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR_HTML))
 	@echo
-	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml/"
-
-pickle:
-	$(call run_grass,$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle)
-	@echo
-	@echo "Build finished; now you can process the pickle files in $(BUILDDIR)/pickle/."
-
-json:
-	$(call run_grass,$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json)
-	@echo
-	@echo "Build finished; now you can process the JSON files in $(BUILDDIR)/json/"
-
-htmlhelp:
-	$(call run_grass,$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp)
-	@echo
-	@echo "Build finished; now you can run HTML Help Workshop with the" \
-	      ".hhp project file in $(BUILDDIR)/htmlhelp/"
-
-qthelp:
-	$(call run_grass,$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp)
-	@echo
-	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
-	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
-	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/PyGrass.qhcp"
-	@echo "To view the help file:"
-	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/PyGrass.qhc"
-
-devhelp:
-	$(call run_grass,$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp)
-	@echo
-	@echo "Build finished."
-	@echo "To view the help file:"
-	@echo "# mkdir -p $$HOME/.local/share/devhelp/PyGrass"
-	@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/PyGrass"
-	@echo "# devhelp"
+	@echo "Build finished. The HTML page is in $(BUILDDIR_HTML)"
 
 epub:
 	$(call run_grass,$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub)
@@ -120,44 +77,10 @@ latexpdf:
 	$(MAKE) -C $(BUILDDIR)/latex all-pdf
 	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex/"
 
-text:
-	$(call run_grass,$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text)
-	@echo
-	@echo "Build finished. The text files are in $(BUILDDIR)/text/"
-
 man:
-	$(call run_grass,$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man)
-	@echo
-	@echo "Build finished. The manual pages are in $(BUILDDIR)/man/"
-
-texinfo:
-	$(call run_grass,$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo)
-	@echo
-	@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
-	@echo "Run \`make' in that directory to run these through makeinfo" \
-	      "(use \`make info' here to do that automatically)."
-
-info:
-	$(call run_grass,$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo)
-	@echo "Running Texinfo files through makeinfo..."
-	make -C $(BUILDDIR)/texinfo info
-	@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo/"
-
-gettext:
-	$(call run_grass,$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale)
-	@echo
-	@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale/"
-
-changes:
-	$(call run_grass,$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes)
-	@echo
-	@echo "The overview file is in $(BUILDDIR)/changes/"
-
-linkcheck:
-	$(call run_grass,$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck)
+	$(call run_grass,$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(MANDIR))
 	@echo
-	@echo "Link check complete; look for any errors in the above output " \
-	      "or in $(BUILDDIR)/linkcheck/output.txt."
+	@echo "Build finished. The manual pages are in $(MANDIR)/"
 
 doctest:
 	$(call run_grass,$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest)

+ 74 - 0
lib/python/pygrass/docs/_static/pygrass.css

@@ -0,0 +1,74 @@
+/* GRASS documentation site style sheet
+ *
+ * send improvements to GRASS Developers list
+ * 
+ *  (eg how to reach the same result on netscape, mozilla konqueror?)
+ *
+ * Fonts:
+ *	http://www.w3.org/TR/REC-CSS2/fonts.html
+ * Tables:
+ *	http://www.w3.org/TR/REC-CSS2/tables.html
+ */
+
+body{
+    background: white;
+    color: black;
+    font-family: arial,sans-serif;
+    width: 99%;
+    margin: 8px;
+}
+
+hr.header {
+    height: 3px;
+    color: gray;
+    background-color: gray;
+    width: 100%;
+}
+
+h1{
+    background-color: transparent;
+    color: rgb(25%, 60%, 25%);
+    font-family: arial,sans-serif;
+    font-weight: bold;
+    font-size: x-large;
+}
+
+h2{
+    background-color: transparent;
+    color: rgb(25%, 60%, 25%);
+    font-family: arial,sans-serif;
+    font-weight: bold;
+    font-size: large;
+}
+
+h3{
+    background-color: transparent;
+    color: rgb(25%, 60%, 25%);
+    font-family: arial,sans-serif;
+    font-weight: bold;
+    font-size: large;
+}
+
+h4{
+    background-color: transparent;
+    color: rgb(25%, 60%, 25%);
+    font-family: arial,sans-serif;
+    font-weight: bold;
+    font-size: medium;
+}
+
+table.border {
+    border-collapse:collapse;
+}
+
+table.border td {
+    border: 1px solid rgb(25%, 60%, 25%);
+}
+
+td {
+    padding: 5px;
+}
+
+div.related {
+    background-color: transparent;
+}

+ 9 - 0
lib/python/pygrass/docs/_templates/layout.html.template

@@ -0,0 +1,9 @@
+{% extends "!layout.html" %}
+{% block extrahead %}
+<link rel="stylesheet" href="{{ pathto('_static/pygrass.css', 1) }}" type="text/css" />
+{% endblock %}
+
+{% block header %}
+<img src="../grass_logo.png" alt="GRASS logo">
+<hr class="header">
+{% endblock %}

+ 25 - 4
lib/python/pygrass/docs/conf.py

@@ -12,6 +12,9 @@
 # serve to show the default.
 
 import sys, os
+from datetime import date
+import string
+from shutil import copy
 
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
@@ -20,6 +23,24 @@ if not os.getenv('GISBASE'):
     sys.exit("GISBASE not defined")
 sys.path.insert(0, os.path.abspath(os.path.join(os.environ['GISBASE'], 'etc', 'python', 'grass')))
 
+from grass.script import core
+
+footer_tmpl = string.Template(\
+r"""
+{% block footer %}<hr class="header">
+<p><a href="../index.html">Help Index</a> | <a href="../topics.html">Topics Index</a> | <a href="../keywords.html">Keywords Index</a> | <a href="../full_index.html">Full Index</a></p>
+<p>&copy; 2003-${year} <a href="http://grass.osgeo.org">GRASS Development Team</a>, GRASS GIS ${grass_version} Reference Manual</p>
+{% endblock %}
+""")
+
+grass_version = core.version()['version']
+today = date.today()
+
+copy("_templates/layout.html.template", "_templates/layout.html")
+with open("_templates/layout.html", "a+b") as f:
+    f.write(footer_tmpl.substitute(grass_version=grass_version, year=today.year))
+    f.close()
+
 # -- General configuration -----------------------------------------------------
 
 # If your documentation needs a minimal Sphinx version, state it here.
@@ -50,9 +71,9 @@ copyright = u'2012-2014, Pietro Zambelli'
 # built documents.
 #
 # The short X.Y version.
-version = '0.2'
+#version = '0.2'
 # The full version, including alpha/beta/rc tags.
-release = 'beta'
+#release = 'beta'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
@@ -100,7 +121,7 @@ intersphinx_mapping = {'python': ('http://docs.python.org/2.7', None)}
 
 # The theme to use for HTML and HTML Help pages.  See the documentation for
 # a list of builtin themes.
-html_theme = 'default'
+html_theme = 'traditional'
 
 # Theme options are theme-specific and customize the look and feel of a theme
 # further.  For a list of options available for each theme, see the
@@ -140,7 +161,7 @@ html_static_path = ['_static']
 #html_use_smartypants = True
 
 # Custom sidebar templates, maps document names to template names.
-#html_sidebars = {}
+html_sidebars = {"**":["localtoc.html",'relations.html','searchbox.html']}
 
 # Additional templates that should be rendered to pages, maps page names to
 # template names.

+ 30 - 0
lib/python/pygrass/docs/gis.rst

@@ -0,0 +1,30 @@
+.. _GRASSdatabase-label:
+
+GRASS database management
+===============================
+
+These classes are used to manage the infrastructure
+of GRASS database: Gisdbase, Location and Mapset
+
+.. autoclass:: pygrass.gis.Gisdbase
+    :members:
+
+.. autoclass:: pygrass.gis.Location
+    :members:
+
+.. autoclass:: pygrass.gis.Mapset
+    :members:
+
+.. autoclass:: pygrass.gis.VisibleMapset
+    :members:
+
+.. _Region-label:
+
+Region management
+======================
+
+The Region class it is useful to obtain information
+about the computational region and to change it.
+
+.. autoclass:: pygrass.gis.region.Region
+    :members:

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 25 - 15
lib/python/pygrass/docs/index.rst


+ 3 - 3
lib/python/pygrass/docs/intro.rst

@@ -4,11 +4,11 @@ Introduction
 To work with ``pygrass`` you need an up-to-date version of GRASS GIS 7.
 You can obtain a recent version following the information provided on the
 `main Web site <http://grass.osgeo.org/download/software/>`_
-of GRASS, and you can read more about compilation on the 
+of GRASS, and you can read more about compilation in the 
 `GRASS GIS Wiki <http://grasswiki.osgeo.org/wiki/Compile_and_Install>`_
 
 The only action before starting to work with ``pygrass`` is to launch 
 GRASS GIS 7 and from the console launch ``python`` or ``ipython`` 
-(the second one is the recommended way)
+(the second one is the recommended way).
 
-Read more about how to work with :doc:`gis`, :doc:`raster`, :doc:`vector`, :doc:`attributes`, :doc:`modules`.
+Read more about how to work with ``pygrass`` in this documentation.

+ 15 - 0
lib/python/pygrass/docs/messages.rst

@@ -0,0 +1,15 @@
+PyGRASS message interface
+=========================
+
+The PyGRASS message interface is a fast and exit-safe
+interface to the `GRASS C-library message functions <http://grass.osgeo.org/programming7/gis_2error_8c.html>`_.
+
+.. autoclass:: pygrass.messages.Messenger
+    :members:
+
+.. autoclass:: pygrass.messages.FatalError
+    :members:
+
+.. autofunction:: pygrass.messages.message_server
+
+.. autofunction:: pygrass.messages.get_msgr

+ 15 - 11
lib/python/pygrass/docs/modules.rst

@@ -1,8 +1,9 @@
-Modules
-=======
+Interface to GRASS GIS modules
+==============================
 
-Grass modules are represented as objects. These objects are generated based
-on the XML module description that is used for GUI generation already. ::
+In "modules", GRASS GIS modules are represented as objects. These objects
+are generated based on the XML module description that is used also for
+the generation of the graphical user interface (GUI). ::
 
     >>> from pygrass.modules import Module
     >>> slope_aspect = Module("r.slope.aspect", elevation='elevation',
@@ -10,7 +11,9 @@ on the XML module description that is used for GUI generation already. ::
     ...                        format='percent', overwrite=True)
 
 
-It is possible to create a run-able module object and run later:
+It is possible to create a run-able module object and run it later (this
+is also needed for registering GRASS GIS commands with more than one dot
+in their name, e.g. r.slope.aspect):
 
     >>> slope_aspect = Module("r.slope.aspect", elevation='elevation',
     ...                        slope='slp',  aspect='asp',
@@ -61,7 +64,8 @@ Create the module object input step by step and run later: ::
 
 
 
-It is possible to access the module info with:
+It is possible to access the module descriptions (name, one line description,
+keywords, label) with:
 
     >>> slope_aspect.name
     'r.slope.aspect'
@@ -130,13 +134,13 @@ and get the module documentation with: ::
 
 
 
-For each inputs and outputs parameters it is possible to get info, to see all
-the module inputs, just type: ::
+For each input and output parameter it is possible to obtain specific
+information. To see all module inputs, just type: ::
 
     >>> slope_aspect.inputs #doctest: +NORMALIZE_WHITESPACE
     TypeDict([('elevation', Parameter <elevation> (required:yes, type:raster, multiple:no)), ('format', Parameter <format> (required:no, type:string, multiple:no)), ('prec', Parameter <prec> (required:no, type:string, multiple:no)), ('zfactor', Parameter <zfactor> (required:no, type:float, multiple:no)), ('min_slp_allowed', Parameter <min_slp_allowed> (required:no, type:float, multiple:no))])
 
-To get info for each parameter: ::
+To get information for each parameter: ::
 
     >>> slope_aspect.inputs["elevation"].description
     'Name of input elevation raster map'
@@ -156,13 +160,13 @@ Or get a small documentation for each parameter with:
         Name of input elevation raster map
 
 
-User or developer can check which parameter are set, with: ::
+User or developer can check which parameters have been set, with: ::
 
     if slope_aspect.outputs['aspect'].value == None:
         print "Aspect is not computed"
 
 
-After we set the parameter and run the module, the execution of the module
+After we set the parameters and run the module, the execution of the module
 instantiate a popen attribute to the class. The `Popen`_ class allow user
 to kill/wait/ the process. ::
 

+ 25 - 0
lib/python/pygrass/docs/modules_grid.rst

@@ -0,0 +1,25 @@
+GridModule for raster multiprocessing
+=====================================
+
+The GridModule class permits to work with raster data and all the 
+processor cores of your computer. It divides the input data into the 
+number of choosen rows and columns and after it patches the results 
+together to obtain only one output map.
+
+.. automodule:: pygrass.modules.grid.grid
+    :members:
+
+Functions
+------------
+
+Split
+^^^^^^^^
+
+.. automodule:: pygrass.modules.grid.split
+    :members:
+
+Patch
+^^^^^^^^
+
+.. automodule:: pygrass.modules.grid.patch
+    :members:

+ 11 - 147
lib/python/pygrass/docs/raster.rst

@@ -1,7 +1,9 @@
 .. _raster-label:
 
-Raster
-======
+Introduction to Raster classes
+==============================
+
+Details about the architecture can be found in the `GRASS GIS 7 Programmer's Manual: GRASS Raster Library <http://grass.osgeo.org/programming7/rasterlib.html>`_
 
 PyGRASS uses 4 different Raster classes, that respect the 4 different approaches
 of GRASS-C API.
@@ -58,102 +60,6 @@ We can rename the map: ::
     >>> print(new)
     new
 
-
-
-
-.. _RasterCategory-label:
-
-Categories
-----------
-
-All the raster classes support raster categories and share commons methods
-to modify the raster category.
-It is possible to check if the map has or not the categories with the
-``has_cats`` method. ::
-
-    >>> elev.has_cats()
-    False
-
-Opening a map that has category, for example the "landcove_1m" raster map
-from the North Carolina mapset. The ``has_cats`` method return True. ::
-
-    >>> land = raster.RasterRow('landcover_1m')
-    >>> land.has_cats()
-    True
-
-Get and set the categories title, with: ::
-
-    >>> land.cats_title
-    'Rural area: Landcover'
-    >>> land.cats_title = 'Rural area: Landcover2'
-    >>> land.cats_title
-    'Rural area: Landcover2'
-    >>> land.cats_title = 'Rural area: Landcover'
-
-Get the number of categories of the map with: ::
-
-    >>> land.num_cats()
-    11
-
-See all the categories with: ::
-
-    >>> land.cats
-    [('pond', 1, None),
-     ('forest', 2, None),
-     ('developed', 3, None),
-     ('bare', 4, None),
-     ('paved road', 5, None),
-     ('dirt road', 6, None),
-     ('vineyard', 7, None),
-     ('agriculture', 8, None),
-     ('wetland', 9, None),
-     ('bare ground path', 10, None),
-     ('grass', 11, None)]
-
-Access a single category, using Rast_get_ith_cat(), with: ::
-
-    >>> land.cats[0]
-    ('pond', 1, None)
-    >>> land.cats['pond']
-    ('pond', 1, None)
-    >>> land.get_cat(0)
-    ('pond', 1, None)
-    >>> land.get_cat('pond')
-    ('pond', 1, None)
-
-Add new or change existing categories: ::
-
-    >>> land.set_cat('label', 1)
-    >>> land.get_cat('label')
-    ('label', 1, None)
-    >>> land.set_cat('pond', 1, 1)
-
-
-Sort categories, with: ::
-
-    >>> land.sort_cats()
-
-
-Copy categories from another raster map with: ::
-
-    >>> land.copy_cats(elev)
-
-Read and Write: ::
-
-    >>> land.read_cats()
-    >>> #land.write_cats()
-
-Get a Category object or set from a Category object: ::
-
-    >>> cats = land.get_cats()
-    >>> land.set_cats(cats)
-
-Export and import from a file: ::
-
-    >>> land.write_cats_rules('land_rules.csv', ';')
-    >>> land.read_cats_rules('land_rules.csv', ';')
-
-
 .. _RasterRow-label:
 
 RastRow
@@ -210,6 +116,8 @@ time you are writing a new map, the row is add to the file as the last row. ::
     >>> new.exist()
     False
 
+.. autoclass:: pygrass.raster.RasterRow
+    :members:
 
 .. _RasterRowIO-label:
 
@@ -233,7 +141,8 @@ for reading and use the default row write access as in the RasterRow class. ::
     [ 144.99488831  145.22894287  145.57142639]
     >>> elev.close()
 
-
+.. autoclass:: pygrass.raster.RasterRowIO
+    :members:
 
 .. _RasterSegment-label:
 
@@ -302,7 +211,8 @@ to write a single value to the map. ::
     >>> elev.close()
     >>> elev.remove()
 
-
+.. autoclass:: pygrass.raster.RasterSegment
+    :members:
 
 .. _RasterNumpy-label:
 
@@ -342,55 +252,9 @@ to load all the map in memory. ::
     True
     >>> el.remove()
 
-
-
-.. _Buffer-label:
-
-Buffer
-------
-
-The buffer class is used to interact with a memory buffer of a map like a
-raster row. The buffer class is based on the `numpy.ndarray`_ class. Therefore
-all the nice feature of the ndarray are allowed.
-
-.. autoclass:: pygrass.raster.buffer.Buffer
-    :members:
-
-.. _numpy.ndarray: http://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.html
-
-
-.. _RowIO-label:
-
-RowIO
-------
-
-.. autoclass:: pygrass.raster.rowio.RowIO
-    :members:
-
-.. _Segment-label:
-
-Segment
--------
-
-.. autoclass:: pygrass.raster.segment.Segment
+.. autoclass:: pygrass.raster.RasterNumpy
     :members:
 
-.. _History-label:
-
-History
---------
-
-.. autoclass:: pygrass.raster.history.History
-    :members:
-
-
-.. _Category-label:
-
-Category
---------
-
-.. autoclass:: pygrass.raster.category.Category
-    :members:
 
 .. _Raster library: http://grass.osgeo.org/programming7/rasterlib.html
 .. _RowIO library: http://grass.osgeo.org/programming7/rowiolib.html

+ 136 - 0
lib/python/pygrass/docs/raster_elements.rst

@@ -0,0 +1,136 @@
+Raster elements
+=================
+
+.. _RasterCategory-label:
+
+Categories
+----------
+
+All the raster classes support raster categories and share commons methods
+to modify the raster category.
+It is possible to check if the map has or not the categories with the
+``has_cats`` method. ::
+
+    >>> elev.has_cats()
+    False
+
+Opening a map that has category, for example the "landcove_1m" raster map
+from the North Carolina mapset. The ``has_cats`` method return True. ::
+
+    >>> land = raster.RasterRow('landcover_1m')
+    >>> land.has_cats()
+    True
+
+Get and set the categories title, with: ::
+
+    >>> land.cats_title
+    'Rural area: Landcover'
+    >>> land.cats_title = 'Rural area: Landcover2'
+    >>> land.cats_title
+    'Rural area: Landcover2'
+    >>> land.cats_title = 'Rural area: Landcover'
+
+Get the number of categories of the map with: ::
+
+    >>> land.num_cats()
+    11
+
+See all the categories with: ::
+
+    >>> land.cats
+    [('pond', 1, None),
+     ('forest', 2, None),
+     ('developed', 3, None),
+     ('bare', 4, None),
+     ('paved road', 5, None),
+     ('dirt road', 6, None),
+     ('vineyard', 7, None),
+     ('agriculture', 8, None),
+     ('wetland', 9, None),
+     ('bare ground path', 10, None),
+     ('grass', 11, None)]
+
+Access a single category, using Rast_get_ith_cat(), with: ::
+
+    >>> land.cats[0]
+    ('pond', 1, None)
+    >>> land.cats['pond']
+    ('pond', 1, None)
+    >>> land.get_cat(0)
+    ('pond', 1, None)
+    >>> land.get_cat('pond')
+    ('pond', 1, None)
+
+Add new or change existing categories: ::
+
+    >>> land.set_cat('label', 1)
+    >>> land.get_cat('label')
+    ('label', 1, None)
+    >>> land.set_cat('pond', 1, 1)
+
+
+Sort categories, with: ::
+
+    >>> land.sort_cats()
+
+
+Copy categories from another raster map with: ::
+
+    >>> land.copy_cats(elev)
+
+Read and Write: ::
+
+    >>> land.read_cats()
+    >>> #land.write_cats()
+
+Get a Category object or set from a Category object: ::
+
+    >>> cats = land.get_cats()
+    >>> land.set_cats(cats)
+
+Export and import from a file: ::
+
+    >>> land.write_cats_rules('land_rules.csv', ';')
+    >>> land.read_cats_rules('land_rules.csv', ';')
+
+.. autoclass:: pygrass.raster.category.Category
+    :members:
+
+.. _Buffer-label:
+
+Buffer
+------
+
+The buffer class is used to interact with a memory buffer of a map like a
+raster row. The buffer class is based on the `numpy.ndarray`_ class. Therefore
+all the nice feature of the ndarray are allowed.
+
+.. autoclass:: pygrass.raster.buffer.Buffer
+    :members:
+
+.. _numpy.ndarray: http://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.html
+
+
+.. _RowIO-label:
+
+RowIO
+------
+
+.. autoclass:: pygrass.raster.rowio.RowIO
+    :members:
+
+.. _Segment-label:
+
+Segment
+-------
+
+.. autoclass:: pygrass.raster.segment.Segment
+    :members:
+
+.. _History-label:
+
+History
+--------
+
+.. autoclass:: pygrass.raster.history.History
+    :members:

+ 9 - 74
lib/python/pygrass/docs/vector.rst

@@ -1,6 +1,10 @@
+.. _vector-label:
+
+Introduction to Vector classes
+==============================
+
+Details about the architecture can be found in the `GRASS GIS 7 Programmer's Manual: GRASS Vector Library <http://grass.osgeo.org/programming7/vectorlib.html>`_
 
-Vector
-========
 
 Instantiation and basic interaction. ::
 
@@ -114,11 +118,6 @@ Now, find an area with an island inside... ::
     Bbox(199947.296494, 199280.969494, 754920.623987, 754351.812986)
 
 
-VectorTopo
-----------
-
-.. autoclass:: pygrass.vector.VectorTopo
-    :members:
 
 Vector
 ----------
@@ -126,72 +125,8 @@ Vector
 .. autoclass:: pygrass.vector.Vector
     :members:
 
+VectorTopo
+----------
 
-Vector Features
-===============
-
-Point
-------
-
-.. autoclass:: pygrass.vector.geometry.Point
-    :members:
-
-
-Line
------
-
-.. autoclass:: pygrass.vector.geometry.Line
-    :members:
-
-Boundary
---------
-
-.. autoclass:: pygrass.vector.geometry.Boundary
-    :members:
-
-Isle
------
-
-.. autoclass:: pygrass.vector.geometry.Isle
-    :members:
-
-
-Isles
------
-
-.. autoclass:: pygrass.vector.geometry.Isles
-    :members:
-
-Area
---------
-
-.. autoclass:: pygrass.vector.geometry.Boundary
-    :members:
-
-Utils
-=====
-
-Bbox
-----
-
-.. autoclass:: pygrass.vector.basic.Bbox
-    :members:
-
-
-BoxList
---------
-
-.. autoclass:: pygrass.vector.basic.BoxList
-    :members:
-
-Ilist
------
-
-.. autoclass:: pygrass.vector.basic.Ilist
+.. autoclass:: pygrass.vector.VectorTopo
     :members:
-
-Cats
------
-
-.. autoclass:: pygrass.vector.basic.Cats
-    :members:

+ 21 - 15
lib/python/pygrass/docs/attributes.rst

@@ -1,5 +1,5 @@
-Attributes
-===========
+Vector Attributes
+===================
 
 It is possible to access the vector attributes with: ::
 
@@ -106,33 +106,39 @@ a new cursor object and interact with the database. ::
     >>> conn.close()
 
 
+DBlinks
+---------
+
+.. autoclass:: pygrass.vector.table.DBlinks
+    :members:
 
 Link
--------
+---------
 
 .. autoclass:: pygrass.vector.table.Link
     :members:
 
-DBlinks
--------
+Table
+---------
 
-.. autoclass:: pygrass.vector.table.DBlinks
+.. autoclass:: pygrass.vector.table.Table
     :members:
 
-Filters
--------
+Columns
+---------
 
-.. autoclass:: pygrass.vector.table.Filters
+.. autoclass:: pygrass.vector.table.Columns
     :members:
 
-Columns
--------
+Filters
+---------
 
-.. autoclass:: pygrass.vector.table.Columns
+.. autoclass:: pygrass.vector.table.Filters
     :members:
 
-Table
------
+SQL
+---------
 
-.. autoclass:: pygrass.vector.table.Table
+.. automodule:: pygrass.vector.sql
     :members:
+

+ 41 - 0
lib/python/pygrass/docs/vector_features.rst

@@ -0,0 +1,41 @@
+Vector Features
+===============
+
+Point
+------
+
+.. autoclass:: pygrass.vector.geometry.Point
+    :members:
+
+
+Line
+-----
+
+.. autoclass:: pygrass.vector.geometry.Line
+    :members:
+
+Boundary
+--------
+
+.. autoclass:: pygrass.vector.geometry.Boundary
+    :members:
+
+Isle
+-----
+
+.. autoclass:: pygrass.vector.geometry.Isle
+    :members:
+
+
+Isles
+-----
+
+.. autoclass:: pygrass.vector.geometry.Isles
+    :members:
+
+Area
+--------
+
+.. autoclass:: pygrass.vector.geometry.Area
+    :members:
+

+ 27 - 0
lib/python/pygrass/docs/vector_utils.rst

@@ -0,0 +1,27 @@
+Vector Utils
+===============
+
+Bbox
+----
+
+.. autoclass:: pygrass.vector.basic.Bbox
+    :members:
+
+
+BoxList
+--------
+
+.. autoclass:: pygrass.vector.basic.BoxList
+    :members:
+
+Ilist
+-----
+
+.. autoclass:: pygrass.vector.basic.Ilist
+    :members:
+
+Cats
+-----
+
+.. autoclass:: pygrass.vector.basic.Cats
+    :members:

+ 77 - 26
lib/python/pygrass/gis/__init__.py

@@ -9,26 +9,12 @@ import shutil
 import ctypes as ct
 import fnmatch
 
-from grass import script
-#from grass.script import setup
-#
-#
-#GISBASE = "/home/pietro/docdat/src/gis/grass/grass70/dist.x86_64-unknown-linux-gnu"
-#LOCATION = "nc_basic_spm_grass7'"
-#GISDBASE = "/home/pietro/docdat/gis"
-#MAPSET = "sqlite"
-#GUI = "wxpython"
-#
-#setup.init(GISBASE, GISDBASE, LOCATION, MAPSET)
-script.gisenv()
 
 import grass.lib.gis as libgis
 from grass.pygrass.functions import getenv
 from grass.pygrass.errors import GrassError
 
 
-#write dec to check if user have permissions or not
-
 ETYPE = {'rast': libgis.G_ELEMENT_RASTER,
          'rast3d': libgis.G_ELEMENT_RASTER3D,
          'vect': libgis.G_ELEMENT_VECTOR,
@@ -56,10 +42,12 @@ def _check(value, path, type):
         return getenv(type)
     else:
         raise GrassError("%s <%s> not found" % (type.title(),
-                                                 join(path, value)))
+                                                join(path, value)))
 
 
 def set_current_mapset(mapset, location=None, gisdbase=None):
+    """Set the current mapset as working area
+    """
     libgis.G_setenv('MAPSET', mapset)
     if location:
         libgis.G_setenv('LOCATION_NAME', location)
@@ -68,6 +56,7 @@ def set_current_mapset(mapset, location=None, gisdbase=None):
 
 
 def make_mapset(mapset, location=None, gisdbase=None):
+    """Create a new mapset"""
     res = libgis.G_make_mapset(gisdbase, location, mapset)
     if res == -1:
         raise GrassError("Cannot create new mapset")
@@ -83,6 +72,7 @@ class Gisdbase(object):
         >>> gisdbase.name == gisenv()['GISDBASE']
         True
 
+    ..
     """
     def __init__(self, gisdbase=''):
         self.name = gisdbase
@@ -93,7 +83,8 @@ class Gisdbase(object):
     def _set_name(self, name):
         self._name = _check(name, '', "GISDBASE")
 
-    name = property(fget=_get_name, fset=_set_name)
+    name = property(fget=_get_name, fset=_set_name,
+                    doc="Set or obtain the name of GISDBASE")
 
     def __str__(self):
         return self.name
@@ -122,6 +113,7 @@ class Gisdbase(object):
         for loc in self.locations():
             yield Location(loc, self.name)
 
+    # TODO remove or complete this function
     def new_location(self):
         if libgis.G__make_location() != 0:
             raise GrassError("Cannot create new location")
@@ -154,6 +146,8 @@ class Location(object):
         True
         >>> location.name == gisenv()['LOCATION_NAME']
         True
+
+    ..
     """
     def __init__(self, location='', gisdbase=''):
         self.gisdbase = gisdbase
@@ -165,7 +159,8 @@ class Location(object):
     def _set_gisdb(self, gisdb):
         self._gisdb = _check(gisdb, '', "GISDBASE")
 
-    gisdbase = property(fget=_get_gisdb, fset=_set_gisdb)
+    gisdbase = property(fget=_get_gisdb, fset=_set_gisdb,
+                        doc="Set or obtain the name of GISDBASE")
 
     def _get_name(self):
         return self._name
@@ -173,7 +168,8 @@ class Location(object):
     def _set_name(self, name):
         self._name = _check(name, self._gisdb, "LOCATION_NAME")
 
-    name = property(fget=_get_name, fset=_set_name)
+    name = property(fget=_get_name, fset=_set_name,
+                    doc="Set or obtain the name of LOCATION")
 
     def __getitem__(self, mapset):
         if mapset in self.mapsets():
@@ -196,11 +192,20 @@ class Location(object):
         return 'Location(%r)' % self.name
 
     def mapsets(self, pattern=None, permissions=True):
-        """Return a list of the available mapsets. ::
+        """Return a list of the available mapsets.
+
+        :param pattern: the pattern to filter the result
+        :type pattern: str
+        :param permissions: check the permission of mapset
+        :type permissions: bool
+        :returns:  a list of mapset's names
+
+        ::
 
             >>> location = Location()
             >>> location.mapsets()
             ['PERMANENT', 'user1']
+        ..
         """
         mapsets = [mapset for mapset in self]
         if permissions:
@@ -226,6 +231,8 @@ class Mapset(object):
         'nc_basic_spm_grass7'
         >>> mapset.name
         'user1'
+
+    ..
     """
     def __init__(self, mapset='', location='', gisdbase=''):
         self.gisdbase = gisdbase
@@ -239,7 +246,8 @@ class Mapset(object):
     def _set_gisdb(self, gisdb):
         self._gisdb = _check(gisdb, '', "GISDBASE")
 
-    gisdbase = property(fget=_get_gisdb, fset=_set_gisdb)
+    gisdbase = property(fget=_get_gisdb, fset=_set_gisdb,
+                        doc="Set or obtain the name of GISDBASE")
 
     def _get_loc(self):
         return self._loc
@@ -247,7 +255,8 @@ class Mapset(object):
     def _set_loc(self, loc):
         self._loc = _check(loc, self._gisdb, "LOCATION_NAME")
 
-    location = property(fget=_get_loc, fset=_set_loc)
+    location = property(fget=_get_loc, fset=_set_loc,
+                        doc="Set or obtain the name of LOCATION")
 
     def _get_name(self):
         return self._name
@@ -255,7 +264,8 @@ class Mapset(object):
     def _set_name(self, name):
         self._name = _check(name, join(self._gisdb, self._loc), "MAPSET")
 
-    name = property(fget=_get_name, fset=_set_name)
+    name = property(fget=_get_name, fset=_set_name,
+                    doc="Set or obtain the name of MAPSET")
 
     def __str__(self):
         return self.name
@@ -279,6 +289,11 @@ class Mapset(object):
             * 'vect',
             * 'view3d'
 
+        :param type: the type of element to query
+        :type type: str
+        :param pattern: the pattern to filter the result
+        :type pattern: str
+
         ::
 
             >>> mapset = Mapset('PERMANENT')
@@ -288,6 +303,8 @@ class Mapset(object):
             ['basins', 'elevation', ...]
             >>> mapset.glist('rast', pattern='el*')
             ['elevation_shade', 'elevation']
+
+        ..
         """
         if type not in ETYPE:
             str_err = "Type %s is not valid, valid types are: %s."
@@ -305,6 +322,7 @@ class Mapset(object):
                 return elist
 
     def is_current(self):
+        """Check if the MAPSET is the working MAPSET"""
         return (self.name == libgis.G_getenv('MAPSET') and
                 self.location == libgis.G_getenv('LOCATION_NAME') and
                 self.gisdbase == libgis.G_getenv('GISDBASE'))
@@ -324,6 +342,14 @@ class Mapset(object):
 
 
 class VisibleMapset(object):
+    """VisibleMapset object::
+
+        >>> mapset = VisibleMapset('user1')
+        >>> mapset
+        ['user1', 'PERMANENT']
+
+    ..
+    """
     def __init__(self, mapset, location='', gisdbase=''):
         self.mapset = mapset
         self.location = Location(location, gisdbase)
@@ -338,21 +364,31 @@ class VisibleMapset(object):
             yield mapset
 
     def read(self):
+        """Return the mapsets in the search path"""
         with open(self.spath, "a+") as f:
             lines = f.readlines()
-            #lines.remove('')
             if lines:
                 return [l.strip() for l in lines]
         lns = ['PERMANENT', ]
         self.write(lns)
         return lns
 
-    def write(self, mapsets):
+    def _write(self, mapsets):
+        """Write to SEARCH_PATH file the changes in the search path
+
+        :param mapsets: a list of mapset's names
+        :type mapsets: list
+        """
         with open(self.spath, "w+") as f:
             ms = self.location.mapsets()
             f.write('%s' % '\n'.join([m for m in mapsets if m in ms]))
 
     def add(self, mapset):
+        """Add a mapset to the search path
+
+        :param mapset: a mapset's name
+        :type mapset: str
+        """
         if mapset not in self.read() and mapset in self.location:
             with open(self.spath, "a+") as f:
                 f.write('\n%s' % mapset)
@@ -360,12 +396,27 @@ class VisibleMapset(object):
             raise TypeError('Mapset not found')
 
     def remove(self, mapset):
+        """Remove mapset to the search path
+
+        :param mapset: a mapset's name
+        :type mapset: str
+        """
         mapsets = self.read()
         mapsets.remove(mapset)
-        self.write(mapsets)
+        self._write(mapsets)
 
     def extend(self, mapsets):
+        """Add more mapsets to the search path
+
+        :param mapsets: a list of mapset's names
+        :type mapsets: list
+        """
         ms = self.location.mapsets()
         final = self.read()
         final.extend([m for m in mapsets if m in ms and m not in final])
-        self.write(final)
+        self._write(final)
+
+    def reset(self):
+        """Reset to the original search path"""
+        final = [self.mapset, 'PERMANENT']
+        self._write(final)

+ 81 - 44
lib/python/pygrass/gis/region.py

@@ -15,34 +15,37 @@ from grass.pygrass.shell.conversion import dict2html
 
 
 class Region(object):
+    """
+    ::
+
+        >>> default = Region(default=True)
+        >>> current_good = Region()
+        >>> current = Region()
+        >>> current.align('elevation')
+        >>> default == current
+        True
+        >>> current.cols
+        1500
+        >>> current.ewres
+        10.0
+        >>> current.cols = 3000
+        >>> current.ewres
+        5.0
+        >>> current.ewres = 20.0
+        >>> current.cols
+        750
+        >>> current.set_current()
+        >>> default == current
+        False
+        >>> current.get_default()
+        >>> default = Region(default=True)
+        >>> default == current
+        True
+        >>> current_good.set_current()
+
+    ..
+    """
     def __init__(self, default=False):
-        """::
-
-            >>> default = Region(default=True)
-            >>> current_good = Region()
-            >>> current = Region()
-            >>> current.align('elevation')
-            >>> default == current
-            True
-            >>> current.cols
-            1500
-            >>> current.ewres
-            10.0
-            >>> current.cols = 3000
-            >>> current.ewres
-            5.0
-            >>> current.ewres = 20.0
-            >>> current.cols
-            750
-            >>> current.set_current()
-            >>> default == current
-            False
-            >>> current.get_default()
-            >>> default = Region(default=True)
-            >>> default == current
-            True
-            >>> current_good.set_current()
-        """
         self.c_region = ctypes.pointer(libgis.Cell_head())
         if default:
             self.get_default()
@@ -61,7 +64,8 @@ class Region(object):
         """Private function to set north value"""
         self.c_region.contents.north = value
 
-    north = property(fget=_get_n, fset=_set_n)
+    north = property(fget=_get_n, fset=_set_n,
+                     doc="Set and obtain north coordinate")
 
     def _get_s(self):
         """Private function to obtain south value"""
@@ -71,7 +75,8 @@ class Region(object):
         """Private function to set south value"""
         self.c_region.contents.south = value
 
-    south = property(fget=_get_s, fset=_set_s)
+    south = property(fget=_get_s, fset=_set_s,
+                     doc="Set and obtain south coordinate")
 
     def _get_e(self):
         """Private function to obtain east value"""
@@ -81,7 +86,8 @@ class Region(object):
         """Private function to set east value"""
         self.c_region.contents.east = value
 
-    east = property(fget=_get_e, fset=_set_e)
+    east = property(fget=_get_e, fset=_set_e,
+                    doc="Set and obtain east coordinate")
 
     def _get_w(self):
         """Private function to obtain west value"""
@@ -91,7 +97,8 @@ class Region(object):
         """Private function to set west value"""
         self.c_region.contents.west = value
 
-    west = property(fget=_get_w, fset=_set_w)
+    west = property(fget=_get_w, fset=_set_w,
+                    doc="Set and obtain west coordinate")
 
     def _get_t(self):
         """Private function to obtain top value"""
@@ -101,7 +108,8 @@ class Region(object):
         """Private function to set top value"""
         self.c_region.contents.top = value
 
-    top = property(fget=_get_t, fset=_set_t)
+    top = property(fget=_get_t, fset=_set_t,
+                   doc="Set and obtain top value")
 
     def _get_b(self):
         """Private function to obtain bottom value"""
@@ -111,7 +119,8 @@ class Region(object):
         """Private function to set bottom value"""
         self.c_region.contents.bottom = value
 
-    bottom = property(fget=_get_b, fset=_set_b)
+    bottom = property(fget=_get_b, fset=_set_b,
+                      doc="Set and obtain bottom value")
 
     #----------RESOLUTION----------
     def _get_rows(self):
@@ -123,7 +132,8 @@ class Region(object):
         self.c_region.contents.rows = value
         self.adjust(rows=True)
 
-    rows = property(fget=_get_rows, fset=_set_rows)
+    rows = property(fget=_get_rows, fset=_set_rows,
+                    doc="Set and obtain number of rows")
 
     def _get_cols(self):
         """Private function to obtain columns value"""
@@ -134,7 +144,8 @@ class Region(object):
         self.c_region.contents.cols = value
         self.adjust(cols=True)
 
-    cols = property(fget=_get_cols, fset=_set_cols)
+    cols = property(fget=_get_cols, fset=_set_cols,
+                    doc="Set and obtain number of columns")
 
     def _get_nsres(self):
         """Private function to obtain north-south value"""
@@ -145,7 +156,8 @@ class Region(object):
         self.c_region.contents.ns_res = value
         self.adjust()
 
-    nsres = property(fget=_get_nsres, fset=_set_nsres)
+    nsres = property(fget=_get_nsres, fset=_set_nsres,
+                     doc="Set and obtain north-south resolution value")
 
     def _get_ewres(self):
         """Private function to obtain east-west value"""
@@ -156,7 +168,8 @@ class Region(object):
         self.c_region.contents.ew_res = value
         self.adjust()
 
-    ewres = property(fget=_get_ewres, fset=_set_ewres)
+    ewres = property(fget=_get_ewres, fset=_set_ewres,
+                     doc="Set and obtain east-west resolution value")
 
     def _get_tbres(self):
         """Private function to obtain top-botton 3D value"""
@@ -167,7 +180,8 @@ class Region(object):
         self.c_region.contents.tb_res = value
         self.adjust()
 
-    tbres = property(fget=_get_tbres, fset=_set_tbres)
+    tbres = property(fget=_get_tbres, fset=_set_tbres,
+                     doc="Set and obtain top-bottom 3D value")
 
     @property
     def zone(self):
@@ -228,12 +242,20 @@ class Region(object):
 
     #----------METHODS----------
     def zoom(self, raster_name):
-        """Shrink region until it meets non-NULL data from this raster map:"""
+        """Shrink region until it meets non-NULL data from this raster map
+
+        :param raster_name: the name of raster
+        :type raster_name: str
+        """
         self._set_param('zoom', str(raster_name))
         self.get_current()
 
     def align(self, raster_name):
-        """Adjust region cells to cleanly align with this raster map"""
+        """Adjust region cells to cleanly align with this raster map
+
+        :param raster_name: the name of raster
+        :type raster_name: str
+        """
         self._set_param('align', str(raster_name))
         self.get_current()
 
@@ -245,13 +267,20 @@ class Region(object):
         libgis.G_adjust_Cell_head(self.c_region, bool(rows), bool(cols))
 
     def vect(self, vector_name):
-        """Adjust bounding box of region using a vector ::
+        """Adjust bounding box of region using a vector
+
+        :param vector_name: the name of vector
+        :type vector_name: str
+
+        ::
 
         >>> reg = Region()
         >>> reg.vect('census')
         >>> reg.get_bbox()
         Bbox(230963.640878, 212125.562878, 645837.437393, 628769.374393)
         >>> reg.get_default()
+
+        ..
         """
         from grass.pygrass.vector import VectorTopo
         vect = VectorTopo(vector_name)
@@ -289,6 +318,8 @@ class Region(object):
         >>> reg = Region()
         >>> reg.get_bbox()
         Bbox(228500.0, 215000.0, 645000.0, 630000.0)
+
+        ..
         """
         from grass.pygrass.vector.basic import Bbox
         return Bbox(north=self.north, south=self.south,
@@ -296,16 +327,22 @@ class Region(object):
                     top=self.top, bottom=self.bottom)
 
     def set_bbox(self, bbox):
-        """Set region from Bbox ::
+        """Set region extent from Bbox
+
+        :param bbox: a Bbox object to set the extent
+        :type bbox: Bbox object
+
+        ::
 
         >>> from grass.pygrass.vector.basic import Bbox
-        >>> b = Bbox(230963.640878, 212125.562878,
-        ...          645837.437393, 628769.374393)
+        >>> b = Bbox(230963.640878, 212125.562878, 645837.437393, 628769.374393)
         >>> reg = Region()
         >>> reg.set_bbox(b)
         >>> reg.get_bbox()
         Bbox(230963.640878, 212125.562878, 645837.437393, 628769.374393)
         >>> reg.get_current()
+
+        ..
         """
         self.north = bbox.north
         self.south = bbox.south

+ 72 - 42
lib/python/pygrass/messages/__init__.py

@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-"""!@package grass.pygrass.massages
+"""@package grass.pygrass.massages
 
 @brief PyGRASS message interface
 
@@ -19,7 +19,7 @@ from multiprocessing import Process, Lock, Pipe
 
 
 class FatalError(Exception):
-    """!This error will be raised in case raise_on_error was set True
+    """This error will be raised in case raise_on_error was set True
        when creating the messenger object.
     """
     def __init__(self, msg):
@@ -30,11 +30,12 @@ class FatalError(Exception):
 
 
 def message_server(lock, conn):
-    """!The GRASS message server function designed to be a target for
+    """The GRASS message server function designed to be a target for
        multiprocessing.Process
 
-       @param lock A multiprocessing.Lock
-       @param conn A multiprocessing.Pipe
+
+       :param lock: A multiprocessing.Lock
+       :param conn: A multiprocessing.Pipe
 
        This function will use the G_* message C-functions from grass.lib.gis
        to provide an interface to the GRASS C-library messaging system.
@@ -59,9 +60,11 @@ def message_server(lock, conn):
                       testing purpose
 
        The that is end through the pipe must be a list of values:
+
        - Messages: ["INFO|VERBOSE|WARNING|ERROR|FATAL", "MESSAGE"]
-       - Debug: ["DEBUG", level, "MESSAGE"]
-       - Percent: ["PERCENT", n, d, s]
+       - Debug:    ["DEBUG", level, "MESSAGE"]
+       - Percent:  ["PERCENT", n, d, s]
+
     """
     libgis.G_debug(1, "Start messenger server")
 
@@ -110,7 +113,7 @@ def message_server(lock, conn):
 
 
 class Messenger(object):
-    """!Fast and exit-safe interface to GRASS C-library message functions
+    """Fast and exit-safe interface to GRASS C-library message functions
 
        This class implements a fast and exit-safe interface to the GRASS
        C-library message functions like: G_message(), G_warning(),
@@ -128,7 +131,6 @@ class Messenger(object):
 
        Usage:
 
-       @code
        >>> msgr = Messenger()
        >>> msgr.debug(0, "debug 0")
        >>> msgr.verbose("verbose message")
@@ -137,7 +139,6 @@ class Messenger(object):
        >>> msgr.percent(1, 1, 1)
        >>> msgr.warning("Ohh")
        >>> msgr.error("Ohh no")
-
        D0/0: debug 0
        message
        important message
@@ -175,7 +176,6 @@ class Messenger(object):
            raise FatalError(message)
        FatalError: Ohh no no no!
 
-       @endcode
     """
     def __init__(self, raise_on_error=False):
         self.client_conn = None
@@ -188,6 +188,8 @@ class Messenger(object):
         self.stop()
 
     def start_server(self):
+        """Start the messenger server and open the pipe
+        """
         self.client_conn, self.server_conn = Pipe()
         self.lock = Lock()
         self.server = Process(target=message_server, args=(self.lock,
@@ -196,7 +198,7 @@ class Messenger(object):
         self.server.start()
 
     def _check_restart_server(self):
-        """!Restart the server if it was terminated
+        """Restart the server if it was terminated
         """
         if self.server.is_alive() is True:
             return
@@ -206,7 +208,10 @@ class Messenger(object):
         self.warning("Needed to restart the messenger server")
 
     def message(self, message):
-        """!Send a message to stderr
+        """Send a message to stderr
+
+        :param message: the text of message
+        :type message: str
 
            G_message() will be called in the messenger server process
         """
@@ -214,7 +219,10 @@ class Messenger(object):
         self.client_conn.send(["INFO", message])
 
     def verbose(self, message):
-        """!Send a verbose message to stderr
+        """Send a verbose message to stderr
+
+        :param message: the text of message
+        :type message: str
 
            G_verbose_message() will be called in the messenger server process
         """
@@ -222,7 +230,10 @@ class Messenger(object):
         self.client_conn.send(["VERBOSE", message])
 
     def important(self, message):
-        """!Send an important message to stderr
+        """Send an important message to stderr
+
+        :param message: the text of message
+        :type message: str
 
            G_important_message() will be called in the messenger server process
         """
@@ -230,7 +241,10 @@ class Messenger(object):
         self.client_conn.send(["IMPORTANT", message])
 
     def warning(self, message):
-        """!Send a warning message to stderr
+        """Send a warning message to stderr
+
+        :param message: the text of message
+        :type message: str
 
            G_warning() will be called in the messenger server process
         """
@@ -238,7 +252,10 @@ class Messenger(object):
         self.client_conn.send(["WARNING", message])
 
     def error(self, message):
-        """!Send an error message to stderr
+        """Send an error message to stderr
+
+        :param message: the text of message
+        :type message: str
 
            G_important_message() with an additional "ERROR:" string at
            the start will be called in the messenger server process
@@ -247,7 +264,10 @@ class Messenger(object):
         self.client_conn.send(["ERROR", message])
 
     def fatal(self, message):
-        """!Send an error message to stderr, call sys.exit(1) or raise FatalError
+        """Send an error message to stderr, call sys.exit(1) or raise FatalError
+
+        :param message: the text of message
+        :type message: str
 
            This function emulates the behavior of G_fatal_error(). It prints
            an error message to stderr and calls sys.exit(1). If raise_on_error
@@ -264,7 +284,10 @@ class Messenger(object):
             sys.exit(1)
 
     def debug(self, level, message):
-        """!Send a debug message to stderr
+        """Send a debug message to stderr
+
+        :param message: the text of message
+        :type message: str
 
            G_debug() will be called in the messenger server process
         """
@@ -272,7 +295,11 @@ class Messenger(object):
         self.client_conn.send(["DEBUG", level, message])
 
     def percent(self, n, d, s):
-        """!Send a percentage to stderr
+        """Send a percentage to stderr
+
+        :param message: the text of message
+        :type message: str
+
 
            G_percent() will be called in the messenger server process
         """
@@ -280,7 +307,7 @@ class Messenger(object):
         self.client_conn.send(["PERCENT", n, d, s])
 
     def stop(self):
-        """!Stop the messenger server and close the pipe
+        """Stop the messenger server and close the pipe
         """
         if self.server is not None and self.server.is_alive():
             self.client_conn.send(["STOP", ])
@@ -290,26 +317,30 @@ class Messenger(object):
             self.client_conn.close()
 
     def set_raise_on_error(self, raise_on_error=True):
-        """!Set the fatal error behavior
+        """Set the fatal error behavior
+
+           :param raise_on_error: if True a FatalError exception will be
+                                  raised instead of calling sys.exit(1)
+           :type raise_on_error: bool
 
-           - If raise_on_error == True, a FatalError exception will be raised if fatal() is called
-           - If raise_on_error == False, sys.exit(1) will be invoked if fatal() is called
+           - If raise_on_error == True, a FatalError exception will be raised
+             if fatal() is called
+           - If raise_on_error == False, sys.exit(1) will be invoked if
+             fatal() is called
 
-           @param raise_on_error If True a FatalError exception will be raised instead
-                 of calling sys.exit(1)
         """
         self.raise_on_error = raise_on_error
 
     def get_raise_on_error(self):
-        """!Get the fatal error behavior
+        """Get the fatal error behavior
 
-           @return True if a FatalError exception will be raised
-                   or False if sys.exit(1) will be called in case of invoking fatal()
+           :returns: True if a FatalError exception will be raised or False if
+                     sys.exit(1) will be called in case of invoking fatal()
         """
         return self.raise_on_error
 
     def test_fatal_error(self, message):
-        """!Force the messenger server to call G_fatal_error()
+        """Force the messenger server to call G_fatal_error()
         """
         import time
         self._check_restart_server()
@@ -318,18 +349,17 @@ class Messenger(object):
 
 
 def get_msgr(_instance=[None, ], *args, **kwargs):
-    """!Return a Messenger instance.
-
-    @return the Messenger instance.
-    @code ::
-
-        >>> msgr0 = get_msgr()
-        >>> msgr1 = get_msgr()
-        >>> msgr2 = Messenger()
-        >>> msgr0 is msgr1
-        True
-        >>> msgr0 is msgr2
-        False
+    """Return a Messenger instance.
+
+       :returns: the Messenger instance.
+
+    >>> msgr0 = get_msgr()
+    >>> msgr1 = get_msgr()
+    >>> msgr2 = Messenger()
+    >>> msgr0 is msgr1
+    True
+    >>> msgr0 is msgr2
+    False
     """
     if not _instance[0]:
         _instance[0] = Messenger(*args, **kwargs)

+ 164 - 234
lib/python/pygrass/modules/grid/grid.py

@@ -25,36 +25,21 @@ from grass.pygrass.modules.grid.patch import rpatch_map
 def select(parms, ptype):
     """Select only a  certain type of parameters.
 
-    Parameters
-    ----------
-
-    params : DictType parameters
-        A DictType parameter with inputs or outputs of a Module class.
-    ptype : string
-        String define the type of parameter that we want to select,
-        valid ptype are: 'raster', 'vector', 'group'
-
-
-    Returns
-    -------
-
-    An iterator with the value of the parameter.
-
-
-    Examples
-    --------
-
-    ::
-
-        >>> slp = Module('r.slope.aspect',
-        ...              elevation='ele', slope='slp', aspect='asp',
-        ...              run_=False)
-        >>> for rast in select(slp.outputs, 'raster'):
-        ...     print rast
-        ...
-        slp
-        asp
-
+    :param parms: a DictType parameter with inputs or outputs of a Module class
+    :type parms: DictType parameters
+    :param ptype: String define the type of parameter that we want to select,
+                  valid ptype are: 'raster', 'vector', 'group'
+    :type ptype: str
+    :returns: An iterator with the value of the parameter.
+
+    >>> slp = Module('r.slope.aspect',
+    ...              elevation='ele', slope='slp', aspect='asp',
+    ...              run_=False)
+    >>> for rast in select(slp.outputs, 'raster'):
+    ...     print rast
+    ...
+    slp
+    asp
     """
     for k in parms:
         par = parms[k]
@@ -68,7 +53,13 @@ def select(parms, ptype):
 
 def copy_special_mapset_files(path_src, path_dst):
     """Copy all the special GRASS files that are contained in
-    a mapset to another mapset."""
+    a mapset to another mapset
+
+    :param path_src: the path to the original mapset
+    :type path_src: str
+    :param path_dst: the path to the new mapset
+    :type path_dst: str
+    """
     for fil in (fi for fi in os.listdir(path_src) if fi.isupper()):
         sht.copy(os.path.join(path_src, fil), path_dst)
 
@@ -76,42 +67,29 @@ def copy_special_mapset_files(path_src, path_dst):
 def copy_mapset(mapset, path):
     """Copy mapset to another place without copying raster and vector data.
 
-    Parameters
-    ----------
-
-    mapset : mapset_like
-        A Mapset instance.
-    path : string
-        Path where the new mapset must be copied.
-
-
-    Returns
-    -------
-
-    The instance of the new Mapset.
-
-
-    Examples
-    --------
-
-    ::
-
-        >>> mset = Mapset()
-        >>> mset.name
-        'user1'
-        >>> import tempfile as tmp
-        >>> import os
-        >>> path = os.path.join(tmp.gettempdir(), 'my_loc', 'my_mset')
-        >>> copy_mapset(mset, path)
-        Mapset('user1')
-        >>> sorted(os.listdir(path))
-        [u'PERMANENT', u'user1']
-        >>> sorted(os.listdir(os.path.join(path, 'PERMANENT')))
-        [u'DEFAULT_WIND', u'PROJ_INFO', u'PROJ_UNITS', u'VAR', u'WIND']
-        >>> sorted(os.listdir(os.path.join(path, 'user1')))
-        [u'CURGROUP', u'SEARCH_PATH', u'VAR', u'WIND']
-        >>> import shutil
-        >>> shutil.rmtree(path)
+    :param mapset: a Mapset instance to copy
+    :type mapset: Mapset object
+    :param path: path where the new mapset must be copied
+    :type path: str
+    :returns: the instance of the new Mapset.
+
+
+    >>> mset = Mapset()
+    >>> mset.name
+    'user1'
+    >>> import tempfile as tmp
+    >>> import os
+    >>> path = os.path.join(tmp.gettempdir(), 'my_loc', 'my_mset')
+    >>> copy_mapset(mset, path)
+    Mapset('user1')
+    >>> sorted(os.listdir(path))
+    [u'PERMANENT', u'user1']
+    >>> sorted(os.listdir(os.path.join(path, 'PERMANENT')))
+    [u'DEFAULT_WIND', u'PROJ_INFO', u'PROJ_UNITS', u'VAR', u'WIND']
+    >>> sorted(os.listdir(os.path.join(path, 'user1')))
+    [u'CURGROUP', u'SEARCH_PATH', u'VAR', u'WIND']
+    >>> import shutil
+    >>> shutil.rmtree(path)
 
     """
     per_old = os.path.join(mapset.gisdbase, mapset.location, 'PERMANENT')
@@ -132,14 +110,13 @@ def read_gisrc(gisrc):
     """Read a GISRC file and return a tuple with the mapset, location
     and gisdbase.
 
-    Examples
-    --------
-
-    ::
+    :param gisrc: the path to GISRC file
+    :type gisrc: str
+    :returns: a tuple with the mapset, location and gisdbase
 
-        >>> import os
-        >>> read_gisrc(os.environ['GISRC'])  # doctest: +ELLIPSIS
-        (u'user1', ...)
+    >>> import os
+    >>> read_gisrc(os.environ['GISRC'])  # doctest: +ELLIPSIS
+    (u'user1', ...)
     """
     with open(gisrc, 'r') as gfile:
         gis = dict([(k.strip(), v.strip())
@@ -150,18 +127,11 @@ def read_gisrc(gisrc):
 def get_mapset(gisrc_src, gisrc_dst):
     """Get mapset from a GISRC source to a GISRC destination.
 
-    Parameters
-    ----------
-
-    gisrc_src : path to the GISRC source
-
-    gisrc_dst : path to the GISRC destination
-
-
-    Returns
-    -------
-
-    A tuple with Mapset(src), Mapset(dst)
+    :param gisrc_src: path to the GISRC source
+    :type gisrc_src: str
+    :param gisrc_dst: path to the GISRC destination
+    :type gisrc_dst: str
+    :returns: a tuple with Mapset(src), Mapset(dst)
 
     """
     msrc, lsrc, gsrc = read_gisrc(gisrc_src)
@@ -180,27 +150,20 @@ def get_mapset(gisrc_src, gisrc_dst):
 
 
 def copy_groups(groups, gisrc_src, gisrc_dst, region=None):
-    """Copy group from one mapset to another, crop the raster to the region.
-
-    Parameters
-    ----------
-
-    groups : list of strings
-        A list of strings with the group that must be copied
-        from a master to another.
-    gisrc_src : path to the GISRC source
-        Path of the GISRC file from where we want to copy the groups.
-    gisrc_dst : path to the GISRC destination
-        Path of the GISRC file where the groups will be created.
-    region : region_like or dictionary
-        A region like object or a dictionary with the region parameters that
-        will be used to crop the rasters of the groups.
-
-
-    Returns
-    -------
-
-    None.
+    """Copy group from one mapset to another, crop the raster to the region
+
+    :param groups: a list of strings with the group that must be copied
+                   from a master to another.
+    :type groups: list of strings
+    :param gisrc_src: path of the GISRC file from where we want to copy the groups
+    :type gisrc_src: str
+    :param gisrc_dst: path of the GISRC file where the groups will be created
+    :type gisrc_dst: str
+    :param region: a region like object or a dictionary with the region
+                   parameters that will be used to crop the rasters of the
+                   groups
+    :type region: Region object or dictionary
+    :returns: None
 
     """
     env = os.environ.copy()
@@ -233,24 +196,17 @@ def copy_groups(groups, gisrc_src, gisrc_dst, region=None):
 def set_region(region, gisrc_src, gisrc_dst, env):
     """Set a region into two different mapsets.
 
-    Parameters
-    ----------
-
-    region : region_like or dictionary
-        A region like object or a dictionary with the region parameters that
-        will be used to crop the rasters.
-    gisrc_src : path to the GISRC source
-        Path of the GISRC file from where we want to copy the rasters.
-    gisrc_dst : path to the GISRC destination
-        Path of the GISRC file where the rasters will be created.
-    region : dictionary
-        A dictionary with the variable environment to use.
-
-
-    Returns
-    -------
-
-    None.
+    :param region: a region like object or a dictionary with the region
+                   parameters that will be used to crop the rasters of the
+                   groups
+    :type region: Region object or dictionary
+    :param gisrc_src: path of the GISRC file from where we want to copy the groups
+    :type gisrc_src: str
+    :param gisrc_dst: path of the GISRC file where the groups will be created
+    :type gisrc_dst: str
+    :param env:
+    :type env:
+    :returns: None
     """
     reg_str = "g.region n=%(north)r s=%(south)r " \
               "e=%(east)r w=%(west)r " \
@@ -265,25 +221,18 @@ def set_region(region, gisrc_src, gisrc_dst, env):
 def copy_rasters(rasters, gisrc_src, gisrc_dst, region=None):
     """Copy rasters from one mapset to another, crop the raster to the region.
 
-    Parameters
-    ----------
-
-    rasters : list of strings
-        A list of strings with the raster map that must be copied
-        from a master to another.
-    gisrc_src : path to the GISRC source
-        Path of the GISRC file from where we want to copy the rasters.
-    gisrc_dst : path to the GISRC destination
-        Path of the GISRC file where the rasters will be created.
-    region : region_like or dictionary
-        A region like object or a dictionary with the region parameters that
-        will be used to crop the rasters.
-
-
-    Returns
-    -------
-
-    None.
+    :param rasters: a list of strings with the raster map that must be copied
+                    from a master to another.
+    :type rasters: list
+    :param gisrc_src: path of the GISRC file from where we want to copy the groups
+    :type gisrc_src: str
+    :param gisrc_dst: path of the GISRC file where the groups will be created
+    :type gisrc_dst: str
+    :param region: a region like object or a dictionary with the region
+                   parameters that will be used to crop the rasters of the
+                   groups
+    :type region: Region object or dictionary
+    :returns: None
     """
     env = os.environ.copy()
     if region:
@@ -316,21 +265,14 @@ def copy_rasters(rasters, gisrc_src, gisrc_dst, region=None):
 def copy_vectors(vectors, gisrc_src, gisrc_dst):
     """Copy vectors from one mapset to another, crop the raster to the region.
 
-    Parameters
-    ----------
-
-    vectors : list of strings
-        A list of strings with the raster map that must be copied
-        from a master to another.
-    gisrc_src : path to the GISRC source
-        Path of the GISRC file from where we want to copy the vectors.
-    gisrc_dst : path to the GISRC destination
-        Path of the GISRC file where the vectors will be created.
-
-    Returns
-    -------
-
-    None.
+    :param vectors: a list of strings with the vector map that must be copied
+                    from a master to another.
+    :type vectors: list
+    :param gisrc_src: path of the GISRC file from where we want to copy the groups
+    :type gisrc_src: str
+    :param gisrc_dst: path of the GISRC file where the groups will be created
+    :type gisrc_dst: str
+    :returns: None
     """
     env = os.environ.copy()
     path_dst = os.path.join(*read_gisrc(gisrc_dst))
@@ -359,23 +301,14 @@ def get_cmd(cmdd):
     pickle a Module class and cnvert into a string that can be used with
     `Popen(get_cmd(cmdd), shell=True)`.
 
-    Parameters
-    ----------
-
-    cmdd : dict
-        A module dictionary with all the parameters.
-
-    Examples
-    --------
-
-    ::
-
-        >>> slp = Module('r.slope.aspect',
-        ...              elevation='ele', slope='slp', aspect='asp',
-        ...              overwrite=True, run_=False)
-        >>> get_cmd(slp.get_dict())  # doctest: +ELLIPSIS
-        ['r.slope.aspect', 'elevation=ele', 'format=degrees', ..., '--o']
+    :param cmdd: a module dictionary with all the parameters
+    :type cmdd: dict
 
+    >>> slp = Module('r.slope.aspect',
+    ...              elevation='ele', slope='slp', aspect='asp',
+    ...              overwrite=True, run_=False)
+    >>> get_cmd(slp.get_dict())  # doctest: +ELLIPSIS
+    ['r.slope.aspect', 'elevation=ele', 'format=degrees', ..., '--o']
     """
     cmd = [cmdd['name'], ]
     cmd.extend(("%s=%s" % (k, v) for k, v in cmdd['inputs']
@@ -396,30 +329,23 @@ def get_cmd(cmdd):
 def cmd_exe(args):
     """Create a mapset, and execute a cmd inside.
 
-    Parameters
-    ----------
-
-    `args` is a tuple that contains:
-
-     bbox : dict
-        A dict with the region parameters (n, s, e, w, etc.)
-        that we want to set before to apply the command.
-    mapnames : dict
-        A dictionary to substitute the input if the domain has
-        been splitted in several tiles.
-    gisrc_src : path to the GISRC source
-        Path of the GISRC file from where we want to copy the groups.
-    gisrc_dst : path to the GISRC destination
-        Path of the GISRC file where the groups will be created.
-    cmd : dictionary
-        A dictionary with all the parameter of a GRASS module.
-    groups: list
-        A list of strings with the groups that we want to copy in the mapset.
-
-    Returns
-    -------
-
-    None.
+    :param args: is a tuple that contains several information see below
+    :type args: tuple
+    :returns: None
+
+    The puple has to contain:
+
+    - bbox (dict): a dict with the region parameters (n, s, e, w, etc.)
+      that we want to set before to apply the command.
+    - mapnames (dict): a dictionary to substitute the input if the domain has
+      been splitted in several tiles.
+    - gisrc_src (str): path of the GISRC file from where we want to copy the
+      groups.
+    - gisrc_dst (str): path of the GISRC file where the groups will be created.
+    - cmd (dict): a dictionary with all the parameter of a GRASS module.
+    - groups (list): a list of strings with the groups that we want to copy in
+      the mapset.
+
     """
     bbox, mapnames, gisrc_src, gisrc_dst, cmd, groups = args
     src, dst = get_mapset(gisrc_src, gisrc_dst)
@@ -447,39 +373,32 @@ def cmd_exe(args):
 
 
 class GridModule(object):
-    """Run GRASS raster commands in a multiproccessing mode.
-
-    Parameters
-    -----------
-
-    cmd: raster GRASS command
-        Only command staring with r.* are valid.
-    width: integer
-        Width of the tile, in pixel.
-    height: integer
-        Height of the tile, in pixel.
-    overlap: integer
-        Overlap between tiles, in pixel.
-    processes: number of threads
-        Default value is equal to the number of processor available.
-    split: boolean
-        If True use r.tile to split all the inputs.
-    run_: boolean
-        If False only instantiate the object.
-    args and kargs: cmd parameters
-        Give all the parameters to the command.
-
-    Examples
-    --------
-
-    ::
-
-        >>> grd = GridModule('r.slope.aspect',
-        ...                  width=500, height=500, overlap=2,
-        ...                  processes=None, split=False,
-        ...                  elevation='elevation',
-        ...                  slope='slope', aspect='aspect', overwrite=True)
-        >>> grd.run()
+    # TODO maybe also i.* could be supported easily
+    """Run GRASS raster commands in a multiprocessing mode.
+
+    :param cmd: raster GRASS command, only command staring with r.* are valid.
+    :type cmd: str
+    :param width: width of the tile, in pixel
+    :type width: int
+    :param height: height of the tile, in pixel.
+    :type height: int
+    :param overlap: overlap between tiles, in pixel.
+    :type overlap: int
+    :param processes: number of threads, default value is equal to the number
+                      of processor available.
+    :param split: if True use r.tile to split all the inputs.
+    :type split: bool
+    :param run_: if False only instantiate the object
+    :type run_: bool
+    :param args: give all the parameters to the command
+    :param kargs: give all the parameters to the command 
+
+    >>> grd = GridModule('r.slope.aspect',
+    ...                  width=500, height=500, overlap=2,
+    ...                  processes=None, split=False,
+    ...                  elevation='elevation',
+    ...                  slope='slope', aspect='aspect', overwrite=True)
+    >>> grd.run()
     """
     def __init__(self, cmd, width=None, height=None, overlap=0, processes=None,
                  split=False, debug=False, region=None, move=None, log=False,
@@ -531,7 +450,11 @@ class GridModule(object):
             os.remove(self.gisrc_dst)
 
     def clean_location(self, location=None):
-        """Remove all created mapsets."""
+        """Remove all created mapsets.
+
+        :param location: a Location instance where we are running the analysis
+        :type location: Location object
+        """
         if location is None:
             if self.n_mset:
                 self.n_mset.current()
@@ -599,7 +522,14 @@ class GridModule(object):
                     inm.value = inm.value + '@%s' % mset
 
     def run(self, patch=True, clean=True):
-        """Run the GRASS command."""
+        """Run the GRASS command
+
+        :param patch: set False if you does not want to patch the results
+        :type patch: bool
+        :param clean: set False if you does not want to remove all the stuff
+                      created by GridModule
+        :type clean: bool
+        """
         self.module.flags.overwrite = True
         self.define_mapset_inputs()
         if self.debug:

+ 33 - 2
lib/python/pygrass/modules/grid/patch.py

@@ -14,6 +14,10 @@ from grass.pygrass.functions import coor2pixel
 def get_start_end_index(bbox_list):
     """Convert a Bounding Box to a list of the index of
     column start, end, row start and end
+
+    :param bbox_list: a list of BBox object to convert
+    :type bbox_list: list of BBox object
+
     """
     ss_list = []
     reg = Region()
@@ -25,7 +29,15 @@ def get_start_end_index(bbox_list):
 
 
 def rpatch_row(rast, rasts, bboxes):
-    """Patch a row of bound boxes."""
+    """Patch a row of bound boxes.
+
+    :param rast: a Raster object to write
+    :type rast: Raster object
+    :param rasts: a list of Raster object to read
+    :type rasts: list of Raster object
+    :param bboxes: a list of BBox object
+    :type bboxes: list of BBox object
+    """
     sei = get_start_end_index(bboxes)
     # instantiate two buffer
     buff = rasts[0][0]
@@ -41,7 +53,26 @@ def rpatch_row(rast, rasts, bboxes):
 
 def rpatch_map(raster, mapset, mset_str, bbox_list, overwrite=False,
                start_row=0, start_col=0, prefix=''):
-    """Patch raster using a bounding box list to trim the raster."""
+    # TODO is prefix useful??
+    """Patch raster using a bounding box list to trim the raster.
+
+    :param raster: the name of output raster
+    :type raster: str
+    :param mapset: the name of mapset to use
+    :type mapset: str
+    :param mset_str:
+    :type mset_str: str
+    :param bbox_list: a list of BBox object to convert
+    :type bbox_list: list of BBox object
+    :param overwrite: overwrite existing raster
+    :type overwrite: bool
+    :param start_row: the starting row of original raster
+    :type start_row: int
+    :param start_col: the starting column of original raster
+    :type start_col: int
+    :param prefix: the prefix of output raster
+    :type prefix: str
+    """
     # Instantiate the RasterRow input objects
     rast = RasterRow(prefix + raster, mapset)
     rtype = RasterRow(name=raster, mapset=mset_str % (0, 0))

+ 51 - 37
lib/python/pygrass/modules/grid/split.py

@@ -11,7 +11,21 @@ from grass.pygrass.vector.basic import Bbox
 
 
 def get_bbox(reg, row, col, width, height, overlap):
-    """Return a Bbox"""
+    """Return a Bbox
+
+    :param reg: a Region object to split
+    :type reg: Region object
+    :param row: the number of row
+    :type row: int
+    :param col: the number of row
+    :type col: int
+    :param width: the width of tiles
+    :type width: int
+    :param height: the width of tiles
+    :type height: int
+    :param overlap: the value of overlap between tiles
+    :type overlap: int
+    """
     north = reg.north - (row * height - overlap) * reg.nsres
     south = reg.north - ((row + 1) * height + overlap) * reg.nsres
     east = reg.west + ((col + 1) * width + overlap) * reg.ewres
@@ -23,25 +37,34 @@ def get_bbox(reg, row, col, width, height, overlap):
 
 
 def split_region_tiles(region=None, width=100, height=100, overlap=0):
-    """Spit a region into a list of Bbox. ::
+    """Spit a region into a list of Bbox.
+
+    :param region: a Region object to split
+    :type region: Region object
+    :param width: the width of tiles
+    :type width: int
+    :param height: the width of tiles
+    :type height: int
+    :param overlap: the value of overlap between tiles
+    :type overlap: int
 
-        >>> reg = Region()
-        >>> reg.north = 1350
-        >>> reg.south = 0
-        >>> reg.nsres = 1
-        >>> reg.east = 1500
-        >>> reg.west = 0
-        >>> reg.ewres = 1
-        >>> reg.cols
-        1500
-        >>> reg.rows
-        1350
-        >>> split_region_tiles(region=reg, width=1000, height=700, overlap=0) # doctest: +NORMALIZE_WHITESPACE
-        [[Bbox(1350.0, 650.0, 1000.0, 0.0), Bbox(1350.0, 650.0, 1500.0, 1000.0)],
-         [Bbox(650.0, 0.0, 1000.0, 0.0), Bbox(650.0, 0.0, 1500.0, 1000.0)]]
-        >>> split_region_tiles(region=reg, width=1000, height=700, overlap=10) # doctest: +NORMALIZE_WHITESPACE
-        [[Bbox(1350.0, 640.0, 1010.0, 0.0), Bbox(1350.0, 640.0, 1500.0, 990.0)],
-         [Bbox(660.0, 0.0, 1010.0, 0.0), Bbox(660.0, 0.0, 1500.0, 990.0)]]
+    >>> reg = Region()
+    >>> reg.north = 1350
+    >>> reg.south = 0
+    >>> reg.nsres = 1
+    >>> reg.east = 1500
+    >>> reg.west = 0
+    >>> reg.ewres = 1
+    >>> reg.cols
+    1500
+    >>> reg.rows
+    1350
+    >>> split_region_tiles(region=reg, width=1000, height=700, overlap=0) # doctest: +NORMALIZE_WHITESPACE
+    [[Bbox(1350.0, 650.0, 1000.0, 0.0), Bbox(1350.0, 650.0, 1500.0, 1000.0)],
+     [Bbox(650.0, 0.0, 1000.0, 0.0), Bbox(650.0, 0.0, 1500.0, 1000.0)]]
+    >>> split_region_tiles(region=reg, width=1000, height=700, overlap=10) # doctest: +NORMALIZE_WHITESPACE
+    [[Bbox(1350.0, 640.0, 1010.0, 0.0), Bbox(1350.0, 640.0, 1500.0, 990.0)],
+     [Bbox(660.0, 0.0, 1010.0, 0.0), Bbox(660.0, 0.0, 1500.0, 990.0)]]
     """
     reg = region if region else Region()
     ncols = (reg.cols + width - 1) // width
@@ -58,25 +81,16 @@ def split_region_tiles(region=None, width=100, height=100, overlap=0):
 
 
 def get_overlap_region_tiles(region=None, width=100, height=100, overlap=0):
-    """Get the Bbox ov the overlapped region. ::
+    """Get the Bbox of the overlapped region. 
 
-        >>> reg = Region()
-        >>> reg.north = 1350
-        >>> reg.south = 0
-        >>> reg.nsres = 1
-        >>> reg.east = 1500
-        >>> reg.west = 0
-        >>> reg.ewres = 1
-        >>> reg.cols
-        1500
-        >>> reg.rows
-        1350
-        >>> split_region_tiles(region=reg, width=1000, height=700, overlap=0) # doctest: +NORMALIZE_WHITESPACE
-        [[Bbox(1350.0, 650.0, 1000.0, 0.0), Bbox(1350.0, 650.0, 1500.0, 1000.0)],
-         [Bbox(650.0, 0.0, 1000.0, 0.0), Bbox(650.0, 0.0, 1500.0, 1000.0)]]
-        >>> split_region_tiles(region=reg, width=1000, height=700, overlap=10) # doctest: +NORMALIZE_WHITESPACE
-        [[Bbox(1350.0, 640.0, 1010.0, 0.0), Bbox(1350.0, 640.0, 1500.0, 990.0)],
-         [Bbox(660.0, 0.0, 1010.0, 0.0), Bbox(660.0, 0.0, 1500.0, 990.0)]]
+    :param region: a Region object to split
+    :type region: Region object
+    :param width: the width of tiles
+    :type width: int
+    :param height: the width of tiles
+    :type height: int
+    :param overlap: the value of overlap between tiles
+    :type overlap: int
     """
     reg = region if region else Region()
     ncols = (reg.cols + width - 1) // width

+ 7 - 1
lib/python/pygrass/modules/interface/flag.py

@@ -8,8 +8,12 @@ from __future__ import (nested_scopes, generators, division, absolute_import,
                         with_statement, print_function, unicode_literals)
 from grass.pygrass.modules.interface import read
 
-
+# TODO add documentation
 class Flag(object):
+    """The Flag object store all information about a flag of module.
+
+    It is possible to set flags of command using this object.
+    """
     def __init__(self, xflag=None, diz=None):
         self.value = False
         diz = read.element2dict(xflag) if xflag is not None else diz
@@ -21,6 +25,7 @@ class Flag(object):
         self.guisection = diz.get('guisection', None)
 
     def get_bash(self):
+        """Prova"""
         if self.value:
             if self.special:
                 return '--%s' % self.name[0]
@@ -30,6 +35,7 @@ class Flag(object):
             return ''
 
     def get_python(self):
+        """Prova"""
         if self.value:
             if self.special:
                 return '%s=True' % self.name

+ 48 - 44
lib/python/pygrass/modules/interface/module.py

@@ -68,7 +68,7 @@ from grass.pygrass.modules.interface.read import GETFROMTAG, DOC
 
 
 class ParallelModuleQueue(object):
-    """!This class is designed to run an arbitrary number of pygrass Module
+    """This class is designed to run an arbitrary number of pygrass Module
        processes in parallel.
 
        Objects of type grass.pygrass.modules.Module can be put into the
@@ -82,8 +82,6 @@ class ParallelModuleQueue(object):
 
        Usage:
 
-       @code
-
        >>> import copy
        >>> import grass.pygrass.modules as pymod
        >>> mapcalc_list = []
@@ -106,27 +104,27 @@ class ParallelModuleQueue(object):
        0
        0
 
-       @endcode
-
     """
     def __init__(self, max_num_procs=1):
-        """!Constructor
+        """Constructor
 
-           @param max_num_procs The maximum number of Module processes that
-                                can be run in parallel
+        :param max_num_procs: The maximum number of Module processes that
+                              can be run in parallel
+        :type max_num_procs: int
         """
         self._num_procs = int(max_num_procs)
         self._list = int(max_num_procs) * [None]
         self._proc_count = 0
 
     def put(self, module):
-        """!Put the next Module object in the queue
+        """Put the next Module object in the queue
 
            To run the Module objects in parallel the run_ and finish_ options
            of the Module must be set to False.
 
-           @param module A preconfigured Module object with run_ and finish_
-                         set to False
+           :param module: a preconfigured Module object with run_ and finish_
+                          set to False
+           :type module: Module object
         """
         self._list[self._proc_count] = module
         self._list[self._proc_count].run()
@@ -136,38 +134,43 @@ class ParallelModuleQueue(object):
             self.wait()
 
     def get(self, num):
-        """!Get a Module object from the queue
+        """Get a Module object from the queue
 
-           @param num The number of the object in queue
-           @return The Module object or None if num is not in the queue
+           :param num: the number of the object in queue
+           :type num: int
+           :returns: the Module object or None if num is not in the queue
         """
         if num < self._num_procs:
             return self._list[num]
         return None
 
     def get_num_run_procs(self):
-        """!Get the number of Module processes that are in the queue running
+        """Get the number of Module processes that are in the queue running
            or finished
 
-           @return The maximum number fo Module processes running/finished in
-                   the queue
+           :returns: the maximum number fo Module processes running/finished in
+                     the queue
         """
         return len(self._list)
 
     def get_max_num_procs(self):
-        """!Return the maximum number of parallel Module processes
+        """Return the maximum number of parallel Module processes
         """
         return self._num_procs
 
     def set_max_num_procs(self, max_num_procs):
-        """!Set the maximum number of Module processes that should run
-           in parallel
+        """Set the maximum number of Module processes that should run
+        in parallel
+
+        :param max_num_procs: The maximum number of Module processes that
+                              can be run in parallel
+        :type max_num_procs: int   
         """
         self._num_procs = int(max_num_procs)
         self.wait()
 
     def wait(self):
-        """!Wait for all Module processes that are in the list to finish
+        """Wait for all Module processes that are in the list to finish
            and set the modules stdout and stderr output options
         """
         for proc in self._list:
@@ -185,24 +188,22 @@ class ParallelModuleQueue(object):
 
 class Module(object):
     """
-
     Python allow developers to not specify all the arguments and
     keyword arguments of a method or function.
 
-    ::
 
         def f(*args):
             for arg in args:
                 print arg
 
-    therefore if we call the function like: ::
+    therefore if we call the function like:
 
         >>> f('grass', 'gis', 'modules')
         grass
         gis
         modules
 
-    or we can define a new list: ::
+    or we can define a new list:
 
         >>> words = ['grass', 'gis', 'modules']
         >>> f(*words)
@@ -210,7 +211,7 @@ class Module(object):
         gis
         modules
 
-    we can do the same with keyword arguments, rewrite the above function: ::
+    we can do the same with keyword arguments, rewrite the above function:
 
         def f(*args, **kargs):
             for arg in args:
@@ -218,7 +219,7 @@ class Module(object):
             for key, value in kargs.items():
                 print "%s = %r" % (key, value)
 
-    now we can use the new function, with: ::
+    now we can use the new function, with:
 
         >>> f('grass', 'gis', 'modules', os = 'linux', language = 'python')
         grass
@@ -228,7 +229,7 @@ class Module(object):
         language = 'python'
 
     or, as before we can, define a dictionary and give the dictionary to
-    the function, like: ::
+    the function, like:
 
         >>> keywords = {'os' : 'linux', 'language' : 'python'}
         >>> f(*words, **keywords)
@@ -376,11 +377,12 @@ class Module(object):
                     raise ParameterError(msg % k)
             return self.run()
 
-
     def get_bash(self):
+        """Prova"""
         return ' '.join(self.make_cmd())
 
     def get_python(self):
+        """Prova"""
         prefix = self.name.split('.')[0]
         name = '_'.join(self.name.split('.')[1:])
         params = ', '.join([par.get_python() for par in self.params_list
@@ -403,7 +405,7 @@ class Module(object):
             return "%s.%s(%s)" % (prefix, name, params)
 
     def __str__(self):
-        """!Return the command string that can be executed in a shell
+        """Return the command string that can be executed in a shell
         """
         return ' '.join(self.make_cmd())
 
@@ -415,7 +417,7 @@ class Module(object):
         """{cmd_name}({cmd_params})
         """
         head = DOC['head'].format(cmd_name=self.name,
-             cmd_params=('\n' +  # go to a new line
+            cmd_params=('\n' +  # go to a new line
              # give space under the function name
              (' ' * (len(self.name) + 1))).join([', '.join(
              # transform each parameter in string
@@ -427,8 +429,8 @@ class Module(object):
         return '\n'.join([head, params, DOC['flag_head'], flags, DOC['foot']])
 
     def get_dict(self):
-        """!Return a dictionary that includes the name, all valid
-            inputs, outputs and flags
+        """Return a dictionary that includes the name, all valid
+        inputs, outputs and flags
         """
         dic = {}
         dic['name'] = self.name
@@ -440,9 +442,9 @@ class Module(object):
         return dic
 
     def make_cmd(self):
-        """!Create the command string that can be executed in a shell
+        """Create the command string that can be executed in a shell
 
-           @return The command string
+        :returns: the command string
         """
         skip = ['stdin', 'stdout', 'stderr']
         args = [self.name, ]
@@ -458,15 +460,17 @@ class Module(object):
         return args
 
     def run(self, node=None):
-        """!Run the module
-
-           This function will wait for the process to terminate
-           in case finish_==True and sets up stdout and stderr.
-           If finish_==False this function will return after starting
-           the process. Use self.popen.communicate() of self.popen.wait()
-           to wait for the process termination. The handling
-           of stdout and stderr must then be done outside of this
-           function.
+        """Run the module
+
+        :param node:
+        :type node:
+
+        This function will wait for the process to terminate in case
+        finish_==True and sets up stdout and stderr. If finish_==False this
+        function will return after starting the process. Use 
+        self.popen.communicate() of self.popen.wait() to wait for the process
+        termination. The handling of stdout and stderr must then be done
+        outside of this function.
         """
         if self.inputs['stdin'].value:
             self.stdin = self.inputs['stdin'].value

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

@@ -12,8 +12,12 @@ import re
 from grass.pygrass.modules.interface.read import GETTYPE, element2dict, DOC
 
 
+# TODO add documentation
 class Parameter(object):
+    """The Parameter object store all information about a parameter of module.
 
+    It is possible to set parameter of command using this object.
+    """
     def __init__(self, xparameter=None, diz=None):
         self._value = None
         diz = element2dict(xparameter) if xparameter is not None else diz
@@ -79,7 +83,7 @@ class Parameter(object):
         # gisprompt
         #
         if 'gisprompt' in diz:
-            self.typedesc = diz['gisprompt']['prompt']
+            self.typedesc = diz['gisprompt'].get('prompt', '')
             self.input = False if diz['gisprompt']['age'] == 'new' else True
         else:
             self.input = True
@@ -138,9 +142,11 @@ class Parameter(object):
 
     # here the property function is used to transform value in an attribute
     # in this case we define which function must be use to get/set the value
-    value = property(fget=_get_value, fset=_set_value)
+    value = property(fget=_get_value, fset=_set_value,
+                     doc="Set or obtain value")
 
     def get_bash(self):
+        """Prova"""
         if isinstance(self._value, list) or isinstance(self._value, tuple):
             value = ','.join([str(v) for v in self._value])
         else:
@@ -148,6 +154,7 @@ class Parameter(object):
         return """%s=%s""" % (self.name, value)
 
     def get_python(self):
+        """Prova"""
         if not self.value:
             return ''
         return """%s=%r""" % (self.name, self._value)

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

@@ -50,7 +50,7 @@ class MetaModule(object):
         return self.cls('%s.%s' % (self.prefix, name.replace('_', '.')))
 
 
-# http://grass.osgeo.org/grass70/manuals/full_index.html
+# http://grass.osgeo.org/grass71/manuals/full_index.html
 #[ d.* | db.* | g.* | i.* | m.* | ps.* | r.* | r3.* | t.* | v.* ]
 #
 #  d.*	display commands

+ 24 - 7
lib/python/pygrass/pygrasslib.dox

@@ -4,13 +4,14 @@ by GRASS Development Team (http://grass.osgeo.org)
 
 \section pygrassIntro Introduction
 
-PyGRASS improves integration between GRASS and Python (see also \ref
-pythonlib), make the use of Python under GRASS more consistent with
-the language itself and make the GRASS scripting and programming
-activity easier and more natural to the final users.
+PyGRASS improves the integration between GRASS GIS and Python (see 
+also \ref pythonlib), making the use of Python under GRASS more 
+consistent with the language itself. Furthermore, it simplifies 
+GRASS scripting and programming and more natural for the user.
 
 \section pygrassPackages PyGRASS packages 
 
+The following PyGRASS packages are provided:
  - \subpage pygrassGis
  - \subpage pygrassRaster
  - \subpage pygrassVector
@@ -18,19 +19,21 @@ activity easier and more natural to the final users.
  - \subpage pygrassFunctions
  - \subpage pygrassMessages
  - \subpage pygrassErrors
+ 
+ Below these packages are illustrated in greater detail.
 
 \subsection pygrassGis GIS Package
 
  - python::pygrass::gis
 
-Basic elements of GRASS data-base:
+Basic elements of the GRASS data-base:
 
   - python::pygrass::gis::Gisdbase
   - python::pygrass::gis::Location
   - python::pygrass::gis::Mapset
   - python::pygrass::gis::VisibleMapset
 
-Computation region:
+Computational region:
 
   - python::pygrass::gis::region::Region
 
@@ -41,6 +44,16 @@ Mapset handling:
 
 \subsection pygrassRaster Raster Package
 
+PyGRASS uses 4 different Raster classes, that respect the 4 
+different approaches of GRASS-C API. The read access is row wise for 
+RastRow and RasterRowIO and additionally cached in the RowIO class. 
+Both classes write sequentially. RowIO is row cached, RastSegment 
+and RasterNumpy are tile cached for reading and writing therefore a 
+randomly access is possible. Hence RasterRow and RasterRowIO should 
+be used in case for fast (cached) row read access and RasterRow for 
+fast sequential writing. Segment and Numpy should be used for random 
+access, but Numpy only for files not larger than 2GB.
+
  - python::pygrass::raster
 
 Reading/writing raster maps:
@@ -101,7 +114,11 @@ Geometry and topology elements handling:
   - python::pygrass::vector::geometry::Isles
   - python::pygrass::vector::geometry::Area
 
-\subsection pygrassModule Interface to GRASS modules
+Vector attribute handling:
+
+ - python::pygrass::vector::attributes
+
+\subsection pygrassModule Interface to GRASS GIS modules
 
  - python::pygrass::modules
 

+ 85 - 71
lib/python/pygrass/raster/__init__.py

@@ -56,7 +56,6 @@ class RasterRow(RasterAbstractBase):
     Examples
     --------
 
-    ::
         >>> elev = RasterRow('elevation')
         >>> elev.exist()
         True
@@ -91,7 +90,7 @@ class RasterRow(RasterAbstractBase):
 
     Open a raster map using the *with statement*: ::
 
-        >>> with RasterRow('elevation') as elev:   
+        >>> with RasterRow('elevation') as elev:
         ...     for row in elev[:3]:
         ...         row[:4]
         ...
@@ -111,6 +110,11 @@ class RasterRow(RasterAbstractBase):
         """Private method that return the row using the read mode
         call the `Rast_get_row` C function.
 
+        :param row: the number of row to obtain
+        :type row: int
+        :param row_buffer: specify the Buffer object that will be instantiate
+        :type row_buffer: bool
+
         >>> elev = RasterRow('elevation')
         >>> elev.open()
         >>> elev[0]                 # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
@@ -129,22 +133,24 @@ class RasterRow(RasterAbstractBase):
     @must_be_open
     def put_row(self, row):
         """Private method to write the row sequentially.
+
+        :param row: a Row object to insert into raster
+        :type row: Buffer object
         """
         libraster.Rast_put_row(self._fd, row.p, self._gtype)
 
     def open(self, mode=None, mtype=None, overwrite=None):
         """Open the raster if exist or created a new one.
 
-        Parameters
-        ------------
-
-        mode: string
-            Specify if the map will be open with read or write mode ('r', 'w')
-        type: string
-            If a new map is open, specify the type of the map(`CELL`, `FCELL`,
-            `DCELL`)
-        overwrite: Boolean
-            Use this flag to set the overwrite mode of existing raster maps
+        :param mode: Specify if the map will be open with read or write mode
+                     ('r', 'w')
+        :type mode: str
+        :param type: If a new map is open, specify the type of the map(`CELL`,
+                     `FCELL`, `DCELL`)
+        :type type: str
+        :param overwrite: Use this flag to set the overwrite mode of existing
+                          raster maps
+        :type overwrite: bool
 
 
         if the map already exist, automatically check the type and set:
@@ -203,11 +209,24 @@ class RasterRowIO(RasterRow):
         super(RasterRowIO, self).__init__(name, *args, **kargs)
 
     def open(self, mode=None, mtype=None, overwrite=False):
+        """Open the raster if exist or created a new one.
+
+        :param mode: specify if the map will be open with read or write mode
+                     ('r', 'w')
+        :type mode: str
+        :param type: if a new map is open, specify the type of the map(`CELL`,
+                     `FCELL`, `DCELL`)
+        :type type: str
+        :param overwrite: use this flag to set the overwrite mode of existing
+                          raster maps
+        :type overwrite: bool
+        """
         super(RasterRowIO, self).open(mode, mtype, overwrite)
         self.rowio.open(self._fd, self._rows, self._cols, self.mtype)
 
     @must_be_open
     def close(self):
+        """Function to close the raster"""
         self.rowio.release()
         libraster.Rast_close(self._fd)
         # update rows and cols attributes
@@ -222,6 +241,10 @@ class RasterRowIO(RasterRow):
             * the read mode and
             * `rowcache` method
 
+        :param row: the number of row to obtain
+        :type row: int
+        :param row_buffer: Specify the Buffer object that will be instantiate
+        :type row_buffer: Buffer object
         """
         if row_buffer is None:
             row_buffer = Buffer((self._cols,), self.mtype)
@@ -260,7 +283,8 @@ class RasterSegment(RasterAbstractBase):
             raise ValueError(str_err.format(mode))
         self._mode = mode
 
-    mode = property(fget=_get_mode, fset=_set_mode)
+    mode = property(fget=_get_mode, fset=_set_mode,
+                    doc="Set or obtain the opening mode of raster")
 
     def __setitem__(self, key, row):
         """Return the row of Raster object, slice allowed."""
@@ -303,13 +327,10 @@ class RasterSegment(RasterAbstractBase):
     def get_row(self, row, row_buffer=None):
         """Return the row using the `segment.get_row` method
 
-        Parameters
-        ------------
-
-        row: integer
-            Specify the row number;
-        row_buffer: Buffer object, optional
-            Specify the Buffer object that will be instantiate.
+        :param row: specify the row number
+        :type row: int
+        :param row_buffer: specify the Buffer object that will be instantiate
+        :type row_buffer: Buffer object
         """
         if row_buffer is None:
             row_buffer = Buffer((self._cols), self.mtype)
@@ -319,13 +340,8 @@ class RasterSegment(RasterAbstractBase):
     def put_row(self, row, row_buffer):
         """Write the row using the `segment.put_row` method
 
-        Parameters
-        ------------
-
-        row: integer
-            Specify the row number;
-        row_buffer: Buffer object
-            Specify the Buffer object that will be write to the map.
+        :param row: a Row object to insert into raster
+        :type row: Buffer object
         """
         self.segment.put_row(row, row_buffer)
 
@@ -333,13 +349,10 @@ class RasterSegment(RasterAbstractBase):
     def get(self, row, col):
         """Return the map value using the `segment.get` method
 
-        Parameters
-        ------------
-
-        row: integer
-            Specify the row number;
-        col: integer
-            Specify the column number.
+        :param row: Specify the row number
+        :type row: int
+        :param col: Specify the column number
+        :type col: int
         """
         return self.segment.get(row, col)
 
@@ -347,15 +360,12 @@ class RasterSegment(RasterAbstractBase):
     def put(self, row, col, val):
         """Write the value to the map using the `segment.put` method
 
-        Parameters
-        ------------
-
-        row: integer
-            Specify the row number;
-        col: integer
-            Specify the column number.
-        val: value
-            Specify the value that will be write to the map cell.
+        :param row: Specify the row number
+        :type row: int
+        :param col: Specify the column number
+        :type col: int
+        :param val: Specify the value that will be write to the map cell
+        :type val: value
         """
         self.segment.val.value = val
         self.segment.put(row, col)
@@ -365,16 +375,15 @@ class RasterSegment(RasterAbstractBase):
         and copy the map to the segment files;
         else, open a new segment map.
 
-        Parameters
-        ------------
-
-        mode: string, optional
-            Specify if the map will be open with read, write or read/write
-            mode ('r', 'w', 'rw')
-        mtype: string, optional
-            Specify the map type, valid only for new maps: CELL, FCELL, DCELL;
-        overwrite: Boolean, optional
-            Use this flag to set the overwrite mode of existing raster maps
+        :param mode: specify if the map will be open with read, write or
+                     read/write mode ('r', 'w', 'rw')
+        :type mode: str
+        :param mtype: specify the map type, valid only for new maps: CELL,
+                      FCELL, DCELL
+        :type mtype: str
+        :param overwrite: use this flag to set the overwrite mode of existing
+                          raster maps
+        :type overwrite: bool
         """
         # read rows and cols from the active region
         self._rows = libraster.Rast_window_rows()
@@ -433,11 +442,8 @@ class RasterSegment(RasterAbstractBase):
     def close(self, rm_temp_files=True):
         """Close the map, copy the segment files to the map.
 
-        Parameters
-        ------------
-
-        rm_temp_files: bool
-            If True all the segments file will be removed.
+        :param rm_temp_files: if True all the segments file will be removed
+        :type rm_temp_files: bool
         """
         if self.mode == "w" or self.mode == "rw":
             self.segment.flush()
@@ -537,7 +543,8 @@ class RasterNumpy(np.memmap, RasterAbstractBase):
             raise ValueError(_("Mode type: {0} not supported.").format(mode))
         self._mode = mode
 
-    mode = property(fget=_get_mode, fset=_set_mode)
+    mode = property(fget=_get_mode, fset=_set_mode,
+                    doc="Set or obtain the opening mode of raster")
 
     def __array_wrap__(self, out_arr, context=None):
         """See:
@@ -584,10 +591,9 @@ class RasterNumpy(np.memmap, RasterAbstractBase):
                 self[i] = rst.get_row(i, buff)
 
     def _write(self):
+        """Write the numpy array into map
         """
-        r.in.bin input=/home/pietro/docdat/phd/thesis/gis/north_carolina/user1/.tmp/eraclito/14325.0 output=new title='' bytes=1,anull='' --verbose --overwrite north=228500.0 south=215000.0 east=645000.0 west=630000.0 rows=1350 cols=1500
-
-        """
+        #r.in.bin input=/home/pietro/docdat/phd/thesis/gis/north_carolina/user1/.tmp/eraclito/14325.0 output=new title='' bytes=1,anull='' --verbose --overwrite north=228500.0 south=215000.0 east=645000.0 west=630000.0 rows=1350 cols=1500
         if not self.exist() or self.mode != 'r':
             self.flush()
             buff = Buffer(self[0].shape, mtype=self.mtype)
@@ -602,11 +608,14 @@ class RasterNumpy(np.memmap, RasterAbstractBase):
         and copy the map to the segment files;
         else, open a new segment map.
 
-        Parameters
-        ------------
-
-        mtype: string, optional
-            Specify the map type, valid only for new maps: CELL, FCELL, DCELL;
+        :param mtype: specify the map type, valid only for new maps: CELL,
+                      FCELL, DCELL;
+        :type mtype: str
+        :param null:
+        :type null:
+        :param overwrite: use this flag to set the overwrite mode of existing
+                          raster maps
+        :type overwrite: bool
         """
         if overwrite is not None:
             self.overwrite = overwrite
@@ -627,6 +636,11 @@ class RasterNumpy(np.memmap, RasterAbstractBase):
         self._fd = 1
 
     def close(self, name=''):
+        """Function to close the map
+
+        :param name: the name of raster
+        :type name: str        
+        """
         if self.is_open():
             name = name if name else self.name
             if not name:
@@ -639,10 +653,10 @@ class RasterNumpy(np.memmap, RasterAbstractBase):
     def get_value(self, point, region=None):
         """This method returns the pixel value of a given pair of coordinates:
 
-        Parameters
-        ------------
-
-        point = pair of coordinates in tuple object
+        :param point: pair of coordinates in tuple object
+        :type point: tuple
+        :param region: the region to crop the request
+        :type region: Region object
         """
         if not region:
             region = Region()

+ 22 - 6
lib/python/pygrass/raster/category.py

@@ -80,11 +80,12 @@ class Category(list):
     def _set_mtype(self, mtype):
         if mtype.upper() not in ('CELL', 'FCELL', 'DCELL'):
             #fatal(_("Raser type: {0} not supported".format(mtype) ) )
-            raise ValueError(_("Raser type: {0} not supported".format(mtype)))
+            raise ValueError(_("Raster type: {0} not supported".format(mtype)))
         self._mtype = mtype
         self._gtype = RTYPE[self.mtype]['grass type']
 
-    mtype = property(fget=_get_mtype, fset=_set_mtype)
+    mtype = property(fget=_get_mtype, fset=_set_mtype,
+                     doc="Set or obtain raster data type")
 
     def _get_title(self):
         return libraster.Rast_get_cats_title(ctypes.byref(self.c_cats))
@@ -93,7 +94,8 @@ class Category(list):
         return libraster.Rast_set_cats_title(newtitle,
                                              ctypes.byref(self.c_cats))
 
-    title = property(fget=_get_title, fset=_set_title)
+    title = property(fget=_get_title, fset=_set_title,
+                     doc="Set or obtain raster title")
 
     def __str__(self):
         return self.__repr__()
@@ -266,7 +268,11 @@ class Category(list):
         libraster.Rast_write_cats(self.name, ctypes.byref(self.c_cats))
 
     def copy(self, category):
-        """Copy from another Category class"""
+        """Copy from another Category class
+
+        :param category: Category class to be copied
+        :type category: Category object
+        """
         libraster.Rast_copy_cats(ctypes.byref(self.c_cats),     # to
                                  ctypes.byref(category._cats))  # from
         self._read_cats()
@@ -293,7 +299,12 @@ class Category(list):
             0.5:1.0:road
             1.0:1.5:urban
 
-        .."""
+        :param filename: the name of file with categories rules
+        :type filename: str
+        :param sep: the separator used to divide values and category
+        :type sep: str
+        ..
+        """
         self.reset()
         with open(filename, 'r') as f:
             for row in f.readlines():
@@ -320,7 +331,12 @@ class Category(list):
             0.5:1.0:road
             1.0:1.5:urban
 
-        .."""
+        :param filename: the name of file with categories rules
+        :type filename: str
+        :param sep: the separator used to divide values and category
+        :type sep: str
+        ..
+        """
         with open(filename, 'w') as f:
             cats = []
             for cat in self.__iter__():

+ 42 - 35
lib/python/pygrass/raster/history.py

@@ -10,31 +10,29 @@ import datetime
 
 
 class History(object):
-    """
-    *Examples*
-
-    ::
-        >>> import grass.lib.gis as libgis
-        >>> libgis.G_gisinit('')
-        >>> hist = History('elevation')
-        >>> hist.creator
-        'helena'
-        >>> hist.src1
-        ''
-        >>> hist.src2
-        ''
-        >>> hist.keyword
-        'generated by r.proj'
-        >>> hist.date
-        datetime.datetime(2006, 11, 7, 1, 9, 51)
-        >>> hist.mapset
-        'PERMANENT'
-        >>> hist.maptype
-        'raster'
-        >>> hist.title
-        'elev_ned10m'
-
-    ..
+    """History class help to manage all the metadata of a raster map
+
+    >>> import grass.lib.gis as libgis
+    >>> libgis.G_gisinit('')
+    >>> hist = History('elevation')
+    >>> hist.read()
+    >>> hist.creator
+    'helena'
+    >>> hist.src1
+    ''
+    >>> hist.src2
+    ''
+    >>> hist.keyword
+    'generated by r.proj'
+    >>> hist.date
+    datetime.datetime(2006, 11, 7, 1, 9, 51)
+    >>> hist.mapset
+    'PERMANENT'
+    >>> hist.maptype
+    'raster'
+    >>> hist.title
+    'elev_ned10m'
+
     """
     def __init__(self, name, mapset='', mtype='',
                  creator='', src1='', src2='', keyword='',
@@ -76,7 +74,8 @@ class History(object):
                                           libraster.HIST_CREATOR,
                                           ctypes.c_char_p(creator))
 
-    creator = property(fget=_get_creator, fset=_set_creator)
+    creator = property(fget=_get_creator, fset=_set_creator,
+                       doc="Set or obtain the creator of map")
 
     #----------------------------------------------------------------------
     #libraster.HIST_DATSRC_1
@@ -89,7 +88,8 @@ class History(object):
                                           libraster.HIST_DATSRC_1,
                                           ctypes.c_char_p(src1))
 
-    src1 = property(fget=_get_src1, fset=_set_src1)
+    src1 = property(fget=_get_src1, fset=_set_src1,
+                    doc="Set or obtain the first source of map")
 
     #----------------------------------------------------------------------
     #libraster.HIST_DATSRC_2
@@ -102,7 +102,8 @@ class History(object):
                                           libraster.HIST_DATSRC_2,
                                           ctypes.c_char_p(src2))
 
-    src2 = property(fget=_get_src2, fset=_set_src2)
+    src2 = property(fget=_get_src2, fset=_set_src2,
+                    doc="Set or obtain the second source of map")
 
     #----------------------------------------------------------------------
     #libraster.HIST_KEYWORD
@@ -115,7 +116,8 @@ class History(object):
                                           libraster.HIST_KEYWRD,
                                           ctypes.c_char_p(keyword))
 
-    keyword = property(fget=_get_keyword, fset=_set_keyword)
+    keyword = property(fget=_get_keyword, fset=_set_keyword,
+                       doc="Set or obtain the keywords of map")
 
     #----------------------------------------------------------------------
     #libraster.HIST_MAPID
@@ -132,7 +134,8 @@ class History(object):
                                               libraster.HIST_MAPID,
                                               ctypes.c_char_p(date_str))
 
-    date = property(fget=_get_date, fset=_set_date)
+    date = property(fget=_get_date, fset=_set_date,
+                    doc="Set or obtain the date of map")
 
     #----------------------------------------------------------------------
     #libraster.HIST_MAPSET
@@ -145,7 +148,8 @@ class History(object):
                                           libraster.HIST_MAPSET,
                                           ctypes.c_char_p(mapset))
 
-    mapset = property(fget=_get_mapset, fset=_set_mapset)
+    mapset = property(fget=_get_mapset, fset=_set_mapset,
+                      doc="Set or obtain the mapset of map")
 
     #----------------------------------------------------------------------
     #libraster.HIST_MAPTYPE
@@ -158,7 +162,8 @@ class History(object):
                                           libraster.HIST_MAPTYPE,
                                           ctypes.c_char_p(maptype))
 
-    maptype = property(fget=_get_maptype, fset=_set_maptype)
+    maptype = property(fget=_get_maptype, fset=_set_maptype,
+                       doc="Set or obtain the type of map")
 
     #----------------------------------------------------------------------
     #libraster.HIST_NUM_FIELDS
@@ -186,7 +191,8 @@ class History(object):
                                           libraster.HIST_TITLE,
                                           ctypes.c_char_p(title))
 
-    title = property(fget=_get_title, fset=_set_title)
+    title = property(fget=_get_title, fset=_set_title,
+                     doc="Set or obtain the title of map")
 
     def append(self, obj):
         """Rast_append_history"""
@@ -200,7 +206,7 @@ class History(object):
                                              *args)
 
     def clear(self):
-        """Rast_clear_history"""
+        """Clear the history"""
         libraster.Rast_clear_history(self.c_hist)
 
     def command(self):
@@ -224,7 +230,8 @@ class History(object):
                                            ctypes.c_int(line))
 
     def read(self):
-        """Rast_read_history. ::
+        """Read the history of map, users need to use this function to
+        obtain all the information of map. ::
 
             >>> import grass.lib.gis as libgis
             >>> libgis.G_gisinit('')

+ 76 - 53
lib/python/pygrass/vector/__init__.py

@@ -40,7 +40,7 @@ _NUMOF = {"areas": libvect.Vect_get_num_areas,
 #=============================================
 
 class Vector(Info):
-    """ ::
+    """Vector class is the grass vector format without topology
 
         >>> from grass.pygrass.vector import Vector
         >>> cens = Vector('census')
@@ -55,7 +55,6 @@ class Vector(Info):
         >>> cens.overwrite
         False
 
-    ..
     """
     def __init__(self, name, mapset='', *args, **kwargs):
         # Set map name and mapset
@@ -99,10 +98,12 @@ class Vector(Info):
 
         ..
         """
-        return read_next_line(self.c_mapinfo, self.table, self.writable)
+        return read_next_line(self.c_mapinfo, self.table, self.writable,
+                              is2D=not self.is_3D())
 
     @must_be_open
     def rewind(self):
+        """Rewind vector map to cause reads to start at beginning."""
         if libvect.Vect_rewind(self.c_mapinfo) == -1:
             raise GrassError("Vect_rewind raise an error.")
 
@@ -110,21 +111,17 @@ class Vector(Info):
     def write(self, geo_obj, attrs=None, set_cats=True):
         """Write geometry features and attributes.
 
-        Parameters
-        ----------
-
-        geo_obj : geometry GRASS object
-            A geometry grass object define in grass.pygrass.vector.geometry.
-        attrs: list, optional
-            A list with the values that will be insert in the attribute table.
-        set_cats, bool, optional
-            If True, the category of the geometry feature is set using the
-            default layer of the vector map and a progressive category value
-            (default), otherwise the c_cats attribute of the geometry object
-            will be used.
-
-        Examples
-        --------
+        :param geo_obj: a geometry grass object define in
+                        grass.pygrass.vector.geometry
+        :type geo_obj: geometry GRASS object
+        :param attrs: a list with the values that will be insert in the
+                      attribute table.
+        :type attrs: list
+        :param set_cats: if True, the category of the geometry feature is set
+                         using the default layer of the vector map and a
+                         progressive category value (default), otherwise the
+                         c_cats attribute of the geometry object will be used.
+        :type set_cats: bool
 
         Open a new vector map ::
 
@@ -175,7 +172,6 @@ class Vector(Info):
             >>> new.close()
             >>> new.remove()
 
-        ..
         """
         self.n_lines += 1
         if self.table is not None and attrs:
@@ -208,8 +204,6 @@ class Vector(Info):
         """Return if vector has color table associated in file system;
         Color table stored in the vector's attribute table well be not checked
 
-        Examples
-        --------
         >>> cens = Vector('census')
         >>> cens.open()
         >>> cens.has_color_table()
@@ -252,6 +246,7 @@ class VectorTopo(Vector):
         >>> schools.is_open()
         False
 
+    ..
     """
     def __init__(self, name, mapset='', *args, **kwargs):
         super(VectorTopo, self).__init__(name, mapset, *args, **kwargs)
@@ -284,16 +279,20 @@ class VectorTopo(Vector):
 
     @must_be_open
     def num_primitive_of(self, primitive):
-        """Primitive are:
+        """Return the number of primitive
 
-            * "boundary",
-            * "centroid",
-            * "face",
-            * "kernel",
-            * "line",
-            * "point"
-            * "area"
-            * "volume"
+        :param primitive: the name of primitive to query; the supported values are:
+
+                            * *boundary*,
+                            * *centroid*,
+                            * *face*,
+                            * *kernel*,
+                            * *line*,
+                            * *point*
+                            * *area*
+                            * *volume*
+
+        :type primitive: str
 
         ::
 
@@ -316,10 +315,13 @@ class VectorTopo(Vector):
 
     @must_be_open
     def number_of(self, vtype):
-        """
-        vtype in ["areas", "dblinks", "faces", "holes", "islands", "kernels",
-                  "line_points", "lines", "nodes", "update_lines",
-                  "update_nodes", "volumes"]
+        """Return the number of the choosen element type
+
+        :param vtype: the name of type to query; the supported values are:
+                      *areas*, *dblinks*, *faces*, *holes*, *islands*,
+                      *kernels*, *line_points*, *lines*, *nodes*,
+                      *update_lines*, *update_nodes*, *volumes*
+        :type vtype: str
 
             >>> cens = VectorTopo('boundary_municp_sqlite')
             >>> cens.open()
@@ -365,7 +367,15 @@ class VectorTopo(Vector):
     def viter(self, vtype, idonly=False):
         """Return an iterator of vector features
 
-        ::
+        :param vtype: the name of type to query; the supported values are:
+                      *areas*, *dblinks*, *faces*, *holes*, *islands*,
+                      *kernels*, *line_points*, *lines*, *nodes*,
+                      *update_lines*, *update_nodes*, *volumes*
+        :type vtype: str
+        :param idonly: variable to return only the id of features instead of
+                       full features
+        :type idonly: bool
+
             >>> cens = VectorTopo('census')
             >>> cens.open()
             >>> big = [area for area in cens.viter('areas')
@@ -385,7 +395,6 @@ class VectorTopo(Vector):
             Area(2552) 298356117.948
             >>> cens.close()
 
-        ..
         """
         if vtype in _GEOOBJ.keys():
             if _GEOOBJ[vtype] is not None:
@@ -425,16 +434,15 @@ class VectorTopo(Vector):
     def cat(self, cat_id, vtype, layer=None, generator=False, geo=None):
         """Return the geometry features with category == cat_id.
 
-        Parameters
-        ----------
-        cat_id : integer
-            Integer with the category number.
-        vtype : string
-            String of the type of geometry feature that we are looking for.
-        layer : integer, optional
-            Integer of the layer that will be used.
-        generator : bool, optional
-            If True return a generator otherwise it return a list of features.
+        :param cat_id: the category number
+        :type cat_id: int
+        :param vtype: the type of geometry feature that we are looking for
+        :type vtype: str
+        :param layer: the layer number that will be used
+        :type layer: int
+        :param generator: if True return a generator otherwise it return a
+                          list of features
+        :type generator: bool
         """
         if geo is None and vtype not in _GEOOBJ:
             keys = "', '".join(sorted(_GEOOBJ.keys()))
@@ -444,18 +452,25 @@ class VectorTopo(Vector):
         libvect.Vect_cidx_find_all(self.c_mapinfo,
                                    layer if layer else self.layer,
                                    Obj.gtype, cat_id, ilist.c_ilist)
+        is2D = not self.is_3D()
         if generator:
             return (read_line(feature_id=v_id, c_mapinfo=self.c_mapinfo,
-                              table=self.table, writable=self.writable)
+                              table=self.table, writable=self.writable,
+                              is2D=is2D)
                     for v_id in ilist)
         else:
             return [read_line(feature_id=v_id, c_mapinfo=self.c_mapinfo,
-                              table=self.table, writable=self.writable)
+                              table=self.table, writable=self.writable,
+                              is2D=is2D)
                     for v_id in ilist]
 
     @must_be_open
     def read(self, feature_id):
-        """Return a geometry object given the feature id. ::
+        """Return a geometry object given the feature id.
+
+            :param feature_id: the id of feature to obtain
+            :type feature_id: int
+
 
             >>> mun = VectorTopo('boundary_municp_sqlite')
             >>> mun.open()
@@ -480,9 +495,9 @@ class VectorTopo(Vector):
             IndexError: Index out of range
             >>> mun.close()
 
-        ..
         """
-        return read_line(feature_id, self.c_mapinfo, self.table, self.writable)
+        return read_line(feature_id, self.c_mapinfo, self.table, self.writable,
+                         is2D=not self.is_3D())
 
     @must_be_open
     def is_empty(self):
@@ -504,7 +519,9 @@ class VectorTopo(Vector):
             attr = [line, ]
             attr.extend(attrs)
             self.table.update(key=line, values=attr)
-
+        elif self.table is None and attrs:
+            print "Table for vector {name} does not exist, attributes not" \
+                  " loaded".format(name=self.name)
         libvect.Vect_cat_set(geo_obj.c_cats, self.layer, line)
         result = libvect.Vect_rewrite_line(self.c_mapinfo,
                                            line, geo_obj.gtype,
@@ -518,6 +535,11 @@ class VectorTopo(Vector):
 
     @must_be_open
     def delete(self, feature_id):
+        """Remove a feature by its id
+
+        :param feature_id: the id of the feature
+        :type feature_id: int
+        """
         if libvect.Vect_rewrite_line(self.c_mapinfo, feature_id) == -1:
             raise GrassError("C funtion: Vect_rewrite_line.")
 
@@ -541,8 +563,9 @@ class VectorTopo(Vector):
 
     @must_be_open
     def select_by_bbox(self, bbox):
-        """Return the BBox of the vecor map
+        """Return the BBox of the vector map
         """
+        # TODO replace with bbox if bbox else Bbox() ??
         bbox = Bbox()
         if libvect.Vect_get_map_box(self.c_mapinfo, bbox.c_bbox) == 0:
             raise GrassError("I can not find the Bbox.")

+ 72 - 46
lib/python/pygrass/vector/abstract.py

@@ -77,7 +77,7 @@ class Info(object):
         >>> cens.close()
 
     """
-    def __init__(self, name, mapset='', layer=None, mode='r'):
+    def __init__(self, name, mapset='', layer=None, mode='r', with_z=False):
         self._name = ''
         self._mapset = ''
         # Set map name and mapset
@@ -90,6 +90,7 @@ class Info(object):
         self.date_fmt = '%a %b  %d %H:%M:%S %Y'
         self.layer = layer
         self.mode = mode
+        self.with_z = with_z
 
     def __enter__(self, *args, **kwargs):
         self.open(*args, **kwargs)
@@ -111,18 +112,20 @@ class Info(object):
             self.rename(newname)
         self._name = newname
 
-    name = property(fget=_get_name, fset=_set_name)
+    name = property(fget=_get_name, fset=_set_name,
+                    doc="Set or obtain the Vector name")
 
     def _get_mapset(self):
-        """Private method to obtain the Vector name"""
+        """Private method to obtain the Vector mapset"""
         return self._mapset
 
     def _set_mapset(self, mapset):
-        """Private method to change the Vector name"""
+        """Private method to change the Vector mapset"""
         if mapset:
             self._mapset = mapset
 
-    mapset = property(fget=_get_mapset, fset=_set_mapset)
+    mapset = property(fget=_get_mapset, fset=_set_mapset,
+                      doc="Set or obtain the Vector mapset")
 
     def _get_organization(self):
         """Private method to obtain the Vector organization"""
@@ -132,7 +135,8 @@ class Info(object):
         """Private method to change the Vector organization"""
         libvect.Vect_get_organization(self.c_mapinfo, ctypes.c_char_p(org))
 
-    organization = property(fget=_get_organization, fset=_set_organization)
+    organization = property(fget=_get_organization, fset=_set_organization,
+                            doc="Set or obtain the Vector organization")
 
     def _get_date(self):
         """Private method to obtain the Vector date"""
@@ -142,7 +146,8 @@ class Info(object):
         """Private method to change the Vector date"""
         return libvect.Vect_set_date(self.c_mapinfo, ctypes.c_char_p(date))
 
-    date = property(fget=_get_date, fset=_set_date)
+    date = property(fget=_get_date, fset=_set_date,
+                    doc="Set or obtain the Vector date")
 
     def _get_person(self):
         """Private method to obtain the Vector person"""
@@ -152,7 +157,8 @@ class Info(object):
         """Private method to change the Vector person"""
         libvect.Vect_set_person(self.c_mapinfo, ctypes.c_char_p(person))
 
-    person = property(fget=_get_person, fset=_set_person)
+    person = property(fget=_get_person, fset=_set_person,
+                      doc="Set or obtain the Vector author")
 
     def _get_title(self):
         """Private method to obtain the Vector title"""
@@ -162,7 +168,8 @@ class Info(object):
         """Private method to change the Vector title"""
         libvect.Vect_set_map_name(self.c_mapinfo, ctypes.c_char_p(title))
 
-    title = property(fget=_get_title, fset=_set_title)
+    title = property(fget=_get_title, fset=_set_title,
+                     doc="Set or obtain the Vector title")
 
     def _get_map_date(self):
         """Private method to obtain the Vector map date"""
@@ -174,7 +181,8 @@ class Info(object):
         date_str = datetimeobj.strftime(self.date_fmt)
         libvect.Vect_set_map_date(self.c_mapinfo, ctypes.c_char_p(date_str))
 
-    map_date = property(fget=_get_map_date, fset=_set_map_date)
+    map_date = property(fget=_get_map_date, fset=_set_map_date,
+                        doc="Set or obtain the Vector map date")
 
     def _get_scale(self):
         """Private method to obtain the Vector scale"""
@@ -184,7 +192,8 @@ class Info(object):
         """Private method to set the Vector scale"""
         return libvect.Vect_set_scale(self.c_mapinfo, ctypes.c_int(scale))
 
-    scale = property(fget=_get_scale, fset=_set_scale)
+    scale = property(fget=_get_scale, fset=_set_scale,
+                     doc="Set or obtain the Vector scale")
 
     def _get_comment(self):
         """Private method to obtain the Vector comment"""
@@ -194,7 +203,8 @@ class Info(object):
         """Private method to set the Vector comment"""
         return libvect.Vect_set_comment(self.c_mapinfo, ctypes.c_char_p(comm))
 
-    comment = property(fget=_get_comment, fset=_set_comment)
+    comment = property(fget=_get_comment, fset=_set_comment,
+                       doc="Set or obtain the Vector comment")
 
     def _get_zone(self):
         """Private method to obtain the Vector projection zone"""
@@ -204,7 +214,8 @@ class Info(object):
         """Private method to set the Vector projection zone"""
         return libvect.Vect_set_zone(self.c_mapinfo, ctypes.c_int(zone))
 
-    zone = property(fget=_get_zone, fset=_set_zone)
+    zone = property(fget=_get_zone, fset=_set_zone,
+                    doc="Set or obtain the Vector projection zone")
 
     def _get_proj(self):
         """Private method to obtain the Vector projection code"""
@@ -214,7 +225,8 @@ class Info(object):
         """Private method to set the Vector projection code"""
         libvect.Vect_set_proj(self.c_mapinfo, ctypes.c_int(proj))
 
-    proj = property(fget=_get_proj, fset=_set_proj)
+    proj = property(fget=_get_proj, fset=_set_proj,
+                    doc="Set or obtain the Vector projection code")
 
     def _get_thresh(self):
         """Private method to obtain the Vector threshold"""
@@ -224,7 +236,8 @@ class Info(object):
         """Private method to set the Vector threshold"""
         return libvect.Vect_set_thresh(self.c_mapinfo, ctypes.c_double(thresh))
 
-    thresh = property(fget=_get_thresh, fset=_set_thresh)
+    thresh = property(fget=_get_thresh, fset=_set_thresh,
+                      doc="Set or obtain the Vector threshold")
 
     @property
     @must_be_open
@@ -248,7 +261,11 @@ class Info(object):
         libvect.Vect_write_header(self.c_mapinfo)
 
     def rename(self, newname):
-        """Method to rename the Vector map"""
+        """Method to rename the Vector map
+
+        :param newname: the new name for the Vector map
+        :type newname: str
+        """
         if self.exist():
             if not self.is_open():
                 functions.rename(self.name, newname, 'vect')
@@ -275,43 +292,49 @@ class Info(object):
         """Return if the Vector is open"""
         return is_open(self.c_mapinfo)
 
-    def open(self, mode=None, layer=1, overwrite=None,
+    def open(self, mode=None, layer=1, overwrite=None, with_z=None,
              # parameters valid only if mode == 'w'
              tab_name='', tab_cols=None, link_name=None, link_key='cat',
              link_db='$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite/sqlite.db',
              link_driver='sqlite'):
         """Open a Vector map.
 
-         Parameters
-        ----------
-        mode : string
-            Open a vector map in ``r`` in reading, ``w`` in writing and
-            in ``rw`` read and write mode
-        layer: int, optional
-            Specify the layer that you want to use
-
-        Some parameters are valid only if we open use the writing mode (``w``)
-
-        overwrite: bool, optional
-            valid only for ``w`` mode
-        tab_name: string, optional
-            Define the name of the table that will be generate
-        tab_cols: list of pairs, optional
-            Define the name and type of the columns of the attribute table
-            of the vecto map
-        link_name: string, optional
-            Define the name of the link connecttion with the database
-        link_key: string, optional
-            Define the nema of the column that will be use as vector category
-        link_db: string, optional
-            Define the database connection parameters
-        link_driver: string, optional
-            Define witch database driver will be used
+         
+        :param mode: open a vector map in ``r`` in reading, ``w`` in writing
+                     and in ``rw`` read and write mode
+        :type mode: str
+        :param layer: specify the layer that you want to use
+        :type layer: int
+        :param overwrite: valid only for ``w`` mode
+        :type overwrite: bool
+        :param with_z: specify if vector map must be open with third dimension
+                       enabled or not. Valid only for ``w`` mode,
+                       default: False
+        :type with_z: bool
+        :param tab_name: define the name of the table that will be generate
+        :type tab_name: str
+        :param tab_cols: define the name and type of the columns of the
+                         attribute table of the vecto map
+        :type tab_cols: list of pairs
+        :param link_name: define the name of the link connecttion with the
+                          database
+        :type link_name: str
+        :param link_key: define the nema of the column that will be use as
+                         vector category
+        :type link_key: str
+        :param link_db: define the database connection parameters
+        :type link_db: str
+        :param link_driver: define witch database driver will be used
+        :param link_driver: str
+
+        Some of the parameters are valid only with mode ``w`` or ``rw``
 
         See more examples in the documentation of the ``read`` and ``write``
-        methods.
+        methods
         """
         self.mode = mode if mode else self.mode
+        self.with_z = self.with_z if with_z is None else with_z
+        with_z = libvect.WITH_Z if self.with_z else libvect.WITHOUT_Z
         # check if map exists or not
         if not self.exist() and self.mode != 'w':
             raise OpenError("Map <%s> not found." % self._name)
@@ -339,8 +362,7 @@ class Info(object):
 
         # If it is opened in write mode
         if self.mode == 'w':
-            openvect = libvect.Vect_open_new(self.c_mapinfo, self.name,
-                                             libvect.WITHOUT_Z)
+            openvect = libvect.Vect_open_new(self.c_mapinfo, self.name, with_z)
             self.dblinks = DBlinks(self.c_mapinfo)
             if tab_cols:
                 # create a link
@@ -377,7 +399,11 @@ class Info(object):
                                                  self.writable), }
 
     def close(self, build=False):
-        """Method to close the Vector"""
+        """Method to close the Vector
+
+        :param build: True if the vector map should be build before close it
+        :type build: bool
+        """
         if hasattr(self, 'table') and self.table is not None:
             self.table.conn.close()
         if self.is_open():

+ 112 - 59
lib/python/pygrass/vector/basic.py

@@ -55,7 +55,8 @@ class Bbox(object):
         """Private method to set the north value"""
         self.c_bbox.contents.N = value
 
-    north = property(fget=_get_n, fset=_set_n)
+    north = property(fget=_get_n, fset=_set_n,
+                     doc="Set and obtain north value")
 
     def _get_s(self):
         """Private method to obtain the south value"""
@@ -65,7 +66,8 @@ class Bbox(object):
         """Private method to set the south value"""
         self.c_bbox.contents.S = value
 
-    south = property(fget=_get_s, fset=_set_s)
+    south = property(fget=_get_s, fset=_set_s,
+                     doc="Set and obtain south value")
 
     def _get_e(self):
         """Private method to obtain the east value"""
@@ -75,7 +77,8 @@ class Bbox(object):
         """Private method to set the east value"""
         self.c_bbox.contents.E = value
 
-    east = property(fget=_get_e, fset=_set_e)
+    east = property(fget=_get_e, fset=_set_e,
+                    doc="Set and obtain east value")
 
     def _get_w(self):
         """Private method to obtain the west value"""
@@ -85,7 +88,8 @@ class Bbox(object):
         """Private method to set the west value"""
         self.c_bbox.contents.W = value
 
-    west = property(fget=_get_w, fset=_set_w)
+    west = property(fget=_get_w, fset=_set_w,
+                    doc="Set and obtain west value")
 
     def _get_t(self):
         """Private method to obtain the top value"""
@@ -95,7 +99,8 @@ class Bbox(object):
         """Private method to set the top value"""
         self.c_bbox.contents.T = value
 
-    top = property(fget=_get_t, fset=_set_t)
+    top = property(fget=_get_t, fset=_set_t,
+                   doc="Set and obtain top value")
 
     def _get_b(self):
         """Private method to obtain the bottom value"""
@@ -105,7 +110,8 @@ class Bbox(object):
         """Private method to set the bottom value"""
         self.c_bbox.contents.B = value
 
-    bottom = property(fget=_get_b, fset=_set_b)
+    bottom = property(fget=_get_b, fset=_set_b,
+                      doc="Set and obtain bottom value")
 
     def __repr__(self):
         return "Bbox({n}, {s}, {e}, {w})".format(n=self.north, s=self.south,
@@ -119,15 +125,17 @@ class Bbox(object):
         return ['north', 'south', 'west', 'east', 'top', 'bottom']
 
     def contains(self, point):
-        """Return True if the object is contained by the BoundingBox. ::
+        """Return True if the object is contained by the BoundingBox
 
-            >>> from grass.pygrass.vector.geometry import Point
-            >>> poi = Point(5,5)
-            >>> bbox = Bbox(north=10, south=0, west=0, east=10)
-            >>> bbox.contains(poi)
-            True
+        :param point: the point to analyze
+        :type point: a Point object or a tuple with the coordinates
+
+        >>> from grass.pygrass.vector.geometry import Point
+        >>> poi = Point(5,5)
+        >>> bbox = Bbox(north=10, south=0, west=0, east=10)
+        >>> bbox.contains(poi)
+        True
 
-        ..
         """
         return bool(libvect.Vect_point_in_box(point.x, point.y,
                                               point.z if point.z else 0,
@@ -137,10 +145,12 @@ class Bbox(object):
         return [(k, self.__getattribute__(k)) for k in self.keys()]
 
     def nsewtb(self, tb=True):
-        """Return a list
+        """Return a list of values from bounding box
+
+        :param tb: if tb parameter is False return only: north, south, east,
+                   west and not top and bottom
+        :type tb: bool
 
-        If tb parameter is False return only:
-        north, south, east, west
         """
         if tb:
             return (self.north, self.south, self.east, self.west,
@@ -193,21 +203,23 @@ class BoxList(object):
 
     def append(self, box):
         """Append a Bbox object to a Boxlist object, using the
-        ``Vect_boxlist_append`` C fuction. ::
-
-            >>> box0 = Bbox()
-            >>> box1 = Bbox(1,2,3,4)
-            >>> box2 = Bbox(5,6,7,8)
-            >>> boxlist = BoxList([box0, box1])
-            >>> boxlist
-            Boxlist([Bbox(0.0, 0.0, 0.0, 0.0), Bbox(1.0, 2.0, 3.0, 4.0)])
-            >>> len(boxlist)
-            2
-            >>> boxlist.append(box2)
-            >>> len(boxlist)
-            3
-
-        ..
+        ``Vect_boxlist_append`` C fuction.
+
+        :param bbox: the bounding box to add to the list
+        :param bbox: a Bbox object
+
+        >>> box0 = Bbox()
+        >>> box1 = Bbox(1,2,3,4)
+        >>> box2 = Bbox(5,6,7,8)
+        >>> boxlist = BoxList([box0, box1])
+        >>> boxlist
+        Boxlist([Bbox(0.0, 0.0, 0.0, 0.0), Bbox(1.0, 2.0, 3.0, 4.0)])
+        >>> len(boxlist)
+        2
+        >>> boxlist.append(box2)
+        >>> len(boxlist)
+        3
+
         """
         indx = self.__len__()
         libvect.Vect_boxlist_append(self.c_boxlist, indx, box.c_bbox)
@@ -247,16 +259,18 @@ class BoxList(object):
     def remove(self, indx):
         """Remove Bbox from the boxlist, given an integer or a list of integer
         or a boxlist, using ``Vect_boxlist_delete`` C function or the
-        ``Vect_boxlist_delete_boxlist``. ::
+        ``Vect_boxlist_delete_boxlist``.
 
-            >>> boxlist = BoxList([Bbox(),
-            ...                    Bbox(1, 0, 0, 1),
-            ...                    Bbox(1, -1, -1, 1)])
-            >>> boxlist.remove(0)
-            >>> boxlist
-            Boxlist([Bbox(1.0, 0.0, 0.0, 1.0), Bbox(1.0, -1.0, -1.0, 1.0)])
+        :param indx: the index value of the Bbox to remove
+        :param indx: int
+
+        >>> boxlist = BoxList([Bbox(),
+        ...                    Bbox(1, 0, 0, 1),
+        ...                    Bbox(1, -1, -1, 1)])
+        >>> boxlist.remove(0)
+        >>> boxlist
+        Boxlist([Bbox(1.0, 0.0, 0.0, 1.0), Bbox(1.0, -1.0, -1.0, 1.0)])
 
-        ..
         """
         if hasattr(indx, 'c_boxlist'):
             libvect.Vect_boxlist_delete_boxlist(self.c_boxlist, indx.c_boxlist)
@@ -268,18 +282,17 @@ class BoxList(object):
 
     def reset(self):
         """Reset the c_boxlist C struct, using the ``Vect_reset_boxlist`` C
-        function. ::
-
-            >>> boxlist = BoxList([Bbox(),
-            ...                    Bbox(1, 0, 0, 1),
-            ...                    Bbox(1, -1, -1, 1)])
-            >>> len(boxlist)
-            3
-            >>> boxlist.reset()
-            >>> len(boxlist)
-            0
-
-        ..
+        function.
+
+        >>> boxlist = BoxList([Bbox(),
+        ...                    Bbox(1, 0, 0, 1),
+        ...                    Bbox(1, -1, -1, 1)])
+        >>> len(boxlist)
+        3
+        >>> boxlist.reset()
+        >>> len(boxlist)
+        0
+
         """
         libvect.Vect_reset_boxlist(self.c_boxlist)
 
@@ -335,7 +348,11 @@ class Ilist(object):
 
     def extend(self, ilist):
         """Extend the list with another Ilist object or
-        with a list of integers"""
+        with a list of integers
+
+        :param ilist: the ilist to append
+        :type ilist: a Ilist object        
+        """
         if isinstance(ilist, Ilist):
             libvect.Vect_list_append_list(self.c_ilist, ilist.ilist)
         else:
@@ -416,19 +433,34 @@ class Cats(object):
 
     def get(self, layer=1):
         """Return the first found category of given layer
-        and the number of category found. """
+        and the number of category found.
+
+        :param layer: the number of layer
+        :type layer: int
+        """
         cat = ctypes.c_int()
         n_cats = libvect.Vect_cat_get(self.c_cats, layer, ctypes.byref(cat))
         return cat.value, n_cats
 
     def set(self, cat, layer=1):
-        """Add new field/cat to category structure if doesn't exist yet."""
+        """Add new field/cat to category structure if doesn't exist yet.
+
+        :param cat: the cat to add
+        :type cat: int
+        :param layer: the number of layer
+        :type layer: int
+        """
         libvect.Vect_cat_set(self.c_cats, layer, cat)
 
     def delete(self, cat=None, layer=1):
         """If cat is given delete cat from line_cats structure
         (using Vect_field_cat_del) else delete all categories of given layer
         (using Vect_cat_del).
+
+        :param cat: the cat to add
+        :type cat: int
+        :param layer: the number of layer
+        :type layer: int
         """
         if cat:
             self.n_del = libvect.Vect_field_cat_del(self.c_cats, layer, cat)
@@ -441,12 +473,22 @@ class Cats(object):
             raise ValueError(err_msg)
 
     def check_cats_constraints(self, cats_list, layer=1):
-        """Check if categories match with category constraints"""
+        """Check if categories match with category constraints
+
+        :param cats_list: a list of categories
+        :type cats_list: list
+        :param layer: the number of layer
+        :type layer: int
+        """
         return bool(libvect.Vect_cats_in_constraint(self.c_cats, layer,
                                                     cats_list.c_cat_list))
 
     def get_list(self, layer=1):
-        """Get list of categories of given field."""
+        """Get list of categories of given field.
+
+        :param layer: the number of layer
+        :type layer: int
+        """
         ilist = Ilist()
         if libvect.Vect_field_cat_get(self.c_cats, layer,
                                       ilist.c_ilist) < 0:
@@ -504,19 +546,30 @@ class CatsList(object):
 
     def from_string(self, string):
         """Converts string of categories and cat ranges separated by commas
-        to cat_list."""
+        to cat_list.
+
+        :param string: a string containing the cats separated by commas
+        :type string: str
+        """
         num_errors = libvect.Vect_str_to_cat_list(string, self.c_cat_list)
         if num_errors:
             from grass.pygrass.errors import GrassError
             raise GrassError("%d number of errors in ranges" % num_errors)
 
     def from_array(self, array):
-        """Convert ordered array of integers to cat_list structure."""
+        """Convert ordered array of integers to cat_list structure.
+
+        :param array: the input array containing the cats
+        :type array: array
+        """
         # Vect_array_to_cat_list(const int *vals, int nvals, ***)
         # TODO: it's not working
         libvect.Vect_array_to_cat_list(array, len(array), self.c_cat_list)
 
     def __contains__(self, cat):
         """Check if category number is in list.
-        int 	Vect_cat_in_cat_list (int cat, const struct cat_list *list)"""
+
+        :param cat: the category number
+        :type cat: int
+        """
         return bool(libvect.Vect_cat_in_cat_list(cat, self.c_cat_list))

+ 7 - 2
lib/python/pygrass/vector/find.py

@@ -14,7 +14,10 @@ from grass.pygrass.vector.geometry import read_line, Isle, Area, Point
 
 class AbstractFinder(object):
     def __init__(self, c_mapinfo, table=None, writable=False):
-        """Find geometry feature around a point.
+        """AbstractFinder
+        -----------------
+        
+        Find geometry feature around a point.
         """
         self.c_mapinfo = c_mapinfo
         self.table = table
@@ -32,7 +35,9 @@ class AbstractFinder(object):
 
 
 class PointFinder(AbstractFinder):
-    """Find the geomtry features of a vector map that are close to a point. ::
+    """PointFinder
+    ------------------
+    Find the geomtry features of a vector map that are close to a point. ::
 
         >>> from grass.pygrass.vector import VectorTopo
         >>> zipcodes = VectorTopo('zipcodes', 'PERMANENT')

+ 169 - 136
lib/python/pygrass/vector/geometry.py

@@ -143,7 +143,8 @@ class Attrs(object):
             # update condition
             self.cond = "%s=%d" % (self.table.key, value)
 
-    cat = property(fget=_get_cat, fset=_set_cat)
+    cat = property(fget=_get_cat, fset=_set_cat,
+                   doc="Set and obtain cat value")
 
     def __getitem__(self, key):
         """Return the value stored in the attribute table. ::
@@ -342,7 +343,8 @@ class Point(Geo):
     def _set_x(self, value):
         self.c_points.contents.x[0] = value
 
-    x = property(fget=_get_x, fset=_set_x)
+    x = property(fget=_get_x, fset=_set_x,
+                 doc="Set and obtain x coordinate")
 
     def _get_y(self):
         return self.c_points.contents.y[0]
@@ -350,7 +352,8 @@ class Point(Geo):
     def _set_y(self, value):
         self.c_points.contents.y[0] = value
 
-    y = property(fget=_get_y, fset=_set_y)
+    y = property(fget=_get_y, fset=_set_y,
+                 doc="Set and obtain y coordinate")
 
     def _get_z(self):
         if self.is2D:
@@ -365,7 +368,8 @@ class Point(Geo):
             self.c_points.contents.z[0] = value
             self.is2D = False
 
-    z = property(fget=_get_z, fset=_set_z)
+    z = property(fget=_get_z, fset=_set_z,
+                 doc="Set and obtain z coordinate")
 
     def __str__(self):
         return self.get_wkt()
@@ -429,7 +433,10 @@ class Point(Geo):
     def distance(self, pnt):
         """Calculate distance of 2 points, using the Vect_points_distance
         C function, If one of the point have z == None, return the 2D distance.
-        ::
+
+        :param pnt: the point for calculate the distance
+        :type pnt: a Point object or a tuple with the coordinates
+
 
             >>> pnt0 = Point(0, 0, 0)
             >>> pnt1 = Point(1, 0)
@@ -441,8 +448,6 @@ class Point(Geo):
             >>> pnt0.distance(pnt1)
             1.4142135623730951
 
-        The distance method require a :class:Point or a tuple with
-        the coordinates.
         """
         if self.is2D or pnt.is2D:
             return libvect.Vect_points_distance(self.x, self.y, 0,
@@ -456,39 +461,29 @@ class Point(Geo):
         """Return the buffer area around the point, using the
         ``Vect_point_buffer2`` C function.
 
-        Parameters
-        ----------
-        dist : numeric
-            The distance around the line.
-        dist_x: numeric, optional
-            The distance along x
-        dist_y: numeric, optional
-            The distance along y
-        angle: numeric, optional
-            The angle between 0x and major axis
-        round_: bool, optional
-            To make corners round
-        tol: float, optional
-            Fix the maximum distance between theoretical arc
-            and output segments
-
-        Returns
-        -------
-        buffer : Area
-            The buffer area around the line.
-
-        Example
-        ---------
+        :param dist: the distance around the point
+        :type dist: num
+        :param dist_x: the distance along x
+        :type dist_x: num
+        :param dist_y: the distance along y
+        :type dist_y: num
+        :param angle: the angle between 0x and major axis
+        :type angle: num
+        :param round_: to make corners round
+        :type round_: bool
+        :param tol: fix the maximum distance between theoretical arc and
+                    output segments
+        :type tol: float
+        :returns: the buffer as Area object
 
-        ::
-            >>> pnt = Point(0, 0)
-            >>> area = pnt.buffer(10)
-            >>> area.boundary                              #doctest: +ELLIPSIS
-            Line([Point(10.000000, 0.000000),...Point(10.000000, 0.000000)])
-            >>> area.centroid
-            Point(0.000000, 0.000000)
-            >>> area.isles
-            []
+        >>> pnt = Point(0, 0)
+        >>> area = pnt.buffer(10)
+        >>> area.boundary                              #doctest: +ELLIPSIS
+        Line([Point(10.000000, 0.000000),...Point(10.000000, 0.000000)])
+        >>> area.centroid
+        Point(0.000000, 0.000000)
+        >>> area.isles
+        []
 
         """
         if dist is not None:
@@ -623,7 +618,10 @@ class Line(Geo):
 
     def append(self, pnt):
         """Appends one point to the end of a line, using the
-        ``Vect_append_point`` C function. ::
+        ``Vect_append_point`` C function.
+        
+        :param pnt: the point to add to line
+        :type pnt: a Point object or a tuple with the coordinates
 
             >>> line = Line()
             >>> line.append((10, 100))
@@ -656,11 +654,13 @@ class Line(Geo):
     def extend(self, line, forward=True):
         """Appends points to the end of a line.
 
-        It is possible to extend a line, give a list of points, or directly
-        with a line_pnts struct.
-
-        If forward is True the line is extend forward otherwise is extend
-        backward. The method use the `Vect_append_points` C function. ::
+        :param line: it is possible to extend a line, give a list of points,
+                     or directly with a line_pnts struct.
+        :type line: Line object ot list of points
+        :param forward: if forward is True the line is extend forward otherwise
+                        is extend backward. The method use the
+                        `Vect_append_points` C function.
+        :type forward: bool
 
             >>> line = Line([(0, 0), (1, 1)])
             >>> line.extend( Line([(2, 2), (3, 3)]) )
@@ -670,8 +670,6 @@ class Line(Geo):
                   Point(2.000000, 2.000000),
                   Point(3.000000, 3.000000)])
 
-        Like python list, it is possible to extend a line, with another line
-        or with a list of points.
         """
         # set direction
         if forward:
@@ -694,7 +692,12 @@ class Line(Geo):
     def insert(self, indx, pnt):
         """Insert new point at index position and move all old points at
         that position and above up, using ``Vect_line_insert_point``
-        C function. ::
+        C function.
+
+        :param indx: the index where add new point
+        :type indx: int
+        :param pnt: the point to add
+        :type pnt: a Point object
 
             >>> line = Line([(0, 0), (1, 1)])
             >>> line.insert(0, Point(1.000000, -1.000000) )
@@ -703,7 +706,6 @@ class Line(Geo):
                   Point(0.000000, 0.000000),
                   Point(1.000000, 1.000000)])
 
-        ..
         """
         if indx < 0:  # Handle negative indices
             indx += self.c_points.contents.n_points
@@ -737,7 +739,12 @@ class Line(Geo):
         return libvect.Vect_line_geodesic_length(self.c_points)
 
     def distance(self, pnt):
-        """Return a tuple with:
+        """Calculate the distance between line and a point. 
+        
+        :param pnt: the point to calculate distance
+        :type pnt: a Point object or a tuple with the coordinates
+        
+        Return a tuple with:
 
             * the closest point on the line,
             * the distance between these two points,
@@ -746,15 +753,10 @@ class Line(Geo):
 
         The distance is compute using the ``Vect_line_distance`` C function.
 
-        Example
-        ---------
-
-        ::
             >>> line = Line([(0, 0), (0, 2)])
             >>> line.distance(Point(1, 1))
             (Point(0.000000, 1.000000), 1.0, 1.0, 1.0)
 
-        ..
         """
         # instantite outputs
         cx = ctypes.c_double(0)
@@ -789,7 +791,10 @@ class Line(Geo):
         pass
 
     def pop(self, indx):
-        """Return the point in the index position and remove from the Line. ::
+        """Return the point in the index position and remove from the Line.
+
+           :param indx: the index where add new point
+           :type indx: int
 
             >>> line = Line([(0, 0), (1, 1), (2, 2)])
             >>> midle_pnt = line.pop(1)
@@ -798,7 +803,6 @@ class Line(Geo):
             >>> line
             Line([Point(0.000000, 0.000000), Point(2.000000, 2.000000)])
 
-        ..
         """
         if indx < 0:  # Handle negative indices
             indx += self.c_points.contents.n_points
@@ -809,14 +813,15 @@ class Line(Geo):
         return pnt
 
     def delete(self, indx):
-        """Remove the point in the index position. ::
+        """Remove the point in the index position.
+           :param indx: the index where add new point
+           :type indx: int
 
             >>> line = Line([(0, 0), (1, 1), (2, 2)])
             >>> line.delete(-1)
             >>> line
             Line([Point(0.000000, 0.000000), Point(1.000000, 1.000000)])
 
-        ..
         """
         if indx < 0:  # Handle negative indices
             indx += self.c_points.contents.n_points
@@ -841,7 +846,10 @@ class Line(Geo):
 
     def prune_thresh(self, threshold):
         """Remove points in threshold, using the ``Vect_line_prune_thresh``
-        C funtion. ::
+        C funtion.
+        
+        :param threshold: the threshold value where prune points
+        :type threshold: num
 
             >>> line = Line([(0, 0), (1.0, 1.0), (1.2, 0.9), (2, 2)])
             >>> line.prune_thresh(0.5)
@@ -858,7 +866,10 @@ class Line(Geo):
 
     def remove(self, pnt):
         """Delete point at given index and move all points above down, using
-        `Vect_line_delete_point` C function. ::
+        `Vect_line_delete_point` C function.
+        
+        :param pnt: the point to remove
+        :type pnt: a Point object or a tuple with the coordinates
 
             >>> line = Line([(0, 0), (1, 1), (2, 2)])
             >>> line.remove((2, 2))
@@ -889,7 +900,9 @@ class Line(Geo):
         libvect.Vect_line_reverse(self.c_points)
 
     def segment(self, start, end):
-        """Create line segment. using the ``Vect_line_segment`` C function."""
+        # TODO improve documentation
+        """Create line segment. using the ``Vect_line_segment`` C function.
+        """
         line = Line()
         libvect.Vect_line_segment(self.c_points, start, end, line.c_points)
         return line
@@ -933,7 +946,10 @@ class Line(Geo):
                for pnt in self.__iter__()])
 
     def from_wkt(self, wkt):
-        """Read a WKT string. ::
+        """Create a line reading a WKT string.
+
+        :param wkt: the WKT string containing the LINESTRING
+        :type wkt: str
 
             >>> line = Line()
             >>> line.from_wkt("LINESTRING(0 0,1 1,1 2)")
@@ -966,41 +982,29 @@ class Line(Geo):
         """Return the buffer area around the line, using the
         ``Vect_line_buffer2`` C function.
 
-        Parameters
-        ----------
-        dist : numeric
-            The distance around the line.
-        dist_x: numeric, optional
-            The distance along x
-        dist_y: numeric, optional
-            The distance along y
-        angle: numeric, optional
-            The angle between 0x and major axis
-        round_: bool, optional
-            To make corners round
-        caps: bool, optional
-            To add caps at line ends
-        tol: float, optional
-            Fix the maximum distance between theoretical arc
-            and output segments
-
-        Returns
-        -------
-        buffer : Area
-            The buffer area around the line.
-
-        Example
-        ---------
-
-        ::
-            >>> line = Line([(0, 0), (0, 2)])
-            >>> area = line.buffer(10)
-            >>> area.boundary                              #doctest: +ELLIPSIS
-            Line([Point(-10.000000, 0.000000),...Point(-10.000000, 0.000000)])
-            >>> area.centroid
-            Point(0.000000, 0.000000)
-            >>> area.isles
-            []
+        :param dist: the distance around the line
+        :type dist: num
+        :param dist_x: the distance along x
+        :type dist_x: num
+        :param dist_y: the distance along y
+        :type dist_y: num
+        :param angle: the angle between 0x and major axis
+        :type angle: num
+        :param round_: to make corners round
+        :type round_: bool
+        :param tol: fix the maximum distance between theoretical arc and
+                    output segments
+        :type tol: float
+        :returns: the buffer as Area object
+
+        >>> line = Line([(0, 0), (0, 2)])
+        >>> area = line.buffer(10)
+        >>> area.boundary                              #doctest: +ELLIPSIS
+        Line([Point(-10.000000, 0.000000),...Point(-10.000000, 0.000000)])
+        >>> area.centroid
+        Point(0.000000, 0.000000)
+        >>> area.isles
+        []
 
         ..
         """
@@ -1080,9 +1084,19 @@ class Boundary(Line):
                 return cntr
 
     def get_left_centroid(self, idonly=False):
+        """Return left value
+
+        :param idonly: True to return only the cat of feature
+        :type idonly: bool        
+        """
         return self._get_centroid(self.left_id, idonly)
 
     def get_right_centroid(self, idonly=False):
+        """Return right value
+
+        :param idonly: True to return only the cat of feature
+        :type idonly: bool
+        """
         return self._get_centroid(self.left_id, idonly)
 
     def get_left_right(self):
@@ -1094,13 +1108,13 @@ class Boundary(Line):
 
     def area(self):
         """Return the area of the polygon.
-        ::
+
             >>> bound = Boundary(points=[(0, 0), (0, 2), (2, 2), (2, 0),
             ...                          (0, 0)])
             >>> bound.area()
             4.0
 
-        .."""
+        """
         libgis.G_begin_polygon_area_calculations()
         return libgis.G_area_of_polygon(self.c_points.contents.x,
                                         self.c_points.contents.y,
@@ -1170,12 +1184,14 @@ class Isle(Geo):
         return "Isle(%d)" % (self.id)
 
     def boundaries(self):
+        """Return a list of boundaries"""
         ilist = Ilist()
         libvect.Vect_get_isle_boundaries(self.c_mapinfo, self.id,
                                          ilist.c_ilist)
         return ilist
 
     def bbox(self, bbox=None):
+        """Return bounding box of Isle"""
         bbox = bbox if bbox else Bbox()
         libvect.Vect_get_isle_box(self.c_mapinfo, self.id, bbox.c_bbox)
         return bbox
@@ -1200,7 +1216,11 @@ class Isle(Geo):
         return bool(libvect.Vect_isle_alive(self.c_mapinfo, self.id))
 
     def contain_pnt(self, pnt):
-        """Check if point is in area."""
+        """Check if point is in area.
+
+        :param pnt: the point to remove
+        :type pnt: a Point object or a tuple with the coordinates
+        """
         bbox = self.bbox()
         return bool(libvect.Vect_point_in_island(pnt.x, pnt.y,
                                                  self.c_mapinfo, self.id,
@@ -1245,15 +1265,22 @@ class Isles(object):
         return self._isles[key]
 
     def get_isles_id(self):
+        """Return the id of isles"""
         return [libvect.Vect_get_area_isle(self.c_mapinfo, self.area_id, i)
                 for i in range(self.__len__())]
 
     def get_isles(self):
+        """Return isles"""
         return [Isle(v_id=isle_id, c_mapinfo=self.c_mapinfo)
                 for isle_id in self._isles_id]
 
     def select_by_bbox(self, bbox):
-        """Vect_select_isles_by_box"""
+        """Vect_select_isles_by_box
+
+        .. warning::
+
+            Not implemented yet.
+        """
         pass
 
 
@@ -1309,12 +1336,21 @@ class Area(Geo):
         self.get_isles()
 
     def get_points(self, line=None):
-        """Return a Line object with the outer ring"""
+        """Return a Line object with the outer ring
+
+        :param line: a Line object to fill with info from points of area
+        :type line: a Line object
+        """
         line = Line() if line is None else line
         libvect.Vect_get_area_points(self.c_mapinfo, self.id, line.c_points)
         return line
 
     def get_centroid(self, centroid=None):
+        """Return the centroid
+
+        :param centroid: a Centroid object to fill with info from centroid of area
+        :type centroid: a Centroid object
+        """
         centroid_id = libvect.Vect_get_area_centroid(self.c_mapinfo, self.id)
         if centroid:
             centroid.id = centroid_id
@@ -1346,8 +1382,10 @@ class Area(Geo):
         return bool(libvect.Vect_area_alive(self.c_mapinfo, self.id))
 
     def bbox(self, bbox=None):
-        """
-        Vect_get_area_box
+        """Return the Bbox of area
+
+        :param bbox: a Bbox object to fill with info from bounding box of area
+        :type bbox: a Bbox object
         """
         bbox = bbox if bbox else Bbox()
         libvect.Vect_get_area_box(self.c_mapinfo, self.id, bbox.c_bbox)
@@ -1358,28 +1396,20 @@ class Area(Geo):
         """Return the buffer area around the area, using the
         ``Vect_area_buffer2`` C function.
 
-        Parameters
-        ----------
-        dist : numeric
-            The distance around the line.
-        dist_x: numeric, optional
-            The distance along x
-        dist_y: numeric, optional
-            The distance along y
-        angle: numeric, optional
-            The angle between 0x and major axis
-        round_: bool, optional
-            To make corners round
-        caps: bool, optional
-            To add caps at line ends
-        tol: float, optional
-            Fix the maximum distance between theoretical arc
-            and output segments
-
-        Returns
-        -------
-        buffer : Area
-            The buffer area around the line.
+        :param dist: the distance around the area
+        :type dist: num
+        :param dist_x: the distance along x
+        :type dist_x: num
+        :param dist_y: the distance along y
+        :type dist_y: num
+        :param angle: the angle between 0x and major axis
+        :type angle: num
+        :param round_: to make corners round
+        :type round_: bool
+        :param tol: fix the maximum distance between theoretical arc and
+                    output segments
+        :type tol: float
+        :returns: the buffer as Area object
 
         """
         if dist is not None:
@@ -1415,8 +1445,9 @@ class Area(Geo):
 
     def cats(self, cats=None):
         """Get area categories.
-        int Vect_get_area_cats (const struct Map_info *Map,
-                                int area, struct line_cats *Cats)
+
+        :param cats: a Cats object to fill with info with area categories
+        :type cats: a Cats object
         """
         cats = cats if cats else Cats()
         libvect.Vect_get_area_cats(self.c_mapinfo, self.id, cats.c_cats)
@@ -1431,9 +1462,11 @@ class Area(Geo):
 
     def contain_pnt(self, pnt, bbox=None):
         """Check if point is in area.
-        int Vect_point_in_area(double x, double y,
-                               const struct Map_info *Map,
-                               int area, struct bound_box box)
+
+        :param pnt: the point to analyze 
+        :type pnt: a Point object or a tuple with the coordinates
+        :param bbox: the bounding box where run the analysis
+        :type bbox: a Bbox object
         """
         bbox = bbox if bbox else self.bbox()
         return bool(libvect.Vect_point_in_area(pnt.x, pnt.y,
@@ -1495,7 +1528,7 @@ def c_read_next_line(c_mapinfo, c_points, c_cats):
 
 
 def read_next_line(c_mapinfo, table=None, writable=False,
-                   c_points=None, c_cats=None):
+                   c_points=None, c_cats=None, is2D=True):
     """Return the next geometry feature of a vector map."""
     c_points = c_points if c_points else ctypes.pointer(libvect.line_pnts())
     c_cats = c_cats if c_cats else ctypes.pointer(libvect.line_cats())
@@ -1503,7 +1536,7 @@ def read_next_line(c_mapinfo, table=None, writable=False,
                                                      c_cats)
     return GV_TYPE[ftype]['obj'](v_id=v_id, c_mapinfo=c_mapinfo,
                                  c_points=c_points, c_cats=c_cats,
-                                 table=table, writable=writable)
+                                 table=table, writable=writable, is2D=is2D)
 
 
 def c_read_line(feature_id, c_mapinfo, c_points, c_cats):
@@ -1520,7 +1553,7 @@ def c_read_line(feature_id, c_mapinfo, c_points, c_cats):
 
 
 def read_line(feature_id, c_mapinfo, table=None, writable=False,
-              c_points=None, c_cats=None):
+              c_points=None, c_cats=None, is2D=True):
     """Return a geometry object given the feature id and the c_mapinfo.
     """
     c_points = c_points if c_points else ctypes.pointer(libvect.line_pnts())
@@ -1530,7 +1563,7 @@ def read_line(feature_id, c_mapinfo, table=None, writable=False,
     if GV_TYPE[ftype]['obj'] is not None:
         return GV_TYPE[ftype]['obj'](v_id=feature_id, c_mapinfo=c_mapinfo,
                                      c_points=c_points, c_cats=c_cats,
-                                     table=table, writable=writable)
+                                     table=table, writable=writable, is2D=is2D)
 
 
 

+ 1 - 6
lib/python/pygrass/vector/sql.py

@@ -1,17 +1,12 @@
 # -*- coding: utf-8 -*-
 """
-SQL
-===
-
-It is a collection of strings to avoid to repeat the code. ::
+It is a collection of strings to avoid to repeat the code.
 
     >>> SELECT.format(cols=', '.join(['cat', 'area']), tname='table')
     'SELECT cat, area FROM table;'
     >>> SELECT_WHERE.format(cols=', '.join(['cat', 'area']),
     ...                     tname='table', condition='area>10000')
     'SELECT cat, area FROM table WHERE area>10000;'
-
-
 """
 
 #

+ 192 - 60
lib/python/pygrass/vector/table.py

@@ -93,19 +93,32 @@ class Filters(object):
         return self
 
     def where(self, condition):
-        """Create the where condition"""
+        """Create the where condition
+
+        :param condition: the condition of where statement, for example
+                          `cat = 1`
+        :type condition: str
+        """
         self._where = 'WHERE {condition}'.format(condition=condition)
         return self
 
     def order_by(self, orderby):
-        """Create the order by condition"""
+        """Create the order by condition
+
+        :param orderby: the name of column/s to order the result
+        :type orderby: str
+        """
         if not isinstance(orderby, unicode):
             orderby = ', '.join(orderby)
         self._orderby = 'ORDER BY {orderby}'.format(orderby=orderby)
         return self
 
     def limit(self, number):
-        """Create the limit condition"""
+        """Create the limit condition
+
+        :param number: the number to limit the result
+        :type number: int
+        """
         if not isinstance(number, int):
             raise ValueError("Must be an integer.")
         else:
@@ -113,7 +126,11 @@ class Filters(object):
         return self
 
     def group_by(self, groupby):
-        """Create the group by condition"""
+        """Create the group by condition
+
+        :param groupby: the name of column/s to group the result
+        :type groupby: str, list
+        """
         if not isinstance(groupby, unicode):
             groupby = ', '.join(groupby)
         self._groupby = 'GROUP BY {groupby}'.format(groupby=groupby)
@@ -347,7 +364,13 @@ class Columns(object):
         return self.odict.items()
 
     def add(self, col_name, col_type):
-        """Add a new column to the table. ::
+        """Add a new column to the table.
+
+        :param col_name: the name of column to add
+        :type col_name: str
+        :param col_type: the tipe of column to add
+        :type col_type: str
+        ::
 
             >>> import sqlite3
             >>> path = '$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite/sqlite.db'
@@ -369,6 +392,11 @@ class Columns(object):
         ..
         """
         def check_col(col_type):
+            """Check the column type if it is supported by GRASS
+
+            :param col_type: the type of column
+            :type col_type: str
+            """
             valid_type = ('DOUBLE PRECISION', 'DOUBLE', 'INT', 'INTEGER',
                           'DATE')
             if 'VARCHAR' in col_type or col_type.upper() not in valid_type:
@@ -397,7 +425,13 @@ class Columns(object):
         self.update_odict()
 
     def rename(self, old_name, new_name):
-        """Rename a column of the table. ::
+        """Rename a column of the table.
+
+        :param old_name: the name of existing column
+        :type old_name: str
+        :param new_name: the name of new column
+        :type new_name: str
+        ::
 
             >>> import sqlite3
             >>> path = '$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite/sqlite.db'
@@ -447,7 +481,13 @@ class Columns(object):
             self.drop(old_name)
 
     def cast(self, col_name, new_type):
-        """Change the column type. ::
+        """Change the column type.
+
+        :param col_name: the name of column
+        :type col_name: str
+        :param new_type: the new type of column
+        :type new_type: str
+        ::
 
             >>> import sqlite3
             >>> path = '$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite/sqlite.db'
@@ -485,7 +525,11 @@ class Columns(object):
             raise DBError('SQLite does not support to cast columns.')
 
     def drop(self, col_name):
-        """Drop a column from the table. ::
+        """Drop a column from the table.
+
+        :param col_name: the name of column to remove
+        :type col_name: str
+        ::
 
             >>> import sqlite3
             >>> path = '$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite/sqlite.db'
@@ -582,7 +626,8 @@ class Link(object):
             raise TypeError("Number must be positive and greater than 0.")
         self.c_fieldinfo.contents.number = number
 
-    layer = property(fget=_get_layer, fset=_set_layer)
+    layer = property(fget=_get_layer, fset=_set_layer,
+                     doc="Set and obtain layer number")
 
     def _get_name(self):
         return self.c_fieldinfo.contents.name
@@ -590,7 +635,8 @@ class Link(object):
     def _set_name(self, name):
         self.c_fieldinfo.contents.name = name
 
-    name = property(fget=_get_name, fset=_set_name)
+    name = property(fget=_get_name, fset=_set_name,
+                    doc="Set and obtain name vale")
 
     def _get_table(self):
         return self.c_fieldinfo.contents.table
@@ -598,7 +644,8 @@ class Link(object):
     def _set_table(self, new_name):
         self.c_fieldinfo.contents.table = new_name
 
-    table_name = property(fget=_get_table, fset=_set_table)
+    table_name = property(fget=_get_table, fset=_set_table,
+                          doc="Set and obtain table name value")
 
     def _get_key(self):
         return self.c_fieldinfo.contents.key
@@ -606,7 +653,8 @@ class Link(object):
     def _set_key(self, key):
         self.c_fieldinfo.contents.key = key
 
-    key = property(fget=_get_key, fset=_set_key)
+    key = property(fget=_get_key, fset=_set_key,
+                   doc="Set and obtain cat value")
 
     def _get_database(self):
         return self.c_fieldinfo.contents.database
@@ -614,7 +662,8 @@ class Link(object):
     def _set_database(self, database):
         self.c_fieldinfo.contents.database = database
 
-    database = property(fget=_get_database, fset=_set_database)
+    database = property(fget=_get_database, fset=_set_database,
+                        doc="Set and obtain database value")
 
     def _get_driver(self):
         return self.c_fieldinfo.contents.driver
@@ -625,7 +674,9 @@ class Link(object):
             raise TypeError(str_err)
         self.c_fieldinfo.contents.driver = driver
 
-    driver = property(fget=_get_driver, fset=_set_driver)
+    driver = property(fget=_get_driver, fset=_set_driver,
+                      doc="Set and obtain driver value. The drivers supported \
+                      by PyGRASS are: SQLite and PostgreSQL")
 
     def __init__(self, layer=1, name=None, table=None, key='cat',
                  database='$GISDBASE/$LOCATION_NAME/'
@@ -777,7 +828,11 @@ class DBlinks(object):
         return "DBlinks(%r)" % [link for link in self.__iter__()]
 
     def by_index(self, indx):
-        """Return a Link object by index"""
+        """Return a Link object by index
+
+        :param indx: the index where add new point
+        :type indx: int
+        """
         nlinks = self.num_dblinks()
         if nlinks == 0:
             raise IndexError
@@ -789,33 +844,45 @@ class DBlinks(object):
         return Link(c_fieldinfo=c_fieldinfo) if c_fieldinfo else None
 
     def by_layer(self, layer):
+        """Return the choosen Link using the layer
+
+        :param layer: the number of layer
+        :type layer: int
+        """
         c_fieldinfo = libvect.Vect_get_field(self.c_mapinfo, layer)
         return Link(c_fieldinfo=c_fieldinfo) if c_fieldinfo else None
 
     def by_name(self, name):
+        """Return the choosen Link using the name
+
+        :param name: the name of Link
+        :type name: str
+        """
         c_fieldinfo = libvect.Vect_get_field_by_name(self.c_mapinfo, name)
         return Link(c_fieldinfo=c_fieldinfo) if c_fieldinfo else None
 
     def num_dblinks(self):
+        """Return the number of DBlinks"""
         return libvect.Vect_get_num_dblinks(self.c_mapinfo)
 
     def add(self, link):
-        """Add a new link.
-           Need to open vector map in write mode::
-
-            >>> from grass.pygrass.vector import VectorTopo
-            >>> municip = VectorTopo('census')
-            >>> municip.open()
-            >>> dblinks = DBlinks(municip.c_mapinfo)
-            >>> dblinks
-            DBlinks([Link(1, census, sqlite)])
-            >>> link = Link(2, 'pg_link', 'boundary_municp_pg', 'cat',
-            ...             'host=localhost dbname=grassdb', 'pg') # doctest: +SKIP
-            >>> dblinks.add(link)                             # doctest: +SKIP
-            >>> dblinks                                       # doctest: +SKIP
-            DBlinks([Link(1, boundary_municp, sqlite)])
+        """Add a new link. Need to open vector map in write mode
+
+       :param link: the Link to add to the DBlinks
+       :type link: a Link object
+
+        >>> from grass.pygrass.vector import VectorTopo
+        >>> municip = VectorTopo('census')
+        >>> municip.open()
+        >>> dblinks = DBlinks(municip.c_mapinfo)
+        >>> dblinks
+        DBlinks([Link(1, census, sqlite)])
+        >>> link = Link(2, 'pg_link', 'boundary_municp_pg', 'cat',
+        ...             'host=localhost dbname=grassdb', 'pg') # doctest: +SKIP
+        >>> dblinks.add(link)                             # doctest: +SKIP
+        >>> dblinks                                       # doctest: +SKIP
+        DBlinks([Link(1, boundary_municp, sqlite)])
 
-        ..
         """
         #TODO: check if open in write mode or not.
         libvect.Vect_map_add_dblink(self.c_mapinfo,
@@ -823,19 +890,25 @@ class DBlinks(object):
                                     link.key, link.database, link.driver)
 
     def remove(self, key, force=False):
-        """Remove a link. If force set to true remove also the table ::
-
-            >>> from grass.pygrass.vector import VectorTopo
-            >>> municip = VectorTopo('census')
-            >>> municip.open()
-            >>> dblinks = DBlinks(municip.c_mapinfo)
-            >>> dblinks
-            DBlinks([Link(1, census, sqlite)])
-            >>> dblinks.remove('pg_link')                     # doctest: +SKIP
-            >>> dblinks  # need to open vector map in write mode
-            DBlinks([Link(1, census, sqlite)])
+        """Remove a link. If force set to true remove also the table
+
+        :param key: the key of Link
+        :type key: str
+        :param force: if True remove also the table from database otherwise
+                      only the link between table and vector
+        :type force: boole
+
+        >>> from grass.pygrass.vector import VectorTopo
+        >>> municip = VectorTopo('census')
+        >>> municip.open()
+        >>> dblinks = DBlinks(municip.c_mapinfo)
+        >>> dblinks
+        DBlinks([Link(1, census, sqlite)])
+        >>> dblinks.remove('pg_link')                     # doctest: +SKIP
+        >>> dblinks  # need to open vector map in write mode
+        DBlinks([Link(1, census, sqlite)])
+
 
-        ..
         """
         if force:
             link = self.by_name(key)
@@ -875,7 +948,11 @@ class Table(object):
         return self._name
 
     def _set_name(self, new_name):
-        """Private method to set the name of table"""
+        """Private method to set the name of table
+
+          :param new_name: the new name of table
+          :type new_name: str
+        """
         old_name = self._name
         cur = self.conn.cursor()
         cur.execute(sql.RENAME_TAB.format(old_name=old_name,
@@ -883,7 +960,8 @@ class Table(object):
         self.conn.commit()
         cur.close()
 
-    name = property(fget=_get_name, fset=_set_name)
+    name = property(fget=_get_name, fset=_set_name,
+                    doc="Set and obtain table name")
 
     def __init__(self, name, connection, key='cat'):
         self._name = name
@@ -917,7 +995,15 @@ class Table(object):
         return self.n_rows()
 
     def drop(self, cursor=None, force=False):
-        """Private method to drop table from database"""
+        """Method to drop table from database
+
+          :param cursor: the cursor to connect, if None it use the cursor
+                         of connection table object
+          :type cursor: Cursor object
+          :param force: True to remove the table, by default False to print
+                        advice
+          :type force: bool
+        """
 
         cur = cursor if cursor else self.conn.cursor()
         if self.exist(cursor=cur):
@@ -950,19 +1036,29 @@ class Table(object):
 
     def execute(self, sql_code=None, cursor=None, many=False, values=None):
         """Execute SQL code from a given string or build with filters and
-        return a cursor object. ::
+        return a cursor object.
+
+        :param sql_code: the SQL code to execute, if not pass it use filters
+                         variable
+        :type sql_code: str
+        :param cursor: the cursor to connect, if None it use the cursor
+                     of connection table object
+        :type cursor: Cursor object
+        :param many: True to run executemany function
+        :type many: bool
+        :param values: The values to substitute into sql_code string
+        :type values: list of tuple
 
-            >>> import sqlite3
-            >>> path = '$GISDBASE/$LOCATION_NAME/PERMANENT/sqlite/sqlite.db'
-            >>> tab_sqlite = Table(name='census',
-            ...                    connection=sqlite3.connect(get_path(path)))
-            >>> tab_sqlite.filters.select('cat', 'TOTAL_POP').order_by('AREA')
-            Filters(u'SELECT cat, TOTAL_POP FROM census ORDER BY AREA;')
-            >>> cur = tab_sqlite.execute()
-            >>> cur.fetchone()
-            (1856, 0)
+        >>> import sqlite3
+        >>> path = '$GISDBASE/$LOCATION_NAME/PERMANENT/sqlite/sqlite.db'
+        >>> tab_sqlite = Table(name='census',
+        ...                    connection=sqlite3.connect(get_path(path)))
+        >>> tab_sqlite.filters.select('cat', 'TOTAL_POP').order_by('AREA')
+        Filters(u'SELECT cat, TOTAL_POP FROM census ORDER BY AREA;')
+        >>> cur = tab_sqlite.execute()
+        >>> cur.fetchone()
+        (1856, 0)
 
-        ..
         """
         try:
             sqlc = sql_code if sql_code else self.filters.get_sql()
@@ -975,26 +1071,62 @@ class Table(object):
             raise ValueError("The SQL is not correct:\n%r" % sqlc)
 
     def exist(self, cursor=None):
-        """Return True if the table already exist in the DB, False otherwise"""
+        """Return True if the table already exist in the DB, False otherwise
+        :param cursor: the cursor to connect, if None it use the cursor
+                     of connection table object
+        :type cursor: Cursor object
+        """
         cur = cursor if cursor else self.conn.cursor()
         return table_exist(cur, self.name)
 
     def insert(self, values, cursor=None, many=False):
-        """Insert a new row"""
+        """Insert a new row
+
+        :param values: a tuple of values to insert, it is possible to insert
+                       more rows using a list of tuple and paramater `many`
+        :type values: tuple
+        :param cursor: the cursor to connect, if None it use the cursor
+                     of connection table object
+        :type cursor: Cursor object
+        :param many: True to run executemany function
+        :type many: bool
+        """
         cur = cursor if cursor else self.conn.cursor()
         if many:
             return cur.executemany(self.columns.insert_str, values)
         return cur.execute(self.columns.insert_str, values)
 
     def update(self, key, values, cursor=None, many=False):
-        """Update a column for each row"""
+        """Update a column for each row
+
+        :param key: the name of column
+        :param values: the values to insert
+        :type values: str
+        :param cursor: the cursor to connect, if None it use the cursor
+                     of connection table object
+        :type cursor: Cursor object
+        :param many: True to run executemany function
+        :type many: bool
+        """
         cur = cursor if cursor else self.conn.cursor()
         vals = list(values)
         vals.append(key)
         return cur.execute(self.columns.update_str, vals)
 
     def create(self, cols, name=None, overwrite=False, cursor=None):
-        """Create a new table"""
+        """Create a new table
+
+        :param cols:
+        :type cols:
+        :param name: the name of table to create, None for the name of Table object
+        :type name: str
+        :param overwrite: overwrite existing table
+        :type overwrite: bool
+        :param cursor: the cursor to connect, if None it use the cursor
+                     of connection table object
+        :type cursor: Cursor object
+
+        """
         cur = cursor if cursor else self.conn.cursor()
         coldef = ',\n'.join(['%s %s' % col for col in cols])
         if name:

+ 130 - 0
lib/python/pygrass/vector/testsuite/test_geometry.py

@@ -0,0 +1,130 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Thu Jun 19 14:13:53 2014
+
+@author: pietro
+"""
+import sys
+import unittest
+import numpy as np
+
+import grass.lib.vector as libvect
+
+from grass.pygrass.vector.geometry import Point, Line
+
+
+class PointTestCase(unittest.TestCase):
+
+    def test_empty_init(self):
+        """Test Point()"""
+        point = Point()
+        self.assertEqual(point.gtype, libvect.GV_POINT)
+        self.assertEqual(point.x, 0)
+        self.assertEqual(point.y, 0)
+        self.assertIsNone(point.z)
+        self.assertTrue(point.is2D)
+
+    def test_init_3d(self):
+        """Test 3D Point(1, 2, 3)"""
+        point = Point(1, 2, 3)
+        self.assertEqual(point.x, 1)
+        self.assertEqual(point.y, 2)
+        self.assertEqual(point.z, 3)
+        self.assertFalse(point.is2D)
+
+    def test_switch_2D_3D_2D(self):
+        """Test switch between: 2D => 3D => 2D"""
+        point = Point()
+        self.assertIsNone(point.z)
+        self.assertTrue(point.is2D)
+        point.z = 1
+        self.assertFalse(point.is2D)
+        point.z = None
+        self.assertTrue(point.is2D, True)
+
+    def test_coords(self):
+        """Test coords method"""
+        self.assertEqual(Point(1, 2).coords(), (1, 2))
+        self.assertEqual(Point(1, 2, 3).coords(), (1, 2, 3))
+
+    def test_get_wkt(self):
+        """Test coords method"""
+        self.assertEqual(Point(1, 2).get_wkt(), 'POINT(1.000000 2.000000)')
+        self.assertEqual(Point(1, 2, 3).get_wkt(),
+                         'POINT(1.000000 2.000000 3.000000)')
+
+    def test_distance(self):
+        """Test distance method"""
+        point0 = Point(0, 0, 0)
+        point1 = Point(1, 0)
+        self.assertEqual(point0.distance(point1), 1.0)
+        point1.z = 1
+        self.assertAlmostEqual(point0.distance(point1), np.sqrt(2.))
+
+    def test_eq(self):
+        """Test __eq__"""
+        point0 = Point(0, 0)
+        point1 = Point(1, 0)
+        self.assertFalse(point0 == point1)
+        self.assertFalse(point0 == (1, 0))
+        self.assertTrue(point0 == point0)
+        self.assertTrue(point0 == (0, 0))
+
+    def test_repr(self):
+        """Test __eq__"""
+        self.assertEqual(repr(Point(1, 2)), 'Point(1.000000, 2.000000)')
+        self.assertEqual(repr(Point(1, 2, 3)),
+                         'Point(1.000000, 2.000000, 3.000000)')
+
+    @unittest.skip("Not implemented yet.")
+    def test_buffer(self):
+        """Test buffer method"""
+        # TODO: verify if the buffer depends from the mapset's projection
+        pass
+
+
+class LineTestCase(unittest.TestCase):
+
+    def test_len(self):
+        """Test __len__ magic method"""
+        self.assertEqual(len(Line()), 0)
+        self.assertEqual(len(Line([(0, 0), (1, 1)])), 2)
+
+    @unittest.skipIf(sys.version_info[:2] < (2, 7), "Require Python >= 2.7")
+    def test_getitem(self):
+        """Test __getitem__ magic method"""
+        line = Line([(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)])
+        self.assertTupleEqual(line[0].coords(), (0, 0))
+        self.assertTupleEqual(line[1].coords(), (1, 1))
+        self.assertTupleEqual(line[-2].coords(), (3, 3))
+        self.assertTupleEqual(line[-1].coords(), (4, 4))
+        self.assertListEqual([p.coords() for p in line[:2]], [(0, 0), (1, 1)])
+        self.assertListEqual([p.coords() for p in line[::2]],
+                             [(0, 0), (2, 2), (4, 4)])
+        with self.assertRaises(IndexError):
+            line[5]
+
+    @unittest.skipIf(sys.version_info[:2] < (2, 7), "Require Python >= 2.7")
+    def test_setitem(self):
+        """Test __setitem__ magic method"""
+        line = Line([(0, 0), (1, 1)])
+        self.assertTupleEqual(line[0].coords(), (0., 0.))
+        line[0] = (10, 10)
+        self.assertTupleEqual(line[0].coords(), (10., 10.))
+
+    @unittest.skipIf(sys.version_info[:2] < (2, 7), "Require Python >= 2.7")
+    def test_get_pnt(self):
+        """Test get_pnt method"""
+        line = Line([(0, 0), (1, 1)])
+        with self.assertRaises(ValueError):
+            line.get_pnt(5)
+        vals = (0.7071067811865475, 0.7071067811865475)
+        self.assertTupleEqual(line.get_pnt(1).coords(), vals)
+
+    def test_bbox(self):
+        line = Line([(0, 0), (0, 1), (2, 1), (2, 0)])
+        bbox = line.bbox()
+
+
+if __name__ == '__main__':
+    unittest.main()

+ 67 - 0
lib/python/pygrass/vector/testsuite/test_vector3d.py

@@ -0,0 +1,67 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Wed Jun 18 17:21:42 2014
+
+@author: pietro
+"""
+import unittest
+import numpy as np
+
+from grass.script.core import run_command
+
+from grass.pygrass.vector import VectorTopo
+from grass.pygrass.vector.geometry import Point
+from grass.pygrass.gis.region import Region
+from grass.pygrass.functions import get_mapset_vector
+
+
+def generate_coordinates(number, bbox=None, with_z=False):
+    """Return 2 or 3 random arrays of coordinates"""
+    bbox = Region() if bbox is None else bbox
+    x = bbox.south + (bbox.north - bbox.south) * np.random.random(number)
+    y = bbox.west + (bbox.east - bbox.west) * np.random.random(number)
+    if with_z:
+        z = np.random.random(number) * 1000
+        return x, y, z
+    return x, y
+
+
+class VectorTopo3DTestCase(unittest.TestCase):
+
+    npoints = 10
+    tmpname = "tmp_vect3d"
+
+    @classmethod
+    def setUpClass(cls):
+        """Generate a number (NPOINTS) of random points"""
+        cls.x, cls.y, cls.z = generate_coordinates(cls.npoints, with_z=True)
+
+    def writing_points(self):
+        """Write the generated random points to a vector map"""
+        with VectorTopo(self.tmpname, mode="w", with_z=True) as vect:
+            for x, y, z in zip(self.x, self.y, self.z):
+                vect.write(Point(x, y, z))
+
+    def reading_points(self):
+        """Read the generated random points from a vector map"""
+        with VectorTopo(self.tmpname, mode="r") as vect:
+            # reading the generated vector points map
+            arr = np.array([(p.x, p.y, p.z) for p in vect])
+            # verify the correspondance
+            for i, coords in enumerate((self.x, self.y, self.z)):
+                np.testing.assert_almost_equal(arr.T[i], coords)
+
+    def test_writing_reading_points(self):
+        self.writing_points()
+        self.reading_points()
+
+    @classmethod
+    def tearDownClass(cls):
+        """Remove the generated vector map, if exist"""
+        mset = get_mapset_vector(cls.tmpname, mapset='')
+        if mset:
+            run_command("g.remove", vect="%s@%s" % (cls.tmpname, mset))
+
+
+if __name__ == '__main__':
+    unittest.main()