[GRASS-SVN] r53350 - in grass/trunk/lib/python: . pygrass pygrass/docs pygrass/modules pygrass/raster pygrass/tests pygrass/vector

svn_grass at osgeo.org svn_grass at osgeo.org
Wed Oct 10 05:24:32 PDT 2012


Author: zarch
Date: 2012-10-10 05:24:32 -0700 (Wed, 10 Oct 2012)
New Revision: 53350

Added:
   grass/trunk/lib/python/pygrass/
   grass/trunk/lib/python/pygrass/Makefile
   grass/trunk/lib/python/pygrass/__init__.py
   grass/trunk/lib/python/pygrass/docs/
   grass/trunk/lib/python/pygrass/docs/Makefile
   grass/trunk/lib/python/pygrass/docs/attributes.rst
   grass/trunk/lib/python/pygrass/docs/conf.py
   grass/trunk/lib/python/pygrass/docs/index.rst
   grass/trunk/lib/python/pygrass/docs/intro.rst
   grass/trunk/lib/python/pygrass/docs/make.bat
   grass/trunk/lib/python/pygrass/docs/modules.rst
   grass/trunk/lib/python/pygrass/docs/raster.rst
   grass/trunk/lib/python/pygrass/docs/vector.rst
   grass/trunk/lib/python/pygrass/env.py
   grass/trunk/lib/python/pygrass/errors.py
   grass/trunk/lib/python/pygrass/modules/
   grass/trunk/lib/python/pygrass/modules/Makefile
   grass/trunk/lib/python/pygrass/modules/__init__.py
   grass/trunk/lib/python/pygrass/orderdict.py
   grass/trunk/lib/python/pygrass/raster/
   grass/trunk/lib/python/pygrass/raster/Makefile
   grass/trunk/lib/python/pygrass/raster/__init__.py
   grass/trunk/lib/python/pygrass/raster/abstract.py
   grass/trunk/lib/python/pygrass/raster/buffer.py
   grass/trunk/lib/python/pygrass/raster/category.py
   grass/trunk/lib/python/pygrass/raster/history.py
   grass/trunk/lib/python/pygrass/raster/raster_type.py
   grass/trunk/lib/python/pygrass/raster/rowio.py
   grass/trunk/lib/python/pygrass/raster/segment.py
   grass/trunk/lib/python/pygrass/region.py
   grass/trunk/lib/python/pygrass/tests/
   grass/trunk/lib/python/pygrass/tests/Makefile
   grass/trunk/lib/python/pygrass/tests/__init__.py
   grass/trunk/lib/python/pygrass/tests/benchmark.py
   grass/trunk/lib/python/pygrass/tests/set_mapset.py
   grass/trunk/lib/python/pygrass/vector/
   grass/trunk/lib/python/pygrass/vector/Makefile
   grass/trunk/lib/python/pygrass/vector/__init__.py
   grass/trunk/lib/python/pygrass/vector/abstract.py
   grass/trunk/lib/python/pygrass/vector/basic.py
   grass/trunk/lib/python/pygrass/vector/geometry.py
   grass/trunk/lib/python/pygrass/vector/sql.py
   grass/trunk/lib/python/pygrass/vector/table.py
   grass/trunk/lib/python/pygrass/vector/vector_type.py
Modified:
   grass/trunk/lib/python/Makefile
Log:
Add pygrass library into grass

Modified: grass/trunk/lib/python/Makefile
===================================================================
--- grass/trunk/lib/python/Makefile	2012-10-09 23:20:48 UTC (rev 53349)
+++ grass/trunk/lib/python/Makefile	2012-10-10 12:24:32 UTC (rev 53350)
@@ -13,12 +13,13 @@
 PYFILES := $(patsubst %,$(DSTDIR)/%.py,$(MODULES) __init__)
 PYCFILES := $(patsubst %,$(DSTDIR)/%.pyc,$(MODULES) __init__)
 
-CLEAN_SUBDIRS = ctypes temporal
+CLEAN_SUBDIRS = ctypes temporal pygrass
 EXTRA_CLEAN_FILES = setup.py
 
 default: $(PYFILES) $(PYCFILES) $(GDIR)/__init__.py $(GDIR)/__init__.pyc
 	-$(MAKE) -C ctypes || echo $(CURDIR)/ctypes >> $(ERRORLOG)
 	-$(MAKE) -C temporal || echo $(CURDIR)/temporal >> $(ERRORLOG)
+	-$(MAKE) -C pygrass || echo $(CURDIR)/pygrass >> $(ERRORLOG)
 
 $(PYDIR):
 	$(MKDIR) $@

Copied: grass/trunk/lib/python/pygrass/Makefile (from rev 53343, grass/trunk/lib/python/Makefile)
===================================================================
--- grass/trunk/lib/python/pygrass/Makefile	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/Makefile	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,37 @@
+MODULE_TOPDIR=../../..
+
+include $(MODULE_TOPDIR)/include/Make/Other.make
+include $(MODULE_TOPDIR)/include/Make/Python.make
+include $(MODULE_TOPDIR)/include/Make/Doxygen.make
+
+PYDIR = $(ETC)/python
+GDIR = $(PYDIR)/grass
+DSTDIR = $(GDIR)/pygrass
+
+MODULES = errors env orderdict region
+
+CLEAN_SUBDIRS = modules raster vector tests
+
+PYFILES := $(patsubst %,$(DSTDIR)/%.py,$(MODULES) __init__)
+PYCFILES := $(patsubst %,$(DSTDIR)/%.pyc,$(MODULES) __init__)
+
+default: $(PYFILES) $(PYCFILES) $(GDIR)/__init__.py $(GDIR)/__init__.pyc
+	-$(MAKE) -C modules || echo $(CURDIR)/modules >> $(ERRORLOG)
+	-$(MAKE) -C raster || echo $(CURDIR)/raster >> $(ERRORLOG)
+	-$(MAKE) -C vector || echo $(CURDIR)/vector >> $(ERRORLOG)
+	-$(MAKE) -C tests || echo $(CURDIR)/tests >> $(ERRORLOG)
+
+$(PYDIR):
+	$(MKDIR) $@
+
+$(GDIR): | $(PYDIR)
+	$(MKDIR) $@
+
+$(DSTDIR): | $(GDIR)
+	$(MKDIR) $@
+
+$(DSTDIR)/%: % | $(DSTDIR)
+	$(INSTALL_DATA) $< $@
+
+#doxygen:
+DOXNAME = pythonpygrass

