| Code Guidelines |
| --------------- |
| A few code guidelines to try to stick to, please comment if none of these make |
| sense, they are pretty basic and mostly apply to old code. However for people |
| who are looking at current code, they make take up bad habits that exist in the |
| current codebase. |
| |
| Python Version |
| -------------- |
| |
| Python 2.6 is the minimum supported version, since it is the first version to |
| support Python 3 syntax. All exception handling should use Python 3 'except' |
| syntax, and the print function should be used instead of Python 2's print |
| statement (from __future__ import print_function). |
| |
| Dependencies |
| ------------ |
| |
| Python and Bash should be the only hard dependencies. Any other dependencies, |
| including external Python modules that are not included with Python itself, |
| must be optionally enabled by run-time detection. |
| |
| Tabs |
| ---- |
| |
| The current code uses tabs, not spaces. Keep whitespace usage consistent |
| between files. New files should use tabs. |
| |
| Line-Wrapping |
| ------------- |
| |
| Lines should typically not be longer than 80 characters; if they are an attempt |
| should be made to wrap them. Move code to the line below and indent once (\t). |
| |
| errors.append(MalformedMetadata( |
| errors.DESCRIPTION_TOO_LONG_ERROR % \ |
| (length, max_desc_len), |
| attr='DESCRIPTION.toolong') |
| |
| Do not do this: |
| |
| errors.append(MalformedMetadata( |
| errors.DESCRIPTION_TOO_LONG_ERROR % \ |
| (length, max_desc_len), |
| attr='DESCRIPTION.toolong') |
| |
| The mixing of tabs and spaces means other developers can't read what you did. |
| This is why the python peps state spaces over tabs; because with spaces the line |
| wrapping is always clear (but you cannot convert spaces as easily as tabwidth). |
| |
| Comparisons |
| ----------- |
| |
| if foo != None |
| |
| should be replaced with: |
| |
| if foo is not None: |
| |
| Is not does a reference comparison (address1 = address2 basically) and |
| the == forces a by value compare (with __eq__()) |
| |
| Dict Lookups |
| ------------ |
| |
| Try not to use has_key, you can use |
| |
| if foo in dict |
| |
| instead of if dict.has_key(foo) |
| |
| Also don't do stuff like: |
| |
| if foo in dict and dict[foo]: |
| |
| Generally you can do two things here, if you are messing with defaults.. |
| |
| dict.get(foo, some_default) |
| |
| will try to retrieve foo from dict, if there is a KeyError, will insert foo |
| into dict with the value of some_default. This method is preferred in cases where |
| you are messing with defaults: |
| |
| try: |
| dict[foo] |
| except KeyError: |
| dict[foo] = default_value |
| |
| The get call is nicer (compact) and faster (try,except are slow). |
| |
| Exceptions |
| ---------- |
| |
| Don't use the format raise Exception, "string" |
| It will be removed in py3k. |
| |
| YES: |
| raise KeyError("No key") |
| |
| NO: |
| raise KeyError, "No key" |
| |
| Imports |
| ------- |
| |
| Import things one per line |
| |
| YES: |
| import os |
| import time |
| import sys |
| |
| NO: |
| import os,sys,time |
| |
| When importing from a module, you may import more than 1 thing at a time. |
| |
| YES: |
| from portage.module import foo, bar, baz |
| |
| Multiline imports are ok (for now :)) |
| |
| Try to group system and package imports separately. |
| |
| YES: |
| import os |
| import sys |
| import time |
| |
| from portage.locks import lockfile |
| from portage.versions import vercmp |
| |
| NO: |
| import os |
| import portage |
| import portage.util |
| import time |
| import sys |
| |
| Try not to import large numbers of things into the namespace of a module. |
| I realize this is done all over the place in current code but it really makes it |
| a pain to do code reflection when the namespace is cluttered with identifiers |
| from other modules. |
| |
| YES: |
| |
| from portage import output |
| |
| NO: |
| |
| from portage.output import bold, create_color_func, darkgreen, \ |
| green, nocolor, red, turquoise, yellow |
| |
| The YES example imports the 'output' module into the current namespace. |
| The negative here is having to use output.COLOR all over the place instead of |
| just COLOR. However it means during introspection of the current namespace |
| 'green','red', 'yellow', etc. will not show up. |
| |
| The NO example just imports a set of functions from the output module. It is |
| somewhat annoying because the import line needs to be modified when functions |
| are needed and often unused functions are left in the import line until someone |
| comes along with a linter to clean up (does not happen often). |