Pocoo Styleguide

The Pocoo styleguide is the styleguide for all Pocoo Projects, includingFlask. This styleguide is a requirement for Patches to Flask and arecommendation for Flask extensions.

In general the Pocoo Styleguide closely follows PEP 8 with some smalldifferences and extensions.

General Layout

  • Indentation:
  • 4 real spaces. No tabs, no exceptions.

  • Maximum line length:

  • 79 characters with a soft limit for 84 if absolutely necessary. Tryto avoid too nested code by cleverly placing break, continue andreturn statements.

  • Continuing long statements:

  • To continue a statement you can use backslashes in which case you shouldalign the next line with the last dot or equal sign, or indent fourspaces:
  1. this_is_a_very_long(function_call, 'with many parameters') \
  2. .that_returns_an_object_with_an_attribute
  3.  
  4. MyModel.query.filter(MyModel.scalar > 120) \
  5. .order_by(MyModel.name.desc()) \
  6. .limit(10)

If you break in a statement with parentheses or braces, align to thebraces:

  1. this_is_a_very_long(function_call, 'with many parameters',
  2. 23, 42, 'and even more')

For lists or tuples with many items, break immediately after theopening brace:

  1. items = [
  2. 'this is the first', 'set of items', 'with more items',
  3. 'to come in this line', 'like this'
  4. ]
  • Blank lines:
  • Top level functions and classes are separated by two lines, everythingelse by one. Do not use too many blank lines to separate logicalsegments in code. Example:
  1. def hello(name):
  2. print 'Hello %s!' % name
  3.  
  4.  
  5. def goodbye(name):
  6. print 'See you %s.' % name
  7.  
  8.  
  9. class MyClass(object):
  10. """This is a simple docstring"""
  11.  
  12. def __init__(self, name):
  13. self.name = name
  14.  
  15. def get_annoying_name(self):
  16. return self.name.upper() + '!!!!111'

Expressions and Statements

  • General whitespace rules:
    • No whitespace for unary operators that are not words(e.g.: -, ~ etc.) as well on the inner side of parentheses.

    • Whitespace is placed between binary operators.

Good:

  1. exp = -1.05
  2. value = (item_value / item_count) * offset / exp
  3. value = my_list[index]
  4. value = my_dict['key']

Bad:

  1. exp = - 1.05
  2. value = ( item_value / item_count ) * offset / exp
  3. value = (item_value/item_count)*offset/exp
  4. value=( item_value/item_count ) * offset/exp
  5. value = my_list[ index ]
  6. value = my_dict ['key']
  • Yoda statements are a no-go:
  • Never compare constant with variable, always variable with constant:

Good:

  1. if method == 'md5':
  2. pass

Bad:

  1. if 'md5' == method:
  2. pass
  • Comparisons:
    • against arbitrary types: == and !=

    • against singletons with is and is not (eg: foo is notNone)

    • never compare something with True or False (for example neverdo foo == False, do not foo instead)

  • Negated containment checks:

  • use foo not in bar instead of not foo in bar

  • Instance checks:

  • isinstance(a, C) instead of type(A) is C, but try to avoidinstance checks in general. Check for features.

Naming Conventions

  • Class names: CamelCase, with acronyms kept uppercase (HTTPWriterand not HttpWriter)

  • Variable names: lowercase_with_underscores

  • Method and function names: lowercase_with_underscores

  • Constants: UPPERCASE_WITH_UNDERSCORES

  • precompiled regular expressions: name_re

Protected members are prefixed with a single underscore. Doubleunderscores are reserved for mixin classes.

On classes with keywords, trailing underscores are appended. Clashes withbuiltins are allowed and must not be resolved by appending anunderline to the variable name. If the function needs to access ashadowed builtin, rebind the builtin to a different name instead.

  • Function and method arguments:
    • class methods: cls as first parameter

    • instance methods: self as first parameter

    • lambdas for properties might have the first parameter replacedwith x like in display_name = property(lambda x: x.real_nameor x.username)

Docstrings

  • Docstring conventions:
  • All docstrings are formatted with reStructuredText as understood bySphinx. Depending on the number of lines in the docstring, they arelaid out differently. If it’s just one line, the closing triplequote is on the same line as the opening, otherwise the text is onthe same line as the opening quote and the triple quote that closesthe string on its own line:
  1. def foo():
  2. """This is a simple docstring"""
  3.  
  4.  
  5. def bar():
  6. """This is a longer docstring with so much information in there
  7. that it spans three lines. In this case the closing triple quote
  8. is on its own line.
  9. """
  • Module header:
  • The module header consists of a utf-8 encoding declaration (if nonASCII letters are used, but it is recommended all the time) and astandard docstring:
  1. # -*- coding: utf-8 -*-
  2. """
  3. package.module
  4. ~~~~~~~~~~~~~~
  5.  
  6. A brief description goes here.
  7.  
  8. :copyright: (c) YEAR by AUTHOR.
  9. :license: LICENSE_NAME, see LICENSE_FILE for more details.
  10. """

Please keep in mind that proper copyrights and license files are arequirement for approved Flask extensions.

Comments

Rules for comments are similar to docstrings. Both are formatted withreStructuredText. If a comment is used to document an attribute, put acolon after the opening pound sign (#):

  1. class User(object):
  2. #: the name of the user as unicode string
  3. name = Column(String)
  4. #: the sha1 hash of the password + inline salt
  5. pw_hash = Column(String)