DEVELOPING: add "Python Version" section
[portage.git] / DEVELOPING
1 Code Guidelines
2 ---------------
3 A few code guidelines to try to stick to, please comment if none of these make
4 sense, they are pretty basic and mostly apply to old code.  However for people
5 who are looking at current code, they make take up bad habits that exist in the
6 current codebase.
7
8 Python Version
9 --------------
10
11 Python 2.6 is the minimum supported version, since it is the first version to
12 support Python 3 syntax. All exception handling should use Python 3 'except'
13 syntax, and the print function should be used instead of Python 2's print
14 statement (from __future__ import print_function).
15
16 Tabs
17 ----
18
19 The current code uses tabs, not spaces.  Keep whitespace usage consistent
20 between files.  New files should use tabs.
21
22 Line-Wrapping
23 -------------
24
25 Lines should typically not be longer than 80 characters; if they are an attempt
26 should be made to wrap them.  Move code to the line below and indent once (\t).
27
28 errors.append(MalformedMetadata(
29         errors.DESCRIPTION_TOO_LONG_ERROR % \
30         (length, max_desc_len),
31         attr='DESCRIPTION.toolong')
32
33 Do not do this:
34
35 errors.append(MalformedMetadata(
36               errors.DESCRIPTION_TOO_LONG_ERROR % \
37               (length, max_desc_len),
38               attr='DESCRIPTION.toolong')
39
40 The mixing of tabs and spaces means other developers can't read what you did.
41 This is why the python peps state spaces over tabs; because with spaces the line
42 wrapping is always clear (but you cannot convert spaces as easily as tabwidth).
43
44 Comparisons
45 -----------
46
47 if foo == None
48
49 should be replaced with:
50
51 if foo is not None:
52
53 Is not does a reference comparison (address1 = address2 basically) and 
54 the == forces a by value compare (with __eq__())
55
56 Dict Lookups
57 ------------
58
59 Try not to use has_key, you can use
60
61 if foo in dict
62
63 instead of if dict.has_key(foo)
64
65 Also don't do stuff like:
66
67 if foo in dict and dict[foo]:
68
69 Generally you can do two things here, if you are messing with defaults..
70
71 dict.get(foo, some_default)
72
73 will try to retrieve foo from dict, if there is a KeyError, will insert foo
74 into dict with the value of some_default.  This method is preferred in cases where
75 you are messing with defaults:
76
77 try:
78         dict[foo]
79 except KeyError:
80         dict[foo] = default_value
81
82 The get call is nicer (compact) and faster (try,except are slow).
83
84 Exceptions
85 ----------
86
87 Don't use the format raise Exception, "string"
88 It will be removed in py3k.
89
90 YES:
91   raise KeyError("No key")
92
93 NO:
94   raise KeyError, "No key"
95
96 Imports
97 -------
98
99 Import things one per line
100
101 YES:
102   import os
103   import time
104   import sys
105
106 NO:
107   import os,sys,time
108
109 When importing from a module, you may import more than 1 thing at a time.
110
111 YES:
112   from portage.module import foo, bar, baz
113
114 Multiline imports are ok (for now :))
115
116 Try to group system and package imports separately.
117
118 YES:
119   import os
120   import sys
121   import time
122
123   from portage.locks import lockfile
124   from portage.versions import vercmp
125
126 NO:
127   import os
128   import portage
129   import portage.util
130   import time
131   import sys
132
133 Try not to import large numbers of things into the namespace of a module.
134 I realize this is done all over the place in current code but it really makes it
135 a pain to do code reflection when the namespace is cluttered with identifiers 
136 from other modules.
137
138 YES:
139
140 from portage import output
141
142 NO:
143
144 from portage.output import bold, create_color_func, darkgreen, \
145   green, nocolor, red, turquoise, yellow
146
147 The YES example imports the 'output' module into the current namespace.
148 The negative here is having to use output.COLOR all over the place instead of
149 just COLOR.  However it means during introspection of the current namespace
150 'green','red', 'yellow', etc. will not show up.
151
152 The NO example just imports a set of functions from the output module.  It is
153 somewhat annoying because the import line needs to be modified when functions
154 are needed and often unused functions are left in the import line until someone
155 comes along with a linter to clean up (does not happen often).  The color is a
156 bit clearer as
157
158   print red('blar')
159
160 is shorter than:
161
162   print output.red('blar')
163
164 Rationale: python -c 'import portage; dir(portage)' (circa 02/2008)