Added: grass/trunk/lib/python/pygrass/__init__.py
===================================================================
--- grass/trunk/lib/python/pygrass/__init__.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/__init__.py	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Fri May 25 12:55:14 2012
+
+ at author: pietro
+"""
+import grass.lib.gis as _libgis
+_libgis.G_gisinit('')
+import os as _os
+import sys as _sys
+
+_pygrasspath = _os.path.dirname(_os.path.realpath( __file__ )).split(_os.sep)
+
+_sys.path.append(_os.path.join(_os.sep,*_pygrasspath[:-1]))
+
+import region
+import raster
+import vector
+import modules
+import errors
+import env
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/docs/Makefile
===================================================================
--- grass/trunk/lib/python/pygrass/docs/Makefile	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/docs/Makefile	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,158 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+ifneq (@(type sphinx-build2 > /dev/null),)
+SPHINXBUILD   = sphinx-build2
+endif
+ifneq (@(type sphinx-build > /dev/null),)
+SPHINXBUILD   = sphinx-build
+endif
+PAPER         =
+BUILDDIR      = _build
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS  = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@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)/*
+
+html:
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+	$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+	@echo
+	@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files."
+
+json:
+	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+	@echo
+	@echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+	$(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:
+	$(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:
+	$(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"
+
+epub:
+	$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+	@echo
+	@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+	@echo "Run \`make' in that directory to run these through (pdf)latex" \
+	      "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo "Running LaTeX files through pdflatex..."
+	$(MAKE) -C $(BUILDDIR)/latex all-pdf
+	@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+	$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+	@echo
+	@echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+	@echo
+	@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+texinfo:
+	$(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:
+	$(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:
+	$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+	@echo
+	@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+changes:
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+	@echo
+	@echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+	@echo "Testing of doctests in the sources finished, look at the " \
+	      "results in $(BUILDDIR)/doctest/output.txt."

Added: grass/trunk/lib/python/pygrass/docs/attributes.rst
===================================================================
--- grass/trunk/lib/python/pygrass/docs/attributes.rst	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/docs/attributes.rst	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,138 @@
+Attributes
+===========
+
+It is possible to access to the vector attributes with: ::
+
+    >>> from pygrass.vector import Vector
+    >>> municip = Vector('boundary_municp_sqlite')
+    >>> municip.open()
+    >>> municip.dblinks
+    DBlinks([[Link(1, boundary_municp, sqlite)]])
+
+The vector map have a ``table`` attributes that contain a Table object, that
+have some useful attributes like: layer, name, driver, etc.
+
+    >>> link = municip.dblinks[1]
+    >>> link.number
+    1
+    >>> link.name
+    'boundary_municp'
+    >>> link.table_name
+    'boundary_municp_sqlite'
+    >>> link.driver
+    'sqlite'
+    >>> link.database                                     # doctest: +ELLIPSIS
+    '.../sqlite.db'
+    >>> link.key
+    'cat'
+
+It is possible to change values, like: ::
+
+    >>> link.name = 'boundary'
+    >>> link.driver = 'pg'
+    >>> link.database = 'host=localhost,dbname=grassdb'
+    >>> link.key = 'gid'
+
+Now change again to old values: ::
+
+    >>> link.name = 'boundary_municp_sqlite'
+    >>> link.driver = 'sqlite'
+    >>> link.database = '$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite.db'
+    >>> link.key = 'cat'
+
+Link object have methods that return a
+:ref:`Connection object <python:library:sqlite3:connection-objects>`, and to
+return a Table object: ::
+
+    >>> conn = link.connection()
+    >>> cur = conn.cursor()
+    >>> import sql
+    >>> cur.execute(sql.SELECT.format(cols=', '.join(['cat', 'AREA']),
+    ...                               tname=link.name))   # doctest: +ELLIPSIS
+    <sqlite3.Cursor object at ...>
+    >>> cur.fetchone()
+    (1, 0.0)
+    >>> cur.close()
+    >>> conn.close()
+
+From the Link object we can instantiate a Table object that allow user to
+make simple query with the Filters object: ::
+
+    >>> table = link.table()
+    >>> table.filters.select('cat', 'COUNTY',
+    ...                      'AREA','PERIMETER').order_by('AREA').limit(3)
+    Filters('SELECT cat, COUNTY, AREA, PERIMETER FROM boundary_municp_sqlite ORDER BY AREA LIMIT 3;')
+    >>> cur = table.execute()
+    >>> for row in cur.fetchall():
+    ...     print repr(row)
+    ...
+    (1, u'SURRY', 0.0, 1415.331)
+    (2, u'SURRY', 0.0, 48286.011)
+    (3, u'CASWELL', 0.0, 5750.087)
+
+
+Then we can get table information about table columns, from the columns
+attribute that is an instantiation of a Columns class.
+
+
+    >>> table.columns                                     # doctest: +ELLIPSIS
+    Columns([(u'cat', u'integer'), ..., (u'ACRES', u'double precision')])
+    >>> table.columns.names()                             # doctest: +ELLIPSIS
+    [u'cat', u'OBJECTID', u'AREA', u'PERIMETER', ..., u'ACRES']
+    >>> table.columns.types()                             # doctest: +ELLIPSIS
+    [u'integer', u'integer', u'double precision', ..., u'double precision']
+
+
+.. note ::
+    If the map use postgresql it is possible to: add/rename/cast/remove columns
+    the sqlite does not support these operations.
+
+
+For people that are used to the standardized Python SQL 2.0 interface:
+
+    * http://docs.python.org/library/sqlite3.html
+    * http://www.python.org/dev/peps/pep-0249/
+
+Therefore advanced user can just use, the connect attribute to build
+a new cursor object and interact with the database. ::
+
+    >>> cur = table.conn.cursor()
+    >>> cur.execute("SELECT * FROM %s" % table.name)     # doctest: +ELLIPSIS
+    <sqlite3.Cursor object at ...>
+    >>> cur.fetchone()[:5]                               # doctest: +ELLIPSIS
+    (1, 1, 0.0, 1415.331, 2.0)
+    >>> # Close communication with the database
+    >>> cur.close()
+    >>> conn.close()
+
+
+
+Link
+-------
+
+.. autoclass:: pygrass.vector.table.Link
+    :members:
+
+DBlinks
+-------
+
+.. autoclass:: pygrass.vector.table.DBlinks
+    :members:
+
+Filters
+-------
+
+.. autoclass:: pygrass.vector.table.Filters
+    :members:
+
+Columns
+-------
+
+.. autoclass:: pygrass.vector.table.Columns
+    :members:
+
+Table
+-----
+
+.. autoclass:: pygrass.vector.table.Table
+    :members:
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/docs/conf.py
===================================================================
--- grass/trunk/lib/python/pygrass/docs/conf.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/docs/conf.py	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,292 @@
+# -*- coding: utf-8 -*-
+#
+# PyGrass documentation build configuration file, created by
+# sphinx-quickstart2 on Sat Jun 16 18:53:32 2012.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# 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
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+sys.path.insert(0, os.path.abspath('../src/'))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.mathjax', 'sphinx.ext.ifconfig', 'sphinx.ext.viewcode']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'PyGrass'
+copyright = u'2012, Pietro Zambelli'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '0.1'
+# The full version, including alpha/beta/rc tags.
+release = 'alpha'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+language = 'python'
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+# If true, doctest flags (comments looking like # doctest: FLAG, ...)
+# at the ends of lines and <BLANKLINE> markers are removed for all code blocks
+# showing interactive Python sessions (i.e. doctests). Default is true.
+trim_doctest_flags = True
+
+
+intersphinx_mapping = {'python': ('http://docs.python.org/2.7', None)}
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+html_theme = 'default'
+
+# 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
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'PyGrassdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+'papersize': 'a4paper',
+
+# The font size ('10pt', '11pt' or '12pt').
+'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+  ('index', 'PyGrass.tex', u'PyGrass Documentation',
+   u'Pietro Zambelli', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+    ('index', 'pygrass', u'PyGrass Documentation',
+     [u'Pietro Zambelli'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output ------------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+#  dir menu entry, description, category)
+texinfo_documents = [
+  ('index', 'PyGrass', u'PyGrass Documentation',
+   u'Pietro Zambelli', 'PyGrass', 'One line description of project.',
+   'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+
+# -- Options for Epub output ---------------------------------------------------
+
+# Bibliographic Dublin Core info.
+epub_title = u'PyGrass'
+epub_author = u'Pietro Zambelli'
+epub_publisher = u'Pietro Zambelli'
+epub_copyright = u'2012, Pietro Zambelli'
+
+# The language of the text. It defaults to the language option
+# or en if the language is not set.
+#epub_language = ''
+
+# The scheme of the identifier. Typical schemes are ISBN or URL.
+#epub_scheme = ''
+
+# The unique identifier of the text. This can be a ISBN number
+# or the project homepage.
+#epub_identifier = ''
+
+# A unique identification for the text.
+#epub_uid = ''
+
+# A tuple containing the cover image and cover page html template filenames.
+#epub_cover = ()
+
+# HTML files that should be inserted before the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#epub_pre_files = []
+
+# HTML files shat should be inserted after the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#epub_post_files = []
+
+# A list of files that should not be packed into the epub file.
+#epub_exclude_files = []
+
+# The depth of the table of contents in toc.ncx.
+#epub_tocdepth = 3
+
+# Allow duplicate toc entries.
+#epub_tocdup = True

Added: grass/trunk/lib/python/pygrass/docs/index.rst
===================================================================
--- grass/trunk/lib/python/pygrass/docs/index.rst	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/docs/index.rst	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,40 @@
+.. PyGrass documentation master file, created by
+   sphinx-quickstart2 on Sat Jun 16 18:53:32 2012.
+   You can adapt this file completely to your liking, but it should at least
+   contain the root `toctree` directive.
+
+Welcome to PyGrass's documentation!
+===================================
+
+Since in the 2006 GRASS developers start to adopt python for the new GUI,
+python becoming more and more important and developers plan to convert all
+the bash scripts in to python for the next major release GRASS 7.
+
+``pygrass`` want to improve integration between GRASS and python, 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.
+
+This project has been funded with support from the google Summer of Code 2012.
+
+
+Contents:
+
+.. toctree::
+   :maxdepth: 2
+
+   intro
+   raster
+   vector
+   attributes
+   modules
+
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+

Added: grass/trunk/lib/python/pygrass/docs/intro.rst
===================================================================
--- grass/trunk/lib/python/pygrass/docs/intro.rst	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/docs/intro.rst	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,30 @@
+Introduction
+=============
+
+To work with ``pygrass`` you need a up-to-date version of GRASS 7.
+You can obtain a recent version following the information on the
+`main web site <http://grass.osgeo.org/download/software.php#g70x>`_
+of GRASS, and you can read more about compilation on the 
+`GRASS wiki <http://grass.osgeo.org/wiki/Compile_and_Install>`_
+
+Now you can download the ``pygrass`` source using ``git``
+
+::
+
+  git clone https://lucadeluge@code.google.com/p/pygrass/ 
+
+If you have not ``git`` you can install it from the `git website <http://git-scm.com/downloads>`_
+or download the source code of ``pygrass`` from `<http://code.google.com/p/pygrass/downloads/list>`_
+
+At this point you have to install ``pygrass``, so enter in the right 
+folder and launch with administration permission
+
+::
+
+  python setup.py install
+  
+The last action before start to work with ``pygrass`` is to run 
+GRASS 7 and from the console launch ``python`` or ``ipython`` 
+(the second one is the the suggested)
+
+Read more about how to work with :doc:`raster`, :doc:`vector`, :doc:`modules`.
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/docs/make.bat
===================================================================
--- grass/trunk/lib/python/pygrass/docs/make.bat	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/docs/make.bat	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,190 @@
+ at ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+	set SPHINXBUILD=sphinx-build2
+)
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+set I18NSPHINXOPTS=%SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+	set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+	set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+	:help
+	echo.Please use `make ^<target^>` where ^<target^> is one of
+	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.  text       to make text files
+	echo.  man        to make manual pages
+	echo.  texinfo    to make Texinfo files
+	echo.  gettext    to make PO message catalogs
+	echo.  changes    to make an overview over 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
+	goto end
+)
+
+if "%1" == "clean" (
+	for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+	del /q /s %BUILDDIR%\*
+	goto end
+)
+
+if "%1" == "html" (
+	%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+	goto end
+)
+
+if "%1" == "dirhtml" (
+	%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+	goto end
+)
+
+if "%1" == "singlehtml" (
+	%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+	goto end
+)
+
+if "%1" == "pickle" (
+	%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can process the pickle files.
+	goto end
+)
+
+if "%1" == "json" (
+	%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can process the JSON files.
+	goto end
+)
+
+if "%1" == "htmlhelp" (
+	%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+	goto end
+)
+
+if "%1" == "qthelp" (
+	%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+	if errorlevel 1 exit /b 1
+	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.ghc
+	goto end
+)
+
+if "%1" == "devhelp" (
+	%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished.
+	goto end
+)
+
+if "%1" == "epub" (
+	%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The epub file is in %BUILDDIR%/epub.
+	goto end
+)
+
+if "%1" == "latex" (
+	%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+	goto end
+)
+
+if "%1" == "text" (
+	%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The text files are in %BUILDDIR%/text.
+	goto end
+)
+
+if "%1" == "man" (
+	%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The manual pages are in %BUILDDIR%/man.
+	goto end
+)
+
+if "%1" == "texinfo" (
+	%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
+	goto end
+)
+
+if "%1" == "gettext" (
+	%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
+	goto end
+)
+
+if "%1" == "changes" (
+	%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.The overview file is in %BUILDDIR%/changes.
+	goto end
+)
+
+if "%1" == "linkcheck" (
+	%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+	goto end
+)
+
+if "%1" == "doctest" (
+	%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+	if errorlevel 1 exit /b 1
+	echo.
+	echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+	goto end
+)
+
+:end

Added: grass/trunk/lib/python/pygrass/docs/modules.rst
===================================================================
--- grass/trunk/lib/python/pygrass/docs/modules.rst	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/docs/modules.rst	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,204 @@
+Modules
+=======
+
+Grass modules are represented as objects. These objects are generated based
+on the XML module description that is used for GUI generation already. ::
+
+    >>> from pygrass.modules import Module
+    >>> slope_aspect = Module("r.slope.aspect", elevation='elevation',
+    ...                        slope='slp',  aspect='asp',
+    ...                        format='percent', overwrite=True)
+
+
+It is possible to create a run-able module object and run later:
+
+    >>> slope_aspect = Module("r.slope.aspect", elevation='elevation',
+    ...                        slope='slp',  aspect='asp',
+    ...                        format='percent', overwrite=True, run_=False)
+
+Then we can run the module with: ::
+
+    >>> slope_aspect()
+
+or using the run method: ::
+
+   >>> slope_aspect.run()
+
+
+It is possible to initialize a module, and give the parameters later: ::
+
+    >>> slope_aspect = Module("r.slope.aspect")
+    >>> slope_aspect(elevation='elevation', slope='slp',  aspect='asp',
+    ...              format='percent', overwrite=True)
+
+
+Create the module object input step by step and run later: ::
+
+    >>> slope_aspect = Module("r.slope.aspect")
+    >>> slope_aspect.inputs['elevation']
+    Parameter <elevation> (required:yes, type:raster, multiple:no)
+    >>> slope_aspect.inputs["elevation"].value = "elevation"
+    >>> slope_aspect.inputs["format"]
+    Parameter <format> (required:no, type:string, multiple:no)
+    >>> print slope_aspect.inputs["format"].__doc__
+    format: 'degrees', optional, string
+        Format for reporting the slope
+        Values: 'degrees', 'percent'
+    >>> slope_aspect.inputs["format"].value = 'percents'
+    Traceback (most recent call last):
+        ...
+    ValueError: The Parameter <format>, must be one of: ['degrees', 'percent']
+    >>> slope_aspect.inputs["format"].value = 'percent'
+    >>> slope_aspect.flags = "g"
+    Traceback (most recent call last):
+        ...
+    ValueError: Flag not valid, valid flag are: ['a']
+    >>> slope_aspect.flags = "a"
+    >>> slope_aspect.flags_dict['overwrite']
+    Flag <overwrite> (Allow output files to overwrite existing files)
+    >>> slope_aspect.flags_dict['overwrite'].value = True
+    >>> slope_aspect()
+
+
+
+It is possible to access to the module info, with:
+
+    >>> slope_aspect.name
+    'r.slope.aspect'
+    >>> slope_aspect.description
+    'Aspect is calculated counterclockwise from east.'
+    >>> slope_aspect.keywords
+    'raster, terrain'
+    >>> slope_aspect.label
+    'Generates raster maps of slope, aspect, curvatures and partial derivatives from a elevation raster map.'
+
+and get the module documentation with: ::
+
+    >>> print slope_aspect.__doc__
+    r.slope.aspect(elevation=elevation, slope=None, aspect=None
+                   format=percent, prec=None, pcurv=None
+                   tcurv=None, dx=None, dy=None
+                   dxx=None, dyy=None, dxy=None
+                   zfactor=None, min_slp_allowed=None)
+    <BLANKLINE>
+    Parameters
+    ----------
+    <BLANKLINE>
+    <BLANKLINE>
+    elevation: required, string
+        Name of input elevation raster map
+    slope: optional, string
+        Name for output slope raster map
+    aspect: optional, string
+        Name for output aspect raster map
+    format: 'degrees', optional, string
+        Format for reporting the slope
+        Values: 'degrees', 'percent'
+    prec: 'float', optional, string
+        Type of output aspect and slope maps
+        Values: 'default', 'double', 'float', 'int'
+    pcurv: optional, string
+        Name for output profile curvature raster map
+    tcurv: optional, string
+        Name for output tangential curvature raster map
+    dx: optional, string
+        Name for output first order partial derivative dx (E-W slope) raster map
+    dy: optional, string
+        Name for output first order partial derivative dy (N-S slope) raster map
+    dxx: optional, string
+        Name for output second order partial derivative dxx raster map
+    dyy: optional, string
+        Name for output second order partial derivative dyy raster map
+    dxy: optional, string
+        Name for output second order partial derivative dxy raster map
+    zfactor: 1.0, optional, float
+        Multiplicative factor to convert elevation units to meters
+    min_slp_allowed: optional, float
+        Minimum slope val. (in percent) for which aspect is computed
+    <BLANKLINE>
+    Flags
+    ------
+    <BLANKLINE>
+    a: None
+        Do not align the current region to the elevation layer
+    overwrite: None
+        Allow output files to overwrite existing files
+    verbose: None
+        Verbose module output
+    quiet: None
+        Quiet module output
+
+
+
+For each inputs and outputs parameters it is possible to get info, to see all
+the 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: ::
+
+    >>> slope_aspect.inputs["elevation"].description
+    'Name of input elevation raster map'
+    >>> slope_aspect.inputs["elevation"].type
+    'raster'
+    >>> slope_aspect.inputs["elevation"].typedesc
+    'string'
+    >>> slope_aspect.inputs["elevation"].multiple
+    False
+    >>> slope_aspect.inputs["elevation"].required
+    True
+
+Or get a small documentation for each parameter with:
+
+    >>> print slope_aspect.inputs["elevation"].__doc__
+    elevation: required, string
+        Name of input elevation raster map
+
+
+User or developer can check which parameter are 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
+instantiate a popen attribute to the class. The `Popen`_ class allow user
+to kill/wait/ the process. ::
+
+    >>> slope_aspect = Module('r.slope.aspect')
+    >>> slope_aspect(elevation='elevation', slope='slp', aspect='asp', overwrite=True, finish_=False)
+    >>> slope_aspect.popen.wait() # *.kill(), *.terminate()
+    0
+    >>> out, err = slope_aspect.popen.communicate()
+    >>> print err #doctest: +NORMALIZE_WHITESPACE
+     100%
+    Aspect raster map <asp> complete
+    Slope raster map <slp> complete
+    <BLANKLINE>
+
+On the above example we use a new parameter `finish_`, if is set to True, the
+run method, automatically store the stdout and stderr to stdout and stderr
+attributes of the class: ::
+
+    >>> slope_aspect = Module('r.slope.aspect')
+    >>> slope_aspect(elevation='elevation', slope='slp', aspect='asp', overwrite=True, finish_=True)
+    >>> print slope_aspect.stderr #doctest: +NORMALIZE_WHITESPACE
+     100%
+    Aspect raster map <asp> complete
+    Slope raster map <slp> complete
+    <BLANKLINE>
+
+Another example of use: ::
+
+    >>> info = Module("r.info", map="elevation", flags="r", finish_=True)
+    >>> from pygrass.modules import stdout2dict
+    >>> stdout2dict(info.stdout)
+    {'max': '156.3299', 'min': '55.57879'}
+    >>> info = Module("r.info", map="elevation", flags="r", finish_=False)
+    >>> category = Module("r.category", map="elevation",
+    ...                   stdin_=info.popen.stdout, finish_=True)
+
+
+
+.. _Popen: http://docs.python.org/library/subprocess.html#Popen

Added: grass/trunk/lib/python/pygrass/docs/raster.rst
===================================================================
--- grass/trunk/lib/python/pygrass/docs/raster.rst	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/docs/raster.rst	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,399 @@
+.. _raster-label:
+
+Raster
+======
+
+PyGrass use 4 different Raster classes, that respect the 4 different approaches
+of C grass API.
+The read access is row wise for :ref:`RasterRow-label` and
+:ref:`RasterRowIO-label` and additionally
+cached in the RowIO class. Booth classes write sequentially.
+RowIO is row cached, :ref:`RasterSegment-label` and :ref:`RasterNumpy-label`
+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.
+
+
+==========================  =======================  ========  ============
+Class Name                  C library                Read      Write
+==========================  =======================  ========  ============
+:ref:`RasterRow-label`      `Raster library`_        randomly  sequentially
+:ref:`RasterRowIO-label`    `RowIO library`_         cached    no
+:ref:`RasterSegment-label`  `Segmentation library`_  cached    randomly
+:ref:`RasterNumpy-label`    `numpy.memmap`_          cached    randomly
+==========================  =======================  ========  ============
+
+
+All these classes share common methods and attributes, necessary to address
+common tasks as rename, remove, open, close, exist, is_open.
+In the next examples we instantiate a RasterRow object. ::
+
+    >>> from pygrass import raster
+    >>> elev = raster.RasterRow('elevation')
+    >>> elev.name
+    'elevation'
+    >>> print(elev)
+    elevation at PERMANENT
+    >>> elev.exist()
+    True
+    >>> elev.is_open()
+    False
+    >>> new = raster.RasterRow('new')
+    >>> new.exist()
+    False
+    >>> new.is_open()
+    False
+
+
+We can rename the map: ::
+
+    >>> # setting the attribute
+    >>> new.name = 'new_map'
+    >>> print(new)
+    new_map
+    >>> # or using the rename methods
+    >>> new.rename('new')
+    >>> 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 to 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
+-------
+
+PyGrass allow user to open the maps, in read and write mode,
+row by row using the `Raster library`_, there is not support to read and write
+to the same map at the same time, for this functionality, please see the
+:ref:`RasterSegment-label` and :ref:`RasterNumpy-label` classes.
+The RasterRow class allow to read in a randomly order the row from a map, but
+it is only possible to write the map using only a sequence order, therefore every
+time you are writing a new map, the row is add to the file as the last row. ::
+
+    >>> raster = reload(raster)
+    >>> elev = raster.RasterRow('elevation')
+    >>> # the cols attribute is set from the current region only when the map is open
+    >>> elev.cols
+    >>> elev.open()
+    >>> elev.is_open()
+    True
+    >>> elev.cols
+    1500
+    >>> # we can read the elevation map, row by row
+    >>> for row in elev[:5]: print(row[:3])
+    [ 141.99613953  141.27848816  141.37904358]
+    [ 142.90461731  142.39450073  142.68611145]
+    [ 143.81854248  143.54707336  143.83972168]
+    [ 144.56524658  144.58493042  144.86477661]
+    [ 144.99488831  145.22894287  145.57142639]
+    >>> # we can open a new map in write mode
+    >>> new = raster.RasterRow('new')
+    >>> new.open('w', 'CELL')
+    >>> # for each elev row we can perform computation, and write the result into
+    >>> # the new map
+    >>> for row in elev:
+    ...     new.put_row(row < 144)
+    ...
+    >>> # close the maps
+    >>> new.close()
+    >>> elev.close()
+    >>> # check if the map exist
+    >>> new.exist()
+    True
+    >>> # we can open the map in read mode
+    >>> new.open('r')
+    >>> for row in new[:5]: print(row[:3])
+    [1 1 1]
+    [1 1 1]
+    [1 1 1]
+    [0 0 0]
+    [0 0 0]
+    >>> new.close()
+    >>> new.remove()
+    >>> new.exist()
+    False
+
+
+.. _RasterRowIO-label:
+
+RasterRowIO
+-----------
+
+The RasterRowIO class use the grass `RowIO library`_, and implement a row
+cache. The RasterRowIO class support only reading the raster, because the
+raster rows can only be written in sequential order, writing by row id is not
+supported by design. Hence, we should use the rowio lib only for caching rows
+for reading and use the default row write access as in the RasterRow class. ::
+
+    >>> raster = reload(raster)
+    >>> elev = raster.RasterRowIO('elevation')
+    >>> elev.open('r')
+    >>> for row in elev[:5]: print(row[:3])
+    [ 141.99613953  141.27848816  141.37904358]
+    [ 142.90461731  142.39450073  142.68611145]
+    [ 143.81854248  143.54707336  143.83972168]
+    [ 144.56524658  144.58493042  144.86477661]
+    [ 144.99488831  145.22894287  145.57142639]
+    >>> elev.close()
+
+
+
+.. _RasterSegment-label:
+
+RastSegment
+-----------
+
+The RasterSegment class use the grass `Segmentation library`_, it work dividing
+the raster map into small different files, that grass read load into the memory
+and write to the hardisk.
+The segment library allow to open a map in a read-write mode. ::
+
+    >>> raster = reload(raster)
+    >>> elev = raster.RasterSegment('elevation')
+    >>> elev.open()
+    >>> for row in elev[:5]: print(row[:3])
+    [ 141.99613953  141.27848816  141.37904358]
+    [ 142.90461731  142.39450073  142.68611145]
+    [ 143.81854248  143.54707336  143.83972168]
+    [ 144.56524658  144.58493042  144.86477661]
+    [ 144.99488831  145.22894287  145.57142639]
+    >>> new = raster.RasterSegment('new')
+    >>> new.open('w', 'CELL')
+    >>> for irow in xrange(elev.rows):
+    ...     new[irow] = elev[irow] < 144
+    ...
+    >>> for row in new[:5]: print(row[:3])
+    [1 1 1]
+    [1 1 1]
+    [1 1 1]
+    [0 0 0]
+    [0 0 0]
+
+The RasterSegment class define two methods to read and write the map:
+
+    * ``get_row`` that return the buffer object with the row that call the
+      C function ``segment_get_row``. ::
+
+        >>> # call explicity the method
+        >>> elev_row0 = elev.get_row(0)
+        >>> # call implicity the method
+        >>> elev_row0 = elev[0]
+
+    * ``get`` that return the value of the call map that call the
+      C function ``segment_get``. ::
+
+        >>> # call explicity the method
+        >>> elev_val_0_0 = elev.get(0, 0)
+        >>> # call implicity the method
+        >>> elev_val_0_0 = elev[0, 0]
+
+Similarly to write the map, with ``put_row``, to write a row and with ``put``
+to write a single value to the map. ::
+
+    >>> # compare the cell value get using the ``get`` method, and take the first
+    >>> # value of the row with the ``get_row`` method
+    >>> elev[0, 0] == elev[0][0]
+    True
+    >>> # write a new value to a cell,
+    >>> new[0, 0] = 10
+    >>> new[0, 0]
+    10
+    >>> new.close()
+    >>> new.exist()
+    True
+    >>> new.remove()
+    >>> elev.close()
+    >>> elev.remove()
+
+
+
+.. _RasterNumpy-label:
+
+RasterNumpy
+-----------
+
+The RasterNumpy class, is based on the `numpy.memmap`_ class If you open an
+existing map, the map will be copied on a binary format, and read to avoid
+to load all the map in memory. ::
+
+    >>> raster = reload(raster)
+    >>> elev = raster.RasterNumpy('elevation', 'PERMANENT')
+    >>> elev.open('r')
+    >>> # in this case RasterNumpy is an extention of the numpy class
+    >>> # therefore you may use all the fancy things of numpy.
+    >>> elev[:5, :3]
+    RasterNumpy([[ 141.99613953,  141.27848816,  141.37904358],
+           [ 142.90461731,  142.39450073,  142.68611145],
+           [ 143.81854248,  143.54707336,  143.83972168],
+           [ 144.56524658,  144.58493042,  144.86477661],
+           [ 144.99488831,  145.22894287,  145.57142639]], dtype=float32)
+    >>> el = elev < 144
+    >>> el[:5, :3]
+    RasterNumpy([[1, 1, 1],
+           [1, 1, 1],
+           [1, 1, 1],
+           [0, 0, 0],
+           [0, 0, 0]], dtype=int32)
+    >>> el.name == None
+    True
+    >>> # give a name to the new map
+    >>> el.name = 'new'
+    >>> el.exist()
+    False
+    >>> el.close()
+    >>> el.exist()
+    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
+    :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
+.. _Segmentation library: http://grass.osgeo.org/programming7/segmentlib.html
+.. _numpy.memmap: http://docs.scipy.org/doc/numpy/reference/generated/numpy.memmap.html
+

Added: grass/trunk/lib/python/pygrass/docs/vector.rst
===================================================================
--- grass/trunk/lib/python/pygrass/docs/vector.rst	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/docs/vector.rst	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,197 @@
+
+Vector
+========
+
+Instantiation and basic interaction. ::
+
+    >>> from pygrass.vector import VectTopo
+    >>> municip = VectTopo('boundary_municp_sqlite')
+    >>> municip.is_open()
+    False
+    >>> municip.mapset
+    ''
+    >>> municip.exist()  # check if exist, and if True set mapset
+    True
+    >>> municip.mapset
+    'user1'
+
+
+
+Open the map with topology: ::
+
+    >>> municip.open()
+
+    get the number of primitive:
+    >>> municip.num_primitive_of('line')
+    0
+    >>> municip.num_primitive_of('centroid')
+    3579
+    >>> municip.num_primitive_of('boundary')
+    5128
+
+
+
+ask for other feature in the vector map: ::
+
+    >>> municip.number_of("areas")
+    3579
+    >>> municip.number_of("islands")
+    2629
+    >>> municip.number_of("holes")
+    0
+    >>> municip.number_of("lines")
+    8707
+    >>> municip.number_of("nodes")
+    4178
+    >>> municip.number_of("pizza")  # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
+    Traceback (most recent call last):
+        ...
+    ValueError: vtype not supported, use one of: 'areas', ..., 'volumes'
+
+
+Suppose that we want to select all and only the areas that have an
+area bigger than 10000m2: ::
+
+    >>> big = [area for area in municip.viter('areas')
+    ...        if area.alive() and area.area >= 10000]
+
+it's pretty easy, isn't it?!? :-)
+
+the method "viter" return an iterator object of the vector features,
+in this way no memory is wasted... User can choose on which
+vector features want to iterate...
+
+
+then you can go on with python stuff like, sort by area dimension: ::
+
+    >>> from operator import methodcaller as method
+    >>> big.sort(key = method('area'), reverse = True)  # sort the list
+    >>> for area in big[:3]:
+    ...     print area, area.area()
+    Area(3102) 697521857.848
+    Area(2682) 320224369.66
+    Area(2552) 298356117.948
+
+
+or sort for the number of isles that are contained inside: ::
+
+    >>> big.sort(key = lambda x: x.isles.__len__(), reverse = True)
+    >>> for area in big[:3]:
+    ...     print area, area.isles.__len__()
+    ...
+    Area(2682) 68
+    Area(2753) 45
+    Area(872) 42
+
+
+or you may have only the list of the areas that contain isles inside, with: ::
+
+    >>> area_with_isles = [area for area in big if area.isles]
+    >>> area_with_isles                                   # doctest: +ELLIPSIS
+    [Area(...), ..., Area(...)]
+
+
+
+Of course is still possible work only with a specific area, with: ::
+
+    >>> from pygrass.vector.geometry import Area
+    >>> area = Area(v_id=1859, c_mapinfo=municip.c_mapinfo)
+    >>> area.area()
+    39486.05401495844
+    >>> area.bbox()  # north, south, east, west
+    Bbox(175711.718494, 175393.514494, 460344.093986, 460115.281986)
+    >>> area.isles
+    Isles([])
+
+
+Now, find an area with an island inside... ::
+
+    >>> area = Area(v_id=2972, c_mapinfo=municip.c_mapinfo)
+    >>> area.isles                                       # doctest: +ELLIPSIS
+    Isles([Isle(1538), Isle(1542), Isle(1543), ..., Isle(2571)])
+    >>> isle = area.isles[0]
+    >>> isle.bbox()
+    Bbox(199947.296494, 199280.969494, 754920.623987, 754351.812986)
+
+
+VectorTopo
+----------
+
+.. autoclass:: pygrass.vector.VectorTopo
+    :members:
+
+Vector
+----------
+
+.. autoclass:: pygrass.vector.Vector
+    :members:
+
+
+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
+    :members:
+
+Cats
+-----
+
+.. autoclass:: pygrass.vector.basic.Cats
+    :members:
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/env.py
===================================================================
--- grass/trunk/lib/python/pygrass/env.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/env.py	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,57 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Tue Jun 26 12:38:48 2012
+
+ at author: pietro
+"""
+import grass.lib.gis as libgis
+import fnmatch
+from grass.script import core as grasscore
+
+
+def looking(filter_string, obj):
+    """
+    >>> import grass.lib.vector as libvect
+    >>> sorted(looking('*by_box*', libvect))  # doctest: +NORMALIZE_WHITESPACE
+    ['Vect_select_areas_by_box', 'Vect_select_isles_by_box',
+     'Vect_select_lines_by_box', 'Vect_select_nodes_by_box']
+
+    """
+    word_list = [i for i in dir(obj)]
+    word_list.sort()
+    return fnmatch.filter(word_list, filter_string)
+
+
+def remove(**kargs):
+    grasscore.run_command('g.remove', **kargs)
+
+
+def rename(oldname, newname, maptype):
+    grasscore.run_command('g.rename',
+                          **{maptype: '{old},{new}'.format(old=oldname,
+                                                           new=newname), })
+
+
+def copy(existingmap, newmap, maptype):
+    grasscore.run_command('g.copy',
+                          **{maptype: '{old},{new}'.format(old=existingmap,
+                                                           new=newmap), })
+
+
+def get_mapset_raster(mapname, mapset=''):
+    return libgis.G_find_raster(mapname, '')
+
+
+def get_mapset_vector(mapname, mapset=''):
+    return libgis.G_find_vector(mapname, '')
+
+
+def exist(mapname, mapset=''):
+    mapset = get_mapset_raster(mapname, mapset)
+    if mapset != '':
+        return True
+    else:
+        mapset = get_mapset_vector(mapname, mapset)
+        if mapset:
+            return True
+    return False
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/errors.py
===================================================================
--- grass/trunk/lib/python/pygrass/errors.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/errors.py	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,22 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Wed Aug 15 17:33:27 2012
+
+ at author: pietro
+"""
+
+
+class GrassError(Exception):
+    def __init__(self, value):
+        self.value = value
+
+    def __str__(self):
+        return repr(self.value)
+
+
+class OpenError(Exception):
+    def __init__(self, value):
+        self.value = value
+
+    def __str__(self):
+        return repr(self.value)
\ No newline at end of file

Copied: grass/trunk/lib/python/pygrass/modules/Makefile (from rev 53343, grass/trunk/lib/python/Makefile)
===================================================================
--- grass/trunk/lib/python/pygrass/modules/Makefile	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/modules/Makefile	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,31 @@
+MODULE_TOPDIR = ../../../..
+
+include $(MODULE_TOPDIR)/include/Make/Other.make
+include $(MODULE_TOPDIR)/include/Make/Python.make
+include $(MODULE_TOPDIR)/include/Make/Doxygen.make
+
+PYDIR = $(ETC)/python
+GDIR = $(PYDIR)/grass
+PGDIR = $(GDIR)/pygrass
+DSTDIR= $(PGDIR)/modules
+
+
+PYFILES := $(patsubst %,$(DSTDIR)/%.py,$(MODULES) __init__)
+PYCFILES := $(patsubst %,$(DSTDIR)/%.pyc,$(MODULES) __init__)
+
+default: $(PYFILES) $(PYCFILES) $(GDIR)/__init__.py $(GDIR)/__init__.pyc
+
+$(PYDIR):
+	$(MKDIR) $@
+
+$(GDIR): | $(PYDIR)
+	$(MKDIR) $@
+
+$(DSTDIR): | $(GDIR)
+	$(MKDIR) $@
+
+$(DSTDIR)/%: % | $(DSTDIR)
+	$(INSTALL_DATA) $< $@
+
+#doxygen:
+DOXNAME = pythonpygrass
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/modules/__init__.py
===================================================================
--- grass/trunk/lib/python/pygrass/modules/__init__.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/modules/__init__.py	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,500 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Thu Jul 12 10:23:15 2012
+
+ at author: pietro
+
+"""
+from __future__ import print_function
+import subprocess
+
+try:
+    from collections import OrderedDict
+except:
+    from pygrass.orderdict import OrderedDict
+
+from itertools import izip_longest
+from xml.etree.ElementTree import fromstring
+import numpy as np
+import grass
+
+
+#
+# this dictionary is used to extract the value of interest from the xml
+# the lambda experssion is used to define small simple functions,
+# is equivalent to: ::
+#
+# def f(p):
+#     return p.text.strip()
+#
+# and then we call f(p)
+#
+_GETFROMTAG = {
+    'description': lambda p: p.text.strip(),
+    'keydesc': lambda p: p.text.strip(),
+    'gisprompt': lambda p: dict(p.items()),
+    'default': lambda p: p.text.strip(),
+    'values': lambda p: [e.text.strip() for e in p.findall('value/name')],
+    'value': lambda p: None,
+    'guisection': lambda p: p.text.strip(),
+    'label': lambda p: p.text.strip(),
+    'suppress_required': lambda p: None,
+    'keywords': lambda p: p.text.strip(),
+}
+
+_GETTYPE = {
+    'string': str,
+    'integer': np.int32,
+    'float': np.float32,
+    'double': np.float64,
+}
+
+
+def stdout2dict(stdout, sep='=', default=None, val_type=None, vsep=None):
+    """Return a dictionary where entries are separated
+    by newlines and the key and value are separated by `sep' (default: `=').
+    Use the grass.core.parse_key_val function
+
+    sep: key/value separator
+    default: default value to be used
+    val_type: value type (None for no cast)
+    vsep: vertical separator (default os.linesep)
+    """
+    return grass.script.core.parse_key_val(stdout, sep, default,
+                                           val_type, vsep)
+
+
+class ParameterError(Exception):
+    pass
+
+
+class FlagError(Exception):
+    pass
+
+
+def _element2dict(xparameter):
+    diz = dict(xparameter.items())
+    for p in xparameter:
+        if p.tag in _GETFROMTAG:
+            diz[p.tag] = _GETFROMTAG[p.tag](p)
+        else:
+            print('New tag: %s, ignored' % p.tag)
+    return diz
+
+# dictionary used to create docstring for the objects
+_DOC = {
+    #------------------------------------------------------------
+    # head
+    'head': """{cmd_name}({cmd_params})
+
+Parameters
+----------
+
+""",
+    #------------------------------------------------------------
+    # param
+    'param': """{name}: {default}{required}{multi}{ptype}
+    {description}{values}""",
+    #------------------------------------------------------------
+    # flag_head
+    'flag_head': """
+Flags
+------
+""",
+    #------------------------------------------------------------
+    # flag
+    'flag': """{name}: {default}
+    {description}""",
+    #------------------------------------------------------------
+    # foot
+    'foot': """
+Special Parameters
+------------------
+
+The Module class have some optional parameters which are distinct using a final
+underscore.
+
+run_: True, optional
+    If True execute the module.
+finish_: True, optional
+    If True wait untill the end of the module execution, and store the module
+    outputs into stdout, stderr attributes of the class.
+stdin_: PIPE,
+    Set the standard input
+"""}
+
+
+class Parameter(object):
+
+    def __init__(self, xparameter=None, diz=None):
+        self._value = None
+        diz = _element2dict(xparameter) if xparameter is not None else diz
+        if diz is None:
+            raise TypeError('Xparameter or diz are required')
+        self.name = diz['name']
+        self.required = True if diz['required'] == 'yes' else False
+        self.multiple = True if diz['multiple'] == 'yes' else False
+        # check the type
+        if diz['type'] in _GETTYPE:
+            self.type = _GETTYPE[diz['type']]
+            self.typedesc = diz['type']
+            self._type = _GETTYPE[diz['type']]
+        else:
+            raise TypeError('New type: %s, ignored' % diz['type'])
+
+        self.description = diz['description']
+        self.keydesc = diz['keydesc'] if 'keydesc' in diz else None
+        self.values = [self._type(
+            i) for i in diz['values']] if 'values' in diz else None
+        self.default = self._type(
+            diz['default']) if 'default' in diz else None
+        self.guisection = diz['guisection'] if 'guisection' in diz else None
+        if 'gisprompt' in diz:
+            self.type = diz['gisprompt']['prompt']
+            self.input = False if diz['gisprompt']['age'] == 'new' else True
+        else:
+            self.input = True
+
+    def _get_value(self):
+        return self._value
+
+    def _set_value(self, value):
+        if isinstance(value, list) or isinstance(value, tuple):
+            if self.multiple:
+                # check each value
+                self._value = [
+                    val for val in value if isinstance(value, self._type)]
+            else:
+                str_err = 'The Parameter <%s>, not support multiple inputs'
+                raise TypeError(str_err % self.name)
+        elif isinstance(value, self._type):
+            if self.values:
+                if value in self.values:
+                    self._value = value
+                else:
+                    raise ValueError('The Parameter <%s>, must be one of: %r' %
+                                     (self.name, self.values))
+            else:
+                self._value = value
+        else:
+            raise TypeError('The Parameter <%s>, require: %s' %
+                            (self.name, self.typedesc))
+
+    # 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)
+
+    def __str__(self):
+        if isinstance(self._value, list) or isinstance(self._value, tuple):
+            value = ','.join([str(v) for v in self._value])
+        else:
+            value = str(self._value)
+        return "%s=%s" % (self.name, value)
+
+    def __repr__(self):
+        str_repr = "Parameter <%s> (required:%s, type:%s, multiple:%s)"
+        return str_repr % (self.name,
+                           "yes" if self.required else "no",
+                           self.type if self.type in (
+                           'raster', 'vector') else self.typedesc,
+                           "yes" if self.multiple else "no")
+
+    # here we use property with a decorator, in this way we mask a method as
+    # a class attribute
+    @property
+    def __doc__(self):
+        """Return the docstring of the parameter
+
+        {name}: {default}{required}{multi}{ptype}
+            {description}{values}"","""
+        return _DOC['param'].format(name=self.name,
+                default=repr(self.default) + ', ' if self.default else '',
+                required='required, ' if self.required else 'optional, ',
+                multi='multi' if self.multiple else '',
+                ptype=self.typedesc, description=self.description,
+                values='\n    Values: {0}'.format(', '.join([repr(val)
+                                                  for val in self.values]))
+                       if self.values else '')
+
+
+class TypeDict(OrderedDict):
+    def __init__(self, dict_type, *args, **kargs):
+        self.type = dict_type
+        super(TypeDict, self).__init__(*args, **kargs)
+
+    def __setitem__(self, key, value):
+        if isinstance(value, self.type):
+            super(TypeDict, self).__setitem__(key, value)
+        else:
+            cl = repr(self.type).translate(None, "'<> ").split('.')
+            str_err = 'The value: %r is not a %s object'
+            raise TypeError(str_err % (value, cl[-1].title()))
+
+    @property
+    def __doc__(self):
+        return '\n'.join([self.__getitem__(obj).__doc__
+                          for obj in self.__iter__()])
+
+    def __call__(self):
+        return [self.__getitem__(obj) for obj in self.__iter__()]
+
+
+class Flag(object):
+    def __init__(self, xflag=None, diz=None):
+        self.value = None
+        diz = _element2dict(xflag) if xflag is not None else diz
+        self.name = diz['name']
+        self.special = True if self.name in (
+            'verbose', 'overwrite', 'quiet', 'run') else False
+        self.description = diz['description']
+        self.default = diz['default'] if 'default' in diz else None
+        self.guisection = diz['guisection'] if 'guisection' in diz else None
+
+    def __str__(self):
+        if self.value:
+            if self.special:
+                return '--%s' % self.name[0]
+            else:
+                return '-%s' % self.name
+        else:
+            return ''
+
+    def __repr__(self):
+        return "Flag <%s> (%s)" % (self.name, self.description)
+
+    @property
+    def __doc__(self):
+        """
+        {name}: {default}
+            {description}"""
+        return _DOC['flag'].format(name=self.name,
+                                   default=repr(self.default),
+                                   description=self.description)
+
+
+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: ::
+
+        >>> f('grass', 'gis', 'modules')
+        grass
+        gis
+        modules
+
+    or we can define a new list: ::
+
+        >>> words = ['grass', 'gis', 'modules']
+        >>> f(*words)
+        grass
+        gis
+        modules
+
+    we can do the same with keyword arguments, rewrite the above function: ::
+
+        def f(*args, **kargs):
+            for arg in args:
+                print arg
+            for key, value in kargs.items():
+                print "%s = %r" % (key, value)
+
+    now we can use the new function, with: ::
+
+        >>> f('grass', 'gis', 'modules', os = 'linux', language = 'python')
+        grass
+        gis
+        modules
+        os = 'linux'
+        language = 'python'
+
+    or, as before we can, define a dictionary and give the dictionary to
+    the function, like: ::
+
+        >>> keywords = {'os' : 'linux', 'language' : 'python'}
+        >>> f(*words, **keywords)
+        grass
+        gis
+        modules
+        os = 'linux'
+        language = 'python'
+
+    In the Module class we heavily use this language feature to pass arguments
+    and keyword arguments to the grass module.
+    """
+    def __init__(self, cmd, *args, **kargs):
+        self.name = cmd
+        # call the command with --interface-description
+        get_cmd_xml = subprocess.Popen([cmd, "--interface-description"],
+                                       stdout=subprocess.PIPE)
+        # get the xml of the module
+        self.xml = get_cmd_xml.communicate()[0]
+        # transform and parse the xml into an Element class:
+        # http://docs.python.org/library/xml.etree.elementtree.html
+        tree = fromstring(self.xml)
+
+        for e in tree:
+            if e.tag not in ('parameter', 'flag'):
+                self.__setattr__(e.tag, _GETFROMTAG[e.tag](e))
+
+        #
+        # extract parameters from the xml
+        #
+        self.params_list = [Parameter(p) for p in tree.findall("parameter")]
+        self.inputs = TypeDict(Parameter)
+        self.outputs = TypeDict(Parameter)
+        self.required = []
+        # Insert parameters into input/output and required
+        for par in self.params_list:
+            if par.input:
+                self.inputs[par.name] = par
+            else:
+                self.outputs[par.name] = par
+            if par.required:
+                self.required.append(par)
+
+        #
+        # extract flags from the xml
+        #
+        flags_list = [Flag(f) for f in tree.findall("flag")]
+        self.flags_dict = TypeDict(Flag)
+        for flag in flags_list:
+            self.flags_dict[flag.name] = flag
+
+        #
+        # Add new attributes to the class
+        #
+        self._flags = ''
+        self.run_ = True
+        self.finish_ = True
+        self.stdin_ = subprocess.PIPE
+        self.stdout = subprocess.PIPE
+        self.stderr = subprocess.PIPE
+        self.popen = None
+
+        if args or kargs:
+            self.__call__(*args, **kargs)
+
+    def _get_flags(self):
+        return self._flags
+
+    def _set_flags(self, value):
+        if isinstance(value, str):
+            flgs = [flg for flg in self.flags_dict
+                    if not self.flags_dict[flg].special]
+            # we need to check if the flag is valid, special flags are not
+            # allow
+            if value in flgs:
+                self._flags = value
+            else:
+                raise ValueError('Flag not valid, valid flag are: %r' % flgs)
+        else:
+            raise TypeError('The flags attribute must be a string')
+
+    flags = property(fget=_get_flags, fset=_set_flags)
+
+    def __call__(self, *args, **kargs):
+        if not args and not kargs:
+            self.run()
+            return
+        #
+        # check for extra kargs, set attribute and remove from dictionary
+        #
+        if 'flags' in kargs:
+            self.flags = kargs['flags']
+            del(kargs['flags'])
+        if 'run_' in kargs:
+            self.run_ = kargs['run_']
+            del(kargs['run_'])
+        if 'stdin_' in kargs:
+            self.stdin_ = kargs['stdin_']
+            del(kargs['stdin_'])
+        if 'finish_' in kargs:
+            self.finish_ = kargs['finish_']
+            del(kargs['finish_'])
+
+        #
+        # check args
+        #
+        for param, arg in zip(self.params_list, args):
+            param.value = arg
+        for key, val in kargs.items():
+            if key in self.inputs:
+                self.inputs[key].value = val
+            elif key in self.outputs:
+                self.outputs[key].value = val
+            elif key in self.flags_dict:
+                # we need to add this, because some parameters (overwrite,
+                # verbose and quiet) work like parameters
+                self.flags_dict[key].value = val
+            else:
+                raise ParameterError('Parameter not found')
+
+        #
+        # check reqire parameters
+        #
+        for par in self.required:
+            if par.value is None:
+                raise ParameterError(
+                    "Required parameter <%s> not set." % par.name)
+
+        #
+        # check flags parameters
+        #
+        if self.flags:
+            # check each character in flags
+            for flag in self.flags:
+                if flag in self.flags_dict:
+                    self.flags_dict[flag].value = True
+                else:
+                    raise FlagError('Flag "%s" not valid.')
+
+        #
+        # check if execute
+        #
+        if self.run_:
+            self.run()
+
+    @property
+    def __doc__(self):
+        """{cmd_name}({cmd_params})
+        """
+        head = _DOC['head'].format(cmd_name=self.name,
+             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
+             [str(param) for param in line if param is not None])
+             # make a list of parameters with only 3 param per line
+             for line in izip_longest(*[iter(self.params_list)] * 3)]),)
+        params = '\n'.join([par.__doc__ for par in self.params_list])
+        flags = self.flags_dict.__doc__
+        return '\n'.join([head, params, _DOC['flag_head'], flags])
+
+    def make_cmd(self):
+        args = [self.name, ]
+        for par in self.params_list:
+            if par.value is not None:
+                args.append(str(par))
+        for flg in self.flags_dict:
+            if self.flags_dict[flg].value is not None:
+                args.append(str(self.flags_dict[flg]))
+        return args
+
+    def run(self, node=None):
+        cmd = self.make_cmd()
+        #print(repr(cmd))
+        self.popen = subprocess.Popen(cmd, stdin=self.stdin_,
+                                      stdout=subprocess.PIPE,
+                                      stderr=subprocess.PIPE)
+        if self.finish_:
+            self.popen.wait()
+            self.stdout, self.stderr = self.popen.communicate()
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/orderdict.py
===================================================================
--- grass/trunk/lib/python/pygrass/orderdict.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/orderdict.py	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,259 @@
+# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy.
+# Passes Python2.7's test suite and incorporates all the latest updates.
+# Created by Raymond Hettinger on Wed, 18 Mar 2009 (MIT License)
+
+try:
+    from thread import get_ident as _get_ident
+except ImportError:
+    from dummy_thread import get_ident as _get_ident
+
+try:
+    from _abcoll import KeysView, ValuesView, ItemsView
+except ImportError:
+    pass
+
+
+class OrderedDict(dict):
+    'Dictionary that remembers insertion order'
+    # An inherited dict maps keys to values.
+    # The inherited dict provides __getitem__, __len__, __contains__, and get.
+    # The remaining methods are order-aware.
+    # Big-O running times for all methods are the same as for regular dictionaries.
+
+    # The internal self.__map dictionary maps keys to links in a doubly linked list.
+    # The circular doubly linked list starts and ends with a sentinel element.
+    # The sentinel element never gets deleted (this simplifies the algorithm).
+    # Each link is stored as a list of length three:  [PREV, NEXT, KEY].
+
+    def __init__(self, *args, **kwds):
+        '''Initialize an ordered dictionary.  Signature is the same as for
+        regular dictionaries, but keyword arguments are not recommended
+        because their insertion order is arbitrary.
+
+        '''
+        if len(args) > 1:
+            raise TypeError('expected at most 1 arguments, got %d' % len(args))
+        try:
+            self.__root
+        except AttributeError:
+            self.__root = root = []                     # sentinel node
+            root[:] = [root, root, None]
+            self.__map = {}
+        self.__update(*args, **kwds)
+
+    def __setitem__(self, key, value, dict_setitem=dict.__setitem__):
+        'od.__setitem__(i, y) <==> od[i]=y'
+        # Setting a new item creates a new link which goes at the end of the linked
+        # list, and the inherited dictionary is updated with the new key/value pair.
+        if key not in self:
+            root = self.__root
+            last = root[0]
+            last[1] = root[0] = self.__map[key] = [last, root, key]
+        dict_setitem(self, key, value)
+
+    def __delitem__(self, key, dict_delitem=dict.__delitem__):
+        'od.__delitem__(y) <==> del od[y]'
+        # Deleting an existing item uses self.__map to find the link which is
+        # then removed by updating the links in the predecessor and successor nodes.
+        dict_delitem(self, key)
+        link_prev, link_next, key = self.__map.pop(key)
+        link_prev[1] = link_next
+        link_next[0] = link_prev
+
+    def __iter__(self):
+        'od.__iter__() <==> iter(od)'
+        root = self.__root
+        curr = root[1]
+        while curr is not root:
+            yield curr[2]
+            curr = curr[1]
+
+    def __reversed__(self):
+        'od.__reversed__() <==> reversed(od)'
+        root = self.__root
+        curr = root[0]
+        while curr is not root:
+            yield curr[2]
+            curr = curr[0]
+
+    def clear(self):
+        'od.clear() -> None.  Remove all items from od.'
+        try:
+            for node in self.__map.itervalues():
+                del node[:]
+            root = self.__root
+            root[:] = [root, root, None]
+            self.__map.clear()
+        except AttributeError:
+            pass
+        dict.clear(self)
+
+    def popitem(self, last=True):
+        '''od.popitem() -> (k, v), return and remove a (key, value) pair.
+        Pairs are returned in LIFO order if last is true or FIFO order if false.
+
+        '''
+        if not self:
+            raise KeyError('dictionary is empty')
+        root = self.__root
+        if last:
+            link = root[0]
+            link_prev = link[0]
+            link_prev[1] = root
+            root[0] = link_prev
+        else:
+            link = root[1]
+            link_next = link[1]
+            root[1] = link_next
+            link_next[0] = root
+        key = link[2]
+        del self.__map[key]
+        value = dict.pop(self, key)
+        return key, value
+
+    # -- the following methods do not depend on the internal structure --
+
+    def keys(self):
+        'od.keys() -> list of keys in od'
+        return list(self)
+
+    def values(self):
+        'od.values() -> list of values in od'
+        return [self[key] for key in self]
+
+    def items(self):
+        'od.items() -> list of (key, value) pairs in od'
+        return [(key, self[key]) for key in self]
+
+    def iterkeys(self):
+        'od.iterkeys() -> an iterator over the keys in od'
+        return iter(self)
+
+    def itervalues(self):
+        'od.itervalues -> an iterator over the values in od'
+        for k in self:
+            yield self[k]
+
+    def iteritems(self):
+        'od.iteritems -> an iterator over the (key, value) items in od'
+        for k in self:
+            yield (k, self[k])
+
+    def update(*args, **kwds):
+        '''od.update(E, **F) -> None.  Update od from dict/iterable E and F.
+
+        If E is a dict instance, does:           for k in E: od[k] = E[k]
+        If E has a .keys() method, does:         for k in E.keys(): od[k] = E[k]
+        Or if E is an iterable of items, does:   for k, v in E: od[k] = v
+        In either case, this is followed by:     for k, v in F.items(): od[k] = v
+
+        '''
+        if len(args) > 2:
+            raise TypeError('update() takes at most 2 positional '
+                            'arguments (%d given)' % (len(args),))
+        elif not args:
+            raise TypeError('update() takes at least 1 argument (0 given)')
+        self = args[0]
+        # Make progressively weaker assumptions about "other"
+        other = ()
+        if len(args) == 2:
+            other = args[1]
+        if isinstance(other, dict):
+            for key in other:
+                self[key] = other[key]
+        elif hasattr(other, 'keys'):
+            for key in other.keys():
+                self[key] = other[key]
+        else:
+            for key, value in other:
+                self[key] = value
+        for key, value in kwds.items():
+            self[key] = value
+
+    __update = update  # let subclasses override update without breaking __init__
+
+    __marker = object()
+
+    def pop(self, key, default=__marker):
+        '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value.
+        If key is not found, d is returned if given, otherwise KeyError is raised.
+
+        '''
+        if key in self:
+            result = self[key]
+            del self[key]
+            return result
+        if default is self.__marker:
+            raise KeyError(key)
+        return default
+
+    def setdefault(self, key, default=None):
+        'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od'
+        if key in self:
+            return self[key]
+        self[key] = default
+        return default
+
+    def __repr__(self, _repr_running={}):
+        'od.__repr__() <==> repr(od)'
+        call_key = id(self), _get_ident()
+        if call_key in _repr_running:
+            return '...'
+        _repr_running[call_key] = 1
+        try:
+            if not self:
+                return '%s()' % (self.__class__.__name__,)
+            return '%s(%r)' % (self.__class__.__name__, self.items())
+        finally:
+            del _repr_running[call_key]
+
+    def __reduce__(self):
+        'Return state information for pickling'
+        items = [[k, self[k]] for k in self]
+        inst_dict = vars(self).copy()
+        for k in vars(OrderedDict()):
+            inst_dict.pop(k, None)
+        if inst_dict:
+            return (self.__class__, (items,), inst_dict)
+        return self.__class__, (items,)
+
+    def copy(self):
+        'od.copy() -> a shallow copy of od'
+        return self.__class__(self)
+
+    @classmethod
+    def fromkeys(cls, iterable, value=None):
+        '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
+        and values equal to v (which defaults to None).
+
+        '''
+        d = cls()
+        for key in iterable:
+            d[key] = value
+        return d
+
+    def __eq__(self, other):
+        '''od.__eq__(y) <==> od==y.  Comparison to another OD is order-sensitive
+        while comparison to a regular mapping is order-insensitive.
+
+        '''
+        if isinstance(other, OrderedDict):
+            return len(self)==len(other) and self.items() == other.items()
+        return dict.__eq__(self, other)
+
+    def __ne__(self, other):
+        return not self == other
+
+    # -- the following methods are only used in Python 2.7 --
+
+    def viewkeys(self):
+        "od.viewkeys() -> a set-like object providing a view on od's keys"
+        return KeysView(self)
+
+    def viewvalues(self):
+        "od.viewvalues() -> an object providing a view on od's values"
+        return ValuesView(self)
+
+    def viewitems(self):
+        "od.viewitems() -> a set-like object providing a view on od's items"
+        return ItemsView(self)
\ No newline at end of file

Copied: grass/trunk/lib/python/pygrass/raster/Makefile (from rev 53343, grass/trunk/lib/python/Makefile)
===================================================================
--- grass/trunk/lib/python/pygrass/raster/Makefile	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/raster/Makefile	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,32 @@
+MODULE_TOPDIR = ../../../..
+
+include $(MODULE_TOPDIR)/include/Make/Other.make
+include $(MODULE_TOPDIR)/include/Make/Python.make
+include $(MODULE_TOPDIR)/include/Make/Doxygen.make
+
+PYDIR = $(ETC)/python
+GDIR = $(PYDIR)/grass
+PGDIR = $(GDIR)/pygrass
+DSTDIR= $(PGDIR)/raster
+
+MODULES = abstract buffer category history raster_type rowio segment
+
+PYFILES := $(patsubst %,$(DSTDIR)/%.py,$(MODULES) __init__)
+PYCFILES := $(patsubst %,$(DSTDIR)/%.pyc,$(MODULES) __init__)
+
+default: $(PYFILES) $(PYCFILES) $(GDIR)/__init__.py $(GDIR)/__init__.pyc
+
+$(PYDIR):
+	$(MKDIR) $@
+
+$(GDIR): | $(PYDIR)
+	$(MKDIR) $@
+
+$(DSTDIR): | $(GDIR)
+	$(MKDIR) $@
+
+$(DSTDIR)/%: % | $(DSTDIR)
+	$(INSTALL_DATA) $< $@
+
+#doxygen:
+DOXNAME = pythonpygrass
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/raster/__init__.py
===================================================================
--- grass/trunk/lib/python/pygrass/raster/__init__.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/raster/__init__.py	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,676 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Fri May 25 12:56:33 2012
+
+ at author: pietro
+"""
+import ctypes
+import numpy as np
+
+#
+# import GRASS modules
+#
+from grass.script import fatal, warning
+from grass.script import core as grasscore
+#from grass.script import core
+#import grass.lib as grasslib
+import grass.lib.gis as libgis
+import grass.lib.raster as libraster
+import grass.lib.segment as libseg
+import grass.lib.rowio as librowio
+
+#
+# import pygrass modules
+#
+from pygrass.errors import OpenError
+from pygrass.region import Region
+
+#
+# import raster classes
+#
+from abstract import RasterAbstractBase
+from raster_type import TYPE as RTYPE, RTYPE_STR
+from buffer import Buffer
+from segment import Segment
+from rowio import RowIO
+from category import Category
+from history import History
+
+class RasterRow(RasterAbstractBase):
+    """Raster_row_access": Inherits: "Raster_abstract_base" and implements
+    the default row access of the Rast library.
+        * Implements row access using row id
+        * The get_row() method must accept a Row object as argument that will
+          be used for value storage, so no new buffer will be allocated
+        * Implements sequential writing of rows
+        * Implements indexed value read only access using the [row][col]
+          operator
+        * Implements the [row] read method that returns a new Row object
+        * Writing is limited using the put_row() method which accepts a
+          Row as argument
+        * No mathematical operation like __add__ and stuff for the Raster
+          object (only for rows), since r.mapcalc is more sophisticated and
+          faster
+
+    Examples
+    --------
+
+    ::
+        >>> elev = RasterRow('elevation')
+        >>> elev.exist()
+        True
+        >>> elev.is_open()
+        False
+        >>> elev.cols
+        >>> elev.open()
+        >>> elev.is_open()
+        True
+        >>> type(elev.cols)
+        <type 'int'>
+        >>> elev.has_cats()
+        False
+        >>> elev.mode
+        'r'
+        >>> elev.mtype
+        'FCELL'
+        >>> elev.num_cats()
+        0
+        >>> elev.range
+        (55.578792572021484, 156.32986450195312)
+
+    Each Raster map have an attribute call ``cats`` that allow user
+    to interact with the raster categories. ::
+
+        >>> land = RasterRow('landcover_1m')
+        >>> land.open()
+        >>> land.cats
+        []
+        >>> land.read_cats()
+        >>> 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)]
+
+
+    """
+    def __init__(self, name, *args, **kargs):
+        super(RasterRow, self).__init__(name, *args, **kargs)
+
+    # mode = "r", method = "row",
+    def get_row(self, row, row_buffer=None):
+        """Private method that return the row using the read mode
+        call the `Rast_get_row` C function.
+
+        >>> elev = RasterRow('elevation')
+        >>> elev.open()
+        >>> elev[0]                 # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
+        Buffer([ 141.99613953, 141.27848816,  141.37904358, ..., 58.40825272,
+                 58.30711365,  58.18310547], dtype=float32)
+        >>> elev.get_row(0)         # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
+        Buffer([ 141.99613953, 141.27848816, 141.37904358, ..., 58.40825272,
+                 58.30711365, 58.18310547], dtype=float32)
+
+        """
+        if row_buffer is None:
+            row_buffer = Buffer((self._cols,), self.mtype)
+        libraster.Rast_get_row(self._fd, row_buffer.p, row, self._gtype)
+        return row_buffer
+
+    def put_row(self, row):
+        """Private method to write the row sequentially.
+        """
+        libraster.Rast_put_row(self._fd, row.p, self._gtype)
+
+    def open(self, mode='r', mtype='CELL', overwrite=False):
+        """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
+
+
+        if the map already exist, automatically check the type and set:
+            * self.mtype
+
+        Set all the privite, attributes:
+            * self._fd;
+            * self._gtype
+            * self._rows and self._cols
+        """
+        self.mode = mode
+        self.mtype = mtype
+        self.overwrite = overwrite
+
+        # check if exist and instantiate all the private attributes
+        if self.exist():
+            if self.mode == 'r':
+                # the map exist, read mode
+                self._fd = libraster.Rast_open_old(self.name, self.mapset)
+                self._gtype = libraster.Rast_get_map_type(self._fd)
+                self.mtype = RTYPE_STR[self._gtype]
+            elif self.overwrite:
+                if self._gtype is None:
+                    raise OpenError(_("Raster type not defined"))
+                self._fd = libraster.Rast_open_new(self.name, self._gtype)
+            else:
+                str_err = _("Raster map <{0}> already exists")
+                raise OpenError(str_err.format(self))
+        else:
+            # Create a new map
+            if self.mode == 'r':
+                # check if we are in read mode
+                str_err = _("The map does not exist, I can't open in 'r' mode")
+                raise OpenError(str_err)
+            self._fd = libraster.Rast_open_new(self.name, self._gtype)
+        # read rows and cols from the active region
+        self._rows = libraster.Rast_window_rows()
+        self._cols = libraster.Rast_window_cols()
+
+
+class RasterRowIO(RasterRow):
+    """Raster_row_cache_access": The same as "Raster_row_access" but uses
+    the ROWIO library for cached row access
+    """
+    def __init__(self, name, *args, **kargs):
+        self.rowio = RowIO()
+        super(RasterRowIO, self).__init__(name, *args, **kargs)
+
+    def open(self, mode='r', mtype='CELL', overwrite=False):
+        super(RasterRowIO, self).open(mode, mtype, overwrite)
+        self.rowio.open(self._fd, self.rows, self.cols, self.mtype)
+
+    def close(self):
+        if self.is_open():
+            self.rowio.release()
+            libraster.Rast_close(self._fd)
+            # update rows and cols attributes
+            self._rows = None
+            self._cols = None
+            self._fd = None
+        else:
+            warning(_("The map is already close!"))
+
+    def get_row(self, row, row_buffer=None):
+        """Private method that return the row using:
+
+            * the read mode and
+            * `rowcache` method
+
+        not implemented yet!"""
+        if row_buffer is None:
+            row_buffer = Buffer((self._cols,), self.mtype)
+        rowio_buf = librowio.Rowio_get(ctypes.byref(self.rowio.crowio), row)
+        ctypes.memmove(row_buffer.p, rowio_buf, self.rowio.row_size)
+        return row_buffer
+
+
+class RasterSegment(RasterAbstractBase):
+    """Raster_segment_access": Inherits "Raster_abstract_base" and uses the
+    segment library for cached randomly reading and writing access.
+        * Implements the [row][col] operator for read and write access using
+          segement_get() and segment_put() functions internally
+        * Implements row read and write access with the [row] operator using
+          segment_get_row() segment_put_row() internally
+        * Implements the get_row() and put_row() method  using
+          segment_get_row() segment_put_row() internally
+        * Implements the flush_segment() method
+        * Implements the copying of raster maps to segments and vice verse
+        * Overwrites the open and close methods
+        * No mathematical operation like __add__ and stuff for the Raster
+          object (only for rows), since r.mapcalc is more sophisticated and
+          faster
+    """
+    def __init__(self, name, srows=64, scols=64, maxmem=100,
+                 *args, **kargs):
+        self.segment = Segment(srows, scols, maxmem)
+        super(RasterSegment, self).__init__(name, *args, **kargs)
+
+    def _get_mode(self):
+        return self._mode
+
+    def _set_mode(self, mode):
+        if mode.lower() not in ('r', 'w', 'rw'):
+            str_err = _("Mode type: {0} not supported ('r', 'w','rw')")
+            raise ValueError(str_err.format(mode))
+        self._mode = mode
+
+    mode = property(fget=_get_mode, fset=_set_mode)
+
+    def __setitem__(self, key, row):
+        """Return the row of Raster object, slice allowed."""
+        if isinstance(key, slice):
+            #Get the start, stop, and step from the slice
+            return [self.put_row(ii, row)
+                    for ii in xrange(*key.indices(len(self)))]
+        elif isinstance(key, tuple):
+            x, y = key
+            return self.put(x, y, row)
+        elif isinstance(key, int):
+            if key < 0:  # Handle negative indices
+                key += self._rows
+            if key >= self._rows:
+                raise IndexError(_("Index out of range: %r.") % key)
+            return self.put_row(key, row)
+        else:
+            raise TypeError("Invalid argument type.")
+
+    def map2segment(self):
+        """Transform an existing map to segment file.
+        """
+        if self.is_open():
+            row_buffer = Buffer((self._cols), self.mtype)
+            for row in xrange(self._rows):
+                libraster.Rast_get_row(
+                    self._fd, row_buffer.p, row, self._gtype)
+                libseg.segment_put_row(ctypes.byref(self.segment.cseg),
+                                       row_buffer.p, row)
+
+    def segment2map(self):
+        """Transform the segment file to a map.
+        """
+        if self.is_open():
+            row_buffer = Buffer((self._cols), self.mtype)
+            for row in xrange(self._rows):
+                libseg.segment_get_row(ctypes.byref(self.segment.cseg),
+                                       row_buffer.p, row)
+                libraster.Rast_put_row(self._fd, row_buffer.p, self._gtype)
+
+    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.
+        """
+        if row_buffer is None:
+            row_buffer = Buffer((self._cols), self.mtype)
+        libseg.segment_get_row(
+            ctypes.byref(self.segment.cseg), row_buffer.p, row)
+        return row_buffer
+
+    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.
+        """
+        libseg.segment_put_row(ctypes.byref(self.segment.cseg),
+                               row_buffer.p, row)
+
+    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.
+        """
+        libseg.segment_get(ctypes.byref(self.segment.cseg),
+                           ctypes.byref(self.segment.val), row, col)
+        return self.segment.val.value
+
+    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.
+        """
+        self.segment.val.value = val
+        libseg.segment_put(ctypes.byref(self.segment.cseg),
+                           ctypes.byref(self.segment.val), row, col)
+
+    def open(self, mode='r', mtype='DCELL', overwrite=False):
+        """Open the map, if the map already exist: determine the map type
+        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
+        """
+        # read rows and cols from the active region
+        self._rows = libraster.Rast_window_rows()
+        self._cols = libraster.Rast_window_cols()
+
+        self.overwrite = overwrite
+        self.mode = mode
+        self.mtype = mtype
+
+        if self.exist():
+            if ((self.mode == "w" or self.mode == "rw") and
+                self.overwrite is False):
+                str_err = _("Raster map <{0}> already exists. Use overwrite.")
+                fatal(str_err.format(self))
+
+            # We copy the raster map content into the segments
+            if self.mode == "rw" or self.mode == "r":
+                self._fd = libraster.Rast_open_old(self.name, self.mapset)
+                self._gtype = libraster.Rast_get_map_type(self._fd)
+                self.mtype = RTYPE_STR[self._gtype]
+                # initialize the segment, I need to determine the mtype of the
+                # map
+                # before to open the segment
+                self.segment.open(self)
+                self.map2segment()
+                self.segment.flush()
+
+                if self.mode == "rw":
+                    warning(_(WARN_OVERWRITE.format(self)))
+                    # Close the file descriptor and open it as new again
+                    libraster.Rast_close(self._fd)
+                    self._fd = libraster.Rast_open_new(
+                        self.name, self._gtype)
+            # Here we simply overwrite the existing map without content copying
+            elif self.mode == "w":
+                #warning(_(WARN_OVERWRITE.format(self)))
+                self._gtype = RTYPE[self.mtype]['grass type']
+                self.segment.open(self)
+                self._fd = libraster.Rast_open_new(self.name, self._gtype)
+        else:
+            if self.mode == "r":
+                str_err = _("Raster map <{0}> does not exists")
+                raise OpenError(str_err.format(self.name))
+
+            self._gtype = RTYPE[self.mtype]['grass type']
+            self.segment.open(self)
+            self._fd = libraster.Rast_open_new(self.name, self._gtype)
+
+    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.
+        """
+        if self.is_open():
+            if self.mode == "w" or self.mode == "rw":
+                self.segment.flush()
+                self.segment2map()
+            if rm_temp_files:
+                self.segment.close()
+            else:
+                self.segment.release()
+            libraster.Rast_close(self._fd)
+            # update rows and cols attributes
+            self._rows = None
+            self._cols = None
+            self._fd = None
+        else:
+            warning(_("The map is already close!"))
+
+
+FLAGS = {1: {'b': 'i', 'i': 'i', 'u': 'i'},
+         2: {'b': 'i', 'i': 'i', 'u': 'i'},
+         4: {'f': 'f', 'i': 'i', 'b': 'i', 'u': 'i'},
+         8: {'f': 'd'}, }
+
+
+class RasterNumpy(np.memmap, RasterAbstractBase):
+    """Raster_cached_narray": Inherits "Raster_abstract_base" and
+    "numpy.memmap". Its purpose is to allow numpy narray like access to
+    raster maps without loading the map into the main memory.
+    * Behaves like a numpy array and supports all kind of mathematical
+      operations: __add__, ...
+    * Overrides the open and close methods
+    * Be aware of the 2Gig file size limit
+
+    >>> import pygrass
+    >>> elev = pygrass.raster.RasterNumpy('elevation')
+    >>> elev.open()
+    >>> elev[:5, :3]
+    RasterNumpy([[ 141.99613953,  141.27848816,  141.37904358],
+       [ 142.90461731,  142.39450073,  142.68611145],
+       [ 143.81854248,  143.54707336,  143.83972168],
+       [ 144.56524658,  144.58493042,  144.86477661],
+       [ 144.99488831,  145.22894287,  145.57142639]], dtype=float32)
+    >>> el = elev < 144
+    >>> el[:5, :3]
+    RasterNumpy([[ True,  True,  True],
+       [ True,  True,  True],
+       [ True,  True,  True],
+       [False, False, False],
+       [False, False, False]], dtype=bool)
+    >>> el._write()
+    0
+
+    """
+    def __new__(cls, name, mapset="", mtype='CELL', mode='r+',
+                overwrite=False):
+        reg = Region()
+        shape = (reg.rows, reg.cols)
+        mapset = libgis.G_find_raster(name, mapset)
+        gtype = None
+        if mapset:
+            # map exist, set the map type
+            gtype = libraster.Rast_map_type(name, mapset)
+            mtype = RTYPE_STR[gtype]
+        filename = grasscore.tempfile()
+        obj = np.memmap.__new__(cls, filename=filename,
+                                dtype=RTYPE[mtype]['numpy'],
+                                mode=mode,
+                                shape=shape)
+        obj.mtype = mtype.upper()
+        obj.gtype = gtype if gtype else RTYPE[mtype]['grass type']
+        obj._rows = reg.rows
+        obj._cols = reg.cols
+        obj.filename = filename
+        obj._name = name
+        obj.mapset = mapset
+        obj.reg = reg
+        obj.overwrite = overwrite
+        return obj
+
+    def __array_finalize__(self, obj):
+        if hasattr(obj, '_mmap'):
+            self._mmap = obj._mmap
+            self.filename = grasscore.tempfile()
+            self.offset = obj.offset
+            self.mode = obj.mode
+            self._rows = obj._rows
+            self._cols = obj._cols
+            self._name = None
+            self.mapset = ''
+            self.reg = obj.reg
+            self.overwrite = obj.overwrite
+            self.mtype = obj.mtype
+            self._fd = obj._fd
+        else:
+            self._mmap = None
+
+    def _get_mode(self):
+        return self._mode
+
+    def _set_mode(self, mode):
+        if mode.lower() not in ('r', 'w+', 'r+', 'c'):
+            raise ValueError(_("Mode type: {0} not supported.").format(mode))
+        self._mode = mode
+
+    mode = property(fget=_get_mode, fset=_set_mode)
+
+    def __array_wrap__(self, out_arr, context=None):
+        """See:
+        http://docs.scipy.org/doc/numpy/user/
+        basics.subclassing.html#array-wrap-for-ufuncs"""
+        if out_arr.dtype.kind in 'bui':
+            # there is not support for boolean maps, so convert into integer
+            out_arr = out_arr.astype(np.int32)
+            out_arr.mtype = 'CELL'
+        #out_arr.p = out_arr.ctypes.data_as(out_arr.pointer_type)
+        return np.ndarray.__array_wrap__(self, out_arr, context)
+
+    def __init__(self, name, *args, **kargs):
+        ## Private attribute `_fd` that return the file descriptor of the map
+        #self._fd = None
+        rows, cols = self.rows, self.cols
+        RasterAbstractBase.__init__(self, name)
+        self._rows, self._cols = rows, cols
+
+    def __unicode__(self):
+        return RasterAbstractBase.__unicode__(self)
+
+    def __str__(self):
+        return self.__unicode__()
+
+    def _get_flags(self, size, kind):
+        if size in FLAGS:
+            if kind in FLAGS[size]:
+                return size, FLAGS[size][kind]
+            else:
+                raise ValueError(_('Invalid type {0}'.forma(kind)))
+        else:
+            raise ValueError(_('Invalid size {0}'.format(size)))
+
+    def _read(self):
+        """!Read raster map into array
+
+        @return 0 on success
+        @return non-zero code on failure
+        """
+        self.null = None
+
+        size, kind = self._get_flags(self.dtype.itemsize, self.dtype.kind)
+        kind = 'f' if kind == 'd' else kind
+        ret = grasscore.run_command('r.out.bin', flags=kind,
+                                    input=self._name, output=self.filename,
+                                    bytes=size, null=self.null,
+                                    quiet=True)
+        return ret
+
+    def _write(self):
+        """
+        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
+
+        """
+        self.tofile(self.filename)
+        size, kind = self._get_flags(self.dtype.itemsize, self.dtype.kind)
+        #print size, kind
+        if kind == 'i':
+            kind = None
+            size = 4
+        size = None if kind == 'f' else size
+
+        # To be set in the future
+        self.title = None
+        self.null = None
+
+        #import pdb; pdb.set_trace()
+        if self.mode in ('w+', 'r+'):
+            if not self._name:
+                import os
+                self._name = "doctest_%i" % os.getpid()
+            ret = grasscore.run_command('r.in.bin', flags=kind,
+                                        input=self.filename, output=self._name,
+                                        title=self.title, bytes=size,
+                                        anull=self.null,
+                                        overwrite=self.overwrite,
+                                        verbose=True,
+                                        north=self.reg.north,
+                                        south=self.reg.south,
+                                        east=self.reg.east,
+                                        west=self.reg.west,
+                                        rows=self.reg.rows,
+                                        cols=self.reg.cols)
+            return ret
+
+    def open(self, mtype='', null=None, overwrite=None):
+        """Open the map, if the map already exist: determine the map type
+        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;
+        """
+        if overwrite is not None:
+            self.overwrite = overwrite
+        self.null = null
+        # rows and cols already set in __new__
+        if self.exist():
+            self._read()
+        else:
+            if mtype:
+                self.mtype = mtype
+            self._gtype = RTYPE[self.mtype]['grass type']
+        # set _fd, because this attribute is used to check
+        # if the map is open or not
+        self._fd = 1
+
+    def close(self):
+        self._write()
+        np.memmap._close(self)
+        grasscore.try_remove(self.filename)
+        self._fd = None
+
+
+def random_map_only_columns(mapname, mtype, overwrite=True, factor=100):
+    region = Region()
+    random_map = RasterRow(mapname)
+    row_buf = Buffer((region.cols, ), mtype,
+                     buffer=(np.random.random(region.cols,) * factor).data)
+    random_map.open('w', mtype, overwrite)
+    for _ in xrange(region.rows):
+        random_map.put_row(row_buf)
+    random_map.close()
+    return random_map
+
+
+def random_map(mapname, mtype, overwrite=True, factor=100):
+    region = Region()
+    random_map = RasterRow(mapname)
+    random_map.open('w', mtype, overwrite)
+    for _ in xrange(region.rows):
+        row_buf = Buffer((region.cols, ), mtype,
+                         buffer=(np.random.random(region.cols,) * factor).data)
+        random_map.put_row(row_buf)
+    random_map.close()
+    return random_map
+
+
+if __name__ == "__main__":
+    import doctest
+    doctest.testmod()
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/raster/abstract.py
===================================================================
--- grass/trunk/lib/python/pygrass/raster/abstract.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/raster/abstract.py	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,344 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Fri Aug 17 16:05:25 2012
+
+ at author: pietro
+"""
+
+
+import ctypes
+
+#
+# import GRASS modules
+#
+from grass.script import fatal, warning, gisenv
+from grass.script import core as grasscore
+#from grass.script import core
+#import grass.lib as grasslib
+import grass.lib.gis as libgis
+import grass.lib.raster as libraster
+
+#
+# import pygrass modules
+#
+import pygrass.env as env
+from pygrass.region import Region
+
+#
+# import raster classes
+#
+from raster_type import TYPE as RTYPE
+from category import Category
+
+
+## Define global variables to not exceed the 80 columns
+WARN_OVERWRITE = "Raster map <{0}> already exists and will be overwritten"
+INDXOUTRANGE = "The index (%d) is out of range, have you open the map?."
+
+
+def clean_map_name(name):
+    name.strip()
+    for char in ' @#^?°,;%&/':
+        name = name.replace(char, '')
+    return name
+
+
+class RasterAbstractBase(object):
+    """Raster_abstract_base: The base class from which all sub-classes
+    inherit. It does not implement any row or map access methods:
+    * Implements raster metadata information access (Type, ...)
+    * Implements an open method that will be overwritten by the sub-classes
+    * Implements the close method that might be overwritten by sub-classes
+      (should work for simple row access)
+    * Implements get and set region methods
+    * Implements color, history and category handling
+    * Renaming, deletion, ...
+    """
+    def __init__(self, name, mapset=""):
+        """The constructor need at least the name of the map
+        *optional* field is the `mapset`. ::
+
+            >>> land = RasterAbstractBase('landcover_1m')
+            >>> land.name
+            'landcover_1m'
+            >>> land.mapset
+            ''
+            >>> land.exist()
+            True
+            >>> land.mapset
+            'PERMANENT'
+
+        ..
+        """
+        self.mapset = mapset
+        #self.region = Region()
+        self.cats = Category()
+
+        self._name = name
+        ## Private attribute `_fd` that return the file descriptor of the map
+        self._fd = None
+        ## Private attribute `_rows` that return the number of rows
+        # in active window, When the class is instanced is empty and it is set
+        # when you open the file, using Rast_window_rows()
+        self._rows = None
+        ## Private attribute `_cols` that return the number of rows
+        # in active window, When the class is instanced is empty and it is set
+        # when you open the file, using Rast_window_cols()
+        self._cols = None
+
+    def _get_mtype(self):
+        return self._mtype
+
+    def _set_mtype(self, mtype):
+        if mtype.upper() not in ('CELL', 'FCELL', 'DCELL'):
+            #fatal(_("Raser type: {0} not supported".format(mtype) ) )
+            str_err = "Raster type: {0} not supported ('CELL','FCELL','DCELL')"
+            raise ValueError(_(str_err).format(mtype))
+        self._mtype = mtype
+        self._gtype = RTYPE[self.mtype]['grass type']
+
+    mtype = property(fget=_get_mtype, fset=_set_mtype)
+
+    def _get_mode(self):
+        return self._mode
+
+    def _set_mode(self, mode):
+        if mode.upper() not in ('R', 'W'):
+            str_err = _("Mode type: {0} not supported ('r', 'w')")
+            raise ValueError(str_err.format(mode))
+        self._mode = mode
+
+    mode = property(fget=_get_mode, fset=_set_mode)
+
+    def _get_overwrite(self):
+        return self._overwrite
+
+    def _set_overwrite(self, overwrite):
+        if overwrite not in (True, False):
+            str_err = _("Overwrite type: {0} not supported (True/False)")
+            raise ValueError(str_err.format(overwrite))
+        self._overwrite = overwrite
+
+    overwrite = property(fget=_get_overwrite, fset=_set_overwrite)
+
+    def _get_name(self):
+        """Private method to return the Raster name"""
+        return self._name
+
+    def _set_name(self, newname):
+        """Private method to change the Raster name"""
+        #import pdb; pdb.set_trace()
+        cleanname = clean_map_name(newname)
+        if self.exist():
+            self.rename(cleanname)
+        self._name = cleanname
+
+    name = property(fget=_get_name, fset=_set_name)
+
+    def _get_rows(self):
+        """Private method to return the Raster name"""
+        return self._rows
+
+    def _set_unchangeable(self, new):
+        """Private method to change the Raster name"""
+        warning(_("Unchangeable attribute"))
+
+    rows = property(fget=_get_rows, fset=_set_unchangeable)
+
+    def _get_cols(self):
+        """Private method to return the Raster name"""
+        return self._cols
+
+    cols = property(fget=_get_cols, fset=_set_unchangeable)
+
+    def _get_range(self):
+        if self.mtype == 'CELL':
+            maprange = libraster.Range()
+            libraster.Rast_read_range(self.name, self.mapset,
+                                      ctypes.byref(maprange))
+            self._min = libgis.CELL()
+            self._max = libgis.CELL()
+        else:
+            maprange = libraster.FPRange()
+            libraster.Rast_read_fp_range(self.name, self.mapset,
+                                         ctypes.byref(maprange))
+            self._min = libgis.DCELL()
+            self._max = libgis.DCELL()
+        libraster.Rast_get_fp_range_min_max(ctypes.byref(maprange),
+                                            ctypes.byref(self._min),
+                                            ctypes.byref(self._max))
+        return self._min.value, self._max.value
+
+    range = property(fget=_get_range, fset=_set_unchangeable)
+
+    def _get_cats_title(self):
+        return self.cats.title
+
+    def _set_cats_title(self, newtitle):
+        self.cats.title = newtitle
+
+    cats_title = property(fget=_get_cats_title, fset=_set_cats_title)
+
+    def __unicode__(self):
+        return self.name_mapset()
+
+    def __str__(self):
+        """Return the string of the object"""
+        return self.__unicode__()
+
+    def __len__(self):
+        return self._rows
+
+    def __getitem__(self, key):
+        """Return the row of Raster object, slice allowed."""
+        if isinstance(key, slice):
+            #import pdb; pdb.set_trace()
+            #Get the start, stop, and step from the slice
+            return (self.get_row(ii) for ii in xrange(*key.indices(len(self))))
+        elif isinstance(key, tuple):
+            x, y = key
+            return self.get(x, y)
+        elif isinstance(key, int):
+            if key < 0:  # Handle negative indices
+                key += self._rows
+            if key >= self._rows:
+                fatal(INDXOUTRANGE.format(key))
+                raise IndexError
+            return self.get_row(key)
+        else:
+            fatal("Invalid argument type.")
+
+    def __iter__(self):
+        """Return a constructor of the class"""
+        return (self.__getitem__(irow) for irow in xrange(self._rows))
+
+    def exist(self):
+        """Return True if the map already exist, and
+        set the mapset if were not set.
+
+        call the C function `G_find_raster`."""
+        if self.name:
+            self.mapset = env.get_mapset_raster(self.name, self.mapset)
+        else:
+            return False
+        if self.mapset:
+            return True
+        else:
+            return False
+
+    def is_open(self):
+        """Return True if the map is open False otherwise"""
+        return True if self._fd is not None and self._fd >= 0 else False
+
+    def close(self):
+        """Close the map"""
+        if self.is_open():
+            libraster.Rast_close(self._fd)
+            # update rows and cols attributes
+            self._rows = None
+            self._cols = None
+            self._fd = None
+        else:
+            warning(_("The map is already close!"))
+
+    def remove(self):
+        """Remove the map"""
+        if self.is_open():
+            self.close()
+        grasscore.run_command('g.remove', rast=self.name)
+
+    def name_mapset(self, name=None, mapset=None):
+        if name is None:
+            name = self.name
+        if mapset is None:
+            self.exist()
+            mapset = self.mapset
+
+        gis_env = gisenv()
+
+        if mapset and mapset != gis_env['MAPSET']:
+            return "{name}@{mapset}".format(name=name, mapset=mapset)
+        else:
+            return name
+
+    def rename(self, newname):
+        """Rename the map"""
+        if self.exist():
+            env.rename(self.name, newname, 'rast')
+        self._name = newname
+
+    def set_from_rast(self, rastname='', mapset=''):
+        """Set the region that will use from a map, if rastername and mapset
+        is not specify, use itself.
+
+        call C function `Rast_get_cellhd`"""
+        if self.is_open():
+            fatal("You cannot change the region if map is open")
+            raise
+        region = Region()
+        if rastname == '':
+            rastname = self.name
+        if mapset == '':
+            mapset = self.mapset
+
+        libraster.Rast_get_cellhd(rastname, mapset,
+                                  ctypes.byref(region._region))
+        # update rows and cols attributes
+        self._rows = libraster.Rast_window_rows()
+        self._cols = libraster.Rast_window_cols()
+
+    def has_cats(self):
+        """Return True if the raster map has categories"""
+        if self.exist():
+            self.open()
+            self.cats.read(self)
+            self.close()
+            if len(self.cats) != 0:
+                return True
+        return False
+
+    def num_cats(self):
+        """Return the number of categories"""
+        return len(self.cats)
+
+    def copy_cats(self, raster):
+        """Copy categories from another raster map object"""
+        self.cats.copy(raster.cats)
+
+    def sort_cats(self):
+        """Sort categories order by range"""
+        self.cats.sort()
+
+    def read_cats(self):
+        """Read category from the raster map file"""
+        self.cats.read(self)
+
+    def write_cats(self):
+        """Write category to the raster map file"""
+        self.cats.write(self)
+
+    def read_cats_rules(self, filename, sep=':'):
+        """Read category from the raster map file"""
+        self.cats.read_rules(filename, sep)
+
+    def write_cats_rules(self, filename, sep=':'):
+        """Write category to the raster map file"""
+        self.cats.write_rules(filename, sep)
+
+    def get_cats(self):
+        """Return a category object"""
+        cat = Category()
+        cat.read(self)
+        return cat
+
+    def set_cats(self, category):
+        """The internal categories are copied from this object."""
+        self.cats.copy(category)
+
+    def get_cat(self, label):
+        """Return a category given an index or a label"""
+        return self.cats[label]
+
+    def set_cat(self, label, min_cat, max_cat=None, index=None):
+        """Set or update a category"""
+        self.cats.set_cat(index, (label, min_cat, max_cat))
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/raster/buffer.py
===================================================================
--- grass/trunk/lib/python/pygrass/raster/buffer.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/raster/buffer.py	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Fri Jun  8 18:46:34 2012
+
+ at author: pietro
+"""
+from raster_type import TYPE as RTYPE
+import ctypes
+import numpy as np
+
+
+class Buffer(np.ndarray):
+    """shape, mtype='FCELL', buffer=None, offset=0,
+    strides=None, order=None
+    """
+
+    def __new__(cls, shape, mtype='FCELL', buffer=None, offset=0,
+                strides=None, order=None):
+        #import pdb; pdb.set_trace()
+        obj = np.ndarray.__new__(cls, shape, RTYPE[mtype]['numpy'],
+                                 buffer, offset, strides, order)
+        obj.pointer_type = ctypes.POINTER(RTYPE[mtype]['ctypes'])
+        obj.p = obj.ctypes.data_as(obj.pointer_type)
+        obj.mtype = mtype
+        return obj
+
+    def __array_finalize__(self, obj):
+        if obj is None:
+            return
+        self.mtype = getattr(obj, 'mtype', None)
+        self.pointer_type = getattr(obj, 'pointer_type', None)
+        self.p = getattr(obj, 'p', None)
+
+    def __array_wrap__(self, out_arr, context=None):
+        """See:
+        http://docs.scipy.org/doc/numpy/user/
+        basics.subclassing.html#array-wrap-for-ufuncs"""
+        if out_arr.dtype == np.bool:
+            # there is not support for boolean maps, so convert into integer
+            out_arr = out_arr.astype(np.int32)
+        out_arr.p = out_arr.ctypes.data_as(out_arr.pointer_type)
+        return np.ndarray.__array_wrap__(self, out_arr, context)
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/raster/category.py
===================================================================
--- grass/trunk/lib/python/pygrass/raster/category.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/raster/category.py	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,348 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Thu Jun 28 17:44:14 2012
+
+ at author: pietro
+"""
+import ctypes
+from operator import itemgetter
+
+import grass.lib.raster as libraster
+
+from pygrass.errors import GrassError
+
+from raster_type import TYPE as RTYPE
+
+
+class Category(list):
+    """
+    I would like to add the following functions:
+
+    Getting the umber of cats:
+    Rast_number_of_cats() <- Important for ith access
+
+    Getting and setting the title:
+    Rast_get_cats_title()
+    Rast_set_cats_title()
+
+    Do not use these functions for category access:
+    Rast_get_cat()
+    and the specialized types for CELL, FCELL and DCELL.
+    Since these functions are working on hidden static buffer.
+
+    Use the ith-get methods:
+    Rast_get_ith_c_cat()
+    Rast_get_ith_f_cat()
+    Rast_get_ith_d_cat()
+
+    This can be implemented using an iterator too. So that the category object
+    provides the [] access operator to the categories, returning a tuple
+    (label, min, max).
+    Using this, the category object must be aware of its raster map type.
+
+    Set categories using:
+    Rast_set_c_cat()
+    Rast_set_f_cat()
+    Rast_set_d_cat()
+
+    Misc:
+    Rast_sort_cats()
+    Rast_copy_cats() <- This should be wrapped so that categories from an
+    existing Python category class are copied.
+
+
+    >>> import grass.lib.raster as libraster
+    >>> import ctypes
+    >>> import pygrass
+    >>> land = pygrass.raster.RasterRow('landcover_1m')
+    >>> cats = pygrass.raster.Category()
+    >>> cats.read(land) # or with cats.read(land.name, land.mapset, land.mtype)
+    >>> cats.labels()
+    ['pond', 'forest', 'developed', 'bare', 'paved road', 'dirt road',
+        'vineyard', 'agriculture', 'wetland', 'bare ground path', 'grass']
+    >>> min_cat = ctypes.c_void_p()
+    >>> max_cat = ctypes.c_void_p()
+    >>> libraster.Rast_get_ith_c_cat(ctypes.byref(cats.cats), 0,
+    ...                              min_cat, max_cat)
+    """
+    def __init__(self, mtype=None, *args, **kargs):
+        self._cats = libraster.Categories()
+        libraster.Rast_init_cats("", ctypes.byref(self._cats))
+        self._mtype = mtype
+        self._gtype = None if mtype is None else RTYPE[mtype]['grass type']
+        super(Category, self).__init__(*args, **kargs)
+
+    def _get_mtype(self):
+        return self._mtype
+
+    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)))
+        self._mtype = mtype
+        self._gtype = RTYPE[self.mtype]['grass type']
+
+    mtype = property(fget=_get_mtype, fset=_set_mtype)
+
+    def _get_title(self):
+        return libraster.Rast_get_cats_title(ctypes.byref(self._cats))
+
+    def _set_title(self, newtitle):
+        return libraster.Rast_set_cats_title(newtitle,
+                                             ctypes.byref(self._cats))
+
+    title = property(fget=_get_title, fset=_set_title)
+
+    def __str__(self):
+        return self.__repr__()
+
+    def __list__(self):
+        cats = []
+        for cat in self.__iter__():
+            cats.append(cat)
+        return cats
+
+    def __dict__(self):
+        diz = dict()
+        for cat in self.__iter__():
+            label, min_cat, max_cat = cat
+            diz[(min_cat, max_cat)] = label
+        return diz
+
+    def __repr__(self):
+        cats = []
+        for cat in self.__iter__():
+            cats.append(repr(cat))
+        return "[{0}]".format(',\n '.join(cats))
+
+    def _chk_index(self, index):
+        if type(index) == str:
+            try:
+                index = self.labels().index(index)
+            except ValueError:
+                raise KeyError(index)
+        return index
+
+    def _chk_value(self, value):
+        if type(value) == tuple:
+            length = len(value)
+            if length == 2:
+                label, min_cat = value
+                value = (label, min_cat, None)
+            elif length < 2 or length > 3:
+                raise TypeError('Tuple with a length that is not supported.')
+        else:
+            raise TypeError('Only Tuple are supported.')
+        return value
+
+    def __getitem__(self, index):
+        return super(Category, self).__getitem__(self._chk_index(index))
+
+    def __setitem__(self, index, value):
+        return super(Category, self).__setitem__(self._chk_index(index),
+                                                 self._chk_value(value))
+
+    def _get_c_cat(self, index):
+        """Returns i-th description and i-th data range from the list of
+        category descriptions with corresponding data ranges. end points of
+        data interval.
+
+        Rast_get_ith_cat(const struct Categories * 	pcats,
+                         int 	i,
+                         void * 	rast1,
+                         void * 	rast2,
+                         RASTER_MAP_TYPE 	data_type
+                         )
+        """
+        min_cat = ctypes.pointer(RTYPE[self.mtype]['grass def']())
+        max_cat = ctypes.pointer(RTYPE[self.mtype]['grass def']())
+        lab = libraster.Rast_get_ith_cat(ctypes.byref(self._cats),
+                                         index,
+                                         ctypes.cast(min_cat, ctypes.c_void_p),
+                                         ctypes.cast(max_cat, ctypes.c_void_p),
+                                         self._gtype)
+        # Manage C function Errors
+        if lab == '':
+            raise GrassError(_("Error executing: Rast_get_ith_cat"))
+        if max_cat.contents.value == min_cat.contents.value:
+            max_cat = None
+        else:
+            max_cat = max_cat.contents.value
+        return lab, min_cat.contents.value, max_cat
+
+    def _set_c_cat(self, label, min_cat, max_cat=None):
+        """Adds the label for range min through max in category structure cats.
+
+        int Rast_set_cat(const void * 	rast1,
+                         const void * 	rast2,
+                         const char * 	label,
+                         struct Categories * 	pcats,
+                         RASTER_MAP_TYPE 	data_type
+                         )
+        """
+        max_cat = min_cat if max_cat is None else max_cat
+        min_cat = ctypes.pointer(RTYPE[self.mtype]['grass def'](min_cat))
+        max_cat = ctypes.pointer(RTYPE[self.mtype]['grass def'](max_cat))
+        err = libraster.Rast_set_cat(ctypes.cast(min_cat, ctypes.c_void_p),
+                                     ctypes.cast(max_cat, ctypes.c_void_p),
+                                     label,
+                                     ctypes.byref(self._cats), self._gtype)
+        # Manage C function Errors
+        if err == 1:
+            return None
+        elif err == 0:
+            raise GrassError(_("Null value detected"))
+        elif err == -1:
+            raise GrassError(_("Error executing: Rast_set_cat"))
+
+    def __del__(self):
+        libraster.Rast_free_cats(ctypes.byref(self._cats))
+
+    def get_cat(self, index):
+        return self.__getitem__(index)
+
+    def set_cat(self, index, value):
+        if index is None:
+            self.append(value)
+        elif index < self.__len__():
+            self.__setitem__(index, value)
+        else:
+            raise TypeError("Index outside range.")
+
+    def reset(self):
+        for i in xrange(len(self) - 1, -1, -1):
+            del(self[i])
+        libraster.Rast_init_cats("", ctypes.byref(self._cats))
+
+    def _read_cats(self):
+        """Copy from the C struct to the list"""
+        for i in xrange(self._cats.ncats):
+            self.append(self._get_c_cat(i))
+
+    def _write_cats(self):
+        """Copy from the list data to the C struct"""
+        # reset only the C struct
+        libraster.Rast_init_cats("", ctypes.byref(self._cats))
+        # write to the c struct
+        for cat in self.__iter__():
+            label, min_cat, max_cat = cat
+            if max_cat is None:
+                max_cat = min_cat
+            self._set_c_cat(label, min_cat, max_cat)
+
+    def read(self, rast, mapset=None, mtype=None):
+        """Read categories from a raster map
+
+        The category file for raster map name in mapset is read into the
+        cats structure. If there is an error reading the category file,
+        a diagnostic message is printed.
+
+        int Rast_read_cats(const char * 	name,
+                           const char * 	mapset,
+                           struct Categories * 	pcats
+                           )
+        """
+        if type(rast) == str:
+            mapname = rast
+            if mapset is None or mtype is None:
+                raise TypeError(_('Mapset and maptype must be specify'))
+        else:
+            mapname = rast.name
+            mapset = rast.mapset
+            mtype = rast.mtype
+
+        self.mtype = mtype
+        self.reset()
+        err = libraster.Rast_read_cats(mapname, mapset,
+                                       ctypes.byref(self._cats))
+        if err == -1:
+            raise GrassError("Can not read the categories.")
+        # copy from C struct to list
+        self._read_cats()
+
+    def write(self, map):
+        """Writes the category file for the raster map name in the current
+           mapset from the cats structure.
+
+        void Rast_write_cats(const char * 	name,
+                             struct Categories * 	cats
+                             )
+        """
+        if type(map) == str:
+            mapname = map
+        else:
+            mapname = map.name
+        # copy from list to C struct
+        self._write_cats()
+        # write to the map
+        libraster.Rast_write_cats(mapname, ctypes.byref(self._cats))
+
+    def copy(self, category):
+        """Copy from another Category class"""
+        libraster.Rast_copy_cats(ctypes.byref(self._cats),     # to
+                                 ctypes.byref(category._cats))  # from
+        self._read_cats()
+
+    def ncats(self):
+        return self.__len__()
+
+    def set_cats_fmt(self, fmt, m1, a1, m2, a2):
+        """Not implemented yet.
+        void Rast_set_cats_fmt()
+        """
+        #TODO: add
+        pass
+
+    def read_rules(self, filename, sep=':'):
+        """Copy categories from a rules file, default separetor is ':', the
+        columns must be: min and/or max and label. ::
+
+            1:forest
+            2:road
+            3:urban
+
+            0.:0.5:forest
+            0.5:1.0:road
+            1.0:1.5:urban
+
+        .."""
+        self.reset()
+        with open(filename, 'r') as f:
+            for row in f.readlines():
+                cat = row.strip().split(sep)
+                if len(cat) == 2:
+                    label, min_cat = cat
+                    max_cat = None
+                elif len(cat) == 3:
+                    label, min_cat, max_cat = cat
+                else:
+                    raise TypeError("Row lenght is greater than 3")
+                #import pdb; pdb.set_trace()
+                self.append((label, min_cat, max_cat))
+
+    def write_rules(self, filename, sep=':'):
+        """Copy categories from a rules file, default separetor is ':', the
+        columns must be: min and/or max and label. ::
+
+            1:forest
+            2:road
+            3:urban
+
+            0.:0.5:forest
+            0.5:1.0:road
+            1.0:1.5:urban
+
+        .."""
+        with open(filename, 'w') as f:
+            cats = []
+            for cat in self.__iter__():
+                if cat[-1] is None:
+                    cat = cat[:-1]
+                cats.append(sep.join([str(i) for i in cat]))
+            f.write('\n'.join(cats))
+
+    def sort(self):
+        libraster.Rast_sort_cats(ctypes.byref(self._cats))
+
+    def labels(self):
+        return map(itemgetter(0), self)
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/raster/history.py
===================================================================
--- grass/trunk/lib/python/pygrass/raster/history.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/raster/history.py	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,236 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Thu Jun 28 17:44:45 2012
+
+ at author: pietro
+"""
+import ctypes
+import grass.lib.raster as libraster
+import datetime
+
+
+class History(object):
+    """
+    *Examples*
+
+    ::
+
+        >>> import pygrass
+        >>> hist = pygrass.raster.History()
+        >>> hist.read('aspect')
+        >>> hist.creator
+        'helena'
+        >>> hist.src1
+        'raster elevation file elev_ned10m'
+        >>> hist.src2
+        ''
+        >>> hist.keyword
+        'generated by r.slope.aspect'
+        >>> hist.date
+        datetime.datetime(2006, 11, 7, 1, 11, 23)
+        >>> hist.mapset
+        'PERMANENT'
+        >>> hist.maptype
+        'raster'
+        >>> hist.title
+        'asp_ned10m'
+
+    ..
+    """
+    def __init__(self):
+        self.hist = libraster.History()
+        #                'Tue Nov  7 01:11:23 2006'
+        self.date_fmt = '%a %b  %d %H:%M:%S %Y'
+
+    def __del__(self):
+        """Rast_free_history"""
+        pass
+
+    #----------------------------------------------------------------------
+    #libraster.HIST_CREATOR
+    def _get_creator(self):
+        return libraster.Rast_get_history(ctypes.byref(self.hist),
+                                          libraster.HIST_CREATOR)
+
+    def _set_creator(self, creator):
+        return libraster.Rast_set_history(ctypes.byref(self.hist),
+                                          libraster.HIST_CREATOR,
+                                          ctypes.c_char_p(creator))
+
+    creator = property(fget=_get_creator, fset=_set_creator)
+
+    #----------------------------------------------------------------------
+    #libraster.HIST_DATSRC_1
+    def _get_src1(self):
+        return libraster.Rast_get_history(ctypes.byref(self.hist),
+                                          libraster.HIST_DATSRC_1)
+
+    def _set_src1(self, src1):
+        return libraster.Rast_set_history(ctypes.byref(self.hist),
+                                          libraster.HIST_DATSRC_1,
+                                          ctypes.c_char_p(src1))
+
+    src1 = property(fget=_get_src1, fset=_set_src1)
+
+    #----------------------------------------------------------------------
+    #libraster.HIST_DATSRC_2
+    def _get_src2(self):
+        return libraster.Rast_get_history(ctypes.byref(self.hist),
+                                          libraster.HIST_DATSRC_2)
+
+    def _set_src2(self, src2):
+        return libraster.Rast_set_history(ctypes.byref(self.hist),
+                                          libraster.HIST_DATSRC_2,
+                                          ctypes.c_char_p(src2))
+
+    src2 = property(fget=_get_src2, fset=_set_src2)
+
+    #----------------------------------------------------------------------
+    #libraster.HIST_KEYWORD
+    def _get_keyword(self):
+        return libraster.Rast_get_history(ctypes.byref(self.hist),
+                                          libraster.HIST_KEYWRD)
+
+    def _set_keyword(self, keyword):
+        return libraster.Rast_set_history(ctypes.byref(self.hist),
+                                          libraster.HIST_KEYWRD,
+                                          ctypes.c_char_p(keyword))
+
+    keyword = property(fget=_get_keyword, fset=_set_keyword)
+
+    #----------------------------------------------------------------------
+    #libraster.HIST_MAPID
+    def _get_date(self):
+        date_str = libraster.Rast_get_history(ctypes.byref(self.hist),
+                                              libraster.HIST_MAPID)
+        return datetime.datetime.strptime(date_str, self.date_fmt)
+
+    def _set_date(self, datetimeobj):
+        date_str = datetimeobj.strftime(self.date_fmt)
+        return libraster.Rast_set_history(ctypes.byref(self.hist),
+                                          libraster.HIST_MAPID,
+                                          ctypes.c_char_p(date_str))
+
+    date = property(fget=_get_date, fset=_set_date)
+
+    #----------------------------------------------------------------------
+    #libraster.HIST_MAPSET
+    def _get_mapset(self):
+        return libraster.Rast_get_history(ctypes.byref(self.hist),
+                                          libraster.HIST_MAPSET)
+
+    def _set_mapset(self, mapset):
+        return libraster.Rast_set_history(ctypes.byref(self.hist),
+                                          libraster.HIST_MAPSET,
+                                          ctypes.c_char_p(mapset))
+
+    mapset = property(fget=_get_mapset, fset=_set_mapset)
+
+    #----------------------------------------------------------------------
+    #libraster.HIST_MAPTYPE
+    def _get_maptype(self):
+        return libraster.Rast_get_history(ctypes.byref(self.hist),
+                                          libraster.HIST_MAPTYPE)
+
+    def _set_maptype(self, maptype):
+        return libraster.Rast_set_history(ctypes.byref(self.hist),
+                                          libraster.HIST_MAPTYPE,
+                                          ctypes.c_char_p(maptype))
+
+    maptype = property(fget=_get_maptype, fset=_set_maptype)
+
+    #----------------------------------------------------------------------
+    #libraster.HIST_NUM_FIELDS
+    #
+    # Never used in any raster modules
+    #
+    #    def _get_num_fields(self):
+    #        return libraster.Rast_get_history(ctypes.byref(self.hist),
+    #                                          libraster.HIST_NUM_FIELDS)
+    #
+    #    def _set_num_fields(self, num_fields):
+    #        return libraster.Rast_set_history(ctypes.byref(self.hist),
+    #                                          libraster.HIST_NUM_FIELDS,
+    #                                          ctypes.c_char_p(num_fields))
+    #
+    #    num_fields = property(fget = _get_num_fields, fset = _set_num_fields)
+    #----------------------------------------------------------------------
+    #libraster.HIST_TITLE
+    def _get_title(self):
+        return libraster.Rast_get_history(ctypes.byref(self.hist),
+                                          libraster.HIST_TITLE)
+
+    def _set_title(self, title):
+        return libraster.Rast_set_history(ctypes.byref(self.hist),
+                                          libraster.HIST_TITLE,
+                                          ctypes.c_char_p(title))
+
+    title = property(fget=_get_title, fset=_set_title)
+
+    def append(self, obj):
+        """Rast_append_history"""
+        libraster.Rast_append_history(ctypes.byref(self.hist),
+                                      ctypes.c_char_p(str(obj)))
+
+    def appent_fmt(self, fmt, *args):
+        """Rast_append_format_history"""
+        libraster.Rast_append_format_history(ctypes.byref(self.hist),
+                                             ctypes.c_char_p(fmt),
+                                             *args)
+
+    def clear(self):
+        """Rast_clear_history"""
+        libraster.Rast_clear_history(ctypes.byref(self.hist))
+
+    def command(self):
+        """Rast_command_history"""
+        libraster.Rast_command_history(ctypes.byref(self.hist))
+
+    def format(self, field, fmt, *args):
+        """Rast_format_history"""
+        libraster.Rast_format_history(ctypes.byref(self.hist),
+                                      ctypes.c_int(field),
+                                      ctypes.c_char_p(fmt),
+                                      *args)
+
+    def length(self):
+        """Rast_history_length"""
+        libraster.Rast_history_length(ctypes.byref(self.hist))
+
+    def line(self, line):
+        """Rast_history_line"""
+        libraster.Rast_history_line(ctypes.byref(self.hist),
+                                    ctypes.c_int(line))
+
+    def read(self, name):
+        """Rast_read_history. ::
+
+            >>> import grass.lib.gis as libgis
+            >>> libgis.G_gisinit('')
+            >>> import ctypes
+            >>> import grass.lib.raster as libraster
+            >>> hist = libraster.History()
+            >>> libraster.Rast_read_history(ctypes.c_char_p('aspect'),
+            ...                             ctypes.c_char_p(''),
+            ...                             ctypes.byref(hist))
+            0
+            >>> libraster.Rast_get_history(ctypes.byref(hist),
+            ...                            libraster.HIST_MAPID)
+            'Tue Nov  7 01:11:23 2006'
+
+        ..
+        """
+        libraster.Rast_read_history(ctypes.c_char_p(name),
+                                    ctypes.c_char_p(''),
+                                    ctypes.byref(self.hist))
+
+    def write(self, name):
+        """Rast_write_history"""
+        libraster.Rast_write_history(ctypes.c_char_p(name),
+                                     ctypes.byref(self.hist))
+
+    def short(self, name, maptype,):
+        """Rast_short_history"""
+        libraster.Rast_short_history(ctypes.c_char_p(name),
+                                     ctypes.c_char_p(maptype),
+                                     ctypes.byref(self.hist))
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/raster/raster_type.py
===================================================================
--- grass/trunk/lib/python/pygrass/raster/raster_type.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/raster/raster_type.py	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,28 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Wed Jun 13 19:42:22 2012
+
+ at author: pietro
+"""
+import grass.lib.raster as libraster
+import ctypes
+import numpy as np
+
+## Private dictionary to convert RASTER_TYPE into type string.
+RTYPE_STR = {libraster.CELL_TYPE:  'CELL',
+             libraster.FCELL_TYPE: 'FCELL',
+             libraster.DCELL_TYPE: 'DCELL'}
+
+
+TYPE = {'CELL':  {'grass type':  libraster.CELL_TYPE,
+                  'grass def':   libraster.CELL,
+                  'numpy':       np.int32,
+                  'ctypes':      ctypes.c_int},
+        'FCELL': {'grass type':  libraster.FCELL_TYPE,
+                  'grass def':   libraster.FCELL,
+                  'numpy':       np.float32,
+                  'ctypes':      ctypes.c_float},
+        'DCELL': {'grass type':  libraster.DCELL_TYPE,
+                  'grass def':   libraster.DCELL,
+                  'numpy':       np.float64,
+                  'ctypes':      ctypes.c_double}}
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/raster/rowio.py
===================================================================
--- grass/trunk/lib/python/pygrass/raster/rowio.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/raster/rowio.py	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,78 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Mon Jun 18 13:22:38 2012
+
+ at author: pietro
+"""
+import ctypes
+
+import grass.lib.rowio as librowio
+import grass.lib.raster as librast
+
+from pygrass.errors import GrassError
+from raster_type import TYPE as RTYPE
+
+
+CMPFUNC = ctypes.CFUNCTYPE(ctypes.c_int,
+                           ctypes.c_int, ctypes.c_void_p,
+                           ctypes.c_int, ctypes.c_int)
+
+
+def getmaprow_CELL(fd, buf, row, l):
+    librast.Rast_get_f_row(fd, ctypes.cast(buf, ctypes.POINTER(librast.CELL)),
+                           row)
+    return 1
+
+
+def getmaprow_FCELL(fd, buf, row, l):
+    librast.Rast_get_f_row(fd, ctypes.cast(buf, ctypes.POINTER(librast.FCELL)),
+                           row)
+    return 1
+
+
+def getmaprow_DCELL(fd, buf, row, l):
+    librast.Rast_get_f_row(fd, ctypes.cast(buf, ctypes.POINTER(librast.DCELL)),
+                           row)
+    return 1
+
+get_row = {
+    'CELL':  CMPFUNC(getmaprow_CELL),
+    'FCELL': CMPFUNC(getmaprow_FCELL),
+    'DCELL': CMPFUNC(getmaprow_DCELL),
+}
+
+
+class RowIO(object):
+
+    def __init__(self):
+        self.crowio = librowio.ROWIO()
+        self.fd = None
+        self.rows = None
+        self.cols = None
+        self.mtype = None
+        self.row_size = None
+
+    def open(self, fd, rows, cols, mtype):
+        self.fd = fd
+        self.rows = rows
+        self.cols = cols
+        self.mtype = mtype
+        self.row_size = ctypes.sizeof(RTYPE[mtype]['grass def'] * cols)
+        if (librowio.Rowio_setup(ctypes.byref(self.crowio), self.fd,
+                                 self.rows,
+                                 self.row_size,
+                                 get_row[self.mtype],
+                                 get_row[self.mtype]) == -1):
+            raise GrassError('Fatal error, Rowio not setup correctly.')
+
+    def release(self):
+        librowio.Rowio_release(ctypes.byref(self.crowio))
+        self.fd = None
+        self.rows = None
+        self.cols = None
+        self.mtype = None
+
+    def get(self, row_index, buf):
+        rowio_buf = librowio.Rowio_get(ctypes.byref(self.crowio), row_index)
+        ctypes.memmove(buf.p, rowio_buf, self.row_size)
+        return buf
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/raster/segment.py
===================================================================
--- grass/trunk/lib/python/pygrass/raster/segment.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/raster/segment.py	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,129 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Mon Jun 11 18:02:27 2012
+
+ at author: pietro
+"""
+import ctypes
+import grass.lib.gis as libgis
+import grass.lib.raster as libraster
+import grass.lib.segment as libseg
+from raster_type import TYPE as RTYPE
+
+
+class Segment(object):
+    def __init__(self, srows=64, scols=64, maxmem=100):
+        self.srows = srows
+        self.scols = scols
+        self.maxmem = maxmem
+        self.cseg = libseg.SEGMENT()
+
+    def rows(self):
+        return libraster.Rast_window_rows()
+
+    def cols(self):
+        return libraster.Rast_window_cols()
+
+    def nseg(self):
+        rows = self.rows()
+        cols = self.cols()
+        return ((rows + self.srows - 1) / self.srows) * \
+               ((cols + self.scols - 1) / self.scols)
+
+    def segments_in_mem(self):
+        if self.maxmem > 0 and self.maxmem < 100:
+            seg_in_mem = (self.maxmem * self.nseg()) / 100
+        else:
+            seg_in_mem = 4 * (self.rows() / self.srows +
+                              self.cols() / self.scols + 2)
+        if seg_in_mem == 0:
+            seg_in_mem = 1
+        return seg_in_mem
+
+    def open(self, mapobj):
+        """Open a segment it is necessary to pass a RasterSegment object.
+
+        """
+        self.val = RTYPE[mapobj.mtype]['grass def']()
+        size = ctypes.sizeof(RTYPE[mapobj.mtype]['ctypes'])
+        file_name = libgis.G_tempfile()
+        #import pdb; pdb.set_trace()
+        libseg.segment_open(ctypes.byref(self.cseg), file_name,
+                            self.rows(), self.cols(),
+                            self.srows, self.scols,
+                            size,
+                            self.nseg())
+        self.flush()
+
+    def format(self, mapobj, file_name='', fill=True):
+        """The segmentation routines require a disk file to be used for paging
+        segments in and out of memory. This routine formats the file open for
+        write on file descriptor fd for use as a segment file.
+        """
+        if file_name == '':
+            file_name = libgis.G_tempfile()
+        mapobj.temp_file = file(file_name, 'w')
+        size = ctypes.sizeof(RTYPE[mapobj.mtype]['ctypes'])
+        if fill:
+            libseg.segment_format(mapobj.temp_file.fileno(), self.rows(),
+                                  self.cols(), self.srows, self.scols, size)
+        else:
+            libseg.segment_format_nofill(mapobj.temp_file.fileno(),
+                                         self.rows(), self.cols(),
+                                         self.srows, self.scols, size)
+        # TODO: why should I close and then re-open it?
+        mapobj.temp_file.close()
+
+    def init(self, mapobj, file_name=''):
+        if file_name == '':
+            file_name = mapobj.temp_file.name
+        mapobj.temp_file = open(file_name, 'w')
+        libseg.segment_init(ctypes.byref(self.cseg), mapobj.temp_file.fileno(),
+                            self.segments_in_mem)
+
+    def get_row(self, row_index, buf):
+        """Return the row using, the `segment` method"""
+        libseg.segment_get_row(ctypes.byref(self.cseg), buf.p, row_index)
+        return buf
+
+    def put_row(self, row_index, buf):
+        """Write the row using the `segment` method"""
+        libseg.segment_put_row(ctypes.byref(self.cseg), buf.p, row_index)
+
+    def get(self, row_index, col_index):
+        """Return the value of the map
+        """
+        libseg.segment_get(ctypes.byref(self.cseg),
+                           ctypes.byref(self.val), row_index, col_index)
+        return self.val.value
+
+    def put(self, row_index, col_index):
+        """Write the value to the map
+        """
+        libseg.segment_put(ctypes.byref(self.cseg),
+                           ctypes.byref(self.val), row_index, col_index)
+
+    def get_seg_number(self, row_index, col_index):
+        """Return the segment number
+        """
+        return row_index / self.srows * self.cols / self.scols + \
+            col_index / self.scols
+
+    def flush(self):
+        """Flush pending updates to disk.
+        Forces all pending updates generated by segment_put() to be written to
+        the segment file seg. Must be called after the final segment_put()
+        to force all pending updates to disk. Must also be called before the
+        first call to segment_get_row."""
+        libseg.segment_flush(ctypes.byref(self.cseg))
+
+    def close(self):
+        """Free memory allocated to segment and delete temp file.  """
+        libseg.segment_close(ctypes.byref(self.cseg))
+
+    def release(self):
+        """Free memory allocated to segment.
+        Releases the allocated memory associated with the segment file seg.
+        Note: Does not close the file. Does not flush the data which may be
+        pending from previous segment_put() calls."""
+        libseg.segment_release(ctypes.byref(self.cseg))
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/region.py
===================================================================
--- grass/trunk/lib/python/pygrass/region.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/region.py	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,207 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Fri May 25 12:57:10 2012
+
+ at author: Pietro Zambelli
+"""
+import ctypes
+import grass.lib.gis as libgis
+import grass.script as grass
+
+from errors import GrassError
+
+
+class Region(object):
+    def __init__(self, default=False):
+        """::
+
+            >>> default = Region(default=True)
+            >>> current = Region()
+            >>> 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.set_default()
+            >>> default = Region(default=True)
+            >>> default == current
+            True
+            >>> default
+            Region(n=228500, s=215000, e=645000, w=630000, nsres=10, ewres=20)
+            >>> current
+            Region(n=228500, s=215000, e=645000, w=630000, nsres=10, ewres=20)
+            >>> default.ewres = 10.
+            >>> default.set_default()
+        """
+        self.c_region = ctypes.pointer(libgis.Cell_head())
+        if default:
+            self.get_default()
+        else:
+            self.get_current()
+
+    def _set_param(self, key, value):
+        grass.run_command('g.region', **{key: value})
+
+    #----------LIMITS----------
+    def _get_n(self):
+        return self.c_region.contents.north
+
+    def _set_n(self, value):
+        self.c_region.contents.north = value
+
+    north = property(fget=_get_n, fset=_set_n)
+
+    def _get_s(self):
+        return self.c_region.contents.south
+
+    def _set_s(self, value):
+        self.c_region.contents.south = value
+
+    south = property(fget=_get_s, fset=_set_s)
+
+    def _get_e(self):
+        return self.c_region.contents.east
+
+    def _set_e(self, value):
+        self.c_region.contents.east = value
+
+    east = property(fget=_get_e, fset=_set_e)
+
+    def _get_w(self):
+        return self.c_region.contents.west
+
+    def _set_w(self, value):
+        self.c_region.contents.west = value
+
+    west = property(fget=_get_w, fset=_set_w)
+
+    def _get_t(self):
+        return self.c_region.contents.top
+
+    def _set_t(self, value):
+        self.c_region.contents.top = value
+
+    top = property(fget=_get_t, fset=_set_t)
+
+    def _get_b(self):
+        return self.c_region.contents.bottom
+
+    def _set_b(self, value):
+        self.c_region.contents.bottom = value
+
+    bottom = property(fget=_get_b, fset=_set_b)
+
+    #----------RESOLUTION----------
+    def _get_rows(self):
+        return self.c_region.contents.rows
+
+    def _set_rows(self, value):
+        self.c_region.contents.rows = value
+        self.adjust(rows=True)
+
+    rows = property(fget=_get_rows, fset=_set_rows)
+
+    def _get_cols(self):
+        return self.c_region.contents.cols
+
+    def _set_cols(self, value):
+        self.c_region.contents.cols = value
+        self.adjust(cols=True)
+
+    cols = property(fget=_get_cols, fset=_set_cols)
+
+    def _get_nsres(self):
+        return self.c_region.contents.ns_res
+
+    def _set_nsres(self, value):
+        self.c_region.contents.ns_res = value
+        self.adjust()
+
+    nsres = property(fget=_get_nsres, fset=_set_nsres)
+
+    def _get_ewres(self):
+        return self.c_region.contents.ew_res
+
+    def _set_ewres(self, value):
+        self.c_region.contents.ew_res = value
+        self.adjust()
+
+    ewres = property(fget=_get_ewres, fset=_set_ewres)
+
+    def _get_tbres(self):
+        return self.c_region.contents.tb_res
+
+    def _set_tbres(self, value):
+        self.c_region.contents.tb_res = value
+        self.adjust()
+
+    tbres = property(fget=_get_tbres, fset=_set_tbres)
+
+    @property
+    def zone(self):
+        return self.c_region.contents.zone
+
+    @property
+    def proj(self):
+        return self.c_region.contents.proj
+
+    #----------MAGIC METHODS----------
+    def __repr__(self):
+        return 'Region(n=%g, s=%g, e=%g, w=%g, nsres=%g, ewres=%g)' % (
+               self.north, self.south, self.east, self.west,
+               self.nsres, self.ewres)
+
+    def __unicode__(self):
+        return grass.pipe_command("g.region", flags="p").communicate()[0]
+
+    def __str__(self):
+        return self.__unicode__()
+
+    def __eq__(self, reg):
+        attrs = ['north', 'south', 'west', 'east', 'top', 'bottom',
+                 'nsres', 'ewres', 'tbres']
+        for attr in attrs:
+            if getattr(self, attr) != getattr(reg, attr):
+                return False
+        return True
+
+
+    #----------METHODS----------
+    def zoom(self, raster_name):
+        """Shrink region until it meets non-NULL data from this raster map:"""
+        self._set_param('zoom', str(raster_name))
+
+    def align(self, raster_name):
+        """Adjust region cells to cleanly align with this raster map"""
+        self._set_param('align', str(raster_name))
+
+    def adjust(self, rows=False, cols=False):
+        """Adjust rows and cols number according with the nsres and ewres
+        resolutions. If rows or cols parameters are True, the adjust method
+        update nsres and ewres according with the rows and cols numbers.
+        """
+        libgis.G_adjust_Cell_head(self.c_region, bool(rows), bool(cols))
+
+    def get_current(self):
+        libgis.G_get_set_window(self.c_region)
+
+    def set_current(self):
+        libgis.G_set_window(self.c_region)
+
+    def get_default(self):
+        libgis.G_get_window(self.c_region)
+
+    def set_default(self):
+        self.adjust()
+        if libgis.G_put_window(self.c_region) < 0:
+            raise GrassError("Cannot change region (WIND file).")
\ No newline at end of file

