changeset 1159:531e77fb67f2

coding_style: Moved more elements to official 'API'
author Olivier Delalleau <delallea@iro>
date Fri, 17 Sep 2010 12:05:14 -0400
parents f2105a06201c
children 8b65a1b27b94
files doc/v2_planning/API_coding_style.txt doc/v2_planning/coding_style.txt
diffstat 2 files changed, 153 insertions(+), 94 deletions(-) [+]
line wrap: on
line diff
--- 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
 =================================================
--- 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
 -----------------