You should follow this guide for all python source code that is created as part of the Chromium OS project i.e. src/platform/*. You may not like some bits of it, but you still need to follow it. In doing so, you ensure that others can work with your code.
This guide may be ignored if you are working on code that is part of an open source project that already conforms to a different style i.e. generally Python code in src/third_party. Autotest is a great example of this--see the other notable python style guides below.
See also overall Chromium coding style.
The Google Python Style guide is the official python style guide for Chromium OS original code. Note that we deviate from that guide in two ways (in order to match the internal Google Python Style guide):
If that guide is silent on an issue, then you should fall back to PEP-8.
PEP-257 is referenced by PEP-8. If it isn't covered in the Comments section, you can also fall back to PEP-257.
There are a number of other python style guidelines out there.
PEP-257 says that "The docstring for a function or method should summarize its behavior and document its arguments, return value(s), side effects, exceptions raised, and restrictions. However, it doesn't specify any details of what this should look like.
Fortunately, the Google python style guide provides a reasonable syntax for arguments and return values. We will use that as our standard (adjusted to two-space indentation):
def FetchBigtableRows(big_table, keys, other_silly_variable=None): """Fetches rows from a Bigtable. Retrieves rows pertaining to the given keys from the Table instance represented by big_table. Silly things may happen if other_silly_variable is not None. Args: big_table: An open Bigtable Table instance. keys: A sequence of strings representing the key of each table row to fetch. other_silly_variable: Another optional variable, that has a much longer name than the other args, and which does nothing. Returns: A dict mapping keys to the corresponding table row data fetched. Each row is represented as a tuple of strings. For example: {'Serak': ('Rigel VII', 'Preparer'), 'Zim': ('Irk', 'Invader'), 'Lrrr': ('Omicron Persei 8', 'Emperor')} If a key from the keys argument is missing from the dictionary, then that row was not found in the table. Raises: IOError: An error occurred accessing the bigtable.Table object. """ pass
Specifically:
Args:
section, using the format above.Args:
, Returns:
, and Raises:
should be the last three things in the docstring, separated by a blank line each.The following rules apply to imports (in addition to rules already talked about in PEP-8):
from subprocess import Popen, PIPE
from __future__ import absolute_import
syntax should be used (see PEP-328).import *
. Always be explicit about what you are importing. Using import *
is useful for interactive python but shouldn't be used in checked in code.All files that are meant to be executed should start with the line:
#!/usr/bin/python2
If your system doesn't support that, it is sufficiently unusual for us to not worry about compatibility with it. Most likely it will break in other fun ways.
Note that files that are not meant to be executed should not contain a shebang line.
The Google style guide says that the ‘{}’.format() style is permitted. That is true, but in CrOS we much more often/always use % instead. You should stick to using % in CrOS code to match existing codebases.
x = 'name: %s; score: %d' % (name, n) x = 'name: %(name)s; score: %(score)d' % {'name': name, 'score': n}
Also keep in mind that for logging type functions, we don't format in place. Instead, we pass them as args to the function.
logging.info('name: %s; score: %d', name, n)
It is OK to leave TODOs in code. Why? Encouraging people to at least document parts of code that need to be thought out more (or that are confusing) is better than leaving this code undocumented. See also the Google style guide here.
All TODOs should be formatted like:
TODO(username): Revisit this code when the frob feature is done.
...where username
is your chromium.org username. If you don't have a chromium.org username, please use an email address.
Please do not use other forms of TODO (like TBD
, FIXME
, XXX
, etc). This makes TODOs much harder for someone to find in the code.
Python code written for Chromium OS should be “pylint clean”.
Pylint is a utility that analyzes python code to look for bugs and for style violations. We run it in Chromium OS because:
Pylint is notoriously picky and sometimes warns about things that are really OK. Because of this, we:
You can use cros lint
so that we can be sure everyone is on the same version. This should work outside and inside the chroot.
All python modules should have a corresponding unit test module called <original name>_unittest.py
in the same directory. We use a few related modules (they're available in the chroot as well):
import mock
) for testing mocksimport mox
) is the old mock frameworkimport unittest
) for unit test suites and methods for testingmain
method. Use if __name__ == 'main': main(sys.argv[1:])
to invoke (not on one line of course).argv[0]
, you should use sys.argv[0]
directly. If you're trying to print an error message, then usually you want to use argparse
(see below) and the parser.error()
helper instead.GFlags
or optparse
.