Copied: grass/trunk/lib/python/pygrass/tests/Makefile (from rev 53343, grass/trunk/lib/python/Makefile)
===================================================================
--- grass/trunk/lib/python/pygrass/tests/Makefile	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/tests/Makefile	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,32 @@
+MODULE_TOPDIR = ../../../..
+
+include $(MODULE_TOPDIR)/include/Make/Other.make
+include $(MODULE_TOPDIR)/include/Make/Python.make
+include $(MODULE_TOPDIR)/include/Make/Doxygen.make
+
+PYDIR = $(ETC)/python
+GDIR = $(PYDIR)/grass
+PGDIR = $(GDIR)/pygrass
+DSTDIR= $(PGDIR)/tests
+
+MODULES = benchmark set_mapset
+
+PYFILES := $(patsubst %,$(DSTDIR)/%.py,$(MODULES) __init__)
+PYCFILES := $(patsubst %,$(DSTDIR)/%.pyc,$(MODULES) __init__)
+
+default: $(PYFILES) $(PYCFILES) $(GDIR)/__init__.py $(GDIR)/__init__.pyc
+
+$(PYDIR):
+	$(MKDIR) $@
+
+$(GDIR): | $(PYDIR)
+	$(MKDIR) $@
+
+$(DSTDIR): | $(GDIR)
+	$(MKDIR) $@
+
+$(DSTDIR)/%: % | $(DSTDIR)
+	$(INSTALL_DATA) $< $@
+
+#doxygen:
+DOXNAME = pythonpygrass
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/tests/__init__.py
===================================================================
Added: grass/trunk/lib/python/pygrass/tests/benchmark.py
===================================================================
--- grass/trunk/lib/python/pygrass/tests/benchmark.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/tests/benchmark.py	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,524 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Sat Jun 16 20:24:56 2012
+
+ at author: soeren
+"""
+import optparse
+#import numpy as np
+import time
+import collections
+import copy
+import cProfile
+import sys, os
+from jinja2 import Template
+sys.path.append(os.getcwd())
+sys.path.append("%s/.."%(os.getcwd()))
+
+import grass.lib.gis as libgis
+import grass.lib.raster as libraster
+import grass.script as core
+import pygrass
+import ctypes
+
+def test__RasterNumpy_value_access__if():
+    test_a = pygrass.RasterNumpy(name="test_a", mtype="CELL", mode="r+")
+    test_a.open()
+
+    test_c = pygrass.RasterNumpy(name="test_c", mtype="CELL", mode="w+", overwrite=True)
+    test_c.open()
+
+    for row in xrange(test_a.rows):
+        for col in xrange(test_a.cols):
+            test_c[row, col] = test_a[row, col] > 50
+
+    test_a.close()
+    test_c.close()
+
+def test__RasterNumpy_value_access__add():
+    test_a = pygrass.RasterNumpy(name="test_a", mode="r+")
+    test_a.open()
+
+    test_b = pygrass.RasterNumpy(name="test_b", mode="r+")
+    test_b.open()
+
+    test_c = pygrass.RasterNumpy(name="test_c", mtype="DCELL", mode="w+", overwrite=True)
+    test_c.open()
+
+    for row in xrange(test_a.rows):
+        for col in xrange(test_a.cols):
+            test_c[row, col] = test_a[row, col] + test_b[row, col]
+
+    test_a.close()
+    test_b.close()
+    test_c.close()
+
+def test__RasterNumpy_row_access__if():
+    test_a = pygrass.RasterNumpy(name="test_a", mtype="CELL", mode="r+")
+    test_a.open()
+
+    test_c = pygrass.RasterNumpy(name="test_c", mtype="CELL", mode="w+", overwrite=True)
+    test_c.open()
+
+    for row in xrange(test_a.rows):
+        test_c[row] = test_a[row] > 50
+
+    test_a.close()
+    test_c.close()
+
+def test__RasterNumpy_row_access__add():
+    test_a = pygrass.RasterNumpy(name="test_a", mode="r+")
+    test_a.open()
+
+    test_b = pygrass.RasterNumpy(name="test_b", mode="r+")
+    test_b.open()
+
+    test_c = pygrass.RasterNumpy(name="test_c", mtype="DCELL", mode="w+", overwrite=True)
+    test_c.open()
+
+    for row in xrange(test_a.rows):
+        test_c[row] = test_a[row] + test_b[row]
+
+    test_a.close()
+    test_b.close()
+    test_c.close()
+
+def test__RasterNumpy_map_access__if():
+    test_a = pygrass.RasterNumpy(name="test_a", mtype="CELL", mode="r+")
+    test_a.open()
+
+    test_c = pygrass.RasterNumpy(name="test_c", mtype="CELL", mode="w+", overwrite=True)
+    test_c.open()
+
+    test_c = test_a > 50
+
+    test_a.close()
+    test_c.close()
+
+def test__RasterNumpy_map_access__add():
+    test_a = pygrass.RasterNumpy(name="test_a", mode="r+")
+    test_a.open()
+
+    test_b = pygrass.RasterNumpy(name="test_b", mode="r+")
+    test_b.open()
+
+    test_c = pygrass.RasterNumpy(name="test_c", mtype="DCELL", mode="w+", overwrite=True)
+    test_c.open()
+
+    test_c = test_a + test_b
+
+    test_a.close()
+    test_b.close()
+    test_c.close()
+
+def test__RasterSegment_value_access__if():
+    test_a = pygrass.RasterSegment(name="test_a")
+    test_a.open(mode="r")
+
+    test_c = pygrass.RasterSegment(name="test_c")
+    test_c.open(mode="w", mtype="CELL", overwrite=True)
+
+    buff_a = pygrass.Buffer(test_a.cols, test_a.mtype)
+
+    for row in xrange(test_a.rows):
+        test_a.get_row(row, buff_a)
+        for col in xrange(test_a.cols):
+            test_c.put(row, col, buff_a[col] > 50)
+
+    test_a.close()
+    test_c.close()
+
+def test__RasterSegment_value_access__add():
+    test_a = pygrass.RasterSegment(name="test_a")
+    test_a.open(mode="r")
+
+    test_b = pygrass.RasterSegment(name="test_b")
+    test_b.open(mode="r")
+
+    test_c = pygrass.RasterSegment(name="test_c")
+    test_c.open(mode="w", mtype="DCELL", overwrite=True)
+
+    buff_a = pygrass.Buffer(test_a.cols, test_a.mtype)
+    buff_b = pygrass.Buffer(test_b.cols, test_b.mtype)
+
+    for row in xrange(test_a.rows):
+        test_a.get_row(row, buff_a)
+        test_b.get_row(row,buff_b)
+        for col in xrange(test_a.cols):
+            test_c.put(row, col, buff_a[col] + buff_b[col])
+
+    test_a.close()
+    test_b.close()
+    test_c.close()
+
+def test__RasterSegment_row_access__if():
+    test_a = pygrass.RasterSegment(name="test_a")
+    test_a.open(mode="r")
+
+    test_c = pygrass.RasterSegment(name="test_c")
+    test_c.open(mode="w", mtype="CELL", overwrite=True)
+
+    buff_a = pygrass.Buffer(test_a.cols, test_a.mtype)
+
+    for row in xrange(test_a.rows):
+        test_a.get_row(row, buff_a)
+        test_c.put_row(row, buff_a > 50)
+
+    test_a.close()
+    test_c.close()
+
+def test__RasterSegment_row_access__add():
+    test_a = pygrass.RasterSegment(name="test_a")
+    test_a.open(mode="r")
+
+    test_b = pygrass.RasterSegment(name="test_b")
+    test_b.open(mode="r")
+
+    test_c = pygrass.RasterSegment(name="test_c")
+    test_c.open(mode="w", mtype="DCELL", overwrite=True)
+
+    buff_a = pygrass.Buffer(test_a.cols, test_a.mtype)
+    buff_b = pygrass.Buffer(test_b.cols, test_b.mtype)
+
+    for row in xrange(test_a.rows):
+        test_a.get_row(row, buff_a)
+        test_b.get_row(row,buff_b)
+        test_c.put_row(row, buff_a + buff_b)
+
+    test_a.close()
+    test_b.close()
+    test_c.close()
+
+def test__RasterRow_value_access__add():
+    test_a = pygrass.RasterRow(name="test_a")
+    test_a.open(mode="r")
+
+    test_b = pygrass.RasterRow(name="test_b")
+    test_b.open(mode="r")
+
+    test_c = pygrass.RasterRow(name="test_c")
+    test_c.open(mode="w", mtype="FCELL", overwrite=True)
+
+    buff_a = pygrass.Buffer(test_a.cols, test_a.mtype)
+    buff_b = pygrass.Buffer(test_b.cols, test_b.mtype)
+    buff_c = pygrass.Buffer(test_b.cols, test_b.mtype)
+
+    for row in xrange(test_a.rows):
+        test_a.get_row(row, buff_a)
+        test_b.get_row(row,buff_b)
+
+        for col in xrange(test_a.cols):
+            buff_c[col] = buff_a[col] + buff_b[col]
+
+        test_c.put_row(buff_c)
+
+    test_a.close()
+    test_b.close()
+    test_c.close()
+
+def test__RasterRow_value_access__if():
+    test_a = pygrass.RasterRow(name="test_a")
+    test_a.open(mode="r")
+
+    test_c = pygrass.RasterRow(name="test_c")
+    test_c.open(mode="w", mtype="CELL", overwrite=True)
+
+    buff_a = pygrass.Buffer(test_a.cols, test_a.mtype)
+    buff_c = pygrass.Buffer(test_a.cols, test_a.mtype)
+
+    for row in xrange(test_a.rows):
+        test_a.get_row(row, buff_a)
+
+        for col in xrange(test_a.cols):
+            buff_c[col] = buff_a[col] > 50
+
+        test_c.put_row(buff_c)
+
+    test_a.close()
+    test_c.close()
+
+def test__RasterRowIO_row_access__add():
+    test_a = pygrass.RasterRowIO(name="test_a")
+    test_a.open(mode="r")
+
+    test_b = pygrass.RasterRowIO(name="test_b")
+    test_b.open(mode="r")
+
+    test_c = pygrass.RasterRowIO(name="test_c")
+    test_c.open(mode="w", mtype="FCELL", overwrite=True)
+
+    buff_a = pygrass.Buffer(test_a.cols, test_a.mtype)
+    buff_b = pygrass.Buffer(test_b.cols, test_b.mtype)
+
+    for row in xrange(test_a.rows):
+        test_a.get_row(row, buff_a)
+        test_b.get_row(row,buff_b)
+        test_c.put_row(buff_a + buff_b)
+
+    test_a.close()
+    test_b.close()
+    test_c.close()
+
+def test__RasterRowIO_row_access__if():
+    test_a = pygrass.RasterRowIO(name="test_a")
+    test_a.open(mode="r")
+
+    test_c = pygrass.RasterRowIO(name="test_c")
+    test_c.open(mode="w", mtype="CELL", overwrite=True)
+
+    buff_a = pygrass.Buffer(test_a.cols, test_a.mtype)
+
+    for row in xrange(test_a.rows):
+        test_a.get_row(row, buff_a)
+        test_c.put_row(buff_a > 50)
+
+    test_a.close()
+    test_c.close()
+
+def test__RasterRow_row_access__add():
+    test_a = pygrass.RasterRow(name="test_a")
+    test_a.open(mode="r")
+
+    test_b = pygrass.RasterRow(name="test_b")
+    test_b.open(mode="r")
+
+    test_c = pygrass.RasterRow(name="test_c")
+    test_c.open(mode="w", mtype="FCELL", overwrite=True)
+
+    buff_a = pygrass.Buffer(test_a.cols, test_a.mtype)
+    buff_b = pygrass.Buffer(test_b.cols, test_b.mtype)
+
+    for row in xrange(test_a.rows):
+        test_a.get_row(row, buff_a)
+        test_b.get_row(row,buff_b)
+        test_c.put_row(buff_a + buff_b)
+
+    test_a.close()
+    test_b.close()
+    test_c.close()
+
+def test__RasterRow_row_access__if():
+    test_a = pygrass.RasterRow(name="test_a")
+    test_a.open(mode="r")
+
+    test_c = pygrass.RasterRow(name="test_c")
+    test_c.open(mode="w", mtype="CELL", overwrite=True)
+
+    buff_a = pygrass.Buffer(test_a.cols, test_a.mtype)
+
+    for row in xrange(test_a.rows):
+        test_a.get_row(row, buff_a)
+        test_c.put_row(buff_a > 50)
+
+    test_a.close()
+    test_c.close()
+
+def test__mapcalc__add():
+    core.mapcalc("test_c = test_a + test_b", quite=True, overwrite=True)
+
+def test__mapcalc__if():
+    core.mapcalc("test_c = if(test_a > 50, 1, 0)", quite=True, overwrite=True)
+
+def mytimer(func, runs=1):
+    times = []
+    t = 0.0
+    for _ in xrange(runs):
+        start = time.time()
+        func()
+        end = time.time()
+        times.append(end - start)
+        t = t + end - start
+
+    return t/runs, times
+
+
+
+def run_benchmark(resolution_list, runs, testdict, profile):
+    regions = []
+    for resolution in resolution_list:
+        core.use_temp_region()
+        core.run_command('g.region', e=50, w=-50, n=50, s=-50, res=resolution, flags='p')
+
+        # Adjust the computational region for this process
+        region = libgis.Cell_head()
+        libraster.Rast_get_window(ctypes.byref(region))
+        region.e = 50
+        region.w = -50
+        region.n = 50
+        region.s = -50
+        region.ew_res = resolution
+        region.ns_res = resolution
+
+        libgis.G_adjust_Cell_head(ctypes.byref(region), 0, 0)
+
+        libraster.Rast_set_window(ctypes.byref(region))
+        libgis.G_set_window(ctypes.byref(region))
+
+        # Create two raster maps with random numbers
+        core.mapcalc("test_a = rand(0, 100)", quite=True, overwrite=True)
+        core.mapcalc("test_b = rand(0.0, 1.0)", quite=True, overwrite=True)
+        result = collections.OrderedDict()
+        result['res'] = resolution
+        result['cols'] = region.cols
+        result['rows'] = region.rows
+        result['cells'] = region.rows * region.cols
+        result['results'] = copy.deepcopy(testdict)
+        for execmode, operation in result['results'].iteritems():
+            print(execmode)
+            for oper, operdict in operation.iteritems():
+                operdict['time'], operdict['times'] = mytimer(operdict['func'],runs)
+                if profile:
+                    filename = '{}_{}_{}'.format(execmode, oper, profile)
+                    cProfile.runctx(operdict['func'].__name__ + '()',
+                                    globals(), locals(), filename = filename)
+                print('    {0}: {1: 40.6f}s'.format(oper, operdict['time']))
+                del(operdict['func'])
+
+        regions.append(result)
+        core.del_temp_region()
+
+    return regions
+
+def get_testlist(loc):
+    testlist = [test for test in loc.keys() if 'test' in test[:5]]
+    testlist.sort()
+    return testlist
+
+def get_testdict(testlist):
+    testdict = collections.OrderedDict()
+    for testfunc in testlist:
+        #import pdb; pdb.set_trace()
+        dummy, execmode, operation = testfunc.split('__')
+        if execmode in testdict.keys():
+            testdict[execmode][operation] = collections.OrderedDict()
+            testdict[execmode][operation]['func'] = loc[testfunc]
+        else:
+            testdict[execmode] = collections.OrderedDict()
+            testdict[execmode][operation] = collections.OrderedDict()
+            testdict[execmode][operation]['func'] = loc[testfunc]
+    return testdict
+
+def print_test(testdict):
+    for execmode, operation in testdict.iteritems():
+        print execmode
+        for oper, operdict in operation.iteritems():
+            print '    ', oper
+            for key, value in operdict.iteritems():
+                print '        ', key
+
+TXT = u"""
+{% for region in regions %}
+{{ '#'*60 }}
+### Benchmark cols = {{ region.cols }} rows = {{ region.rows}} cells = {{ region.cells }}
+{{ '#'*60 }}
+
+    # equation: c = a + b
+    {% for execmode, operation in region.results.iteritems() %}
+        {{ "%-30s - %5s % 12.6fs"|format(execmode, 'add', operation.add.time) }}
+    {%- endfor %}
+
+    # equation: c = if a > 50 then 1 else 0
+    {% for execmode, operation in region.results.iteritems() %}
+        {{ "%-30s - %5s % 12.6fs"|format(execmode, 'if', operation.if.time) }}
+    {%- endfor %}
+{%- endfor %}
+"""
+
+
+CSV = """Class; Mode; Operation;
+
+"""
+
+RST = """
+"""
+#>>> txt = Template(TxT)
+#>>> txt.render(name='John Doe')
+
+
+def get_txt(results):
+    txt = Template(TXT)
+    return txt.render(regions = results)
+
+
+#classes for required options
+strREQUIRED = 'required'
+
+class OptionWithDefault(optparse.Option):
+    ATTRS = optparse.Option.ATTRS + [strREQUIRED]
+
+    def __init__(self, *opts, **attrs):
+        if attrs.get(strREQUIRED, False):
+            attrs['help'] = '(Required) ' + attrs.get('help', "")
+        optparse.Option.__init__(self, *opts, **attrs)
+
+class OptionParser(optparse.OptionParser):
+    def __init__(self, **kwargs):
+        kwargs['option_class'] = OptionWithDefault
+        optparse.OptionParser.__init__(self, **kwargs)
+
+    def check_values(self, values, args):
+        for option in self.option_list:
+            if hasattr(option, strREQUIRED) and option.required:
+                if not getattr(values, option.dest):
+                    self.error("option %s is required".format(str(option)))
+        return optparse.OptionParser.check_values(self, values, args)
+
+
+def main(testdict):
+    """Main function"""
+    #usage
+    usage = "usage: %prog [options] raster_map"
+    parser = OptionParser(usage=usage)
+    # ntime
+    parser.add_option("-n", "--ntimes", dest="ntime",default=5, type="int",
+                      help="Number of run for each test.")
+    # res
+    parser.add_option("-r", "--resolution", action="store", type="string",
+                      dest="res", default = '1,0.25',
+                      help="Resolution list separete by comma.")
+    # fmt
+    parser.add_option("-f", "--fmt", action="store", type="string",
+                      dest="fmt", default = 'txt',
+                      help="Choose the output format: 'txt', 'csv', 'rst'.")
+
+    # output
+    parser.add_option("-o", "--output", action="store", type="string",
+                      dest="output", help="The output filename.")
+
+    # store
+    parser.add_option("-s", "--store", action="store", type="string",
+                      dest="store", help="The filename of pickle obj.")
+
+    # profile
+    parser.add_option("-p", "--profile", action="store", type="string",
+                      dest="profile", help="The filename of the profile results.")
+
+    #return options and argument
+    options, args = parser.parse_args()
+    res = [float(r) for r in options.res.split(',')]
+    #res = [1, 0.25, 0.1, 0.05]
+
+    results = run_benchmark(res, options.ntime, testdict, options.profile)
+
+    if options.store:
+        import pickle
+        output = open(options.store, 'wb')
+        pickle.dump(results, output)
+        output.close()
+    #import pdb; pdb.set_trace()
+    print get_txt(results)
+
+
+#add options
+if __name__ == "__main__":
+    #import pdb; pdb.set_trace()
+    loc = locals()
+    testlist = get_testlist(loc)
+    testdict = get_testdict(testlist)
+    #print_test(testdict)
+
+
+
+    #import pdb; pdb.set_trace()
+
+    main(testdict)
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/tests/set_mapset.py
===================================================================
--- grass/trunk/lib/python/pygrass/tests/set_mapset.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/tests/set_mapset.py	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,81 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Thu Aug 23 11:07:38 2012
+
+ at author: pietro
+
+"""
+import os
+import subprocess
+import optparse
+
+from grass.script import core as grasscore
+
+def read_gisrc(gisrcpath):
+    gisrc = open(gisrcpath, 'r')
+    diz = {}
+    for row in gisrc:
+        key, val = row.split(':')
+        diz[key.strip()] = val.strip()
+    return diz
+
+def main():
+    # default option
+    gisrc = read_gisrc(os.environ['GISRC'])
+    user = os.environ['USER']
+    # start optparse
+    usage = "usage: %prog [options]"
+    parser = optparse.OptionParser(usage=usage)
+    parser.add_option("-U", "--user", dest="user", default=user,
+                      help="PostgreSQL user [default=%default]")
+    parser.add_option("-P", "--password", dest="passwd", default=None,
+                      help="PostgreSQL password for user [default=%default]")
+    parser.add_option("-D", "--database", dest="db", default='pygrassdb_doctest',
+                      help="PostgreSQL database name [default=%default]")                      
+                      
+    (opts, args) = parser.parse_args()
+    #
+    # Create DB
+    #
+    print("\n\nCreate a new DB: %s...\n" % opts.db)
+    createdb = ['createdb', '--encoding=UTF-8', '--owner=%s' % opts.user,
+                '--host=localhost', '--username=%s' % opts.user, opts.db]
+    if opts.passwd:
+        print opts.passwd
+        createdb.append("--password=%s" % opts.passwd)
+    else:
+        createdb.append("--no-password")
+    subprocess.Popen(createdb)
+    
+    #
+    # set postgreSQL
+    #
+    print("\n\nSet Postgres connection...\n")
+    grasscore.run_command('db.connect', driver='pg',
+                          database='host=localhost,dbname=%s' % opts.db)
+    
+    grasscore.run_command('db.login', user=opts.user)
+    print("\n\nCopy the map from PERMANENT to user1...\n")
+    grasscore.run_command('g.copy',
+                          vect="boundary_municp at PERMANENT,boundary_municp_pg",
+                          overwrite=True)
+    print("\n\nBuild topology...\n")
+    grasscore.run_command('v.build', map='boundary_municp_pg', overwrite=True)
+    
+    
+    #
+    # set sqlite
+    #
+    db = [gisrc['GISDBASE'], gisrc['LOCATION_NAME'], gisrc['MAPSET'], 'sqlite.db']
+    print("\n\nSet Sqlite connection...\n")
+    grasscore.run_command('db.connect', driver='sqlite',
+                          database=os.path.join(db))
+    print("\n\nCopy the map from PERMANENT to user1...\n")
+    grasscore.run_command('g.copy',
+                          vect="boundary_municp at PERMANENT,boundary_municp_sqlite",
+                          overwrite=True)
+    print("\n\nBuild topology...\n")
+    grasscore.run_command('v.build', map='boundary_municp_sqlite', overwrite=True)
+    
+if __name__ == "__main__":
+    main()
\ No newline at end of file

