diff --git a/CONVENTIONS.md b/CONVENTIONS.md index 4e300f4..aa83f8b 100644 --- a/CONVENTIONS.md +++ b/CONVENTIONS.md @@ -12,83 +12,181 @@ interpreted as described in [RFC 2119][]. [PEP 257]: http://www.python.org/dev/peps/pep-0257/ -General -------- +Files +----- -* Use classes as much as possible. -* A file SHOULD contain only one class (module == class). -* Each statement MUST end with a semicolon `;`. +* Code MUST use 4 spaces for indenting, not tabs. +* All Python files MUST use the Unix LF (line feed) line ending. +* All Python files MUST end with a single blank line. +* A file MAY contain one or many interdependent classes. +* An `exception` module MUST contain all exception classes of a package. -Idioms ------- +Structure +--------- -* Use only format() method to formatting strings. -* `print` is a function. +* Each statement MUST end with a semicolon `;`; +* Add a single space after each comma delimiter; -Files ------ +* For sequence types (`dict`, `list`, ...) in a multi-line form, add a comma + after each item, even the last one; -* Code MUST use 4 spaces for indenting, not tabs. -* All Python files MUST use the Unix LF (line feed) line ending. -* All Python files MUST end with a single blank line. +* Add a blank line before `return` statements, unless the return is alone inside + a statement-group (like an `if` statement); +* Use classes as much as possible; -Classes -------- +* Declare public methods first, then protected ones and finally private ones. + The exceptions to this rule are the class constructor and the `setUp` and `tearDown` methods + of unittest tests, which SHOULD always be the first methods to increase readability; -* Class names MUST be declared in `StudlyCaps`. -* Method names MUST be declared in `camelCase`. -* Property/Method names MUST start but not ending with - TWO underscores `__` to indicate private visibility. -* Property/Method names MUST start but not ending with - ONE underscores `_` to indicate protected visibility. -* `exception` module SHOULD contain all `Exception` class. -* You can put an `Exception` definition at the end of a file - if the file is the only one that uses that exception. -* Every `Exception` class MUST end with `Exception`. +* Strings SHOULD be concatenated using the `format()` method; +* Use `print()` as a function with `from __future__ import print_function;` + on top of the module; -Example -------- -```Python -import sys; -from package.class_name import ClassName; +Naming Conventions +------------------ -class ClassName(): - def __init__(self, arg1, arg2): - """Python magic method""" - self.propertyName = "{1}".format("Public property"); - self._propertyName = arg1; # Protected property - self.__propertyName = arg2; # Private property +* Use StudlyCaps for class names; - print(self.propertyName, end="", file=sys.stderr); +* Use camelCase, not underscores, for variable, function, method, and argument names; - def methodName(self): - """Public method""" - pass; +* Use underscores for option names and parameter names; - def _methodName(self): - """protected method""" - pass; +* Prefix abstract classes with `Abstract`; - def __methodName(self): - """private method""" - pass; +* Suffix interfaces with `Interface`; -class ClassNameException(Exception): - """A ClassName Exception""" - pass; +* Suffix exceptions with `Exception`; -``` +* Property and method names SHOULD NOT end with an underscore `_`; + +* Prefix property and method names with `_` to indicate protected visibility; + +* Prefix property and method names with `__` to indicate private visibility; +* Use lowercase alphanumeric characters and underscores for file names; -String ------- + +String Delimiters +----------------- * Double quotes for text + * Single quotes for anything that behaves like an identifier + * Double quoted raw string literals for regexps + * Tripled double quotes for docstrings + + +Documentation +------------- + +* Add EpyDoc blocks for all classes, methods, and functions; + +* Omit the `@return` tag if the method does not return anything; + +* The `@param`, `@return` and `@raise` annotations SHOULD only be used; + + +License +------- + +* Cyg-apt is released under the GNU GPLv3 license, and the license block has to be present + at the top of every Python file, before the first import. + + +Example +------- + +Since a picture - or some code - is worth a thousand words, here's a short example containing most features described below: + +```Python +# -*- coding: utf-8 -*- +######################## BEGIN LICENSE BLOCK ######################## +# This file is part of the cygapt package. +# +# Copyright (C) 2002-2009 Jan Nieuwenhuizen +# 2002-2009 Chris Cormie +# 2012 James Nylen +# 2012-2014 Alexandre Quercia +# +# For the full copyright and license information, please view the +# LICENSE file that was distributed with this source code. +######################### END LICENSE BLOCK ######################### + +class BarInterface(): + """Coding standards demonstration. + """ + + def getValue(self): + """Gets a value. + + @return: str The value + """ + +class FooBar(BarInterface): + """Coding standards demonstration. + """ + + SOME_CONST = 42; + + def __init__(self, dummy, bar=None): + """Constructor. + + @param dummy: str Some argument description + @param bar: BarInterface Some argument description + """ + assert isinstance(dummy, str); + assert None is bar or isinstance(bar, BarInterface); + + # define a private property + self.__fooBar = bar.getValue() if bar else self.__transformText(dummy); + + def getValue(self): + """Gets a value. + + @return: str The value + """ + return self.__fooBar; + + def __transformText( + self, + dummy, + some_default="values", + another_default="more values", + third_default="more and more values", + ): + """Transforms the dummy following options. + + @param dummy: str Some argument description + @param some_default: str Some argument description + @param another_default: str Some long argument description + with some useful explication + @param third_default: str Some argument description + + @return: str|None Transformed input + + @raise Exception: When unrecognized dummy option + """ + assert isinstance(dummy, str); + assert isinstance(some_default, str); + assert isinstance(another_default, str); + assert isinstance(third_default, str); + + if True is dummy : + return; + + if "string" == dummy : + if "values" == some_default : + return dummy[:5]; + + return dummy.title(); + + raise Exception('Unrecognized dummy option "{0}"'.format(dummy)); + +```