← Back to team overview

openerp-expert-framework team mailing list archive

Re: Coding guidelines and standards - additional info

 

Hi Ferdinand,

Is there a wiki for these guidelines?

On Tue, Dec 15, 2009 at 2:29 PM, Ferdinand Gassauer <office@xxxxxxxxxx>wrote:

> some additional ideas
>
> we also prefer to code table descriptions for better readability
> (see screen shot)
> * fixed column width for name and filed type
> (I know sometimes the name is to short ....)
> * alphabetical order of fields
> * split long lines
>
>
>
> The Syntax is "MoinMoin"-Wiki.
>
> -------------------------------------------------------------
> --
> Best Regards
>
> ChriCar Beteiligungs- und Beratungs- GmbH
> http://www.chricar.at/ChriCar/index.html
> Dr. Ferdinand Gassauer
> Official Tiny Partner
>
>
> = Introduction =
>
> These rules augment the rules stated in PEP-0008 (
> http://www.python.org/dev/peps/pep-0008/).
>
> == Purpose ==
> Coding guidelines help to:
>  * '''ensure maintainability''' -- any programmer should feel "at home"
> when reading any source code. Therefore, any source code needs to have a
> uniform structure. Moreover, it is essential to disallow difficult-to-read
> code fragments requiring a lot of time to be understood.
>  * '''ensure automatization''' -- so that we can automatically rewrite code
> and generate documentation, for example, API documentations and reference
> manuals.
>  * '''avoid faulty software''' -- following the below guidelines will help
> programmers to avoid or circumvent common errors and pitfalls.
>
> == Scope ==
>  * These coding guidelines apply to Python files only. However, major parts
> can be adapted to other languages as well.
>  * '''Any Python file must conform with these coding guidelines,'''
> regardless of whether it is a library, a tool-specific file, a "goodies"
> script or just a quick hack for rapid prototyping.
>  *  However, there might be some cases where it makes sense to break a
> rule. It is up to you as careful and intelligent programmers to identify
> these cases and handle them in a proper way:
>   * If it appears to be a single case, the item shall be documented in the
> artefact itself.
>   * If the violation is considered to be systemic and should be taken into
> account in the guidelines, file a change-request against the documents. See
> section 6 how to do so.
>
> == Terminology ==
>  * The word "shall" is used for requirements. You need to have a very good
> reason not to use "shall" where it is mandatory, and you have to document,
> why you have done so.
>  * The word "should" is used for recommendations, good practices and hints.
>
> == General Advice ==
>  * Program '''defensively'''. Consider in particular that parameters of a
> function may be incomplete (for example, filename without extension or full
> path) or have a different type (`int` instead of `float`, `tuple` instead of
> `list`, ...).
>  * Program for '''portability'''. For example, use `os.path.join` instead
> of concatenating strings with "/".
>  * Program '''unambiguously'''. Define unique values only once.
>  * Avoid defining "magic" numbers in the source code. Use definitions
> instead of hard-coded numbers.
>  * Use '''symbolic names'''. This improves readability, makes the program
> easier to maintain, reduces the potential for errors, and requires less
> development effort.
>
>
> = Formatting =
>
> == General ==
>  1. There shall be no trailing spaces
>
> == Header ==
>
>  1. Every file shall start with a header.
>   This header shall include:
>   * the Python coding cookie. You had best use the `iso-8859-1` charset.
>   * licence information.
>   * The name of the file, as it would be imported by Python. For the
> `App_Type` module in the`_TTA` package, this would be `_TTA.App_Type`.
>   * the purpose of the file.
>   * revision dates including the Bugtracking  number.
>  2. The header shall ''not'' include:
>   * hash-bangs so that the Python script can be executed just by calling it
> (that is, "`#! \usr\bin\env python`"). When the Python version is changed,
> it can be very hard to find errors caused by these hash-bangs.
>
>     '''Hint:'''
>     It is good practice to check the header of every file you edit.
>
>  3. The header shall have the following format. (Two different licenses are
> given as example.)
>    {{{
> #!python
> # -*- coding: iso-8859-1 -*-
> # Copyright (C) 2000-2004 Swing GmBH. All rights reserved.
> # Gruenlandgasse 1, 2620 Neunkirchen, Austria. office@xxxxxxxxxxxxxxxx
> #
> #++
> # Name
> #    _TTA.App_Type
> #
> # Purpose
> #    Define application types for TTA tools
> #
> # Revision Dates
> #     7-Nov-2000 (GK) Creation
> #    28-Jul-2002 (GK) [4711] Adapted to packaging of `TOM`
> #     2-Apr-2004 (GK) [4712, 4713] `NODE__cluster` added to definition of
> `NDT`
> #    ««revision-date»»···
> #--
>    }}}
>
>    {{{
> #!python
> # -*- coding: iso-8859-1 -*-
> # Copyright (C) 2000-2004 Swing GmBH. All rights reserved.
> # Gruenlandgasse 1, 2620 Neunkirchen, Austria. office@xxxxxxxxxxxxxxxx
> #
> #
> ****************************************************************************
> # This library is free software; you can redistribute it and/or
> # modify it under the terms of the GNU Library General Public
> # License, as published by the Free Software Foundation; either
> # version 2 of the License, or (at your option) any later version.
> #
> # This library is distributed in the hope that it will be useful,
> # but WITHOUT ANY WARRANTY; without even the implied warranty of
> # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> # Library General Public License for more details.
> #
> # You should have received a copy of the GNU Library General Public
> # License along with this library; if not, write to the Free
> # Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> #
> ****************************************************************************
> #
> #++
> # Name
> #    _TFL.DL_List
> #
> # Purpose
> #    Doubly linked list
> #
> # Revision Dates
> #    11-Sep-2003 (GK) Creation
> #    12-Sep-2003 (GK) Creation continued
> #     9-Mar-2004 (GK) [4714] `_doc_test` changed to not use `import`
> #    ««revision-date»»···
> #--
>    }}}
>
> == Footer ==
>  1. Every file shall end with the following comment, repeating the name of
> the header.
>    {{{
> #!python
> ### __END__ TTA.App_Type
>    }}}
>
> == End of Classes and Functions ==
>  1. Every class shall have a closing comment with the syntax as shown
> below.
>  2. Every method shall have a closing comment with the syntax as shown
> below.
>    '''Example:'''
>    {{{
> #!python
> class Coding_Guidelines (Guidelines) :
>    """General and abstract guidelines."""
>
>    def __init__ (self, name) :
>        self._name = name
>    # end def __init__
>
>    def formatted_name (self) :
>        """Returns the internal variable `_name` nicely formatted.
>        """
>
>        return ">>%s<<" % self._name
>    # end def formatted_name
> # end class Coding_Guidelines
>    }}}
>
> == Indentation and Spacing ==
> (See http://en.wikipedia.org/wiki/Bracket on a definition of brackets,
> parentheses and braces.)
>
>  1. Source files shall not contain consecutive multiple blank lines.
>  1. There shall exactly be one blank line between a method and a class
> definition.
>  1. You shall use a blank space before `\` or `:`
>  1. You shall use a blank space before and after any operator.
>  1. You shall use a blank space after `,` or  `;` or `:`
>  1. You shall not place spaces after openings and before closings.
>  1. You should concentrate args, but never keywords.
>    '''Example:'''
>    {{{
> #!python
>    CSE_Object_Selector.__init__ \
>        ( self, r_map, master
>        , label = "Subsystem"
>        , list  = list
>        , name  = "subsystem_selector"
>        )
>    }}}
>
> == Alignment ==
>  1. If, and only if, a call or definition exceeds one line, it shall
> immediately be broken after the name, keyword or (assignment) operator.
>  1. Exception names shall be in the same line as `raise` or `except` to be
> able to ''grep'' for them.
>    '''Example:'''
>    {{{
> #!python
>    raise TypeError, \
>        "%s needs a list as first argument, not a %s." % (self.name, type
> (x))
>    }}}
>  1. If the remaining line is still too long, one line shall be used for
> every parameter.
>  1. Brackets and commas shall be aligned horizontally.
>  1. If a closing bracket is on a different line than its opening bracket,
> both shall be in the same column.
>  1. `=` signs for keyword defaults shall be aligned horizontally.
>  1. `=` signs shall be aligned horizontally, in consecutive lines of
> statements.
>  1. Triple-quotes (`"""`) shall be normally indented and horizontally
> aligned.
>  1. Expressions shall be aligned so that their visual appearance matches
> their logical structure.
>    '''Example:'''
>    {{{
> #!python
> class Function_Definitions (Coding_Guidelines) :
>    """More about function definitions. Several lines are welcome,
>       and they do not affect the general layout of this class or
>       function description.
>    """
>
>    def __init__ \
>        ( self, typ, version
>        , a_default_parameter    = "something"
>        , a_long_parameter_name  = 1
>        , another_parameter      = "something other"
>        ) :
>
>        self.typ          = typ
>        self.version      = version
>        self.r_map.tag_highlight \
>            (event, self.f_tag, self.r_map.frame_high, "current_frame")
>        self.name         = self.r_map.name + self.version
>        self.userints [i] = self.map_from_object \
>            (self.r_map, self, rtag, i + 1, typ = "host")
>        CSE_Object_Selector.__init__ \
>            ( self, r_map, master
>            , label = "Subsystem"
>            , list  = list
>            , name  = "subsystem_selector"
>            )
>    # end def __init__
> # end class Function_Definitions
>    }}}
>
> == EOL Quotes ==
>  1. You shall use the EOL quote (backslash + carriage_return) only if
> really necessary. The only exception is right after a function name, a
> keyword or an assignment operator, if the line would otherwise be too long.
>  1. There shall be no more than one EOL quote per statement.
>  1. Adjacent text literals on multiple lines shall be put in parentheses,
> instead of quoting the line ends with backslashes. See example below.
>  1. You shall factor as much as possible, even in text literals.
>  1. Expressions spanning multiple lines shall also be parenthesized.
>    '''Example:'''
>    {{{
> #!python
>    Abbreviations = "\n".join \
>        ( ( "`bb` ... bytes_bus effective length of the frame on the bus"
>          , "`vs` ... validity_span duration in which the frame is valid "
>            " in the CNI, starting at the next slot"
>          , "`tt` ... transmission_time duration of the transmission phase
> on"
>            " the bus"
>          , "`d`  ... duration slot duration"
>          , "`s`  ... size net size of the frame in bytes"
>          )
>        )
>    }}}
>  1. You shall not use an EOL quote, if the subsequent opening bracket is
> below the EOL quote or to the right of it.
>    '''Bad Example:'''
>    {{{
> #!python
>    if \
>        ( long_expression
>        and another_long_expression
>        ) :
>    }}}
>    '''Good Example:'''
>    {{{
> #!python
>    if  (   long_expression
>        and another_long_expression
>        ) :
>    }}}
>  1. Long strings shall be broken into pieces or written with triple-quotes.
> The new line shall be aligned with the beginning of the string at the same
> level on the previous line.
>    '''Example:'''
>    {{{
> #!python
>    a_rather_long_string = \
>        ( "A very long string "
>          "split over multiple lines."
>        )
>    another_rather_long_string = \
>        """A very long string
>           split over multiple lines.
>        """
>    }}}
>
> = Structure =
>
> == Module and Class ==
>  1. Every file shall have a file history documenting any modification made.
>
> == Order of Definitions ==
>  1. The most important class should be the last one.
>  1. Within a class, you shall first define the attributes of this class,
> then properties if any, then the methods.
>  1. The methods of a class shall be sorted in the following order:
>   * First `__new__`, then `__init__`, then `__call__`.
>   * Then the public interface (that is, externally used methods) shall
> follow. Such methods look like "`x`".
>   * Then non-public methods shall follow. Such methods look like "`_x`".
>   * Then other special methods shall follow. Such methods look like
> "`__x__`".
>   * Name-mangled methods (looking like "`__x`") shall not be used.
>  1. Within the above sections, methods should be sorted in a natural way
> (for example, most important first, according to the control flow, grouped
> logically), else in alphabetical order.
>  1. The `__main__` script shall be at the end of a module.
>  1. If there are long lists of attributes, keywords, or other items, for
> example, they should be sorted alphabetically (or numerically, if
> applicable).
>  1. '_' shall be ignored when sorting, but underscores should be grouped.
> For example, `affe`, `ameise`, `_aachen`, `_amsterdam`, `bingo`, ...
>
> == Package Name Space ==
>  1. Related modules shall be grouped into a Python package.
>  1. Each package shall be implemented as a Package_Namespace.
>   * The name of the package shall start with a single underscore, for
> example, `_Foo`.
>   * The name of the package namespace shall be the same as that of the
> package, with the exception of the leading underscore, for example, `Foo`.
>   * The package file `__init__.py` shall define the package namespace
> instance (see package `TOM` for an example).
>   * All the modules of the namespace package shall contain an export
> statement guarded by `__name__ != "__main__"` at the bottom of the file.
>    '''Example:'''
>    {{{
> #!python
> if __name__ != "__main__" :
>    TFL._Export ("*")
>    }}}
>  1. Any access to objects of a namespace package shall use a qualified name
> which shall start with the name of the namespace package, for example,
> `Foo.bar ()`.
>    '''Example:'''
>    {{{
> #!python
> from _TFL import TFL
> import _TFL.DL_List
> ...
> l = TFL.DL_List ()
>    }}}
>  1. `From` `import` shall not be used to import objects from a namespace
> package.
>    '''Bad Example:'''
>    {{{
> #!python
> from _TFL.DL_List import DL_List
>    }}}
>
> == Nesting and Recursion ==
>  1. Nested function definitions should be avoided.
>  1. Recursion shall be used only, if it substantially simplifies the code.
>
> = Semantics =
>
> == Documentation ==
>  1. Any comments and descriptions documenting a source file shall be
> written in '''English'''.
>  1. Any documentation in the source code has the following objectives:
>   * Defining a uniform structure of all source code modules.
>   * Providing an easy way to find information on the file contents.
>   * Making it easier to maintain files.
>   * Providing information on how a certain problem has been solved.
>   * Facilitating to generate additional documentation (such as reference
> manuals) automatically.
>  1. If actual names or values appear in any documentation, they shall be
> enclosed by backquotes (`).
>
> == Docstrings ==
>
> There is '''no''' reason (IP-protection, etc.) to '''not''' write
> docstrings.
>
>  1. Docstrings presented to the user shall have appropriate wording and may
> contain whatever is necessary for the specific purpose and due to usability
> considerations.
>  1. Docstrings that are not presented to the user shall contain a brief
> description of the relevant class or method. This description should not
> contain any redundant information (and repeat, for example, the default
> value) or misleading information (for example, requiring an int although any
> numeric would do).
>  1. The constructor should not have a description.
>  1. Docstrings should contain doctests whereever feasible.
>  1. Docstrings shall be concise. About the content see sub-section
> "Detailed Documentation" below.
>
> == Detailed Documentation ==
>
> The intention is to document any Python package or module using Sphinx.
>
>  1. A Python package shall be documented in the `__init__.py` file by using
> Sphinx. The generated documentation shall explain the purpose of the package
> and its structure and components.
>  1. A Python module shall be documented by the module docstring using
> Sphinx. The generated documentation shall explain the purpose of the module,
> its primary use case(es) and its structure.
>  1. Detailed documentation should contain design decisions, rationales,
> background information, usage examples and other helpful information for
> developers. It shall not repeat what is obvious from the code.
>  1. Detailed package or module documentation shall be done inline
> (docstring) or in a dedicated directory. For lib/python, this is
> `_DOC/Sphinx/packages`, maintaining the same structure as the source code.
>  1. Detailed documentation of concepts shall be done in a dedicated
> directory. For lib/python, this is `_DOC/Sphinx/concepts`.
>  1. As scripts are usually seen and used without the context of lib/python,
> all necessary documentation shall be in the same file as the source code
> itself.
>  1. Detailed documentation shall reference but not repeat other documents
> (SDD, customer's specifications, standards, etc.).
>  1. For detailed documentation in other files, a reference to this location
> shall be given. The location may be omitted if it is obvious. For Sphinx,
> use:
>    {{{
> #!python
>    # SPHINX_DOC [location]
>     }}}
>
>
> == Comments ==
> Always consider that someone who sees your code for the first time has to
> be able to understand it.
>  1. You should use doctests (or at least docstrings) instead of comments.
>  1. Comments shall describe why something is done in a particular way, and
> not what is done or how something is done. This is documented by the code
> itself!
>  1. You shall place comments after a line, if possible (length). Otherwise,
> place it above the line of code to which it belongs.
>  1. You shall use the "`### XXX`" prefix for comments relating to future
> versions or constituing hints how to fix a problem.
>    '''Example:'''
>    {{{
> #!python
>        another_function \
>            ( first_very_long_parameter
>            , (some * complicated + expression)
>            , elapsed_time # in microseconds
>            )
>        # avoid rounding errors
>        e = ((w_x * (ttime + self.ifg_in_ns)) / self.duration_in_ns) - d
>        ### XXX adapt to improved Package_Namespace
>        pkg_namespace_import_pat = Regexp (r"x", re.X)
>    }}}
>  1. You shall use self-explanatory names instead of comments.
>    '''Bad Example:'''
>    {{{
> #!python
>    a_function \
>        ( first_long_parameter
>        , 42 # number of lines
>        )
>    }}}
>    '''Good Example:'''
>    {{{
> #!python
>    a_function \
>        ( first_long_parameter
>        , number_of_lines = 42
>        )
>    }}}
>
> == Naming ==
>  1. The name of a module shall have the extension ".py".
>  1. The base name of the module shall be identical to the name of the (only
> or most important) class.
>  1. If a module contains no class, its base name should refer to the
> intended use.
>  1. The name of the identifier shall be unambiguous and self-explanatory to
> specify the purpose of the identifier.
>  1. The larger the scope of visibility, the longer a name should be (and
> vice versa), this means that loop variables should be as short as possible,
> global names should be long enough to convey sufficient meaning.
>  1. If the name comprises multiple words, they shall be separated by
> underscores ("`_`").
>  1. `CamelCaseWordsLikeThisOne` shall not be used.
>  1. Magic names, to be specific, names with two leading and two trailing
> underscores, shall not be used except when magic methods are to be defined,
> as is defined by Python (otherwise existing code might become invalid in
> future Python versions, when the set of official magic gets bigger).
>  1. Any class name shall start with a capital letter (to be specific, with
> a capital letter at the beginning of the name and after every underscore).
> The rest are lowercase letters, underscore or digits. Exceptions are allowed
> when the name consists of an abbreviation (for example, `PCP_Driver`) or
> when the class implements an association (for example, `Host_uses_Message`).
>  1. Constants shall be all uppercase with words separated by underscores or
> digits.
>  1. The other identifiers (which can also have an underscore as the first
> letter) shall be all lowercase with words separated by underscores or
> digits. Exceptions are allowed for names being abbreviations.
>  1. Class names shall be nouns or noun phrases, in mixed case, with the
> first letter of each internal word capitalized (see above).
>  1. Mixin class names shall be adjectives or nouns having the "`_mixin`"
> suffix.
>  1. Names of states that change functions shall be verbs (for example,
> `connect`, `schedule`) or verb phrases.
>  1. Names of states that query functions shall be adjectives,
> noun-verb-adjective combinations or verb-noun combinations (for example,
> `connected`, `is_valid`, `has_key`).
>  1. You shall avoid "`get_`" prefixes.
>    '''Bad Example:'''
>    {{{
> #!python
>    def get_version (self) :
>        return "%s.%s.%s" % (self.major, self.minor, self.patchlevel)
>    # end def get_version
>    }}}
>    '''Good Example:'''
>    {{{
> #!python
>    def version (self) :
>        """Returns the version as <major>.<minor>.<patchlevel>."""
>
>        return "%s.%s.%s" % (self.major, self.minor, self.patchlevel)
>    # end def version
>    }}}
>  1. Non-public names shall start and end with a single underscore ("`_`").
>
> = Pragmatics =
>
> == Avoid redundancy ==
>
>  1. Do not repeat yourself (DRY!). This also applies to
>   * literals: use named constants,
>   * (sub)-expressions: assign them to named variables,
>   * blocks of code: factor them into functions or methods,
>   * sets of methods: factor tem into common ancestors.
>  1. You shall be brief and concise.
>    '''Bad Example:'''
>    {{{
> #!python
>        (x, y) = (self.current_slot [0], self.current_slot [1])
>    }}}
>    '''Good Example:'''
>    {{{
> #!python
>        (x, y) = self.current_slot [:2]
>    }}}
>  1. You shall make the closing clearly visible.
>    '''Example:'''
>    {{{
> #!python
>        (time, value) = reduce \
>            ( lambda l, r, o = grid_opt : min (l, (o / r + r / o, r))
>            , self.time_list
>            , (2 * self.time_list [-1], ) * 2
>            )
>        r_slot = filter \
>            ( lambda l, rs = rs : l.r_slot.round == rs.round
>              and l.slot.number == rs.slot
>              ### XXX place filter condition for Cluster_Mode here
>            , r_slot
>            ) [0].r_slot
>        return \
>            ( self.slot.duration * self.r_map.pix_per_MT_x
>            + 2                  * self.r_map.frame_border_x
>            )
>    }}}
>
> == New-style classes ==
>  1. For newly written code, new-style classes shall be used whenever
> possible, which is unfortunately not yet feasible for exceptions or
> descendents of some classic classes already existing.
>  1. New-style classes should normally inherit directly or indirectly from
> `TFL.Meta.Object`.
>
> == Reference to Ancestor Class ==
>  1. For new-style classes, `__super` shall be used to upchain method calls
> (`__super` is provided by the `TFL.Meta.M_Autosuper` meta-class).
>  1. Every classic class shall define an ancestor attribute which shall be
> used throughout the class to upchain method calls.
>
> == Import order ==
>  1. The role types of an TOM association shall be imported before the
> association itself. Role types are the object types connected ("linked")
> with the association.
>    '''Good Example:'''
>    {{{
> #!python
>    from _TTA import TTA
>    import TTA.Message
>    import TTA.Subsystem
>    import TTA.Subsystem_sends_Message
>    }}}
>
>    '''Bad Example:'''
>    {{{
> #!python
>    from _TTA import TTA
>    import TTA.Subsystem_sends_Message
>    import TTA.Message
>    import TTA.Subsystem
>    }}}
>
> == Use of properties ==
> For new-style classes, properties shall be used whenever control over
> attribute access is called for. A Python property associates an attribute
> name with methods to get, set, and delete the attribute's value and to an
> optional documentation for the attribute.
>  1. Properties shall be only used inside new-style classes.
>  * Using properties for readonly attributes:
>    {{{
> #!python
>    class Foo (TFL.Meta.Object) :
>        ro = property (lambda s : s._ro)
>        def __init__ (self, x = 0) :
>            self._ro = x
>    }}}
>    {{{
>
> >>>>>> f = Foo (1)
> >>>>>> f.ro
>
> 1
>
> >>>>>> f.ro = 3
>
> Traceback (most recent call last):
>  File "<stdin>", line 1, in ?
> AttributeError: can't set attribute
>    }}}
>  * Using properties for read/write attributes:
>    {{{
> #!python
>    class Complex (TFL.Meta.Object) :
>
>        def _get_r (self) :
>            return math.sqrt (self.x ** 2 + self.y ** 2)
>        # end def _get_r
>
>        def _set_r (self, r) :
>            theta  = math.atan2 (self.y, self.x)
>            self.x = r * math.cos (theta)
>            self.y = r * math.sin (theta)
>        # end def _set_r
>
>        r = property (_get_r, _set_r)
>    }}}
>
>  1. Properties shall be used instead of parameterless access functions.
>    '''Bad Example:'''
>    {{{
> #!python
>    class Foo (TFL.Meta.Object) :
>        def position (self) :
>            return self._position
>    }}}
>    '''Good Example:'''
>    {{{
> #!python
>    class Foo (TFL.Meta.Object) :
>        position = property (lambda s : s._position, doc = "attribute
> documentation")
>    }}}
>
> == Scope of Visibility ==
>  1. Do not make an identifier visible outside the scope for which it is
> required.
>  1. The larger the scope of visibility, the longer an identifier should be.
>
> == Identity vs. Equality ==
>  1. `is` shall be used to check for identity. As a general rule, identity
> checks should be used only for singleton objects.
>  1. `is` shall not be used to check immutable objects, such as numbers,
> strings, and tuples.
>  1. `==` shall be used to check for equality.
>  1. `==` shall not be used to check, whether a name refers to `None`.
>  1. To check for a specific type, use `isinstance (i, o)`.
>    '''Bad Example:'''
>    {{{
> #!python
> type (s) == type ("")
> type (s) is type ("")
> import types
> type (s) == types.StringType
> isinstance (s, type (""))
>    }}}
>    '''Good Example:'''
>    {{{
> #!python
> isinstance (s, str)
> isinstance (s, (str, unicode))
>    }}}
>
> == Boolean Expressions ==
>  1. Boolean values shall not be compared against `True` or `False`.
>    '''Bad Example:'''
>    {{{
> #!python
> if x == True :
>    do_something ()
>    }}}
>    '''Good Example:'''
>    {{{
> #!python
> if x :
>    do_something ()
>    }}}
>  2. To test, if a list or dictionary contains elements, you shall not use
> `len`.
>    '''Bad Example:'''
>    {{{
> #!python
> if len (x) == 0 :
>    do_something ()
>    }}}
>    '''Good Example:'''
>    {{{
> #!python
> if not x :
>    do_something ()
>    }}}
>  3. To test, if a name refers to `None`, identity testing shall be used.
>    '''Bad Example:'''
>    {{{
> #!python
> if not x : ### will be entered for any empty structure or zero-valued
> number
>    do_something ()
> if x != None : ### calls `__cmp__` of x.__class__
>    do_some_otherthing ()
>    }}}
>    '''Good Example:'''
>    {{{
> #!python
> if x is not None :
>    do_something ()
>    }}}
>
> == Parentheses ==
>  1. You should use rather more than less parentheses.
>  1. You shall avoid redundant parentheses, like in `if (x == 5) :`.
>  1. You shall avoid precedence gotchas.
>    '''Bad example:'''
>    {{{
> #!python
>    a = b and not c or d
>    }}}
>    '''Good example:'''
>    {{{
> #!python
>    a = (b and (not c)) or d
>    }}}
>  1. You should do the optical layout in a such way that the code can be
> read correctly. If unsure, use parentheses.
>    '''Bad example (actually incorrect code, see bug report 9073):'''
>    {{{
> #!python
>    return int \
>        ( self.home_scope.TTA.Cluster.root.max_delay
>        + preamble_bits
>        +
> (start_of_frame_bits[self.home_scope.TTA.Cluster.root.physical_interface]
>        + self.protocol.header_bits
>        + databits
>        + self.protocol.crc_bits
>        ) * (1E6 / speed) # convert kbit/sec to nanoseconds/bit
>        )
>    }}}
>    '''Good example:'''
>    {{{
> #!python
>    TTA = self.home_scope.TTA
>    return int \
>        ( TTA.Cluster.root.max_delay
>        + ( preamble_bits
>          + start_of_frame_bits [TTA.Cluster.root.physical_interface]
>          + self.protocol.header_bits
>          + databits
>          + self.protocol.crc_bits
>          )
>        * (1E6 / speed) # convert kbit/sec to nanoseconds/bit
>        )
>    }}}
>
> == Avoid Numeric Indices ==
>  1. You should provide names for command line arguments instead of
> accessing them by index. You had best use the `Command_Line` module.
>  1. You shall extend lists and tuples by meaningful names, not by index.
>    '''Bad Example:'''
>    {{{
> #!python
>    for t in self.type_list :
>        c_name = "%s_%s (%s)" % (t[0], t[1], t[2])
>    }}}
>    '''Good Example:'''
>    {{{
> #!python
>    for (t_name, t_def, t_len) in self.type_list :
>        c_name = "%s_%s (%s)" % (t_name, t_len, t_def)
>    }}}
>
> == Avoid Long Lines ==
>  1. You shall start with operators to avoid EOL quotes.
>    '''Example:'''
>    {{{
> #!python
> mc_y_min = \
>    ( (r_map.mchange_clear_y_min * 100)
>    / (100 - r_map.mchange_y_min_percent)
>    + r_map.frame_border_y
>    )
>    }}}
>  1. You should precompute a value to shorten the subsequent function call
> or expression and improve its readability.
>    '''Example:'''
>    {{{
> #!python
> y_ui_0 = y      + self.frame_y_m
> y_ui_1 = y_ui_0 + self.ui_y_b
> self.userints [0].insert (canvas, x, y_ui_0, bx, 0, typ_label, self)
> self.userints [1].insert (canvas, x, y_ui_1, bx, 0, typ_label, self)
>    }}}
>  1. You shall use one format string to assemble strings from several parts.
>    '''Bad Example:'''
>    {{{
> #!python
> result = (result + ", tt = %d us, IFG = %d us, idle = %d us"
>       % (ttime, ifg, idle))
>    }}}
>    '''Good Example:'''
>    {{{
> #!python
> result = \
>    ( "%s, tt = %d us, IFG = %d us, idle = %d us"
>    % (result, ttime, ifg, idle)
>    )
>    }}}
>
> == Exceptions ==
>  1. No strings shall be used as exceptions.
>  1. All exceptions shall end with `_Error` and follow the naming guidelines
> for classes.
>  1. All exceptions shall be derived from `StandardError`.
>    '''Example:'''
>    {{{
> #!python
> class TGW_Error (StandardError) :
>    pass
> # end class TGW_Error
>    }}}
>  1. There should be a file `Errors.py` in every package which defines a
> significant number of package-specific errors. The `Errors.py` file shall
> define all the exceptions specific to this package.
>  1. You shall catch only the exceptions you really know. However, sometimes
> you have to catch all Python-related exceptions, for example, when
> interpreting a string entered by the user.
>  1. If you want to print a traceback and go on, you should do as shown
> below. The import statement should be at the top of the file (and should
> thus not be conditional).
>    '''Example:'''
>    {{{
> #!python
> def test_it_again ():
>    try :
>        x.run (cmd)
>    except KeyboardInterrupt :
>        raise
>    except I_Expect_Error :
>        # Do whatever you have to do.
>    except StandardError :
>        import traceback
>        traceback.print_exc ()
> # end def test_it_again
>    }}}
>
> == Performance gotchas ==
>  1. Strings shall not be concatened by the `+` operator. Its repeated use
> in a loop can result in major performance bottlenecks.
>   * Implicit concatenation shall be used to concatenate string literals.
>   * The `%` operator shall be used to concatenate a fixed set of variable
> strings.
>   * The `join` method shall be used to concatenate a dynamic set of
> strings.
>    '''Bad Example:'''
>    {{{
> #!python
> lit_cat = "first" + "second"
> message = str (n) + "errors " + x + "detected"
>
> result = ""
> for x in some_list :
>    result += str (x)
>    }}}
>    '''Good Example:'''
>    {{{
> #!python
> lit_cat = \
>    ( "first"
>      "second"
>    )
> message = "%d errors %s detected" % (n, x)
> r = []
> for x in some_list :
>    r.append (str (x))
> result = "".join (r)
>    }}}
>    '''Even better Example:'''
>    {{{
> #!python
> lit_cat = "firstsecond"
> result  = "".join ([str (x) for x in some_list])
>    }}}
>  1. The `in` operator shall not be used for repeated membership tests in
> lists.
>  1. The `keys` method of dictionaries shall not be used for membership
> tests.
>    '''Bad Example:'''
>    {{{
> #!python
> if x in d.keys () :
>    do_something ()
>    }}}
>    '''Good Example:'''
>    {{{
> #!python
> if x in d :
>    do_something ()
>    }}}
>
> = Revisions of these Coding Guidelines =
>
> If you encounter an error or would like to change or add something to these
> coding guidelines, the following process applies:
>
>  * write an email to your team leader
>  * your request will be discussed in the Teamleader Meeting
>  * in the Teamleader Meeting it also will be decided if and how to apply
> the changes
>  * the changes will be made by one of the maintainers of these guidelines
> (currently AloisGoller and GerhardKönighofer) and announced to the public
>  * several change requestes might be grouped, and handled en-bloc by the
> Teamleader Meeting
>
> == Ideas for extension of these guidelines ==
>  * guidelines on ''generators''
>  * only use doctest, since U_Test is far too complex
>  * no 'else' for unit tests:
> '''Bad Example:'''
> {{{
> if __name__ != "__main" :
>     TGW._Export ("*")
> else :
>     import U_Test
>
>     def _doc_test () :
>         return U_Test.run_module_doc_tests ("_TGW.Menu")
>     # end def _doc_test
>
>     def _test () :
>         _doc_test  ()
>     # end def _test
>
>     _test ()
>
> ### __END__ TGW.Menu
> }}}
> '''Good Example:'''
> {{{
> if __name__ != "__main" :
>     TGW._Export ("*")
> ### __END__ TGW.Menu
> }}}
>
>  * pass arguments with name and value if the name and/or position is
> different in the called method
>
>
> == Proposal for middle-requirements ==
>
> Coding guidelines help to:
>
>  * '''ensure readability''' -- any programmer should feel "at home" when
> reading any source code. Therefore, any source code needs to have a uniform
> structure. Moreover, it is essential to avoid difficult-to-read code
> fragments requiring a lot of time to be understood.
>
>    * self-explanatory names
>    * well structured code
>    * short functions and methods
>
>  * '''ensure maintainability''' -- a programmer should be able to
> understand and change a code fragment quickly and without reading the
> complete code and understanding every single detail. Therefore, it is
> important to accurately and consistently represent the logical structure of
> the code and to keep things local and modular. In addition to readability,
> it is also important that the change can be made easily and does not require
> to change the whole file.
>
>    * comments commenting the why, not the how
>    * no complicated or complex expressions
>    * simple formatting rules so that lines easily can be extended
>    * comments about future changes
>
>  * '''facilitate automatization''' -- so that one can automatically rewrite
> code and generate documentation, e.g., API documentations and reference
> manuals; and that there is no need to manually cleanup things afterwards.
>
>  * '''ensure correctness''' -- as well as intended behavior. The programmer
> thus can avoid or circumvent common errors and pitfalls. Correct and
> supporting documentation and test cases inlined in the source code also help
> to avoid misunderstandings and thus errors.
>
>    * use parantheses
>    * align "," and parantheses in multi-line statements
>    * describe the signature and functionality in docstrings
>    * use (various kinds of) unit tests
>
>  * '''ensure conciseness''' -- so that a programmer can see (and then
> comprehend) as much as possible without navigating around. Moreover, to
> improve performance of the code. Conciseness contributes to efficiency as
> well as maintainability.
>
>    * few blank lines
>    * 80 columns max, so that 2 pages can be displayed on one screen
>    * short names
>    * refactor where possible and meaningful (i.e. Don't Repeat Yourself)
>    * use / harness the syntactic features of the language
> _______________________________________________
> Mailing list: https://launchpad.net/~openerp-expert-framework
> Post to     : openerp-expert-framework@xxxxxxxxxxxxxxxxxxx
> Unsubscribe : https://launchpad.net/~openerp-expert-framework
> More help   : https://help.launchpad.net/ListHelp
>
>


-- 
Sharoon Thomas
Business Analyst & ERP Consultant
http://bit.ly/5FAJKU

Follow ups

References