xref: /aosp_15_r20/external/autotest/docs/coding-style.md (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1*9c5db199SXin Li# Coding style for autotest in ChromeOS / Android / Brillo
2*9c5db199SXin LiThese rules elaborate on, but rarely deviate from PEP-8.  When in doubt, go
3*9c5db199SXin Liwith PEP-8.
4*9c5db199SXin Li
5*9c5db199SXin Li
6*9c5db199SXin Li## Language
7*9c5db199SXin Li * Use Python where possible
8*9c5db199SXin Li * Prefer writing more Python to a smaller amount of shell script in host
9*9c5db199SXin Li   commands.  In practice, the Python tends to be easier to maintain.
10*9c5db199SXin Li * Some tests use C/C++ in test dependencies, and this is also ok.
11*9c5db199SXin Li
12*9c5db199SXin Li
13*9c5db199SXin Li## Indentation & whitespace
14*9c5db199SXin Li
15*9c5db199SXin LiFormat your code for an 80 character wide screen.
16*9c5db199SXin Li
17*9c5db199SXin LiIndentation is 4 spaces, as opposed to hard tabs (which it used to be).
18*9c5db199SXin LiThis is the Python standard.
19*9c5db199SXin Li
20*9c5db199SXin LiFor hanging indentation, use 8 spaces plus all args should be on the new line.
21*9c5db199SXin Li
22*9c5db199SXin Li```
23*9c5db199SXin Li
24*9c5db199SXin Li     # Either of the following hanging indentation is considered acceptable.
25*9c5db199SXin LiYES: return 'class: %s, host: %s, args = %s' % (
26*9c5db199SXin Li             self.__class__.__name__, self.hostname, self.args)
27*9c5db199SXin Li
28*9c5db199SXin LiYES: return 'class: %s, host: %s, args = %s' % (
29*9c5db199SXin Li             self.__class__.__name__,
30*9c5db199SXin Li             self.hostname,
31*9c5db199SXin Li             self.args)
32*9c5db199SXin Li
33*9c5db199SXin Li     # Do not use 4 spaces for hanging indentation
34*9c5db199SXin LiNO:  return 'class: %s, host: %s, args = %s' % (
35*9c5db199SXin Li         self.__class__.__name__, self.hostname, self.args)
36*9c5db199SXin Li
37*9c5db199SXin Li     # Do put all args on new line
38*9c5db199SXin LiNO:  return 'class: %s, host: %s, args = %s' % (self.__class__.__name__,
39*9c5db199SXin Li             self.hostname, self.args)
40*9c5db199SXin Li```
41*9c5db199SXin Li
42*9c5db199SXin LiDon't leave trailing whitespace, or put whitespace on blank lines.
43*9c5db199SXin Li
44*9c5db199SXin Li
45*9c5db199SXin Li## Variable names and UpPeR cAsE
46*9c5db199SXin Li * Use descriptive variable names where possible
47*9c5db199SXin Li * Use `variable_names_like_this`
48*9c5db199SXin Li * Use `method_and_function_names_like_this`
49*9c5db199SXin Li * Use `UpperCamelCase` for class names
50*9c5db199SXin Li
51*9c5db199SXin Li
52*9c5db199SXin Li## Importing modules
53*9c5db199SXin Li
54*9c5db199SXin LiThe order of imports should be as follows:
55*9c5db199SXin Li
56*9c5db199SXin Li * Standard python modules
57*9c5db199SXin Li * Non-standard python modules
58*9c5db199SXin Li * Autotest modules
59*9c5db199SXin Li
60*9c5db199SXin LiWithin one of these three sections, all module imports using the from
61*9c5db199SXin Likeyword should appear after regular imports.
62*9c5db199SXin LiEach module should be imported on its own line.
63*9c5db199SXin LiDo not use Wildcard imports (`from x import *`) if possible.
64*9c5db199SXin Li
65*9c5db199SXin LiImport modules, not classes.  For example:
66*9c5db199SXin Li
67*9c5db199SXin Li```
68*9c5db199SXin Lifrom common_lib import error
69*9c5db199SXin Li
70*9c5db199SXin Lidef foo():
71*9c5db199SXin Li    raise error.AutoservError(...)
72*9c5db199SXin Li```
73*9c5db199SXin Li
74*9c5db199SXin Liand not:
75*9c5db199SXin Li
76*9c5db199SXin Li```
77*9c5db199SXin Lifrom common_lib.error import AutoservError
78*9c5db199SXin Li```
79*9c5db199SXin Li
80*9c5db199SXin LiFor example:
81*9c5db199SXin Li
82*9c5db199SXin Li```
83*9c5db199SXin Liimport os
84*9c5db199SXin Liimport pickle
85*9c5db199SXin Liimport random
86*9c5db199SXin Liimport re
87*9c5db199SXin Liimport select
88*9c5db199SXin Liimport shutil
89*9c5db199SXin Liimport signal
90*9c5db199SXin Liimport subprocess
91*9c5db199SXin Li
92*9c5db199SXin Liimport common   # Magic autotest_lib module and sys.path setup code.
93*9c5db199SXin Liimport MySQLdb  # After common so that we check our site-packages first.
94*9c5db199SXin Li
95*9c5db199SXin Lifrom common_lib import error
96*9c5db199SXin Li```
97*9c5db199SXin Li
98*9c5db199SXin Li### Automatically reorder imports
99*9c5db199SXin Li
100*9c5db199SXin LiTo sort the imports on a list of files:
101*9c5db199SXin Li
102*9c5db199SXin Li`isort -o common -t common -sl FILENAMES`
103*9c5db199SXin Li
104*9c5db199SXin LiOr all the files in the current commit:
105*9c5db199SXin Li
106*9c5db199SXin Li`isort -o common -t common -sl $(git diff --name-only HEAD^ HEAD)`
107*9c5db199SXin Li
108*9c5db199SXin LiOr all the unstaged files:
109*9c5db199SXin Li
110*9c5db199SXin Li`isort -o common -t common -sl $(git diff --name-only)`
111*9c5db199SXin Li
112*9c5db199SXin Li## Testing None
113*9c5db199SXin Li
114*9c5db199SXin LiUse `is None` rather than `== None` and `is not None` rather than `!= None`.
115*9c5db199SXin LiThis way you'll never run into a case where someone's `__eq__` or `__ne__`
116*9c5db199SXin Limethod does the wrong thing.
117*9c5db199SXin Li
118*9c5db199SXin Li
119*9c5db199SXin Li## Comments
120*9c5db199SXin Li
121*9c5db199SXin LiGenerally, you want your comments to tell WHAT your code does, not HOW.
122*9c5db199SXin LiWe can figure out how from the code itself (or if not, your code needs fixing).
123*9c5db199SXin Li
124*9c5db199SXin LiTry to describle the intent of a function and what it does in a triple-quoted
125*9c5db199SXin Li(multiline) string just after the def line. We've tried to do that in most
126*9c5db199SXin Liplaces, though undoubtedly we're not perfect. A high level overview is
127*9c5db199SXin Liincredibly helpful in understanding code.
128*9c5db199SXin Li
129*9c5db199SXin Li
130*9c5db199SXin Li## Hardcoded String Formatting
131*9c5db199SXin Li
132*9c5db199SXin LiStrings should use only single quotes for hardcoded strings in the code.
133*9c5db199SXin LiDouble quotes are acceptable when single quote is used as part of the string.
134*9c5db199SXin LiMultiline strings should not use '\' but wrap the string using parentheseses.
135*9c5db199SXin Li
136*9c5db199SXin Li```
137*9c5db199SXin LiREALLY_LONG_STRING = ('This is supposed to be a really long string that is '
138*9c5db199SXin Li                      'over 80 characters and does not use a slash to '
139*9c5db199SXin Li                      'continue.')
140*9c5db199SXin Li```
141*9c5db199SXin Li
142*9c5db199SXin Li## Docstrings
143*9c5db199SXin Li
144*9c5db199SXin LiDocstrings are important to keep our code self documenting. While it's not
145*9c5db199SXin Linecessary to overdo documentation, we ask you to be sensible and document any
146*9c5db199SXin Linontrivial function. When creating docstrings, please add a newline at the
147*9c5db199SXin Libeginning of your triple quoted string and another newline at the end of it. If
148*9c5db199SXin Lithe docstring has multiple lines, please include a short summary line followed
149*9c5db199SXin Liby a blank line before continuing with the rest of the description. Please
150*9c5db199SXin Licapitalize and punctuate accordingly the sentences. If the description has
151*9c5db199SXin Limultiple lines, put two levels of indentation before proceeding with text. An
152*9c5db199SXin Liexample docstring:
153*9c5db199SXin Li
154*9c5db199SXin Li```python
155*9c5db199SXin Lidef foo(param1, param2):
156*9c5db199SXin Li    """
157*9c5db199SXin Li    Summary line.
158*9c5db199SXin Li
159*9c5db199SXin Li    Long description of method foo.
160*9c5db199SXin Li
161*9c5db199SXin Li    @param param1: A Spam object that has methods bar() and baz()
162*9c5db199SXin Li            which raise SpamError if something goes awry.
163*9c5db199SXin Li    @type param1: Spam
164*9c5db199SXin Li
165*9c5db199SXin Li    @return: a list of integers describing changes in a source tree
166*9c5db199SXin Li    @rtype: list
167*9c5db199SXin Li
168*9c5db199SXin Li    @raise SpamError: when some stated condition occurs.
169*9c5db199SXin Li
170*9c5db199SXin Li    """
171*9c5db199SXin Li```
172*9c5db199SXin Li
173*9c5db199SXin LiThe tags that you can put inside your docstring are tags recognized by systems
174*9c5db199SXin Lilike epydoc. Not all places need all tags defined, so choose them wisely while
175*9c5db199SXin Liwriting code. Generally always list any parameters, the return value (if there
176*9c5db199SXin Liis one), and exceptions that can be raised.
177*9c5db199SXin Li
178*9c5db199SXin Li|   Tag    | Description
179*9c5db199SXin Li|----------|-------------------------------------------------------------------
180*9c5db199SXin Li| @author  | Code author
181*9c5db199SXin Li| @cvar    | Class variable (defined on `self.__class__.`)
182*9c5db199SXin Li| @ivar    | Instance variable for a class (defined on `self.`)
183*9c5db199SXin Li| @param   | Parameter description
184*9c5db199SXin Li| @raise   | Exception type the function can throw, and the conditions for it
185*9c5db199SXin Li| @return  | Return value description
186*9c5db199SXin Li| @rtype   | The type the method returns
187*9c5db199SXin Li| @see     | Reference to other parts of the codebase
188*9c5db199SXin Li| @type    | The type of a given parameter or variable
189*9c5db199SXin Li| @warning | Call attention to potential problems with the code
190*9c5db199SXin Li| @version | Version string
191*9c5db199SXin Li
192*9c5db199SXin LiFor additional information and fields, refer to the epydoc manual:
193*9c5db199SXin Lihttp://epydoc.sourceforge.net/manual-fields.html
194*9c5db199SXin Li
195*9c5db199SXin Li## Simple code
196*9c5db199SXin Li
197*9c5db199SXin LiKeep it simple; this is not the right place to show how smart you are. We
198*9c5db199SXin Lihave plenty of system failures to deal with without having to spend ages
199*9c5db199SXin Lifiguring out your code, thanks ;-) Readbility, readability, readability.
200*9c5db199SXin LiStrongly prefer readability and simplicity over compactness.
201*9c5db199SXin Li
202*9c5db199SXin Li"Debugging is twice as hard as writing the code in the first place. Therefore,
203*9c5db199SXin Liif you write the code as cleverly as possible, you are, by definition, not
204*9c5db199SXin Lismart enough to debug it."  Brian Kernighan
205*9c5db199SXin Li
206*9c5db199SXin Li
207*9c5db199SXin Li## Function length
208*9c5db199SXin Li
209*9c5db199SXin LiPlease keep functions short, under 30 lines or so if possible. Even though
210*9c5db199SXin Liyou are amazingly clever, and can cope with it, the rest of us are busy and
211*9c5db199SXin Listupid, so be nice and help us out. To quote the Linux Kernel coding style:
212*9c5db199SXin Li
213*9c5db199SXin LiFunctions should be short and sweet, and do just one thing.  They should
214*9c5db199SXin Lifit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24,
215*9c5db199SXin Lias we all know), and do one thing and do that well.
216*9c5db199SXin Li
217*9c5db199SXin Li
218*9c5db199SXin Li## Exceptions
219*9c5db199SXin Li
220*9c5db199SXin LiWhen raising exceptions, the preferred syntax for it is:
221*9c5db199SXin Li
222*9c5db199SXin Li```
223*9c5db199SXin Liraise FooException('Exception Message')
224*9c5db199SXin Li```
225*9c5db199SXin Li
226*9c5db199SXin LiPlease don't raise string exceptions, as they're deprecated and will be removed
227*9c5db199SXin Lifrom future versions of python. If you're in doubt about what type of exception
228*9c5db199SXin Liyou will raise, please look at http://docs.python.org/lib/module-exceptions.html
229*9c5db199SXin Liand client/common\_lib/error.py, the former is a list of python built in
230*9c5db199SXin Liexceptions and the later is a list of autotest/autoserv internal exceptions. Of
231*9c5db199SXin Licourse, if you really need to, you can extend the exception definitions on
232*9c5db199SXin Liclient/common\_lib/error.py.
233*9c5db199SXin Li
234*9c5db199SXin Li
235*9c5db199SXin Li## Submitting patches
236*9c5db199SXin Li
237*9c5db199SXin LiSubmit changes through the ChromeOS gerrit instance.  This process is
238*9c5db199SXin Lidocumented on
239*9c5db199SXin Li[chromium.org](http://dev.chromium.org/developers/contributing-code).
240