[[TOC]] = Submitting Python = == File structure == === GRASS module === 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 Use the directory structure to place your script appropriately into the source tree: scripts go into `scripts` directory. Also add a Makefile and a .html file into this directory. See existing Python scripts for examples. 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 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. === Python library === Files are placed in `lib/python`. This directory becomes a package `grass` after compilation. Each subdirectory is a subpackage. == Style == Follow PEP8 standard and use `pep8` tool to check compliance of your code to this standard. Note that not all code is currently compliant to complete PEP8, so we are using a custom configuration stored in `tools/pep8config.txt`, so use: {{{ pep8 --config=tools/pep8config.txt directory_to_check }}} Alternatively, you can use `pep8` with `--diff` option to check just the parts of the code you have changed: {{{ svn diff | pep8 --diff --config=tools/pep8config.txt }}} The best practice is to use pep8 with default configuration (i.e., without custom configuration file) for new files and new code in old files. Use 4-space indentation (GNU Emacs python-mode default). Do not use tabs (tabulators) at all. Note that Python determines nesting based upon indentation, so it is quite crucial to be consistent, i.e. use given rules. Make sure a new line is at the end of each file and there are no trailing spaces. Do not fix (intentionally or unintentionally) existing style issues in code (at lines) you are not changing. If you are fixing style issues, do it in a separate commit. 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) }}} Use three double quotes for docstrings (`"""..."""`). Use double quotes for translatable (user visible) strings, single quotes for the rest. == Writing the code == === Temporary files === Create and use secure temporary files and directories. Use the grass.tempfile() or grass.tempdir() functions to do this. e.g. {{{ #!python # setup temporary file TMP = grass.tempfile() if TMP is None: grass.fatal("Unable to create temporary files") }}} TODO: this needs to be fixed, it's more complicated === Checking inputs of a module === Use grass.findfile() when there is a need to test if a map exists. {{{ #!python # 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 === 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(). {{{ #!python #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) }}} Do not use the `print` statement (print function in Python 3) for informational output. This is reserved for standard module output if it has one. === 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 == Comment your classes and functions with docstrings. Use Sphinx (reStructuredText) syntax. Comment also the code itself such as the meaning of variables, conditions etc. 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. == Checking the code == 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 === * wiki:Submitting/General general GRASS and svn instructions * wiki:Submitting/Docs user documentation of modules and GUI * wiki:Submitting/wxGUI wxPython-based GUI has its own rules === GRASS documentation === * GRASS Programming manual for API and existing classes: http://grass.osgeo.org/programming7/ (add more specific link) * GRASS wiki has pages about how to develop GRASS scripts in Python: http://grasswiki.osgeo.org === External documentation === * Style Guide for Python Code: http://www.python.org/dev/peps/pep-0008/ * Python Style Guide by Guido van Rossum: http://www.python.org/doc/essays/styleguide.html * Additional info on Python docstrings: http://epydoc.sourceforge.net/docstrings.html