Browse code

Add the start of a coding guidelines document.

Michael DeHaan authored on 2014/01/27 06:42:21
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,247 @@
0
+Coding Guidelines
1
+=================
2
+
3
+Hi!  Thanks for interest in contributing to Ansible.
4
+
5
+Here are some guidelines for contributing code.  The purpose of this document are to establish what we're looking for in code contributions, and to make sure
6
+new contributions know some of the conventions that we've been using.
7
+
8
+We don't think much of this should be too strange to readers familar with contributing to Python projects, though it helps if we all get on the same page.
9
+
10
+Language
11
+========
12
+
13
+  * While not all components of Ansible must be in Python, core contributions to the Ansible repo must be written in Python.  This is to maximize the ability of everyone to contribute.
14
+  * If you want to write non-Python ansible modules or inventory scripts, that's fine, but they are not going to get merged in most likely.  Sorry!!  
15
+
16
+PEP8 and basic style checks
17
+===========================
18
+
19
+  * PEP8 is a great Python style guide, which you should read.
20
+  * PEP8 must not be strictly followed in all aspects, but most of it is good advice
21
+  * In particular, we don't really care about line lengths.  Buy a bigger monitor!
22
+  * To run checks for things we care about, run "make pep8"
23
+  * Similarly, additional checks can be made with "make pyflakes"
24
+  * There is no need to submit code changes for pep8 and pyflake fixes, as these break attribution history.  Project leadership will make these periodically.
25
+  * Do not submit pull requests that simply adjust whitespace in the code
26
+
27
+Whitespace
28
+==========
29
+
30
+  * Four space indent is strictly required
31
+  * Include meaningful whitespace between lines of code
32
+
33
+Shebang Lines
34
+=============
35
+ 
36
+  * /usr/bin/scripts should start with '/usr/bin/env python'
37
+  * module code should still use '/usr/bin/python' as this is replaced automatically by 'ansible_python_interpeter', see the FAQ in the docs for more info.
38
+
39
+Comments
40
+========
41
+
42
+  * Readability is one of the most important goals for this project
43
+  * Comment any non-trivial code where someone might not know why you are doing something in a particular way
44
+  * Though if something should be commented, that's often a sign someone should write a function
45
+  * All new functions must have a basic docstring comment
46
+  * Commenting above a line is preferable to commenting at the end of a line
47
+
48
+Classes
49
+=======
50
+
51
+  * With the exception of module code (where inline is better), it is deseriable to see classes in their own files.
52
+  * Classes should generally not cause side effects as soon as they are instantiated, move meaningful behavior to methods rather than constructors.
53
+ 
54
+Functions and Methods
55
+=====================
56
+
57
+  * In general, functions should not be 'too long' and should describe a meaningful amount of work
58
+  * When code gets too nested, that's usually the sign the loop body could benefit from being a function
59
+  * Functions should have names that describe what they do, along with docstrings
60
+  * Functions should be named with_underscores
61
+
62
+Variables
63
+=========
64
+
65
+  * Use descriptive variable names instead of variables like 'x', unless x is a obvious loop index
66
+  * Ansible python code uses identifiers like 'ClassesLikeThis and variables_like_this
67
+  * Module parameters should also use_underscores and not runtogether
68
+
69
+Misc Preferences
70
+================
71
+
72
+Use the dict constructor where possible when allocating dictionaries:
73
+
74
+    # not this:
75
+    foo = {
76
+       'a' : 12,
77
+       'b' : 34
78
+    }
79
+
80
+    # this:
81
+    foo = dict(
82
+       a = 12,
83
+       b = 34
84
+    )
85
+
86
+Line up variables
87
+
88
+    # not this
89
+    a  = 12
90
+    foosball = 34
91
+    xyz = 'dog'
92
+
93
+    # this
94
+    a        = 12
95
+    foosball = 34
96
+    xyz      = 'dog'
97
+
98
+Don't use line continuations:
99
+
100
+    # no
101
+    if (this_is_a_very_long_line and foo and /
102
+       i_am_going_to_continue_it):
103
+          bar()
104
+
105
+    # better:
106
+    if (this_is_a_very_long_line and foo and i_am_going_to_continue_it):
107
+       bar()
108
+
109
+Spacing:
110
+
111
+    # no
112
+    x=[1,2,3]
113
+
114
+    # no
115
+    x = [1,2,3]
116
+
117
+    # yes
118
+    x = [ 1, 2, 3 ]
119
+
120
+Spacing continued:
121
+
122
+    # no
123
+    x=foo(12)
124
+
125
+    # no
126
+    x = foo( 12 )
127
+
128
+    # yes
129
+    x = foo(12)
130
+
131
+Licenses
132
+========
133
+
134
+Every file should have a license header, including the copyright of the original author.  Major additions to the module are allowed
135
+to add an additional copyright line, and this is especially true of rewrites, but original authorship copyright messages should be preserved.
136
+
137
+All contributions to the core repo should preserve original licenses and new contributions must include the GPLv3 header.
138
+
139
+Module Documentation
140
+====================
141
+
142
+All module pull requests must include a DOCUMENTATION docstring (YAML format, see other modules for examples) as well as an EXAMPLES docstring, which
143
+is free form.  
144
+
145
+When adding new modules, any new parameter must have a "version_added" attribute.  When submitting a new module, the module should have a "version_added"
146
+attribute in the pull request as well, set to the current development version.
147
+
148
+Be sure to check grammar and spelling.
149
+
150
+It's frequently the case that modules get submitted with YAML that isn't valid, so you can run "make webdocs" from the checkout to preview your module's documentation.
151
+If it fails to build, take a look at your DOCUMENTATION string or you might have a Python syntax error in there too.
152
+
153
+Python Imports
154
+==============
155
+
156
+To make it clear what a module is importing, imports should not be sprinkled throughout the code. 
157
+
158
+Python Imports should happen at the top of the file, exempting code from module_utils.
159
+
160
+When a conditional runtime import is required, do so something like this instead:
161
+
162
+   HAS_FOO = False
163
+   try:
164
+      import foo
165
+      HAS_FOO = True
166
+   except ImportError:
167
+      pass
168
+
169
+   ...
170
+
171
+   if not HAS_FOO:
172
+      raise Exception("the foo library is required")
173
+
174
+This makes it clear what optional dependencies are but allows this to be deferred until runtime.   In the case of module code, the raising of the Exception will be replaced
175
+with a "module.exit_json" call.
176
+
177
+Exceptions
178
+==========
179
+
180
+In the main body of the code, use typed exceptions where possible:
181
+
182
+   raise errors.AnsibleError("panic!")
183
+
184
+versus:
185
+
186
+   raise Exception("panic!")
187
+
188
+Similarly, exception checking should be fine grained:
189
+
190
+   # not this
191
+   try:
192
+      foo()
193
+   except:
194
+      bar()
195
+
196
+   # but this
197
+   try:
198
+      foo()
199
+   except SomeTypedException
200
+      bar()
201
+
202
+List Comprehensions
203
+===================
204
+
205
+In general list comprehensions are always preferred to map() and filter() calls.
206
+
207
+However, they can be abused.  Optimize for readability, and avoid nesting them
208
+
209
+Cleverness
210
+==========
211
+
212
+Ansible's code is intended to be read by as many people as possible, so we don't particularly encourage clever or heavily idiomatic code.
213
+
214
+In particular, metaclasses are probably not appropriate, however entertaining they may be to add.
215
+
216
+Git Practices
217
+=============
218
+
219
+Pull requests cannot be accepted that contain merge commits.
220
+
221
+Always do "git pull --rebase" and "git rebase" vs "git pull" or "git merge".
222
+
223
+Always create a new branch for each pull request to avoid intertwingling different features or fixes on the same branch.
224
+
225
+   
226
+Python Version Compliance
227
+=========================
228
+
229
+All code in Ansible core must support a minimum version of Python 2.6.
230
+
231
+Module code must support a minimum of Python 2.4, with occasional exception for modules that require code that themselves require 2.6 and later.
232
+
233
+A quick reminder is that list comprehensions in Python 2.4 are not as fully fleshed out, there are not 'dict' comprehensions, and there is no 'with' statement.
234
+But otherwise it's pretty much all the same.
235
+
236
+The End
237
+=======
238
+
239
+This was not meant to be a scary document, so we hope it wasn't, but we also hope this helps you write code that is easier to maintain by others in the future.
240
+If you have questions about this document, please ask on the ansible-devel mailing list.
241
+
242
+Thank you!
243
+
244
+
245
+
246
+