Copied: grass/trunk/lib/python/pygrass/vector/Makefile (from rev 53343, grass/trunk/lib/python/Makefile)
===================================================================
--- grass/trunk/lib/python/pygrass/vector/Makefile	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/vector/Makefile	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,32 @@
+MODULE_TOPDIR = ../../../..
+
+include $(MODULE_TOPDIR)/include/Make/Other.make
+include $(MODULE_TOPDIR)/include/Make/Python.make
+include $(MODULE_TOPDIR)/include/Make/Doxygen.make
+
+PYDIR = $(ETC)/python
+GDIR = $(PYDIR)/grass
+PGDIR = $(GDIR)/pygrass
+DSTDIR= $(PGDIR)/vector
+
+MODULES = abstract basic geometry sql table vector_type
+
+PYFILES := $(patsubst %,$(DSTDIR)/%.py,$(MODULES) __init__)
+PYCFILES := $(patsubst %,$(DSTDIR)/%.pyc,$(MODULES) __init__)
+
+default: $(PYFILES) $(PYCFILES) $(GDIR)/__init__.py $(GDIR)/__init__.pyc
+
+$(PYDIR):
+	$(MKDIR) $@
+
+$(GDIR): | $(PYDIR)
+	$(MKDIR) $@
+
+$(DSTDIR): | $(GDIR)
+	$(MKDIR) $@
+
+$(DSTDIR)/%: % | $(DSTDIR)
+	$(INSTALL_DATA) $< $@
+
+#doxygen:
+DOXNAME = pythonpygrass
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/vector/__init__.py
===================================================================
--- grass/trunk/lib/python/pygrass/vector/__init__.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/vector/__init__.py	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,390 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Tue Jul 17 08:51:53 2012
+
+ at author: pietro
+"""
+import ctypes
+
+import grass.lib.vector as libvect
+from vector_type import VTYPE, GV_TYPE
+
+#
+# import pygrass modules
+#
+from pygrass.errors import GrassError
+
+from basic import Bbox
+import geometry
+from abstract import Info
+
+import grass.script.core as core
+_GRASSENV = core.gisenv()
+
+_NUMOF = {"areas": libvect.Vect_get_num_areas,
+          "dblinks": libvect.Vect_get_num_dblinks,
+          "faces": libvect.Vect_get_num_faces,
+          "holes": libvect.Vect_get_num_holes,
+          "islands": libvect.Vect_get_num_islands,
+          "kernels": libvect.Vect_get_num_kernels,
+          "line_points": libvect.Vect_get_num_line_points,
+          "lines": libvect.Vect_get_num_lines,
+          "nodes": libvect.Vect_get_num_nodes,
+          "updated_lines": libvect.Vect_get_num_updated_lines,
+          "updated_nodes": libvect.Vect_get_num_updated_nodes,
+          "volumes": libvect.Vect_get_num_volumes}
+
+_GEOOBJ = {"areas": geometry.Area,
+           "dblinks": None,
+           "faces": None,
+           "holes": None,
+           "islands": geometry.Isle,
+           "kernels": None,
+           "line_points": None,
+           "lines": geometry.Boundary,
+           "nodes": geometry.Node,
+           "volumes": None}
+
+
+#=============================================
+# VECTOR
+#=============================================
+
+class Vector(Info):
+    """ ::
+
+        >>> from pygrass.vector import Vector
+        >>> municip = Vector('boundary_municp_sqlite')
+        >>> municip.is_open()
+        False
+        >>> municip.mapset
+        ''
+        >>> municip.exist()
+        True
+        >>> municip.mapset
+        '%s'
+        >>> municip.overwrite
+        False
+
+    ..
+    """ % _GRASSENV['MAPSET']
+    def __init__(self, name, mapset=''):
+        # Set map name and mapset
+        super(Vector, self).__init__(name, mapset)
+        self._topo_level = 1
+        self._class_name = 'Vector'
+        self.overwrite = False
+        self.dblinks = None
+
+    def __repr__(self):
+        if self.exist():
+            return "%s(%r, %r)" % (self._class_name, self.name, self.mapset)
+        else:
+            return "%s(%r)" % (self._class_name, self.name)
+
+    def __iter__(self):
+        """::
+
+            >>> mun = Vector('boundary_municp_sqlite')
+            >>> mun.open()
+            >>> features = [feature for feature in mun]
+            >>> features[:3]
+            [Boundary(v_id=None), Boundary(v_id=None), Boundary(v_id=None)]
+            >>> mun.close()
+
+        ..
+        """
+        #return (self.read(f_id) for f_id in xrange(self.num_of_features()))
+        return self
+
+    def next(self):
+        """::
+
+            >>> mun = Vector('boundary_municp_sqlite')
+            >>> mun.open()
+            >>> mun.next()
+            Boundary(v_id=None)
+            >>> mun.next()
+            Boundary(v_id=None)
+            >>> mun.close()
+
+        ..
+        """
+        v_id = self.c_mapinfo.contents.next_line
+        v_id = v_id if v_id != 0 else None
+        c_points = ctypes.pointer(libvect.line_pnts())
+        c_cats = ctypes.pointer(libvect.line_cats())
+        ftype = libvect.Vect_read_next_line(self.c_mapinfo, c_points, c_cats)
+        if ftype == -2:
+            raise StopIteration()
+        if ftype == -1:
+            raise
+        #if  GV_TYPE[ftype]['obj'] is not None:
+        return GV_TYPE[ftype]['obj'](v_id=v_id,
+                                     c_mapinfo=self.c_mapinfo,
+                                     c_points=c_points,
+                                     c_cats=c_cats)
+
+    def bbox(self):
+        """Return the BBox of the vecor map
+        """
+        bbox = Bbox()
+        libvect.Vect_get_map_box(self.c_mapinfo, bbox.c_bbox)
+        return bbox
+
+    def write(self, geo_obj):
+        """::
+
+            >>> mun = Vector('boundary_municp_sqlite')         #doctest: +SKIP
+            >>> mun.open(mode='rw')            #doctest: +SKIP
+            >>> feature1 = mun.read(1)                         #doctest: +SKIP
+            >>> feature1                                       #doctest: +SKIP
+            Boundary(v_id=1)
+            >>> feature1[:3]             #doctest: +SKIP +NORMALIZE_WHITESPACE
+            [Point(463718.874987, 310970.844494),
+             Point(463707.405987, 310989.499494),
+             Point(463714.593986, 311084.281494)]
+            >>> from geometry import Point                     #doctest: +SKIP
+            >>> feature1.insert(1, Point(463713.000000, 310980.000000))
+            ...                                                #doctest: +SKIP
+            >>> feature1[:4]             #doctest: +SKIP +NORMALIZE_WHITESPACE
+            [Point(463718.874987, 310970.844494),
+             Point(463713.000000, 310980.000000),
+             Point(463707.405987, 310989.499494),
+             Point(463714.593986, 311084.281494)]
+            >>> mun.write(feature1)                            #doctest: +SKIP
+            >>> feature1                                       #doctest: +SKIP
+            Boundary(v_id=8708)
+            >>> mun.close()                                    #doctest: +SKIP
+
+        ..
+        """
+        result = libvect.Vect_write_line(self.c_mapinfo, geo_obj.gtype,
+                                         geo_obj.c_points, geo_obj.c_cats)
+        if result == -1:
+            raise GrassError("Not able to write the vector feature.")
+        if self._topo_level == 2:
+            # return new feature id (on level 2)
+            geo_obj.id = result
+        else:
+            # return offset into file where the feature starts (on level 1)
+            geo_obj.offset = result
+
+
+#=============================================
+# VECTOR WITH TOPOLOGY
+#=============================================
+
+class VectorTopo(Vector):
+    def __init__(self, name, mapset=''):
+        super(VectorTopo, self).__init__(name, mapset)
+        self._topo_level = 2
+        self._class_name = 'VectorTopo'
+
+    def __len__(self):
+        return libvect.Vect_get_num_lines(self.c_mapinfo)
+
+    def __getitem__(self, key):
+        """::
+
+            >>> mun = VectorTopo('boundary_municp_sqlite')
+            >>> mun.open()
+            >>> mun[:3]
+            [Boundary(v_id=1), Boundary(v_id=2), Boundary(v_id=3)]
+            >>> mun.close()
+
+        ..
+        """
+        if isinstance(key, slice):
+            #import pdb; pdb.set_trace()
+            #Get the start, stop, and step from the slice
+            return [self.read(indx + 1)
+                    for indx in xrange(*key.indices(len(self)))]
+        elif isinstance(key, int):
+            self.read(key)
+        else:
+            raise ValueError("Invalid argument type: %r." % key)
+
+    def num_primitive_of(self, primitive):
+        """Primitive are:
+
+            * "boundary",
+            * "centroid",
+            * "face",
+            * "kernel",
+            * "line",
+            * "point"
+
+        ::
+
+            >>> municip = VectorTopo('boundary_municp_sqlite')
+            >>> municip.open()
+            >>> municip.num_primitive_of('point')
+            0
+            >>> municip.num_primitive_of('line')
+            0
+            >>> municip.num_primitive_of('centroid')
+            3579
+            >>> municip.num_primitive_of('boundary')
+            5128
+            >>> municip.close()
+
+        ..
+        """
+        return libvect.Vect_get_num_primitives(self.c_mapinfo,
+                                               VTYPE[primitive])
+
+    def number_of(self, vtype):
+        """
+        vtype in ["areas", "dblinks", "faces", "holes", "islands", "kernels",
+                  "line_points", "lines", "nodes", "update_lines",
+                  "update_nodes", "volumes"]
+
+            >>> municip = VectorTopo('boundary_municp_sqlite')
+            >>> municip.open()
+            >>> municip.number_of("areas")
+            3579
+            >>> municip.number_of("islands")
+            2629
+            >>> municip.number_of("holes")
+            0
+            >>> municip.number_of("lines")
+            8707
+            >>> municip.number_of("nodes")
+            4178
+            >>> municip.number_of("pizza")
+            ...                     # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
+            Traceback (most recent call last):
+                ...
+            ValueError: vtype not supported, use one of:
+            'areas', 'dblinks', 'faces', 'holes', 'islands', 'kernels',
+            'line_points', 'lines', 'nodes', 'updated_lines', 'updated_nodes',
+            'volumes'
+            >>> municip.close()
+
+
+        ..
+        """
+        if vtype in _NUMOF.keys():
+            return _NUMOF[vtype](self.c_mapinfo)
+        else:
+            keys = "', '".join(sorted(_NUMOF.keys()))
+            raise ValueError("vtype not supported, use one of: '%s'" % keys)
+
+    def viter(self, vtype):
+        """Return an iterator of vector features
+
+        ::
+            >>> municip = VectorTopo('boundary_municp_sqlite')
+            >>> municip.open()
+            >>> big = [area for area in municip.viter('areas')
+            ...        if area.alive() and area.area >= 10000]
+            >>> big[:3]
+            [Area(1), Area(2), Area(3)]
+
+
+        to sort the result in a efficient way, use: ::
+
+            >>> from operator import methodcaller as method
+            >>> big.sort(key = method('area'), reverse = True)  # sort the list
+            >>> for area in big[:3]:
+            ...     print area, area.area()
+            Area(3102) 697521857.848
+            Area(2682) 320224369.66
+            Area(2552) 298356117.948
+            >>> municip.close()
+
+        ..
+        """
+        if vtype in _GEOOBJ.keys():
+            if _GEOOBJ[vtype] is not None:
+                return (_GEOOBJ[vtype](v_id=indx, c_mapinfo=self.c_mapinfo)
+                        for indx in xrange(1, self.number_of(vtype) + 1))
+        else:
+            keys = "', '".join(sorted(_GEOOBJ.keys()))
+            raise ValueError("vtype not supported, use one of: '%s'" % keys)
+
+    def rewind(self):
+        """Rewind vector map to cause reads to start at beginning. ::
+
+            >>> mun = VectorTopo('boundary_municp_sqlite')
+            >>> mun.open()
+            >>> mun.next()
+            Boundary(v_id=1)
+            >>> mun.next()
+            Boundary(v_id=2)
+            >>> mun.next()
+            Boundary(v_id=3)
+            >>> mun.rewind()
+            >>> mun.next()
+            Boundary(v_id=1)
+            >>> mun.close()
+
+        ..
+        """
+        libvect.Vect_rewind(self.c_mapinfo)
+
+    def read(self, feature_id):
+        """Return a geometry object given the feature id. ::
+
+            >>> mun = VectorTopo('boundary_municp_sqlite')
+            >>> mun.open()
+            >>> feature1 = mun.read(0)                     #doctest: +ELLIPSIS
+            Traceback (most recent call last):
+                ...
+            ValueError: The index must be >0, 0 given.
+            >>> feature1 = mun.read(1)
+            >>> feature1
+            Boundary(v_id=1)
+            >>> feature1.length()
+            1415.3348048582038
+            >>> mun.read(-1)
+            Centoid(649102.382010, 15945.714502)
+            >>> len(mun)
+            8707
+            >>> mun.read(8707)
+            Centoid(649102.382010, 15945.714502)
+            >>> mun.read(8708)                             #doctest: +ELLIPSIS
+            Traceback (most recent call last):
+              ...
+            IndexError: Index out of range
+            >>> mun.close()
+
+        ..
+        """
+        if feature_id < 0:  # Handle negative indices
+                feature_id += self.__len__() + 1
+        if feature_id >= (self.__len__() + 1):
+            raise IndexError('Index out of range')
+        if feature_id > 0:
+            c_points = ctypes.pointer(libvect.line_pnts())
+            c_cats = ctypes.pointer(libvect.line_cats())
+            ftype = libvect.Vect_read_line(self.c_mapinfo, c_points,
+                                           c_cats, feature_id)
+            if  GV_TYPE[ftype]['obj'] is not None:
+                return GV_TYPE[ftype]['obj'](v_id=feature_id,
+                                             c_mapinfo=self.c_mapinfo,
+                                             c_points=c_points,
+                                             c_cats=c_cats)
+        else:
+            raise ValueError('The index must be >0, %r given.' % feature_id)
+
+    def rewrite(self, geo_obj):
+        result = libvect.Vect_rewrite_line(self.c_mapinfo,
+                                           geo_obj.id, geo_obj.gtype,
+                                           geo_obj.c_points,
+                                           geo_obj.c_cats)
+        # return offset into file where the feature starts
+        geo_obj.offset = result
+
+    def delete(self, feature_id):
+        if libvect.Vect_rewrite_line(self.c_mapinfo, feature_id) == -1:
+            raise GrassError("C funtion: Vect_rewrite_line.")
+
+    def restore(self, geo_obj):
+        if hasattr(geo_obj, 'offset'):
+            if libvect.Vect_restore_line(self.c_mapinfo, geo_obj.id,
+                                         geo_obj.offset) == -1:
+                raise GrassError("C funtion: Vect_restore_line.")
+        else:
+            raise ValueError("The value have not an offset attribute.")
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/vector/abstract.py
===================================================================
--- grass/trunk/lib/python/pygrass/vector/abstract.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/vector/abstract.py	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,287 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Fri Aug 17 17:24:03 2012
+
+ at author: pietro
+"""
+import ctypes
+import datetime
+import grass.lib.vector as libvect
+from vector_type import MAPTYPE
+
+import pygrass.env as env
+from pygrass.errors import GrassError, OpenError
+from table import DBlinks
+
+
+def must_be_open(method):
+    def wrapper(self):
+        if self.is_open():
+            return method(self)
+        else:
+            print "You must open the map."
+    return wrapper
+
+
+#=============================================
+# VECTOR ABSTRACT CLASS
+#=============================================
+
+class Info(object):
+    """Basic vector info.
+    To get access to the vector info the map must be opened. ::
+
+        >>> municip = Info('boundary_municp', 'PERMANENT')
+        >>> municip.full_name
+        You must open the map.
+
+        >>> municip.open()
+
+    Then it is possible to read and write the following map attributes: ::
+
+        >>> municip.organization
+        'NC OneMap'
+        >>> municip.person
+        'helena'
+        >>> municip.title
+        'North Carolina municipality boundaries (polygon map)'
+        >>> municip.map_date
+        datetime.datetime(2006, 11, 7, 0, 1, 27)
+        >>> municip.date
+        ''
+        >>> municip.scale
+        1
+        >>> municip.comment
+        ''
+        >>> municip.comment = "One useful comment!"
+        >>> municip.comment
+        'One useful comment!'
+        >>> municip.zone
+        0
+        >>> municip.proj
+        99
+
+    There are some read only attributes: ::
+
+        >>> municip.full_name
+        'boundary_municp at PERMANENT'
+        >>> municip.proj_name
+        'Lambert Conformal Conic'
+        >>> municip.maptype
+        'native'
+
+    And some basic methods: ::
+
+        >>> municip.is_3D()
+        False
+        >>> municip.exist()
+        True
+        >>> municip.is_open()
+        True
+        >>> municip.close()
+
+    """
+    def __init__(self, name, mapset=''):
+        # Set map name and mapset
+        self._name = name
+        self.mapset = mapset
+        self.c_mapinfo = ctypes.pointer(libvect.Map_info())
+        self._topo_level = 1
+        self._class_name = 'Vector'
+        self.overwrite = False
+        self.date_fmt = '%a %b  %d %H:%M:%S %Y'
+
+    def _get_name(self):
+        if self.exist() and self.is_open():
+            return libvect.Vect_get_name(self.c_mapinfo)
+        else:
+            return self._name
+
+    def _set_name(self, newname):
+        self.rename(newname)
+
+    name = property(fget=_get_name, fset=_set_name)
+
+#    @property
+#    def mapset(self):
+#        return libvect.Vect_get_mapset(self.c_mapinfo)
+
+    def _get_organization(self):
+        return libvect.Vect_get_organization(self.c_mapinfo)
+
+    def _set_organization(self, org):
+        libvect.Vect_get_organization(self.c_mapinfo, ctypes.c_char_p(org))
+
+    organization = property(fget=_get_organization, fset=_set_organization)
+
+    def _get_date(self):
+        return libvect.Vect_get_date(self.c_mapinfo)
+
+    def _set_date(self, date):
+        return libvect.Vect_set_date(self.c_mapinfo, ctypes.c_char_p(date))
+
+    date = property(fget=_get_date, fset=_set_date)
+
+    def _get_person(self):
+        return libvect.Vect_get_person(self.c_mapinfo)
+
+    def _set_person(self, person):
+        libvect.Vect_set_person(self.c_mapinfo, ctypes.c_char_p(person))
+
+    person = property(fget=_get_person, fset=_set_person)
+
+    def _get_title(self):
+        return libvect.Vect_get_map_name(self.c_mapinfo)
+
+    def _set_title(self, title):
+        libvect.Vect_set_map_name(self.c_mapinfo, ctypes.c_char_p(title))
+
+    title = property(fget=_get_title, fset=_set_title)
+
+    def _get_map_date(self):
+        date_str = libvect.Vect_get_map_date(self.c_mapinfo)
+        return datetime.datetime.strptime(date_str, self.date_fmt)
+
+    def _set_map_date(self, datetimeobj):
+        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)
+
+    def _get_scale(self):
+        return libvect.Vect_get_scale(self.c_mapinfo)
+
+    def _set_scale(self, scale):
+        return libvect.Vect_set_scale(self.c_mapinfo, ctypes.c_int(scale))
+
+    scale = property(fget=_get_scale, fset=_set_scale)
+
+    def _get_comment(self):
+        return libvect.Vect_get_comment(self.c_mapinfo)
+
+    def _set_comment(self, comm):
+        return libvect.Vect_set_comment(self.c_mapinfo, ctypes.c_char_p(comm))
+
+    comment = property(fget=_get_comment, fset=_set_comment)
+
+    def _get_zone(self):
+        return libvect.Vect_get_zone(self.c_mapinfo)
+
+    def _set_zone(self, zone):
+        return libvect.Vect_set_zone(self.c_mapinfo, ctypes.c_int(zone))
+
+    zone = property(fget=_get_zone, fset=_set_zone)
+
+    def _get_proj(self):
+        return libvect.Vect_get_proj(self.c_mapinfo)
+
+    def _set_proj(self, proj):
+        libvect.Vect_set_proj(self.c_mapinfo, ctypes.c_int(proj))
+
+    proj = property(fget=_get_proj, fset=_set_proj)
+
+    def _get_thresh(self):
+        return libvect.Vect_get_thresh(self.c_mapinfo)
+
+    def _set_thresh(self, thresh):
+        return libvect.Vect_set_thresh(self.c_mapinfo, ctypes.c_double(thresh))
+
+    thresh = property(fget=_get_thresh, fset=_set_thresh)
+
+    @property
+    @must_be_open
+    def full_name(self):
+        return libvect.Vect_get_full_name(self.c_mapinfo)
+
+    @property
+    @must_be_open
+    def maptype(self):
+        return MAPTYPE[libvect.Vect_maptype(self.c_mapinfo)]
+
+    @property
+    @must_be_open
+    def proj_name(self):
+        return libvect.Vect_get_proj_name(self.c_mapinfo)
+
+    def _write_header(self):
+        libvect.Vect_write_header(self.c_mapinfo)
+
+    def rename(self, newname):
+        """Rename the map"""
+        if self.exist():
+            env.rename(self.name, newname, 'vect')
+        self._name = newname
+
+    def is_3D(self):
+        return bool(libvect.Vect_is_3d(self.c_mapinfo))
+
+    def exist(self):
+        if self._name:
+            self.mapset = env.get_mapset_vector(self._name, self.mapset)
+        else:
+            return False
+        if self.mapset:
+            return True
+        else:
+            return False
+
+    def is_open(self):
+        return bool(self.c_mapinfo.contents.open)
+
+    def open(self, mode='r', layer='0', overwrite=None):
+        """::
+
+            >>> mun = Info('boundary_municp_sqlite')
+            >>> mun.open()
+            >>> mun.is_open()
+            True
+            >>> mun.close()
+
+        ..
+        """
+        print "Sto aprendo..."
+        # check if map exists or not
+        if not self.exist() and mode != 'w':
+            raise OpenError("Map <%s> not found." % self._name)
+        if libvect.Vect_set_open_level(self._topo_level) != 0:
+            raise OpenError("Invalid access level.")
+        # update the overwrite attribute
+        self.overwrite = overwrite if overwrite is not None else self.overwrite
+        # check if the mode is valid
+        if mode not in ('r', 'rw', 'w'):
+            raise ValueError("Mode not supported. Use one of: 'r', 'rw', 'w'.")
+        # check if the map exist
+        if self.exist() and mode == 'r':
+            openvect = libvect.Vect_open_old2(self.c_mapinfo, self.name,
+                                              self.mapset, layer)
+        # If it is opened in write mode
+        if mode == 'w':
+            #TODO: build topo if new
+            openvect = libvect.Vect_open_new(self.c_mapinfo, self.name,
+                                             libvect.WITHOUT_Z)
+        elif mode == 'rw':
+            openvect = libvect.Vect_open_update2(self.c_mapinfo, self.name,
+                                                 self.mapset, layer)
+        # initialize the dblinks object
+        self.dblinks = DBlinks(self.c_mapinfo)
+        # check the C function result.
+        if openvect != self._topo_level:
+            str_err = "Not able to open the map, C function return %d."
+            raise OpenError(str_err % openvect)
+
+    def close(self):
+        if self.is_open():
+            if libvect.Vect_close(self.c_mapinfo) != 0:
+                str_err = 'Error when trying to close the map with Vect_close'
+                raise GrassError(str_err)
+
+    def remove(self):
+        """Remove vector map"""
+        if self.is_open():
+            self.close()
+        env.remove(vect=self.name)
+
+    def build(self):
+        """Build vector Topology"""
+        #TODO: Add function
+        pass
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/vector/basic.py
===================================================================
--- grass/trunk/lib/python/pygrass/vector/basic.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/vector/basic.py	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,319 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Tue Jul 31 13:06:20 2012
+
+ at author: pietro
+"""
+import ctypes
+import grass.lib.vector as libvect
+from collections import Iterable
+
+
+class Bbox(object):
+    """Instantiate a Bounding Box class that contain
+    a ctypes pointer to the C struct bound_box, that could be use
+    by C GRASS functions. ::
+
+        >>> bbox = Bbox()
+        >>> bbox
+        Bbox(0.0, 0.0, 0.0, 0.0)
+
+    The default parameters are 0. It is possible to set or change
+    the parameters later, with: ::
+
+        >>> bbox.north = 10
+        >>> bbox.south = -10
+        >>> bbox.east = -20
+        >>> bbox.west = 20
+        >>> bbox
+        Bbox(10.0, -10.0, -20.0, 20.0)
+
+    Or directly istantiate the class with the values, with: ::
+
+        >>> bbox = Bbox(north=100, south=0, east=0, west=100)
+        >>> bbox
+        Bbox(100.0, 0.0, 0.0, 100.0)
+
+    ..
+    """
+    def __init__(self, north=0, south=0, east=0, west=0, top=0, bottom=0):
+        self.c_bbox = ctypes.pointer(libvect.bound_box())
+        self.north = north
+        self.south = south
+        self.east = east
+        self.west = west
+        self.top = top
+        self.bottom = bottom
+
+    def _get_n(self):
+        return self.c_bbox.contents.N
+
+    def _set_n(self, value):
+        self.c_bbox.contents.N = value
+
+    north = property(fget=_get_n, fset=_set_n)
+
+    def _get_s(self):
+        return self.c_bbox.contents.S
+
+    def _set_s(self, value):
+        self.c_bbox.contents.S = value
+
+    south = property(fget=_get_s, fset=_set_s)
+
+    def _get_e(self):
+        return self.c_bbox.contents.E
+
+    def _set_e(self, value):
+        self.c_bbox.contents.E = value
+
+    east = property(fget=_get_e, fset=_set_e)
+
+    def _get_w(self):
+        return self.c_bbox.contents.W
+
+    def _set_w(self, value):
+        self.c_bbox.contents.W = value
+
+    west = property(fget=_get_w, fset=_set_w)
+
+    def _get_t(self):
+        return self.c_bbox.contents.T
+
+    def _set_t(self, value):
+        self.c_bbox.contents.T = value
+
+    top = property(fget=_get_t, fset=_set_t)
+
+    def _get_b(self):
+        return self.c_bbox.contents.B
+
+    def _set_b(self, value):
+        self.c_bbox.contents.B = value
+
+    bottom = property(fget=_get_b, fset=_set_b)
+
+    def __repr__(self):
+        return "Bbox({n}, {s}, {e}, {w})".format(n=self.north, s=self.south,
+                                                 e=self.east, w=self.west)
+
+
+class BoxList(object):
+    def __init__(self, boxlist=None):
+        self.c_boxlist = ctypes.pointer(libvect.boxlist())
+        # if set to 0, the list will hold only ids and no boxes
+        self.c_boxlist.contents.have_boxes = 1
+        if boxlist is not None:
+            for box in boxlist:
+                self.append(box)
+
+    def __len__(self):
+        return self.c_boxlist.contents.n_values
+
+    def __repr__(self):
+        return "Boxlist([%s])" % ", ".join([repr(box)
+                                            for box in self.__iter__()])
+
+    def __getitem__(self, indx):
+        bbox = Bbox()
+        bbox.c_bbox = ctypes.pointer(self.c_boxlist.contents.box[indx])
+        return bbox
+
+    def __setitem__(self, indx, bbox):
+        self.c_boxlist.cotents.box[indx] = bbox
+
+    def __iter__(self):
+        return (self.__getitem__(box_id) for box_id in xrange(self.__len__()))
+
+    def __str__(self):
+        return self.__repr__()
+
+    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
+
+        ..
+        """
+        indx = self.__len__()
+        libvect.Vect_boxlist_append(self.c_boxlist, indx, box.c_bbox.contents)
+
+#    def extend(self, boxlist):
+#        """Extend a boxlist with another boxlist or using a list of Bbox, using
+#        ``Vect_boxlist_append_boxlist`` c function. ::
+#
+#            >>> box0 = Bbox()
+#            >>> box1 = Bbox(1,2,3,4)
+#            >>> box2 = Bbox(5,6,7,8)
+#            >>> box3 = Bbox(9,8,7,6)
+#            >>> boxlist0 = BoxList([box0, box1])
+#            >>> boxlist0
+#            Boxlist([Bbox(0.0, 0.0, 0.0, 0.0), Bbox(1.0, 2.0, 3.0, 4.0)])
+#            >>> boxlist1 = BoxList([box2, box3])
+#            >>> len(boxlist0)
+#            2
+#            >>> boxlist0.extend(boxlist1)
+#            >>> len(boxlist0)
+#            4
+#            >>> boxlist1.extend([box0, box1])
+#            >>> len(boxlist1)
+#            4
+#
+#        ..
+#        """
+#        if hasattr(boxlist, 'c_boxlist'):
+#            #import pdb; pdb.set_trace()
+#            # FIXME: doesn't work
+#            libvect.Vect_boxlist_append_boxlist(self.c_boxlist,
+#                                                boxlist.c_boxlist)
+#        else:
+#            for box in boxlist:
+#                self.append(box)
+
+    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``. ::
+
+            >>> 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)
+        elif isinstance(indx, int):
+            libvect.Vect_boxlist_delete(self.c_boxlist, indx)
+        else:
+            for ind in indx:
+                libvect.Vect_boxlist_delete(self.c_boxlist, ind)
+
+    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
+
+        ..
+        """
+        libvect.Vect_reset_boxlist(self.c_boxlist)
+
+
+class Ilist(object):
+    """Instantiate a list of integer using the C GRASS struct ``ilist``,
+    the class contains this struct as ``c_ilist`` attribute. """
+    def __init__(self, integer_list=None):
+        self.c_ilist = ctypes.pointer(libvect.struct_ilist())
+        if integer_list is not None:
+            self.extend(integer_list)
+
+    def __getitem__(self, key):
+        if isinstance(key, slice):
+            #import pdb; pdb.set_trace()
+            #Get the start, stop, and step from the slice
+            return [self.c_ilist.contents.value[indx]
+                    for indx in xrange(*key.indices(len(self)))]
+        elif isinstance(key, int):
+            if key < 0:  # Handle negative indices
+                key += self.c_ilist.contents.n_values
+            if key >= self.c_ilist.contents.n_values:
+                raise IndexError('Index out of range')
+            return self.c_ilist.contents.value[key]
+        else:
+            raise ValueError("Invalid argument type: %r." % key)
+
+    def __setitem__(self, key, value):
+        if self.contains(value):
+            raise ValueError('Integer already in the list')
+        self.c_ilist.contents.value[key] = int(value)
+
+    def __len__(self):
+        return self.c_ilist.contents.n_values
+
+    def __iter__(self):
+        return [self.c_ilist.contents.value[i] for i in xrange(self.__len__())]
+
+    def __repr__(self):
+        return "Ilist(%r)" % repr(self.__iter__())
+
+    def append(self, value):
+        """Append an integer to the list"""
+        if libvect.Vect_list_append(self.c_ilist, value):
+            raise  # TODO
+
+    def reset(self):
+        """Reset the list"""
+        libvect.Vect_reset_list(self.c_ilist)
+
+    def extend(self, ilist):
+        """Extend the list with another Ilist object or
+        with a list of integers"""
+        if isinstance(ilist, Ilist):
+            libvect.Vect_list_append_list(self.c_ilist, ilist.ilist)
+        else:
+            for i in ilist:
+                self.append(i)
+
+    def remove(self, value):
+        """Remove a value from a list"""
+        if isinstance(value, int):
+            libvect.Vect_list_delete(self.c_ilist, value)
+        elif isinstance(value, Ilist):
+            libvect.Vect_list_delete_list(self.c_ilist, value.ilist)
+        elif isinstance(value, Iterable):
+            for i in value:
+                libvect.Vect_list_delete(self.c_ilist, int(i))
+        else:
+            raise ValueError('Value: %r, is not supported' % value)
+
+    def contains(self, value):
+        """Check if value is in the list"""
+        return bool(libvect.Vect_val_in_list(self.c_ilist, value))
+
+
+class Cats(object):
+    """Instantiate a Category class that contains a ctypes pointer
+    to the Map_info C struct, and a ctypes pointer to that C cats struct,
+    that could be used by C functions.
+    """
+
+    def __init__(self, c_mapinfo, v_id, c_cats=None):
+        self.c_mapinfo = c_mapinfo
+        self.id = v_id
+        if c_cats is not None:
+            self.c_cats = c_cats
+        else:
+            self.c_cats = ctypes.pointer(libvect.line_cats())
+            self.get_area_cats()
+
+    def get_area_cats(self):
+        """Get area categories, set the c_cats struct given an area, using the
+        ``Vect_get_area_cats`` function.
+        """
+        libvect.Vect_get_area_cats(self.c_mapinfo, self.id, self.c_cats)
+
+    def reset(self):
+        """Reset the C cats struct from previous values."""
+        libvect.Vect_reset_cats(self.c_cats)
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/vector/geometry.py
===================================================================
--- grass/trunk/lib/python/pygrass/vector/geometry.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/vector/geometry.py	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,1146 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Wed Jul 18 10:46:25 2012
+
+ at author: pietro
+
+"""
+import ctypes
+import numpy as np
+import re
+
+import grass.lib.gis as libgis
+import grass.lib.vector as libvect
+
+from basic import Ilist, Bbox, Cats
+
+
+WKT = {'POINT\((.*)\)': 'point',  # 'POINT\(\s*([+-]*\d+\.*\d*)+\s*\)'
+       'LINESTRING\((.*)\)': 'line'}
+
+
+def read_WKT(string):
+    """Read the string and return a geometry object
+
+    WKT:
+    POINT(0 0)
+    LINESTRING(0 0,1 1,1 2)
+    POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1))
+    MULTIPOINT(0 0,1 2)
+    MULTILINESTRING((0 0,1 1,1 2),(2 3,3 2,5 4))
+    MULTIPOLYGON(((0 0,4 0,4 4,0 4,0 0),(1 1,2 1,2 2,1 2,1 1)),
+                 ((-1 -1,-1 -2,-2 -2,-2 -1,-1 -1)))
+    GEOMETRYCOLLECTION(POINT(2 3),LINESTRING(2 3,3 4))
+
+
+    EWKT:
+    POINT(0 0 0) -- XYZ
+    SRID=32632;POINT(0 0) -- XY with SRID
+    POINTM(0 0 0) -- XYM
+    POINT(0 0 0 0) -- XYZM
+    SRID=4326;MULTIPOINTM(0 0 0,1 2 1) -- XYM with SRID
+    MULTILINESTRING((0 0 0,1 1 0,1 2 1),(2 3 1,3 2 1,5 4 1))
+    POLYGON((0 0 0,4 0 0,4 4 0,0 4 0,0 0 0),(1 1 0,2 1 0,2 2 0,1 2 0,1 1 0))
+    MULTIPOLYGON(((0 0 0,4 0 0,4 4 0,0 4 0,0 0 0),
+                  (1 1 0,2 1 0,2 2 0,1 2 0,1 1 0)),
+                 ((-1 -1 0,-1 -2 0,-2 -2 0,-2 -1 0,-1 -1 0)))
+    GEOMETRYCOLLECTIONM( POINTM(2 3 9), LINESTRINGM(2 3 4, 3 4 5) )
+    MULTICURVE( (0 0, 5 5), CIRCULARSTRING(4 0, 4 4, 8 4) )
+    POLYHEDRALSURFACE( ((0 0 0, 0 0 1, 0 1 1, 0 1 0, 0 0 0)),
+                       ((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)),
+                       ((0 0 0, 1 0 0, 1 0 1, 0 0 1, 0 0 0)),
+                       ((1 1 0, 1 1 1, 1 0 1, 1 0 0, 1 1 0)),
+                       ((0 1 0, 0 1 1, 1 1 1, 1 1 0, 0 1 0)),
+                       ((0 0 1, 1 0 1, 1 1 1, 0 1 1, 0 0 1)) )
+    TRIANGLE ((0 0, 0 9, 9 0, 0 0))
+    TIN( ((0 0 0, 0 0 1, 0 1 0, 0 0 0)), ((0 0 0, 0 1 0, 1 1 0, 0 0 0)) )
+
+    """
+    for regexp, obj in WKT.items():
+        if re.match(regexp, string):
+            geo = 10
+            return obj(geo)
+
+
+def read_WKB(buff):
+    """Read the binary buffer and return a geometry object"""
+    pass
+
+
+#=============================================
+# GEOMETRY
+#=============================================
+
+
+def get_xyz(pnt):
+    """Return a tuple with: x, y, z. ::
+
+        >>> pnt = Point(0, 0)
+        >>> get_xyz(pnt)
+        (0.0, 0.0, 0.0)
+        >>> get_xyz((1, 1))
+        (1, 1, 0.0)
+        >>> get_xyz((1, 1, 2))
+        (1, 1, 2)
+        >>> get_xyz((1, 1, 2, 2))                          #doctest: +ELLIPSIS
+        Traceback (most recent call last):
+            ...
+        ValueError: The the format of the point is not supported: (1, 1, 2, 2)
+
+    ..
+    """
+    if isinstance(pnt, Point):
+        if pnt.is2D:
+            x, y = pnt.x, pnt.y
+            z = 0.
+        else:
+            x, y, z = pnt.x, pnt.y, pnt.z
+    else:
+        if len(pnt) == 2:
+            x, y = pnt
+            z = 0.
+        elif len(pnt) == 3:
+            x, y, z = pnt
+        else:
+            str_error = "The the format of the point is not supported: {0!r}"
+            raise ValueError(str_error.format(pnt))
+    return x, y, z
+
+
+class Geo(object):
+    """
+    >>> geo0 = Geo()
+    >>> points = ctypes.pointer(libvect.line_pnts())
+    >>> cats = ctypes.pointer(libvect.line_cats())
+    >>> geo1 = Geo(c_points=points, c_cats=cats)
+    """
+    def __init__(self, v_id=None, c_mapinfo=None, c_points=None, c_cats=None):
+        self.id = v_id  # vector id
+        self.c_mapinfo = c_mapinfo
+
+        # set c_points
+        if c_points is None:
+            self.c_points = ctypes.pointer(libvect.line_pnts())
+        else:
+            self.c_points = c_points
+
+        # set c_cats
+        if c_cats is None:
+            self.c_cats = ctypes.pointer(libvect.line_cats())
+        else:
+            self.c_cats = c_cats
+
+    def is_with_topology(self):
+        if self.c_mapinfo is not None:
+            return self.c_mapinfo.contents.level == 2
+        else:
+            return False
+
+    def read(self):
+        """Read and set the coordinates of the centroid from the vector map,
+        using the centroid_id and calling the Vect_read_line C function"""
+        libvect.Vect_read_line(self.c_mapinfo, self.c_points,
+                               self.c_cats, self.id)
+
+    def write(self):
+        """Write the centroid to the Map."""
+        libvect.Vect_write_line(self.c_mapinfo, libvect.GV_CENTROID,
+                                self.c_points, self.c_cats)
+
+
+class Point(Geo):
+    """Instantiate a Point object that could be 2 or 3D, default
+    parameters are 0.
+
+    ::
+
+        >>> pnt = Point()
+        >>> pnt.x
+        0.0
+        >>> pnt.y
+        0.0
+        >>> pnt.z
+        >>> pnt.is2D
+        True
+        >>> pnt
+        Point(0.000000, 0.000000)
+        >>> pnt.z = 0
+        >>> pnt.is2D
+        False
+        >>> pnt
+        Point(0.000000, 0.000000, 0.000000)
+        >>> print pnt
+        POINT(0.000000, 0.000000, 0.000000)
+
+    ..
+    """
+    def __init__(self, x=0, y=0, z=None, **kargs):
+        super(Point, self).__init__(**kargs)
+        self.is2D = True if z is None else False
+        z = z if z is not None else 0
+        libvect.Vect_append_point(self.c_points, x, y, z)
+
+        # geometry type
+        self.gtype = libvect.GV_POINT
+
+    def _get_x(self):
+        return self.c_points.contents.x[0]
+
+    def _set_x(self, value):
+        self.c_points.contents.x[0] = value
+
+    x = property(fget=_get_x, fset=_set_x)
+
+    def _get_y(self):
+        return self.c_points.contents.y[0]
+
+    def _set_y(self, value):
+        self.c_points.contents.y[0] = value
+
+    y = property(fget=_get_y, fset=_set_y)
+
+    def _get_z(self):
+        if self.is2D:
+            return None
+        return self.c_points.contents.z[0]
+
+    def _set_z(self, value):
+        if value is None:
+            self.is2D = True
+            self.c_points.contents.z[0] = 0
+        else:
+            self.c_points.contents.z[0] = value
+            self.is2D = False
+
+    z = property(fget=_get_z, fset=_set_z)
+
+    def __str__(self):
+        return self.get_wkt()
+
+    def __repr__(self):
+        return "Point(%s)" % ', '.join(['%f' % coor for coor in self.coords()])
+
+    def __eq__(self, pnt):
+        if isinstance(pnt, Point):
+            return pnt.coords() == self.coords()
+
+        return Point(*pnt).coords() == self.coords()
+
+    def coords(self):
+        """Return a tuple with the point coordinates. ::
+
+            >>> pnt = Point(10, 100)
+            >>> pnt.coords()
+            (10.0, 100.0)
+
+        If the point is 2D return a x, y tuple. But if we change the ``z``
+        the Point object become a 3D point, therefore the method return a
+        x, y, z tuple. ::
+
+            >>> pnt.z = 1000.
+            >>> pnt.coords()
+            (10.0, 100.0, 1000.0)
+
+        ..
+        """
+        if self.is2D:
+            return self.x, self.y
+        else:
+            return self.x, self.y, self.z
+
+    def get_wkt(self):
+        """Return a "well know text" (WKT) geometry string. ::
+
+            >>> pnt = Point(10, 100)
+            >>> pnt.get_wkt()
+            'POINT(10.000000, 100.000000)'
+
+        .. warning::
+
+            Only ``POINT`` (2/3D) are supported, ``POINTM`` and ``POINT`` with:
+            ``XYZM`` are not supported yet.
+        """
+        return "POINT(%s)" % ', '.join(['%f' % coord
+                                        for coord in self.coords()])
+
+    def get_wkb(self):
+        """Return a "well know binary" (WKB) geometry buffer
+
+        .. warning::
+
+            Not implemented yet.
+
+        """
+        pass
+
+    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.
+        ::
+
+            >>> pnt0 = Point(0, 0, 0)
+            >>> pnt1 = Point(1, 0)
+            >>> pnt0.distance(pnt1)
+            1.0
+            >>> pnt1.z = 1
+            >>> pnt1
+            Point(1.000000, 0.000000, 1.000000)
+            >>> 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,
+                                                pnt.x, pnt.y, 0, 0)
+        else:
+            return libvect.Vect_points_distance(self.x, self.y, self.z,
+                                                pnt.x, pnt.y, pnt.z, 1)
+
+    def buffer(self, dist=None, dist_x=None, dist_y=None, angle=0,
+               round_=True, tol=0.1):
+        """Return an Area object using the ``Vect_point_buffer2`` C function.
+        Creates buffer around the point (px, py).
+        """
+        print "Not implemented yet"
+        raise
+        if dist is not None:
+            dist_x = dist
+            dist_y = dist
+        area = Area()
+        libvect.Vect_point_buffer2(self.x, self.y,
+                                   dist_x, dist_y,
+                                   angle, int(round_), tol,
+                                   area.c_points)
+        return area
+
+
+class Line(Geo):
+    """Instantiate a new Line with a list of tuple, or with a list of Point. ::
+
+        >>> line = Line([(0, 0), (1, 1), (2, 0), (1, -1)])
+        >>> line                               #doctest: +NORMALIZE_WHITESPACE
+        Line([Point(0.000000, 0.000000),
+              Point(1.000000, 1.000000),
+              Point(2.000000, 0.000000),
+              Point(1.000000, -1.000000)])
+
+    ..
+    """
+    def __init__(self, points=None, is2D=True, **kargs):
+        super(Line, self).__init__(**kargs)
+        if points is not None:
+            for pnt in points:
+                self.append(pnt)
+
+        self.is2D = is2D
+        # geometry type
+        self.gtype = libvect.GV_LINE
+
+    def __getitem__(self, key):
+        """Get line point of given index,  slice allowed. ::
+
+            >>> line = Line([(0, 0), (1, 1), (2, 2), (3, 3)])
+            >>> line[1]
+            Point(1.000000, 1.000000)
+            >>> line[-1]
+            Point(3.000000, 3.000000)
+            >>> line[:2]
+            [Point(0.000000, 0.000000), Point(1.000000, 1.000000)]
+
+        ..
+        """
+        #TODO:
+        # line[0].x = 10 is not working
+        #pnt.c_px = ctypes.pointer(self.c_points.contents.x[indx])
+        # pnt.c_px = ctypes.cast(id(self.c_points.contents.x[indx]),
+        # ctypes.POINTER(ctypes.c_double))
+        if isinstance(key, slice):
+            #import pdb; pdb.set_trace()
+            #Get the start, stop, and step from the slice
+            return [Point(self.c_points.contents.x[indx],
+                          self.c_points.contents.y[indx],
+                    None if self.is2D else self.c_points.contents.z[indx])
+                    for indx in xrange(*key.indices(len(self)))]
+        elif isinstance(key, int):
+            if key < 0:  # Handle negative indices
+                key += self.c_points.contents.n_points
+            if key >= self.c_points.contents.n_points:
+                raise IndexError('Index out of range')
+            return Point(self.c_points.contents.x[key],
+                         self.c_points.contents.y[key],
+                         None if self.is2D else self.c_points.contents.z[key])
+        else:
+            raise ValueError("Invalid argument type: %r." % key)
+
+    def __setitem__(self, indx, pnt):
+        """Change the coordinate of point. ::
+
+            >>> line = Line([(0, 0), (1, 1)])
+            >>> line[0] = (2, 2)
+            >>> line
+            Line([Point(2.000000, 2.000000), Point(1.000000, 1.000000)])
+
+        ..
+        """
+        x, y, z = get_xyz(pnt)
+        self.c_points.contents.x[indx] = x
+        self.c_points.contents.y[indx] = y
+        self.c_points.contents.z[indx] = z
+
+    def __iter__(self):
+        """Return a Point generator of the Line"""
+        return (self.__getitem__(i) for i in range(self.__len__()))
+
+    def __len__(self):
+        """Return the number of points of the line."""
+        return self.c_points.contents.n_points
+
+    def __str__(self):
+        return self.get_wkt()
+
+    def __repr__(self):
+        return "Line([%s])" % ', '.join([repr(pnt) for pnt in self.__iter__()])
+
+    def get_pnt(self, distance, angle=0, slope=0):
+        """Return a Point object on line in the specified distance, using the
+        `Vect_point_on_line` C function.
+        Raise a ValueError If the distance exceed the Line length. ::
+
+            >>> line = Line([(0, 0), (1, 1)])
+            >>> line.get_pnt(5)      #doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
+            Traceback (most recent call last):
+                ...
+            ValueError: The distance exceed the lenght of the line,
+            that is: 1.414214
+            >>> line.get_pnt(1)
+            Point(0.707107, 0.707107)
+
+        ..
+        """
+        # instantiate an empty Point object
+        maxdist = self.length()
+        if distance > maxdist:
+            str_err = "The distance exceed the lenght of the line, that is: %f"
+            raise ValueError(str_err % maxdist)
+        pnt = Point(0, 0, -9999)
+        libvect.Vect_point_on_line(self.c_points, distance,
+                                   pnt.c_points.contents.x,
+                                   pnt.c_points.contents.y,
+                                   pnt.c_points.contents.z,
+                                   angle, slope)
+        pnt.is2D = self.is2D
+        return pnt
+
+    def append(self, pnt):
+        """Appends one point to the end of a line, using the
+        ``Vect_append_point`` C function. ::
+
+            >>> line = Line()
+            >>> line.append((10, 100))
+            >>> line
+            Line([Point(10.000000, 100.000000)])
+            >>> line.append((20, 200))
+            >>> line
+            Line([Point(10.000000, 100.000000), Point(20.000000, 200.000000)])
+
+        Like python list.
+        """
+        x, y, z = get_xyz(pnt)
+        libvect.Vect_append_point(self.c_points, x, y, z)
+
+    def bbox(self):
+        """Return the bounding box of the line, using ``Vect_line_box``
+        C function. ::
+
+            >>> line = Line([(0, 0), (0, 1), (2, 1), (2, 0)])
+            >>> bbox = line.bbox()
+            >>> bbox
+            Bbox(1.0, 0.0, 2.0, 0.0)
+
+        ..
+        """
+        bbox = Bbox()
+        libvect.Vect_line_box(self.c_points, bbox.c_bbox)
+        return bbox
+
+    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. ::
+
+            >>> line = Line([(0, 0), (1, 1)])
+            >>> line.extend( Line([(2, 2), (3, 3)]) )
+            >>> line                           #doctest: +NORMALIZE_WHITESPACE
+            Line([Point(0.000000, 0.000000),
+                  Point(1.000000, 1.000000),
+                  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:
+            direction = libvect.GV_FORWARD
+        else:
+            direction = libvect.GV_BACKWARD
+        # check if is a Line object
+        if isinstance(line, Line):
+            c_points = line.c_points
+        else:
+            # instantiate a Line object
+            lin = Line()
+            for pnt in line:
+                # add the points to the line
+                lin.append(pnt)
+            c_points = lin.c_points
+
+        libvect.Vect_append_points(self.c_points, c_points, direction)
+
+    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. ::
+
+            >>> line = Line([(0, 0), (1, 1)])
+            >>> line.insert(0, Point(1.000000, -1.000000) )
+            >>> line                           #doctest: +NORMALIZE_WHITESPACE
+            Line([Point(1.000000, -1.000000),
+                  Point(0.000000, 0.000000),
+                  Point(1.000000, 1.000000)])
+
+        ..
+        """
+        if indx < 0:  # Handle negative indices
+            indx += self.c_points.contents.n_points
+        if indx >= self.c_points.contents.n_points:
+            raise IndexError('Index out of range')
+        x, y, z = get_xyz(pnt)
+        libvect.Vect_line_insert_point(self.c_points, indx, x, y, z)
+
+    def length(self):
+        """Calculate line length, 3D-length in case of 3D vector line, using
+        `Vect_line_length` C function.  ::
+
+            >>> line = Line([(0, 0), (1, 1), (0, 1)])
+            >>> line.length()
+            2.414213562373095
+
+        ..
+        """
+        return libvect.Vect_line_length(self.c_points)
+
+    def length_geodesic(self):
+        """Calculate line length, usig `Vect_line_geodesic_length` C function.
+        ::
+
+            >>> line = Line([(0, 0), (1, 1), (0, 1)])
+            >>> line.length_geodesic()
+            2.414213562373095
+
+        ..
+        """
+        return libvect.Vect_line_geodesic_length(self.c_points)
+
+    def distance(self, pnt):
+        """Return a tuple with:
+
+            * the closest point on the line,
+            * the distance between these two points,
+            * distance of point from segment beginning
+            * distance of point from line
+
+        The distance is compute using the ``Vect_line_distance`` C function.
+        """
+        # instantite outputs
+        cx = ctypes.c_double(0)
+        cy = ctypes.c_double(0)
+        cz = ctypes.c_double(0)
+        dist = ctypes.c_double(0)
+        sp_dist = ctypes.c_double(0)
+        lp_dist = ctypes.c_double(0)
+
+        libvect.Vect_line_distance(self.c_points,
+                                   pnt.x, pnt.y, pnt.z, 0 if self.is2D else 1,
+                                   ctypes.byref(cx), ctypes.byref(cy),
+                                   ctypes.byref(cz), ctypes.byref(dist),
+                                   ctypes.byref(sp_dist),
+                                   ctypes.byref(lp_dist))
+        # instantiate the Point class
+        point = Point(cx.value, cy.value, cz.value)
+        point.is2D = self.is2D
+        return point, dist, sp_dist, lp_dist
+
+    def get_first_cat(self):
+        """Fetches FIRST category number for given vector line and field, using
+        the ``Vect_get_line_cat`` C function.
+
+        .. warning::
+
+            Not implemented yet.
+        """
+        # TODO: add this method.
+        libvect.Vect_get_line_cat(self.map, self.id, self.field)
+        pass
+
+    def pop(self, indx):
+        """Return the point in the index position and remove from the Line. ::
+
+            >>> line = Line([(0, 0), (1, 1), (2, 2)])
+            >>> midle_pnt = line.pop(1)
+            >>> midle_pnt
+            Point(1.000000, 1.000000)
+            >>> 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
+        if indx >= self.c_points.contents.n_points:
+            raise IndexError('Index out of range')
+        pnt = self.__getitem__(indx)
+        libvect.Vect_line_delete_point(self.c_points, indx)
+        return pnt
+
+    def delete(self, indx):
+        """Remove the point in the index position. ::
+
+            >>> 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
+        if indx >= self.c_points.contents.n_points:
+            raise IndexError('Index out of range')
+        libvect.Vect_line_delete_point(self.c_points, indx)
+
+    def prune(self):
+        """Remove duplicate points, i.e. zero length segments, using
+        `Vect_line_prune` C function. ::
+
+            >>> line = Line([(0, 0), (1, 1), (1, 1), (2, 2)])
+            >>> line.prune()
+            >>> line                           #doctest: +NORMALIZE_WHITESPACE
+            Line([Point(0.000000, 0.000000),
+                  Point(1.000000, 1.000000),
+                  Point(2.000000, 2.000000)])
+
+        ..
+        """
+        libvect.Vect_line_prune(self.c_points)
+
+    def prune_thresh(self, threshold):
+        """Remove points in threshold, using the ``Vect_line_prune_thresh``
+        C funtion. ::
+
+            >>> line = Line([(0, 0), (1.0, 1.0), (1.2, 0.9), (2, 2)])
+            >>> line.prune_thresh(0.5)
+            >>> line                     #doctest: +SKIP +NORMALIZE_WHITESPACE
+            Line([Point(0.000000, 0.000000),
+                  Point(1.000000, 1.000000),
+                  Point(2.000000, 2.000000)])
+
+        .. warning ::
+
+            prune_thresh is not working yet.
+        """
+        libvect.Vect_line_prune(self.c_points, ctypes.c_double(threshold))
+
+    def remove(self, pnt):
+        """Delete point at given index and move all points above down, using
+        `Vect_line_delete_point` C function. ::
+
+            >>> line = Line([(0, 0), (1, 1), (2, 2)])
+            >>> line.remove((2, 2))
+            >>> line[-1]
+            Point(1.000000, 1.000000)
+
+        ..
+        """
+        for indx, point in enumerate(self.__iter__()):
+            if pnt == point:
+                libvect.Vect_line_delete_point(self.c_points, indx)
+                return
+        raise ValueError('list.remove(x): x not in list')
+
+    def reverse(self):
+        """Reverse the order of vertices, using `Vect_line_reverse`
+        C function. ::
+
+            >>> line = Line([(0, 0), (1, 1), (2, 2)])
+            >>> line.reverse()
+            >>> line                           #doctest: +NORMALIZE_WHITESPACE
+            Line([Point(2.000000, 2.000000),
+                  Point(1.000000, 1.000000),
+                  Point(0.000000, 0.000000)])
+
+        ..
+        """
+        libvect.Vect_line_reverse(self.c_points)
+
+    def segment(self, start, end):
+        """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
+
+    def tolist(self):
+        """Return a list of tuple. ::
+
+            >>> line = Line([(0, 0), (1, 1), (2, 0), (1, -1)])
+            >>> line.tolist()
+            [(0.0, 0.0), (1.0, 1.0), (2.0, 0.0), (1.0, -1.0)]
+
+        ..
+        """
+        return [pnt.coords() for pnt in self.__iter__()]
+
+    def toarray(self):
+        """Return an array of coordinates. ::
+
+            >>> line = Line([(0, 0), (1, 1), (2, 0), (1, -1)])
+            >>> line.toarray()                 #doctest: +NORMALIZE_WHITESPACE
+            array([[ 0.,  0.],
+                   [ 1.,  1.],
+                   [ 2.,  0.],
+                   [ 1., -1.]])
+
+        ..
+        """
+        return np.array(self.tolist())
+
+    def get_wkt(self):
+        """Return a Well Known Text string of the line. ::
+
+            >>> line = Line([(0, 0), (1, 1), (1, 2)])
+            >>> line.get_wkt()                 #doctest: +ELLIPSIS
+            'LINESTRING(0.000000 0.000000, ..., 1.000000 2.000000)'
+
+        ..
+        """
+        return "LINESTRING(%s)" % ', '.join([
+               ' '.join(['%f' % coord for coord in pnt.coords()])
+               for pnt in self.__iter__()])
+
+    def from_wkt(self, wkt):
+        """Read a WKT string. ::
+
+            >>> line = Line()
+            >>> line.from_wkt("LINESTRING(0 0,1 1,1 2)")
+            >>> line                           #doctest: +NORMALIZE_WHITESPACE
+            Line([Point(0.000000, 0.000000),
+                  Point(1.000000, 1.000000),
+                  Point(1.000000, 2.000000)])
+
+        ..
+        """
+        match = re.match('LINESTRING\((.*)\)', wkt)
+        if match:
+            self.reset()
+            for coord in match.groups()[0].strip().split(','):
+                self.append(tuple([float(e) for e in coord.split(' ')]))
+        else:
+            return None
+
+    def get_wkb(self):
+        """Return a WKB buffer.
+
+        .. warning::
+
+            Not implemented yet.
+        """
+        pass
+
+    def buffer(self, dist=None, dist_x=None, dist_y=None,
+               angle=0, round_=True, tol=0.1):
+        """Return the buffer area around the line, using the
+        ``Vect_line_buffer2`` C function.
+
+        .. warning::
+
+            Not implemented yet.
+        """
+        if dist is not None:
+            dist_x = dist
+            dist_y = dist
+        area = Area()
+        libvect.Vect_line_buffer2(self.c_points,
+                                  dist_x, dist_y,
+                                  angle, int(round_), tol,
+                                  area.boundary.c_points,
+                                  area.isles.c_points,
+                                  area.num_isles)
+        return area
+
+    def reset(self):
+        """Reset line, using `Vect_reset_line` C function. ::
+
+            >>> line = Line([(0, 0), (1, 1), (2, 0), (1, -1)])
+            >>> len(line)
+            4
+            >>> line.reset()
+            >>> len(line)
+            0
+            >>> line
+            Line([])
+
+        ..
+        """
+        libvect.Vect_reset_line(self.c_points)
+
+
+class Node(object):
+    pass
+
+
+class Boundary(Line):
+    """
+    """
+    def __init__(self, area_id=None, lines=None, left=None, right=None,
+                 **kargs):
+        super(Boundary, self).__init__(**kargs)
+        self.area_id = area_id
+        self.ilist = Ilist()
+        self.lines = lines
+        if lines:
+            if len(lines) != len(left) or len(lines) != len(right):
+                str_err = "Left and right must have the same length of lines"
+                raise ValueError(str_err)
+        self.left = Ilist()
+        self.right = Ilist()
+        # geometry type
+        self.gtype = libvect.GV_BOUNDARY
+
+    def __repr__(self):
+        return "Boundary(v_id=%r)" % self.id
+
+    def boundaries(self):
+        """Returna Ilist object with the line id"""
+        bounds = Ilist()
+        libvect.Vect_get_area_boundaries(self.c_mapinfo, self.area_id,
+                                         bounds.c_ilist)
+        return bounds
+
+    def get_left_right(self):
+        """Return left and right value"""
+        left = ctypes.poiter(ctypes.c_int())
+        right = ctypes.poiter(ctypes.c_int())
+        libvect.Vect_get_line_areas(self.c_mapinfo, self.id,
+                                    left, right)
+        return left.contents.value, right.contents.value
+
+
+class Centroid(Point):
+    """The Centroid class inherit from the Point class.
+    Centroid contains an attribute with the C Map_info struct, and attributes
+    with the id of the Area. ::
+
+        >>> centroid = Centroid(x=0, y=10)
+        >>> centroid
+        Centoid(0.000000, 10.000000)
+        >>> import pygrass
+        >>> mun = pygrass.vector.VectorTopo('boundary_municp_sqlite')
+        >>> mun.open()
+        >>> centroid = Centroid(v_id=5129, c_mapinfo=mun.c_mapinfo)
+        >>> centroid
+        Centoid(463784.493822, 311023.913274)
+
+        ..
+        """
+    def __init__(self, area_id=None, **kargs):
+        super(Centroid, self).__init__(**kargs)
+        self.area_id = area_id
+        if self.id and self.c_mapinfo and self.area_id is None:
+            self.area_id = self.get_area_id()
+        elif self.c_mapinfo and self.area_id and self.id is None:
+            self.id = self.get_centroid_id()
+        if self.area_id is not None:
+            self.cats = Cats(c_mapinfo=self.c_mapinfo, v_id=self.area_id)
+            #TODO: why not pass the self.id?
+            self.read()
+
+        # geometry type
+        self.gtype = libvect.GV_CENTROID
+        #self.c_pline = ctypes.pointer(libvect.P_line()) if topology else None
+
+    def __repr__(self):
+        return "Centoid(%s)" % ', '.join(['%f' % co for co in self.coords()])
+
+    def get_centroid_id(self):
+        """Return the centroid_id, using the c_mapinfo and an area_id
+        attributes of the class, and calling the Vect_get_area_centroid
+        C function, if no centroid_id were found return None"""
+        centroid_id = libvect.Vect_get_area_centroid(self.c_mapinfo,
+                                                     self.area_id)
+        return centroid_id if centroid_id != 0 else None
+
+    def get_area_id(self):
+        """Return the area_id, using the c_mapinfo and an centroid_id
+        attributes of the class, and calling the Vect_get_centroid_area
+        C function, if no area_id were found return None"""
+        area_id = libvect.Vect_get_centroid_area(self.c_mapinfo,
+                                                 self.id)
+        return area_id if area_id != 0 else None
+
+
+class Isle(Geo):
+    """An Isle is an area contained by another area.
+    """
+    def __init__(self, **kargs):
+        super(Isle, self).__init__(**kargs)
+        #self.area_id = area_id
+
+    def __repr__(self):
+        return "Isle(%d)" % (self.id)
+
+    def boundaries(self):
+        ilist = Ilist()
+        libvect.Vect_get_isle_boundaries(self.c_mapinfo, self.id,
+                                         ilist.c_ilist)
+        return ilist
+
+    def bbox(self):
+        bbox = Bbox()
+        libvect.Vect_get_isle_box(self.c_mapinfo, self.id, bbox.c_bbox)
+        return bbox
+
+    def points(self):
+        """Return a Line object with the outer ring points"""
+        line = Line()
+        libvect.Vect_get_isle_points(self.c_mapinfo, self.id, line.c_points)
+        return line
+
+    def points_geos(self):
+        """Return a Line object with the outer ring points
+        """
+        return libvect.Vect_get_isle_points_geos(self.c_mapinfo, self.id)
+
+    def area_id(self):
+        """Returns area id for isle."""
+        return libvect.Vect_get_isle_area(self.c_mapinfo, self.id)
+
+    def alive(self):
+        """Check if isle is alive or dead (topology required)"""
+        return bool(libvect.Vect_isle_alive(self.c_mapinfo, self.id))
+
+    def contain_pnt(self, pnt):
+        """Check if point is in area."""
+        bbox = self.bbox()
+        return bool(libvect.Vect_point_in_island(pnt.x, pnt.y,
+                                                 self.c_mapinfo, self.id,
+                                                 bbox.c_bbox.contents))
+
+    def area(self):
+        """Return the area value of an Isle"""
+        border = self.points()
+        return libgis.G_area_of_polygon(border.c_points.contents.x,
+                                        border.c_points.contents.y,
+                                        border.c_points.contents.n_points)
+
+    def perimeter(self):
+        """Return the perimeter value of an Isle.
+        ::
+            double Vect_area_perimeter()
+
+        """
+        border = self.points()
+        return libvect.Vect_area_perimeter(border.c_points)
+
+
+class Isles(object):
+    def __init__(self, c_mapinfo, area_id):
+        self.c_mapinfo = c_mapinfo
+        self.area_id = area_id
+        self._isles_id = self.get_isles_id()
+        self._isles = self.get_isles()
+
+    def __len__(self):
+        return libvect.Vect_get_area_num_isles(self.c_mapinfo, self.area_id)
+
+    def __repr__(self):
+        return "Isles(%r)" % self._isles
+
+    def __getitem__(self, key):
+        return self._isles[key]
+
+    def get_isles_id(self):
+        return [libvect.Vect_get_area_isle(self.c_mapinfo, self.area_id, i)
+                for i in range(self.__len__())]
+
+    def get_isles(self):
+        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"""
+        pass
+
+
+class Area(Geo):
+    """
+     'Vect_build_line_area',
+     'Vect_find_area',
+     'Vect_get_area_box',
+     'Vect_get_area_points_geos',
+     'Vect_get_centroid_area',
+
+     'Vect_get_isle_area',
+     'Vect_get_line_areas',
+     'Vect_get_num_areas',
+     'Vect_get_point_in_area',
+     'Vect_isle_find_area',
+     'Vect_point_in_area',
+     'Vect_point_in_area_outer_ring',
+
+     'Vect_read_area_geos',
+     'Vect_remove_small_areas',
+     'Vect_select_areas_by_box',
+     'Vect_select_areas_by_polygon']
+    """
+
+    def __init__(self, boundary=None, centroid=None, isles=[], **kargs):
+        super(Area, self).__init__(**kargs)
+        self.boundary = self.points()
+        self.centroid = self.centroid()
+        self.isles = self.get_isles()
+        # geometry type
+        self.gtype = libvect.GV_AREA
+
+    def __repr__(self):
+        return "Area(%d)" % self.id
+
+    def init_from_id(self, area_id=None):
+        """Return an Area object"""
+        if area_id is None and self.id is None:
+            raise ValueError("You need to give or set the area_id")
+        self.id = area_id if area_id is not None else self.id
+        # get boundary
+        self.get_boundary()
+        # get isles
+        self.get_isles()
+        pass
+
+    def points(self):
+        """Return a Line object with the outer ring"""
+        line = Line()
+        libvect.Vect_get_area_points(self.c_mapinfo, self.id, line.c_points)
+        return line
+
+    def centroid(self):
+        centroid_id = libvect.Vect_get_area_centroid(self.c_mapinfo, self.id)
+        #import pdb; pdb.set_trace()
+        return Centroid(v_id=centroid_id, c_mapinfo=self.c_mapinfo,
+                        area_id=self.id)
+
+    def num_isles(self):
+        return libvect.Vect_get_area_num_isles(self.c_mapinfo, self.id)
+
+    def get_isles(self):
+        """Instantiate the boundary attribute reading area_id"""
+        return Isles(self.c_mapinfo, self.id)
+
+    def area(self):
+        """Returns area of area without areas of isles.
+        double Vect_get_area_area (const struct Map_info *Map, int area)
+
+        """
+        return libvect.Vect_get_area_area(self.c_mapinfo, self.id)
+
+    def alive(self):
+        """Check if area is alive or dead (topology required)
+        """
+        return bool(libvect.Vect_area_alive(self.c_mapinfo, self.id))
+
+    def bbox(self):
+        """
+        Vect_get_area_box
+        """
+        bbox = Bbox()
+        libvect.Vect_get_area_box(self.c_mapinfo, self.id, bbox.c_bbox)
+        return bbox
+
+    def buffer(self):
+        """Creates buffer around area.
+
+        Parameters:
+        Map	vector map
+        area	area id
+        da	distance along major axis
+        db	distance along minor axis
+        dalpha	angle between 0x and major axis
+        round	make corners round
+        caps	add caps at line ends
+        tol	maximum distance between theoretical arc and output segments
+        [out]	oPoints	output polygon outer border (ccw order)
+        [out]	inner_count	number of holes
+        [out]	iPoints	array of output polygon's holes (cw order)
+
+        void Vect_area_buffer2(const struct Map_info * Map,
+                               int 	area,
+                               double 	da,
+                               double 	db,
+                               double 	dalpha,
+                               int 	round,
+                               int 	caps,
+                               double 	tol,
+                               struct line_pnts ** 	oPoints,
+                               struct line_pnts *** 	iPoints,
+                               int * 	inner_count)
+        """
+        pass
+
+    def boundaries(self):
+        """Creates list of boundaries for given area.
+
+        int Vect_get_area_boundaries(const struct Map_info *Map,
+                                     int area, struct ilist *List)
+        """
+        ilist = Ilist()
+        libvect.Vect_get_area_boundaries(self.c_mapinfo, self.id,
+                                         ilist.c_ilist)
+        return ilist
+
+    def cats(self):
+        """Get area categories.
+        int Vect_get_area_cats (const struct Map_info *Map,
+                                int area, struct line_cats *Cats)
+        """
+        return Cats(self.c_mapinfo, self.id)
+
+    def get_first_cat(self):
+        """Find FIRST category of given field and area.
+
+        int Vect_get_area_cat(const struct Map_info *Map, int area, int field)
+        """
+        pass
+
+    def contain_pnt(self, pnt):
+        """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)
+        """
+        bbox = self.bbox()
+        libvect.Vect_point_in_area(pnt.x, pnt.y, self.c_mapinfo, self.id,
+                                   bbox.c_bbox)
+        return bbox
+
+    def perimeter(self):
+        """Calculate area perimeter.
+
+        double Vect_area_perimeter (const struct line_pnts *Points)
+
+        """
+        border = self.points()
+        return libvect.Vect_area_perimeter(border.c_points)
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/vector/sql.py
===================================================================
--- grass/trunk/lib/python/pygrass/vector/sql.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/vector/sql.py	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,47 @@
+# -*- coding: utf-8 -*-
+"""
+SQL
+===
+
+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;'
+
+
+"""
+
+#
+# SQL
+#
+
+#ALTER TABLE
+ADD_COL = "ALTER TABLE {tname} ADD COLUMN {cname} {ctype};"
+DROP_COL = "ALTER TABLE {tname} DROP COLUMN {cname};"
+DROP_COL_SQLITE = ';\n'.join([
+"CREATE TEMPORARY TABLE {tname}_backup({coldef})",
+"INSERT INTO {tname}_backup SELECT {colnames} FROM {tname}",
+"DROP TABLE {tname}",
+"CREATE TABLE {tname}({coldef})",
+"INSERT INTO {tname} SELECT {colnames} FROM {tname}_backup",
+"CREATE UNIQUE INDEX {tname}_cat ON {tname} ({keycol} )",
+"DROP TABLE {tname}_backup",
+])
+RENAME_COL = "ALTER TABLE {tname} RENAME COLUMN {old_name} TO {new_name};"
+CAST_COL = "ALTER TABLE {tname} ALTER COLUMN {col} SET DATA TYPE {ctype};"
+RENAME_TAB = "ALTER TABLE {old_name} RENAME TO {new_name};"
+
+#SELECT
+SELECT = "SELECT {cols} FROM {tname};"
+SELECT_WHERE = "SELECT {cols} FROM {tname} WHERE {condition};"
+SELECT_ORDERBY = "SELECT {cols} FROM {tname} ORDER BY {orderby};"
+
+#UPDATE
+UPDATE = "UPDATE {tname} SET {new_col} = {old_col};"
+UPDATE_WHERE = "UPDATE {tname} SET {new_col} = {old_col} WHERE {condition};"
+
+# GET INFO
+PRAGMA = "PRAGMA table_info({tname});"
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/vector/table.py
===================================================================
--- grass/trunk/lib/python/pygrass/vector/table.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/vector/table.py	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,839 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Wed Aug  8 15:29:21 2012
+
+ at author: pietro
+
+
+
+"""
+import ctypes
+
+try:
+    from collections import OrderedDict
+except:
+    from pygrass.orderdict import OrderedDict
+
+import grass.lib.vector as libvect
+import grass.script.core as core
+
+import sql
+
+
+DRIVERS = ('sqlite', 'pg')
+
+
+class DBError(Exception):
+    def __init__(self, value):
+        self.value = value
+
+    def __str__(self):
+        return repr(self.value)
+
+
+def get_path(path):
+    if "$" not in path:
+        return path
+    else:
+        grassenv = core.gisenv()
+        path = path.replace('$GISDBASE', grassenv['GISDBASE'])
+        path = path.replace('$LOCATION_NAME', grassenv['LOCATION_NAME'])
+        path = path.replace('$MAPSET', grassenv['MAPSET'])
+        return path
+
+
+class Filters(object):
+    """Help user to build a simple sql query. ::
+
+        >>> filter = Filters('table')
+        >>> filter.get_sql()
+        'SELECT * FROM table;'
+        >>> filter.where("area<10000").get_sql()
+        'SELECT * FROM table WHERE area<10000;'
+        >>> filter.select("cat", "area").get_sql()
+        'SELECT cat, area FROM table WHERE area<10000;'
+        >>> filter.order_by("area").limit(10).get_sql()
+        'SELECT cat, area FROM table WHERE area<10000 ORDER BY area LIMIT 10;'
+
+    ..
+    """
+    def __init__(self, tname):
+        self.tname = tname
+        self._select = None
+        self._where = None
+        self._orderby = None
+        self._limit = None
+
+    def __repr__(self):
+        return "Filters(%r)" % self.get_sql()
+
+    def select(self, *args):
+        cols = ', '.join(args) if args else '*'
+        select = sql.SELECT[:-1]
+        self._select = select.format(cols=cols, tname=self.tname)
+        return self
+
+    def where(self, condition):
+        self._where = 'WHERE {condition}'.format(condition=condition)
+        return self
+
+    def order_by(self, orderby):
+        if not isinstance(orderby, str):
+            orderby = ', '.join(orderby)
+        self._orderby = 'ORDER BY {orderby}'.format(orderby=orderby)
+        return self
+
+    def limit(self, number):
+        if not isinstance(number, int):
+            raise ValueError("Must be an integer.")
+        else:
+            self._limit = 'LIMIT {number}'.format(number=number)
+        return self
+
+    def get_sql(self):
+        sql_list = list()
+        if self._select is None:
+            self.select()
+        sql_list.append(self._select)
+
+        if self._where is not None:
+            sql_list.append(self._where)
+        if self._orderby is not None:
+            sql_list.append(self._orderby)
+        if self._limit is not None:
+            sql_list.append(self._limit)
+        return "%s;" % ' '.join(sql_list)
+
+    def reset(self):
+        self._select = None
+        self._where = None
+        self._orderby = None
+        self._limit = None
+
+
+class Columns(object):
+    """Object to work with columns table.
+
+    It is possible to instantiate a Columns object given the table name and
+    the database connection.
+
+    For a sqlite table: ::
+
+        >>> import sqlite3
+        >>> path = '$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite.db'
+        >>> cols_sqlite = Columns('boundary_municp_sqlite',
+        ...                       sqlite3.connect(get_path(path)))
+        >>> cols_sqlite.tname
+        'boundary_municp_sqlite'
+
+    For a postgreSQL table: ::
+
+        >>> import psycopg2 as pg
+        >>> cols_pg = Columns('boundary_municp_pg',
+        ...                   pg.connect('host=localhost dbname=grassdb'))
+        >>> cols_pg.tname
+        'boundary_municp_pg'
+
+    ..
+    """
+    def __init__(self, tname, connection, key='cat'):
+        self.tname = tname
+        self.conn = connection
+        self.key = key
+        self.odict = None
+        self.update_odict()
+
+    def __contains__(self, item):
+        return item in self.names()
+
+    def __repr__(self):
+        return "Columns(%r)" % self.items()
+
+    def __getitem__(self, key):
+        return self.odict[key]
+
+    def __setitem__(self, name, new_type):
+        self.cast(name, new_type)
+        self.update_odict(self)
+
+    def __iter__(self):
+        return self.odict.__iter__()
+
+    def __len__(self):
+        return self.odict.__len__()
+
+    def __eq__(self, obj):
+        return obj.tname == self.tname and obj.odict == self.odict
+
+    def is_pg(self):
+        """Return True if is a psycopg connection. ::
+
+            >>> import sqlite3
+            >>> path = '$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite.db'
+            >>> cols_sqlite = Columns('boundary_municp_sqlite',
+            ...                       sqlite3.connect(get_path(path)))
+            >>> cols_sqlite.is_pg()
+            False
+            >>> import psycopg2 as pg
+            >>> cols_pg = Columns('boundary_municp_pg',
+            ...                   pg.connect('host=localhost dbname=grassdb'))
+            >>> cols_pg.is_pg()
+            True
+
+        ..
+        """
+        return hasattr(self.conn, 'xid')
+
+    def update_odict(self):
+        """Read columns name and types from table and update the odict
+        attribute.
+        """
+        if self.is_pg():
+            # is a postgres connection
+            cur = self.conn.cursor()
+            cur.execute("SELECT oid,typname FROM pg_type")
+            diz = dict(cur.fetchall())
+            cur.execute(sql.SELECT.format(cols='*', tname=self.tname))
+            descr = cur.description
+            odict = OrderedDict()
+            for column in descr:
+                name, ctype = column[:2]
+                odict[name] = diz[ctype]
+            self.odict = odict
+        else:
+            # is a sqlite connection
+            cur = self.conn.cursor()
+            cur.execute(sql.PRAGMA.format(tname=self.tname))
+            descr = cur.fetchall()
+            odict = OrderedDict()
+            for column in descr:
+                name, ctype = column[1:3]
+                odict[name] = ctype
+            self.odict = odict
+
+    def sql_descr(self, remove=None):
+        """Return a string with description of columns.
+           Remove it is used to remove a columns.::
+
+            >>> import sqlite3
+            >>> path = '$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite.db'
+            >>> cols_sqlite = Columns('boundary_municp_sqlite',
+            ...                       sqlite3.connect(get_path(path)))
+            >>> cols_sqlite.sql_descr()                   # doctest: +ELLIPSIS
+            u'cat integer, OBJECTID integer, AREA double precision, ...'
+            >>> import psycopg2 as pg
+            >>> cols_pg = Columns('boundary_municp_pg',
+            ...                   pg.connect('host=localhost dbname=grassdb'))
+            >>> cols_pg.sql_descr()                       # doctest: +ELLIPSIS
+            'cat int4, objectid int4, area float8, perimeter float8, ...'
+        """
+        if remove:
+            return ', '.join(['%s %s' % (key, val) for key, val in self.items()
+                             if key != remove])
+        else:
+            return ', '.join(['%s %s' % (key, val)
+                              for key, val in self.items()])
+
+    def types(self):
+        """Return a list with the column types. ::
+
+            >>> import sqlite3
+            >>> path = '$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite.db'
+            >>> cols_sqlite = Columns('boundary_municp_sqlite',
+            ...                       sqlite3.connect(get_path(path)))
+            >>> cols_sqlite.types()                       # doctest: +ELLIPSIS
+            [u'integer', u'integer', ...]
+            >>> import psycopg2 as pg
+            >>> cols_pg = Columns('boundary_municp_pg',
+            ...                   pg.connect('host=localhost dbname=grassdb'))
+            >>> cols_pg.types()                           # doctest: +ELLIPSIS
+            ['int4', 'int4', 'float8', 'float8', 'float8', ...]
+
+
+        ..
+        """
+        return self.odict.values()
+
+    def names(self, remove=None, unicod=True):
+        """Return a list with the column names.
+           Remove it is used to remove a columns.::
+
+            >>> import sqlite3
+            >>> path = '$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite.db'
+            >>> cols_sqlite = Columns('boundary_municp_sqlite',
+            ...                       sqlite3.connect(get_path(path)))
+            >>> cols_sqlite.names()                      # doctest: +ELLIPSIS
+            [u'cat', u'OBJECTID', u'AREA', u'PERIMETER', ...]
+            >>> import psycopg2 as pg
+            >>> cols_pg = Columns('boundary_municp_pg',
+            ...                   pg.connect('host=localhost dbname=grassdb'))
+            >>> cols_pg.names()                           # doctest: +ELLIPSIS
+            ['cat', 'objectid', 'area', 'perimeter', ...]
+
+
+        ..
+        """
+        if remove:
+            nams = self.odict.keys()
+            nams.remove(remove)
+        else:
+            nams = self.odict.keys()
+        if unicod:
+            return nams
+        else:
+            return [str(name) for name in nams]
+
+    def items(self):
+        """Return a list of tuple with column name and column type.  ::
+
+            >>> import sqlite3
+            >>> path = '$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite.db'
+            >>> cols_sqlite = Columns('boundary_municp_sqlite',
+            ...                       sqlite3.connect(get_path(path)))
+            >>> cols_sqlite.items()                       # doctest: +ELLIPSIS
+            [(u'cat', u'integer'), ...]
+            >>> import psycopg2 as pg
+            >>> cols_pg = Columns('boundary_municp_pg',
+            ...                   pg.connect('host=localhost dbname=grassdb'))
+            >>> cols_pg.items()                           # doctest: +ELLIPSIS
+            [('cat', 'int4'), ('objectid', 'int4'), ('area', 'float8'), ...]
+
+        ..
+        """
+        return self.odict.items()
+
+    def add(self, col_name, col_type):
+        """Add a new column to the table. ::
+
+            >>> import sqlite3
+            >>> path = '$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite.db'
+            >>> cols_sqlite = Columns('boundary_municp_sqlite',
+            ...                       sqlite3.connect(get_path(path)))
+            >>> cols_sqlite.add('n_pizza', 'int4')
+            >>> 'n_pizza' in cols_sqlite
+            True
+
+            >>> import psycopg2 as pg
+            >>> cols_pg = Columns('boundary_municp_pg',
+            ...                   pg.connect('host=localhost dbname=grassdb'))
+            >>> cols_pg.add('n_pizza', 'int4')
+            >>> 'n_pizza' in cols_pg
+            True
+
+        ..
+        """
+        cur = self.conn.cursor()
+        cur.execute(sql.ADD_COL.format(tname=self.tname,
+                                       cname=col_name,
+                                       ctype=col_type))
+        self.conn.commit()
+        cur.close()
+        self.update_odict()
+
+    def rename(self, old_name, new_name):
+        """Rename a column of the table. ::
+
+            >>> import sqlite3
+            >>> path = '$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite.db'
+            >>> cols_sqlite = Columns('boundary_municp_sqlite',
+            ...                       sqlite3.connect(get_path(path)))
+            >>> cols_sqlite.rename('n_pizza', 'n_pizzas')  # doctest: +ELLIPSIS
+            >>> 'n_pizza' in cols_sqlite
+            False
+            >>> 'n_pizzas' in cols_sqlite
+            True
+
+            >>> import psycopg2 as pg
+            >>> cols_pg = Columns('boundary_municp_pg',
+            ...                   pg.connect('host=localhost dbname=grassdb'))
+            >>> cols_pg.rename('n_pizza', 'n_pizzas')
+            >>> 'n_pizza' in cols_pg
+            False
+            >>> 'n_pizzas' in cols_pg
+            True
+
+        ..
+        """
+        cur = self.conn.cursor()
+        if self.is_pg():
+            cur.execute(sql.RENAME_COL.format(tname=self.tname,
+                                              old_name=old_name,
+                                              new_name=new_name))
+            self.conn.commit()
+            cur.close()
+            self.update_odict()
+        else:
+            cur.execute(sql.ADD_COL.format(tname=self.tname,
+                                           cname=new_name,
+                                           ctype=str(self.odict[old_name])))
+            cur.execute(sql.UPDATE.format(tname=self.tname,
+                                          new_col=new_name,
+                                          old_col=old_name))
+            self.conn.commit()
+            cur.close()
+            self.update_odict()
+            self.drop(old_name)
+
+    def cast(self, col_name, new_type):
+        """Change the column type. ::
+
+            >>> import sqlite3
+            >>> path = '$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite.db'
+            >>> cols_sqlite = Columns('boundary_municp_sqlite',
+            ...                       sqlite3.connect(get_path(path)))
+            >>> cols_sqlite.cast('n_pizzas', 'float8')  # doctest: +ELLIPSIS
+            Traceback (most recent call last):
+              ...
+            DBError: 'SQLite does not support to cast columns.'
+            >>> import psycopg2 as pg
+            >>> cols_pg = Columns('boundary_municp_pg',
+            ...                   pg.connect('host=localhost dbname=grassdb'))
+            >>> cols_pg.cast('n_pizzas', 'float8')
+            >>> cols_pg['n_pizzas']
+            'float8'
+
+        .. warning ::
+
+            It is not possible to cast a column with sqlite
+        ..
+        """
+        if self.is_pg():
+            cur = self.conn.cursor()
+            cur.execute(sql.CAST_COL.format(tname=self.tname, col=col_name,
+                                            ctype=new_type))
+            self.conn.commit()
+            cur.close()
+            self.update_odict()
+        else:
+            # sqlite does not support rename columns:
+            raise DBError('SQLite does not support to cast columns.')
+
+    def drop(self, col_name):
+        """Drop a column from the table. ::
+
+            >>> import sqlite3
+            >>> path = '$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite.db'
+            >>> cols_sqlite = Columns('boundary_municp_sqlite',
+            ...                       sqlite3.connect(get_path(path)))
+            >>> cols_sqlite.drop('n_pizzas')  # doctest: +ELLIPSIS
+            >>> 'n_pizzas' in cols_sqlite
+            False
+
+            >>> import psycopg2 as pg
+            >>> cols_pg = Columns('boundary_municp_pg',
+            ...                   pg.connect('host=localhost dbname=grassdb'))
+            >>> cols_pg.drop('n_pizzas')
+            >>> 'n_pizzas' in cols_pg
+            False
+
+        ..
+        """
+        cur = self.conn.cursor()
+        if self.is_pg():
+            cur.execute(sql.DROP_COL.format(tname=self.tname,
+                                            cname=col_name))
+        else:
+            desc = str(self.sql_descr(remove=col_name))
+            names = ', '.join(self.names(remove=col_name, unicod=False))
+            queries = sql.DROP_COL_SQLITE.format(tname=self.tname,
+                                                 keycol=self.key,
+                                                 coldef=desc,
+                                                 colnames=names).split('\n')
+            for query in queries:
+                cur.execute(query)
+        self.conn.commit()
+        cur.close()
+        self.update_odict()
+
+
+class Link(object):
+    """Define a Link between vector map and the attributes table.
+
+    It is possible to define a Link object or given all the information
+    (number, name, table name, key, database, driver): ::
+
+        >>> link = Link(1, 'link0', 'boundary_municp_sqlite', 'cat',
+        ...             '$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite.db', 'sqlite')
+        >>> link.number
+        1
+        >>> link.name
+        'link0'
+        >>> link.table_name
+        'boundary_municp_sqlite'
+        >>> link.key
+        'cat'
+        >>> link.database
+        '$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite.db'
+        >>> link.driver
+        'sqlite'
+        >>> link
+        Link(1, link0, sqlite)
+
+
+    It is possible to change parameters with: ::
+
+        >>> link.driver = 'pg'
+        >>> link.driver
+        'pg'
+        >>> link.driver = 'postgres'                      # doctest: +ELLIPSIS
+        Traceback (most recent call last):
+          ...
+        TypeError: Driver not supported, use: sqlite, pg.
+        >>> link.driver
+        'pg'
+        >>> link.number = 0                               # doctest: +ELLIPSIS
+        Traceback (most recent call last):
+          ...
+        TypeError: Number must be positive and greater than 0.
+
+
+    Or given a c_fieldinfo object that is a ctypes pointer to the field_info C
+    struct. ::
+
+        >>> link = Link(c_fieldinfo = ctypes.pointer(libvect.field_info()))
+
+
+    ..
+    """
+    def _get_number(self):
+        return self.c_fieldinfo.contents.number
+
+    def _set_number(self, number):
+        if number <= 0:
+            raise TypeError("Number must be positive and greater than 0.")
+        self.c_fieldinfo.contents.number = number
+
+    number = property(fget=_get_number, fset=_set_number)
+
+    def _get_name(self):
+        return self.c_fieldinfo.contents.name
+
+    def _set_name(self, name):
+        self.c_fieldinfo.contents.name = name
+
+    name = property(fget=_get_name, fset=_set_name)
+
+    def _get_table(self):
+        return self.c_fieldinfo.contents.table
+
+    def _set_table(self, new_name):
+        self.c_fieldinfo.contents.table = new_name
+
+    table_name = property(fget=_get_table, fset=_set_table)
+
+    def _get_key(self):
+        return self.c_fieldinfo.contents.key
+
+    def _set_key(self, key):
+        self.c_fieldinfo.contents.key = key
+
+    key = property(fget=_get_key, fset=_set_key)
+
+    def _get_database(self):
+        return self.c_fieldinfo.contents.database
+
+    def _set_database(self, database):
+        self.c_fieldinfo.contents.database = database
+
+    database = property(fget=_get_database, fset=_set_database)
+
+    def _get_driver(self):
+        return self.c_fieldinfo.contents.driver
+
+    def _set_driver(self, driver):
+        if driver not in ('sqlite', 'pg'):
+            str_err = "Driver not supported, use: %s." % ", ".join(DRIVERS)
+            raise TypeError(str_err)
+        self.c_fieldinfo.contents.driver = driver
+
+    driver = property(fget=_get_driver, fset=_set_driver)
+
+    def __init__(self, number=None, name=None, table=None, key=None,
+                 database=None, driver=None, c_fieldinfo=None):
+        if c_fieldinfo is not None:
+            self.c_fieldinfo = c_fieldinfo
+        else:
+            self.c_fieldinfo = ctypes.pointer(libvect.field_info())
+            self.number = number
+            self.name = name
+            self.table_name = table
+            self.key = key
+            self.database = database
+            self.driver = driver
+
+    def __repr__(self):
+        return "Link(%d, %s, %s)" % (self.number, self.name, self.driver)
+
+    def connection(self):
+        """Return a connection object. ::
+
+            >>> link = Link(1, 'link0', 'boundary_municp_sqlite', 'cat',
+            ...             '$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite.db',
+            ...             'sqlite')
+            >>> conn = link.connection()
+            >>> cur = conn.cursor()
+            >>> cur.execute("SELECT cat,COUNTY,PERIMETER FROM %s" %
+            ...             link.table_name)              # doctest: +ELLIPSIS
+            <sqlite3.Cursor object at ...>
+            >>> cur.fetchone()
+            (1, u'SURRY', 1415.331)
+            >>> cur.close()
+            >>> conn.close()
+
+        ...
+        """
+        if self.driver == 'sqlite':
+            import sqlite3
+            return sqlite3.connect(get_path(self.database))
+        elif self.driver == 'pg':
+            try:
+                import psycopg2
+                db = ' '.join(self.database.split(','))
+                return psycopg2.connect(db)
+            except ImportError:
+                er = "You need to install psycopg2 to connect with this table."
+                raise ImportError(er)
+        else:
+            str_err = "Driver is not supported yet, pleas use: sqlite or pg"
+            raise TypeError(str_err)
+
+    def table(self):
+        """Return a Table object. ::
+
+            >>> link = Link(1, 'link0', 'boundary_municp_sqlite', 'cat',
+            ...             '$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite.db',
+            ...             'sqlite')
+            >>> table = link.table()
+            >>> table.filters.select('cat', 'COUNTY', 'PERIMETER')
+            Filters('SELECT cat, COUNTY, PERIMETER FROM boundary_municp_sqlite;')
+            >>> cur = table.execute()
+            >>> cur.fetchone()
+            (1, u'SURRY', 1415.331)
+            >>> cur.close()
+
+        ..
+        """
+        return Table(self.table_name, self.connection(), self.key)
+
+    def info(self):
+        """Print information of the link. ::
+
+            >>> link = Link(1, 'link0', 'boundary_municp_sqlite', 'cat',
+            ...             '$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite.db',
+            ...             'sqlite')
+            >>> link.info()
+            number:    1
+            name:      link0
+            table:     boundary_municp_sqlite
+            key:       cat
+            database:  $GISDBASE/$LOCATION_NAME/$MAPSET/sqlite.db
+            driver:    sqlite
+
+        ..
+        """
+        print "number:   ", self.number
+        print "name:     ", self.name
+        print "table:    ", self.table_name
+        print "key:      ", self.key
+        print "database: ", self.database
+        print "driver:   ", self.driver
+
+
+class DBlinks(object):
+    """Interface containing link to the table DB. ::
+
+        >>> from pygrass.vector import VectorTopo
+        >>> municip = VectorTopo('boundary_municp_sqlite')
+        >>> municip.open()
+        >>> dblinks = DBlinks(municip.c_mapinfo)
+        >>> dblinks
+        DBlinks([Link(1, boundary_municp, sqlite)])
+        >>> dblinks[1]
+        Link(1, boundary_municp, sqlite)
+        >>> dblinks[0]                                    # doctest: +ELLIPSIS
+        Traceback (most recent call last):
+            ...
+        TypeError: The index must be != 0.
+        >>> dblinks['boundary_municp']
+        Link(1, boundary_municp, sqlite)
+
+    ..
+    """
+    def __init__(self, c_mapinfo):
+        self.c_mapinfo = c_mapinfo
+
+    def __len__(self):
+        return self.num_dblinks()
+
+    def __iter__(self):
+        return (self.by_number(ilink)
+                for ilink in xrange(1, self.num_dblinks() + 1))
+
+    def __getitem__(self, key):
+        """
+
+        """
+        if isinstance(key, int):
+            if key != 0:
+                return self.by_number(key)
+            else:
+                raise TypeError("The index must be != 0.")
+        else:
+            return self.by_name(key)
+
+    def __repr__(self):
+        return "DBlinks(%r)" % [link for link in self.__iter__()]
+
+    def by_number(self, number):
+        c_fieldinfo = libvect.Vect_get_field(self.c_mapinfo, number)
+        return Link(c_fieldinfo=c_fieldinfo)
+
+    def by_name(self, name):
+        c_fieldinfo = libvect.Vect_get_field_by_name(self.c_mapinfo, name)
+        return Link(c_fieldinfo=c_fieldinfo)
+
+    def num_dblinks(self):
+        return libvect.Vect_get_num_dblinks(self.c_mapinfo)
+
+    def add(self, link):
+        """Add a new link. ::
+
+            >>> from pygrass.vector import VectorTopo
+            >>> municip = VectorTopo('boundary_municp_sqlite')
+            >>> municip.open()
+            >>> dblinks = DBlinks(municip.c_mapinfo)
+            >>> dblinks
+            DBlinks([Link(1, boundary_municp, sqlite)])
+            >>> link = Link(2, 'pg_link', 'boundary_municp_pg', 'cat',
+            ...             'host=localhost dbname=grassdb', 'pg')
+            >>> dblinks.add(link)
+            >>> dblinks   # need to open vector map in write mode
+            DBlinks([Link(1, boundary_municp, sqlite)])
+
+        ..
+        """
+        #TODO: check if open in write mode or not.
+        libvect.Vect_map_add_dblink(self.c_mapinfo,
+                                    link.number, link.name, link.table_name,
+                                    link.key, link.database, link.driver)
+
+    def remove(self, key):
+        """Remove a link. ::
+
+            >>> from pygrass.vector import VectorTopo
+            >>> municip = VectorTopo('boundary_municp_sqlite')
+            >>> municip.open()
+            >>> dblinks = DBlinks(municip.c_mapinfo)
+            >>> dblinks
+            DBlinks([Link(1, boundary_municp, sqlite)])
+            >>> dblinks.remove('pg_link')
+            >>> dblinks  # need to open vector map in write mode
+            DBlinks([Link(1, boundary_municp, sqlite)])
+
+        ..
+        """
+        if isinstance(key, str):
+            key = self.from_name_to_num(key)
+        libvect.Vect_map_del_dblink(self.c_mapinfo, key)
+
+    def from_name_to_num(self, name):
+        """
+        Vect_get_field_number
+        """
+        return libvect.Vect_get_field_number(self.c_mapinfo, name)
+
+
+class Table(object):
+    """::
+
+        >>> import sqlite3
+        >>> path = '$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite.db'
+        >>> tab_sqlite = Table(name='boundary_municp_sqlite',
+        ...                    connection=sqlite3.connect(get_path(path)))
+        >>> tab_sqlite.name
+        'boundary_municp_sqlite'
+        >>> import psycopg2
+        >>> tab_pg = Table('boundary_municp_pg',
+        ...                psycopg2.connect('host=localhost dbname=grassdb',
+        ...                                 'pg'))
+        >>> tab_pg.columns                                # doctest: +ELLIPSIS
+        Columns([('cat', 'int4'), ...])
+
+    ..
+    """
+    def _get_name(self):
+        return self._name
+
+    def _set_name(self, new_name):
+        old_name = self._name
+        cur = self.conn.cursor()
+        cur.execute(sql.RENAME_TAB.format(old_name=old_name,
+                                          new_name=new_name))
+        cur.commit()
+        cur.close()
+
+    name = property(fget=_get_name, fset=_set_name)
+
+    def __init__(self, name, connection, key='cat'):
+        self._name = name
+        self.conn = connection
+        self.key = key
+        self.columns = Columns(self.name,
+                               self.conn,
+                               self.key)
+        self.filters = Filters(self.name)
+
+    def __repr__(self):
+        """::
+
+            >>> import sqlite3
+            >>> path = '$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite.db'
+            >>> tab_sqlite = Table(name='boundary_municp_sqlite',
+            ...                    connection=sqlite3.connect(get_path(path)))
+            >>> tab_sqlite
+            Table('boundary_municp_sqlite')
+
+        ..
+        """
+        return "Table(%r)" % (self.name)
+
+    def __iter__(self):
+        cur = self.execute()
+        return (cur.fetchone() for _ in xrange(self.__len__()))
+
+    def __len__(self):
+        """Return the nuber of rows"""
+        return self.num_rows()
+
+    def num_rows(self):
+        cur = self.conn.cursor()
+        cur.execute(sql.SELECT.format(cols='Count(*)', tname=self.name))
+        number = cur.fetchone()[0]
+        cur.close()
+        return number
+
+    def execute(self, sql_code=None):
+        """Execute SQL code from a given string or build with filters and
+        return a cursor object. ::
+
+            >>> import sqlite3
+            >>> path = '$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite.db'
+            >>> tab_sqlite = Table(name='boundary_municp_sqlite',
+            ...                    connection=sqlite3.connect(get_path(path)))
+            >>> tab_sqlite.filters.select('cat', 'COUNTY').order_by('AREA')
+            Filters('SELECT cat, COUNTY FROM boundary_municp_sqlite ORDER BY AREA;')
+            >>> cur = tab_sqlite.execute()
+            >>> cur.fetchone()
+            (1, u'SURRY')
+
+        ..
+        """
+        if sql_code is not None:
+            cur = self.conn.cursor()
+            return cur.execute(sql_code)
+
+        # get the sql from filters
+        sql_code = self.filters.get_sql()
+        if sql_code is not None:
+            cur = self.conn.cursor()
+            return cur.execute(sql_code)
\ No newline at end of file

