# Coding style for autotest in Chrome OS / Android / Brillo
These rules elaborate on, but rarely deviate from PEP-8.  When in doubt, go
with PEP-8.


## Language
 * Use Python where possible
 * Prefer writing more Python to a smaller amount of shell script in host
   commands.  In practice, the Python tends to be easier to maintain.
 * Some tests use C/C++ in test dependencies, and this is also ok.


## Indentation & whitespace

Format your code for an 80 character wide screen.

Indentation is 4 spaces, as opposed to hard tabs (which it used to be).
This is the Python standard.

For hanging indentation, use 8 spaces plus all args should be on the new line.

```

     # Either of the following hanging indentation is considered acceptable.
YES: return 'class: %s, host: %s, args = %s' % (
             self.__class__.__name__, self.hostname, self.args)

YES: return 'class: %s, host: %s, args = %s' % (
             self.__class__.__name__,
             self.hostname,
             self.args)

     # Do not use 4 spaces for hanging indentation
NO:  return 'class: %s, host: %s, args = %s' % (
         self.__class__.__name__, self.hostname, self.args)

     # Do put all args on new line
NO:  return 'class: %s, host: %s, args = %s' % (self.__class__.__name__,
             self.hostname, self.args)
```

Don't leave trailing whitespace, or put whitespace on blank lines.


## Variable names and UpPeR cAsE
 * Use descriptive variable names where possible
 * Use `variable_names_like_this`
 * Use `method_and_function_names_like_this`
 * Use `UpperCamelCase` for class names


## Importing modules

The order of imports should be as follows:

 * Standard python modules
 * Non-standard python modules
 * Autotest modules

Within one of these three sections, all module imports using the from
keyword should appear after regular imports.
Each module should be imported on its own line.
Do not use Wildcard imports (`from x import *`) if possible.

Import modules, not classes.  For example:

```
from common_lib import error

def foo():
    raise error.AutoservError(...)
```

and not:

```
from common_lib.error import AutoservError
```

For example:

```
import os
import pickle
import random
import re
import select
import shutil
import signal
import subprocess

import common   # Magic autotest_lib module and sys.path setup code.
import MySQLdb  # After common so that we check our site-packages first.

from common_lib import error
```

### Automatically reorder imports

To sort the imports on a list of files:

`isort -o common -t common -sl FILENAMES`

Or all the files in the current commit:

`isort -o common -t common -sl $(git diff --name-only HEAD^ HEAD)`

Or all the unstaged files:

`isort -o common -t common -sl $(git diff --name-only)`

## Testing None

Use `is None` rather than `== None` and `is not None` rather than `!= None`.
This way you'll never run into a case where someone's `__eq__` or `__ne__`
method does the wrong thing.


## Comments

Generally, you want your comments to tell WHAT your code does, not HOW.
We can figure out how from the code itself (or if not, your code needs fixing).

Try to describle the intent of a function and what it does in a triple-quoted
(multiline) string just after the def line. We've tried to do that in most
places, though undoubtedly we're not perfect. A high level overview is
incredibly helpful in understanding code.


## Hardcoded String Formatting

Strings should use only single quotes for hardcoded strings in the code.
Double quotes are acceptable when single quote is used as part of the string.
Multiline strings should not use '\' but wrap the string using parentheseses.

```
REALLY_LONG_STRING = ('This is supposed to be a really long string that is '
                      'over 80 characters and does not use a slash to '
                      'continue.')
```

## Docstrings

Docstrings are important to keep our code self documenting. While it's not
necessary to overdo documentation, we ask you to be sensible and document any
nontrivial function. When creating docstrings, please add a newline at the
beginning of your triple quoted string and another newline at the end of it. If
the docstring has multiple lines, please include a short summary line followed
by a blank line before continuing with the rest of the description. Please
capitalize and punctuate accordingly the sentences. If the description has
multiple lines, put two levels of indentation before proceeding with text. An
example docstring:

```python
def foo(param1, param2):
    """
    Summary line.

    Long description of method foo.

    @param param1: A Spam object that has methods bar() and baz()
            which raise SpamError if something goes awry.
    @type param1: Spam

    @return: a list of integers describing changes in a source tree
    @rtype: list

    @raise SpamError: when some stated condition occurs.

    """
```

The tags that you can put inside your docstring are tags recognized by systems
like epydoc. Not all places need all tags defined, so choose them wisely while
writing code. Generally always list any parameters, the return value (if there
is one), and exceptions that can be raised.

|   Tag    | Description
|----------|-------------------------------------------------------------------
| @author  | Code author
| @cvar    | Class variable (defined on `self.__class__.`)
| @ivar    | Instance variable for a class (defined on `self.`)
| @param   | Parameter description
| @raise   | Exception type the function can throw, and the conditions for it
| @return  | Return value description
| @rtype   | The type the method returns
| @see     | Reference to other parts of the codebase
| @type    | The type of a given parameter or variable
| @warning | Call attention to potential problems with the code
| @version | Version string

For additional information and fields, refer to the epydoc manual:
http://epydoc.sourceforge.net/manual-fields.html

## Simple code

Keep it simple; this is not the right place to show how smart you are. We
have plenty of system failures to deal with without having to spend ages
figuring out your code, thanks ;-) Readbility, readability, readability.
Strongly prefer readability and simplicity over compactness.

"Debugging is twice as hard as writing the code in the first place. Therefore,
if you write the code as cleverly as possible, you are, by definition, not
smart enough to debug it."  Brian Kernighan


## Function length

Please keep functions short, under 30 lines or so if possible. Even though
you are amazingly clever, and can cope with it, the rest of us are busy and
stupid, so be nice and help us out. To quote the Linux Kernel coding style:

Functions should be short and sweet, and do just one thing.  They should
fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24,
as we all know), and do one thing and do that well.


## Exceptions

When raising exceptions, the preferred syntax for it is:

```
raise FooException('Exception Message')
```

Please don't raise string exceptions, as they're deprecated and will be removed
from future versions of python. If you're in doubt about what type of exception
you will raise, please look at http://docs.python.org/lib/module-exceptions.html
and client/common\_lib/error.py, the former is a list of python built in
exceptions and the later is a list of autotest/autoserv internal exceptions. Of
course, if you really need to, you can extend the exception definitions on
client/common\_lib/error.py.


## Submitting patches

Submit changes through the Chrome OS gerrit instance.  This process is
documented on
[chromium.org](http://dev.chromium.org/developers/contributing-code).
