wiki:Submitting/Python

Version 1 (modified by wenzeslaus, 10 years ago) ( diff )

slightly reformated content of source:grass/trunk/SUBMITTING_PYTHON?rev=60796 and source:grass/trunk/SUBMITTING_WXGUI?rev=60796 (no general things)

Submitting Python

Structure of the file

Instructions for the GRASS script parser can be found in the g.parser module's help page. http://grass.osgeo.org/grass70/manuals/g.parser.html

  1. Use the directory structure to place your script appropriately into

the source tree

  • scripts go into scripts/

Also add a Makefile and a <module>.html file into this directory. See existing Python scripts for examples.

  1. Add a header section to the script you submit and make sure you

include the copyright. The purpose section is meant to contain a general over view of the code in the file to assist other programmers that will need to make changes to your code. For this purpose use Python Docstring, see http://epydoc.sourceforge.net/docstrings.html

Example (fictitious header for a script called g.myscript):

!python
"""
MODULE:    g.myscript

AUTHOR(S): John Doe <email AT some domain>

PURPOSE:   Describe your script here...

COPYRIGHT: (C) 2007 John Doe, and by the GRASS Development Team

           This program is free software under the GNU General Public
           License (>=v2). Read the file COPYING that comes with GRASS
           for details.
"""

The copyright protects your rights according to GNU General Public License (www.gnu.org).

You can easily autogenerate the header and parameters from an existing module using the --script flag. Example:

d.rast --script

Just select an existing module which is close to your application to save efforts.

Style

Follow PEP8 and use pep8 tool.

As Python determines nesting based upon indentation, it isn't just a stylistic issue.

Use 4-space indentation (GNU Emacs python-mode default).

Make sure a new line is at the end of each file.

Use named parameters in functions (without space around '='), e.g.

!python
dlg = wx.FileDialog(parent=self, message=_("Choose file to save current workspace"),
                    wildcard=_("GRASS Workspace File (*.gxw)|*.gxw"), style=wx.FD_SAVE)

instead of

!python

dlg = wx.FileDialog(self, _("Choose file to save current workspace"),
                    _("GRASS Workspace File (*.gxw)|*.gxw"), wx.FD_SAVE)

Writing the code

Temporary files

  1. Create and use secure temporary files and directories. Use the

grass.tempfile() or grass.tempdir() functions to do this. e.g.

        # setup temporary file
        TMP = grass.tempfile()
        if TMP is None:
            grass.fatal("Unable to create temporary files")
  1. Use grass.findfile() when there is a need to test if a map exists.
        # test for input raster map
        result = grass.find_file(name = map_name, element = 'cell', quiet = True)
        if not result['file']
          grass.fatal("Raster map <%s> not found" % map_name)

        # test for input vector map
        result = grass.find_file(name = map_name, element = 'vector', quiet = True)
        if not result['file']
          grass.fatal("Vector map <%s> not found" % map_name)

... and so forth. See 'g.manual g.findfile' for details.

Messages

  1. For any informational output, use the grass.message()

function. For error messages should be used grass.fatal_error() or grass.error() and for warnings grass.warning(). For debugging purposes grass.debug().

        #normal message:
        grass.message("Done")

        # warning:
        grass.warning("No input values found, using default values")

        # error:
        grass.error("No map found")

        # fatal error:
        grass.fatal_error("No map found, exiting")

        # debug output (use g.gisenv to enable/disable)
        grass.debug("Our calculated value is: %d" % value)

Try to omit any usage of the 'print' command for informational output.

Translations

To enable translating of messages to other languages (than English), use full strings, e.g.

!python
if ...:
    win.SetLabel(_("Name for new 3D raster map to create"))
else:
    win.SetLabel(_("Name for new raster map to create"))

instead of constructing string from several parts

!python
if ...:
    maplabel = 'raster map'
else:
    maplabel = '3D raster map'
win.SetLabel(_("Name for new %s to create") % maplabel)

Documentation and comments

  1. Comment your classes and functions with docstrings. Use Sphinx syntax.

Comment also the code itself such as the meaning of variables, conditions etc.

  1. PLEASE take the time to add comments throughout your code explaining what

the code is doing. It will save a HUGE amount of time and frustration for other programmers that may have to change your code in the future.

  1. Use tools such as pylint and pep8 to check your code (both style and

correctness). Just note that default settings of these tools is not fully compatible with wxGUI/wxPython style and that some of the reported errors may not apply to your code.

Testing

See also

Related submitting rules

GRASS documentation

External documentation

Note: See TracWiki for help on using the wiki.