Added: grass/trunk/lib/python/pygrass/vector/vector_type.py
===================================================================
--- grass/trunk/lib/python/pygrass/vector/vector_type.py	                        (rev 0)
+++ grass/trunk/lib/python/pygrass/vector/vector_type.py	2012-10-10 12:24:32 UTC (rev 53350)
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Wed Jul 18 10:49:26 2012
+
+ at author: pietro
+"""
+
+import grass.lib.vector as libvect
+import geometry as geo
+
+MAPTYPE = {libvect.GV_FORMAT_NATIVE:     "native",
+           libvect.GV_FORMAT_OGR:        "OGR",
+           libvect.GV_FORMAT_OGR_DIRECT: "OGR",
+           libvect.GV_FORMAT_POSTGIS:    "PostGIS"}
+
+VTYPE = {'point':    libvect.GV_POINT,  # 1
+         'line':     libvect.GV_LINE,   # 2
+         'boundary': libvect.GV_BOUNDARY,  # 3
+         'centroid': libvect.GV_CENTROID,  # 4
+         'face':     libvect.GV_FACE,  # 5
+         'kernel':   libvect.GV_KERNEL,  # 6
+         'area':     libvect.GV_AREA,  # 7
+         'volume':   libvect.GV_VOLUME}  # 8
+
+GV_TYPE = {libvect.GV_POINT:    {'label': 'point',    'obj': geo.Point},
+           libvect.GV_LINE:     {'label': 'line',     'obj': geo.Line},
+           libvect.GV_BOUNDARY: {'label': 'boundary', 'obj': geo.Boundary},
+           libvect.GV_CENTROID: {'label': 'centroid', 'obj': geo.Centroid},
+           libvect.GV_FACE:     {'label': 'face',     'obj': None},
+           libvect.GV_KERNEL:   {'label': 'kernel',   'obj': None},
+           libvect.GV_AREA:     {'label': 'area',     'obj': geo.Area},
+           libvect.GV_VOLUME:   {'label': 'volume',   'obj': None}, }
\ No newline at end of file



More information about the grass-commit mailing list