Changes between Version 1 and Version 2 of Submitting/Python


Ignore:
Timestamp:
06/11/14 20:21:10 (11 years ago)
Author:
wenzeslaus
Comment:

few updates (mostly for style), fixed formatting

Legend:

Unmodified
Added
Removed
Modified
  • Submitting/Python

    v1 v2  
    33= Submitting Python =
    44
    5 
    6 
    7 == Structure of the file ==
     5== File structure ==
     6
     7=== GRASS module ===
    88
    99Instructions for the GRASS script parser can be found in the g.parser
     
    1111http://grass.osgeo.org/grass70/manuals/g.parser.html
    1212
    13 
    14 2.  Use the directory structure to place your script appropriately into
    15     the source tree
    16         - scripts go into scripts/
    17 
    18     Also add a Makefile and a <module>.html file into this directory.
    19     See existing Python scripts for examples.
    20 
    21 3.  Add a header section to the script you submit and make sure you
    22     include the copyright. The purpose section is meant to contain a
    23     general over view of the code in the file to assist other
    24     programmers that will need to make changes to your code. For this
    25     purpose use Python Docstring, see
    26     http://epydoc.sourceforge.net/docstrings.html
    27 
    28     Example (fictitious header for a script called g.myscript):
     13Use the directory structure to place your script appropriately into
     14the source tree: scripts go into `scripts` directory.
     15
     16Also add a Makefile and a <module>.html file into this directory.
     17See existing Python scripts for examples.
     18
     19Add a header section to the script you submit and make sure you
     20include the copyright. The purpose section is meant to contain a
     21general over view of the code in the file to assist other
     22programmers that will need to make changes to your code. For this
     23purpose use Python Docstring, see
     24http://epydoc.sourceforge.net/docstrings.html
     25
     26Example (fictitious header for a script called g.myscript):
    2927
    3028{{{
     
    5048module using the --script flag. Example:
    5149
     50{{{
    5251d.rast --script
     52}}}
    5353
    5454Just select an existing module which is close to your application to save efforts.
    5555
     56=== Python library ===
     57
     58Files are placed in `lib/python`. This directory becomes a package `grass` after compilation. Each subdirectory is a subpackage.
     59
    5660
    5761== Style ==
    5862
    59 Follow PEP8 and use pep8 tool.
    60 
    61 As Python determines nesting based upon indentation, it isn't just
    62 a stylistic issue.
    63 
    64 Use 4-space indentation (GNU Emacs python-mode default).
    65 
    66 Make sure a new line is at the end of each file.
     63Follow PEP8 standard and use `pep8` tool to check compliance of your code to this standard.
     64Note that not all code is currently compliant to complete PEP8, so we are using a custom configuration stored in `tools/pep8config.txt`, so use:
     65
     66{{{
     67pep8 --config=tools/pep8config.txt directory_to_check
     68}}}
     69
     70Alternatively, you can use `pep8` with `--diff` option to check just the parts of the code you have changed:
     71
     72{{{
     73svn diff | pep8 --diff --config=tools/pep8config.txt
     74}}}
     75
     76The best practice is to use pep8 with default configuration (i.e., without custom configuration file) for new files and new code in old files.
     77
     78Use 4-space indentation (GNU Emacs python-mode default). Do not use tabs (tabulators) at all.
     79Note that Python determines nesting based upon indentation, so it is quite crucial to be consistent, i.e. use given rules.
     80
     81Make sure a new line is at the end of each file and there are no trailing spaces.
     82
     83Do not fix (intentionally or unintentionally) existing style issues in code (at lines) you are not changing.
     84If you are fixing style issues, do it in a separate commit.
    6785
    6886Use named parameters in functions (without space around '='), e.g.
     
    7896{{{
    7997!python
    80 
    8198dlg = wx.FileDialog(self, _("Choose file to save current workspace"),
    8299                    _("GRASS Workspace File (*.gxw)|*.gxw"), wx.FD_SAVE)
    83100}}}
    84101
     102Use three double quotes for docstrings (`"""..."""`).
     103Use double quotes for translatable (user visible) strings, single quotes for the rest.
    85104
    86105
     
    89108=== Temporary files ===
    90109
    91 5.  Create and use secure temporary files and directories. Use the
    92     grass.tempfile() or grass.tempdir() functions to do this. e.g.
     110Create and use secure temporary files and directories. Use the
     111grass.tempfile() or grass.tempdir() functions to do this. e.g.
    93112
    94113{{{
    95114#!python
    96         # setup temporary file
    97         TMP = grass.tempfile()
    98         if TMP is None:
    99             grass.fatal("Unable to create temporary files")
    100 }}}
    101 
    102 6.  Use grass.findfile() when there is a need to test if a map exists.
     115# setup temporary file
     116TMP = grass.tempfile()
     117if TMP is None:
     118    grass.fatal("Unable to create temporary files")
     119}}}
     120
     121TODO: this needs to be fixed, it's more complicated
     122
     123=== Checking inputs of a module ===
     124
     125Use grass.findfile() when there is a need to test if a map exists.
    103126
    104127
    105128{{{
    106129#!python
    107         # test for input raster map
    108         result = grass.find_file(name = map_name, element = 'cell', quiet = True)
    109         if not result['file']
    110           grass.fatal("Raster map <%s> not found" % map_name)
    111 
    112         # test for input vector map
    113         result = grass.find_file(name = map_name, element = 'vector', quiet = True)
    114         if not result['file']
    115           grass.fatal("Vector map <%s> not found" % map_name)
    116 }}}
    117 
    118      ... and so forth. See 'g.manual g.findfile' for details.
     130# test for input raster map
     131result = grass.find_file(name = map_name, element = 'cell', quiet = True)
     132if not result['file']
     133  grass.fatal("Raster map <%s> not found" % map_name)
     134
     135# test for input vector map
     136result = grass.find_file(name = map_name, element = 'vector', quiet = True)
     137if not result['file']
     138  grass.fatal("Vector map <%s> not found" % map_name)
     139}}}
     140
     141... and so forth. See 'g.manual g.findfile' for details.
    119142
    120143=== Messages ===
    121144
    122 7.  For any informational output, use the grass.message()
    123     function. For error messages should be used grass.fatal_error() or
    124     grass.error() and for warnings grass.warning(). For debugging
    125     purposes grass.debug().
     145For any informational output, use the grass.message()
     146function. For error messages should be used grass.fatal_error() or
     147grass.error() and for warnings grass.warning(). For debugging
     148purposes grass.debug().
    126149
    127150
    128151{{{
    129152#!python
    130         #normal message:
    131         grass.message("Done")
    132 
    133         # warning:
    134         grass.warning("No input values found, using default values")
    135 
    136         # error:
    137         grass.error("No map found")
    138 
    139         # fatal error:
    140         grass.fatal_error("No map found, exiting")
    141 
    142         # debug output (use g.gisenv to enable/disable)
    143         grass.debug("Our calculated value is: %d" % value)
    144 }}}
    145 
    146     Try to omit any usage of the 'print' command for informational output.
     153#normal message:
     154grass.message("Done")
     155
     156# warning:
     157    grass.warning("No input values found, using default values")
     158
     159# error:
     160    grass.error("No map found")
     161
     162# fatal error:
     163grass.fatal_error("No map found, exiting")
     164
     165# debug output (use g.gisenv to enable/disable)
     166    grass.debug("Our calculated value is: %d" % value)
     167}}}
     168
     169Do not use the `print` statement (print function in Python 3) for informational output. This is reserved for standard module output if it has one.
    147170
    148171
     
    172195== Documentation and comments ==
    173196
    174 
    175 
    176 6.  Comment your classes and functions with docstrings. Use Sphinx syntax.
    177 
    178     Comment also the code itself such as the meaning of variables,
    179     conditions etc.
    180 
    181 
    182 8.  PLEASE take the time to add comments throughout your code explaining what
    183     the code is doing. It will save a HUGE amount of time and frustration for
    184     other programmers that may have to change your code in the future.
    185 
    186 
    187 
    188 9.  Use tools such as pylint and pep8 to check your code (both style and
    189     correctness). Just note that default settings of these tools is not fully
    190     compatible with wxGUI/wxPython style and that some of the reported errors
    191     may not apply to your code.
     197Comment your classes and functions with docstrings. Use Sphinx (reStructuredText) syntax.
     198
     199Comment also the code itself such as the meaning of variables, conditions etc.
     200
     201Take the time to add comments throughout your code explaining what
     202the code is doing. It will save a huge amount of time and frustration for
     203other programmers that may have to change your code in the future.
     204
     205== Checking the code ==
     206
     207Use tools such as pylint and pep8 to check your code (both style and
     208correctness). Just note that default settings of these tools is not fully
     209compatible with wxGUI/wxPython style and that some of the reported errors
     210may not apply to your code.
    192211
    193212