# HG changeset patch # User Olivier Delalleau # Date 1284739514 14400 # Node ID 531e77fb67f23f5095efc0bb470bb868ba6cd9ca # Parent f2105a06201c7a6973386c5084d679db5009f094 coding_style: Moved more elements to official 'API' diff -r f2105a06201c -r 531e77fb67f2 doc/v2_planning/API_coding_style.txt --- a/doc/v2_planning/API_coding_style.txt Fri Sep 17 11:21:15 2010 -0400 +++ b/doc/v2_planning/API_coding_style.txt Fri Sep 17 12:05:14 2010 -0400 @@ -63,14 +63,35 @@ We emphasize here a few important topics that are found in the official guidelines: + * Only use ASCII characters in code files. + + * Code indent must be done with four blank characters (no tabs). + + * Limit lines to 79 characters. + + * Naming conventions: ``ClassName``, ``TOP_LEVEL_CONSTANT``, + ``everything_else``. + + * Comments should start with a capital letter (unless the first word is a + code identifier) and end with a period (short inline comments may skip + the period at the end). + + * Imports should be listed in alphabetical order. It makes it easier to + verify that something is imported, and avoids duplicated imports. + + * Use absolute imports only. This is compatible across a wider range of + Python versions, and avoids confusion about what is being + imported. + * Avoid using lists if all you care about is iterating on something. Using lists: - - uses more memory (and possibly more CPU if the code may break out of - the iteration), - - can lead to ugly code when converted to Python 3 with 2to3, - - can have a different behavior if evaluating elements in the list has - side effects (if you want these side effects, make it explicit by - assigning the list to some variable before iterating on it). + + - uses more memory (and possibly more CPU if the code may break out of + the iteration), + - can lead to ugly code when converted to Python 3 with 2to3, + - can have a different behavior if evaluating elements in the list has + side effects (if you want these side effects, make it explicit by + assigning the list to some variable before iterating on it). +------------------------+------------------------+ | Iterative version | List version | @@ -100,7 +121,7 @@ for f_x in imap(f, x): ... all_f_x = map(f, x) - map(f, x) + map(f, x) # f has some side effect. # Bad. for element in map(f, x): ... @@ -132,12 +153,89 @@ has_key = my_dict.has_key(key) has_substring = my_string.find(substring) >= 0 + * Do not use mutable arguments as default values. Instead, use a helper + function (conditional expressions are forbidden at this point, see + below). + + .. code-block:: python + + # Good. + def f(array=None): + array = pylearn.if_none(array, []) + ... + # Bad. + def f(array=[]): # Dangerous if `array` is modified down the road. + ... + + * Use a leading underscore '_' in names of internal attributes / methods, + but avoid the double underscore '__' unless you know what you are + doing. + Additional Recommendations -------------------------- Things you should do even if they are not listed in official guidelines: + * No conditional expression (not supported in Python 2.4). These are + expressions of the form ``x = y if condition else z``. + + * Use ``//`` for integer division and ``/ float(...)`` if you want the + floating point operation (for readability and compatibility across all + versions of Python). + + .. code-block:: python + + # Good. + n_samples_per_split = n_samples // n_splits + mean_x = sum(x) / float(len(x)) + # Bad. + n_samples_per_split = n_samples / n_splits + mean_x = sum(x) / len(x) + + * Always raise an exception with ``raise MyException(args)`` where ``MyException`` + inherits from ``Exception``. This is required for compatibility across + all versions of Python. + + .. code-block:: python + + # Good. + raise NotImplementedError('The Pylearn team is too lazy.') + # Bad. + raise NotImplementedError, 'The Pylearn team is too lazy.' + raise 'The Pylearn team is too lazy to implement this.' + + * Use either ``try ... except`` or ``try ... finally``, but do not mix + ``except`` with ``finally`` (which is not supported in Python 2.4). + You can however embed one into the other to mimic the ``try ... except ... + finally`` behavior. + + .. code-block:: python + + # Good. + try: + try: + something_that_may_fail() + except SomeError: + do_something_if_it_failed() + finally: + always_do_this_regardless_of_what_happened() + # Bad. + try: + something_that_may_fail() + except SomeError: + do_something_if_it_failed() + finally: + always_do_this_regardless_of_what_happened() + + * Do not use the ``all`` and ``any`` builtin functions (they are not supported + in Python 2.4). Instead, import them from ``theano.gof.python25`` (or + use ``numpy.all`` / ``numpy.any`` for array data). + + * Do not use the ``hashlib`` module (not supported in Python 2.4). We will + probably provide a wrapper around it to be compatible with all Python + versions. + * Avoid backslashes whenever possible. They make it more difficult to edit code, and they are ugly (as well as potentially dangerous if there are trailing white spaces). @@ -193,6 +291,50 @@ my_everything]: ... + * Use the ``key`` argument instead of ``cmp`` when sorting (for Python 3 + compatibility). + + .. code-block:: python + + # Good. + my_list.sort(key=abs) + # Bad. + my_list.sort(cmp=lambda x, y: cmp(abs(x), abs(y))) + + * Whenever you read / write binary files, specify it in the mode ('rb' for + reading, 'wb' for writing). This is important for cross-platform and + Python 3 compatibility (e.g. when pickling / unpickling objects). + + .. code-block:: python + + # Good. + cPickle.dump(obj, open('my_obj.pkl', 'wb', protocol=-1)) + # Bad. + cPickle.dump(obj, open('my_obj.pkl', 'w', protocol=-1)) + + * Avoid tuple parameter unpacking as it can lead to very ugly code when + converting to Python 3. + + .. code-block:: python + + # Good. + def f(x, y_z): + y, z = y_z + ... + # Bad. + def f(x, (y, z)): + ... + + * Only use ``cPickle``, not ``pickle`` (except for debugging purpose since + error messages from ``pickle`` are sometimes easier to understand). + + * A script's only top-level code should be something like: + + .. code-block:: python + + if __name__ == '__main__': + sys.exit(main()) + The ``logging`` Module vs. the ``warning`` Module ================================================= diff -r f2105a06201c -r 531e77fb67f2 doc/v2_planning/coding_style.txt --- a/doc/v2_planning/coding_style.txt Fri Sep 17 11:21:15 2010 -0400 +++ b/doc/v2_planning/coding_style.txt Fri Sep 17 12:05:14 2010 -0400 @@ -288,86 +288,13 @@ Have a sample code that showcases everything one should comply to. -Some coding guidelines (work-in-progress from OD) -------------------------------------------------- - - - * Use the `key` argument instead of `cmp` when sorting (for Python 3 - compatibility). - Yes: - my_list.sort(key=abs) - No: - my_list.sort(cmp=lambda x, y: cmp(abs(x), abs(y))) - - * Use // for integer division (for readability and Python 3 compatibility). - Yes: - n_samples_per_split = n_samples // n_splits - No: - n_samples_per_split = n_samples / n_splits - - * Only use ASCII characters in code files. - - * Code indent must be done with four blank characters (not with tabs). - - * Limit lines to 79 characters. - - * Comments should start with a capital letter (unless the first word is a - code identifier) and end with a period (very short inline comments may - ignore this rule). - - * Whenever you read / write binary files, specify it in the mode ('rb' for - reading, 'wb' for writing). This is important for cross-platform and - Python 3 compatibility (e.g. when pickling / unpickling objects). - - * Avoid tuple parameter unpacking to avoid very ugly code when converting - to Python 3. - Yes: - def f(x, y_z): - y, z = y_z - No: - def f(x, (y, z)) +Fred's suggestion to solve issue with hashlib not available in Python 2.4: +-------------------------------------------------------------------------- - * Only use cPickle, not pickle. - - * Always raise exception with - raise MyException(args) - where MyException inherits from Exception. - - * Imports should be listed in alphabetical order. It makes it easier to - verify that something is imported, and avoids duplicated imports. - - * Use absolute imports only. This is compatible across a wider range of - Python versions, and avoids confusion about what is being - imported. - - * Use a leading underscore '_' for internal attributes / methods, - but avoid the double underscore '__' unless you know what you are - doing. - - * A script's only top-level code should be something like: - if __name__ == '__main__': - sys.exit(main()) +You can do as in theano.gof.cc: - * No conditional expression (not supported in Python 2.4). These are - expressions of the form - x = y if condition else z - - * Use either "try ... except" or "try ... finally", but do not mix - "except" with "finally" (which is not supported in Python 2.4). - You can make a try... except inside a try... finally if you need both. + ..code:: - * Do not use the `all` and `any` builtin functions (they are not supported - in Python 2.4). - You can use numpy.{all,any} instead of import theano.gof.python25 that - define all and any. - OD: I think we should have something like pylearn.compat.{all,any}. - numpy.{all,any} are meant to be used on arrays only. - OD: As agreed during committee's meeting, we will use - theano.gof.python25 - - * Do not use the `hashlib` module (not supported in Python 2.4). - You can do as in theano.gof.cc: - ..code:: if sys.version_info[:2] >= (2,5): import hashlib def hash_from_code(msg): @@ -376,17 +303,7 @@ import md5 def hash_from_code(msg): return md5.new(msg).hexdigest() - OD: Yep, we could probably come up with such a wrapper in a pylearn.compat - module. - * Do not use mutable arguments as default values. Instead, use a helper - function: - Yes: - def f(array=None): - array = pylearn.if_none(array, []) - No: - def f(array=[]): - # Dangerous if `array` is modified down the road. Mercurial commits -----------------