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