Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Improved coding standards #49

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
204 changes: 151 additions & 53 deletions CONVENTIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <janneke@gnu.org>
# 2002-2009 Chris Cormie <cjcormie@gmail.com>
# 2012 James Nylen <jnylen@gmail.com>
# 2012-2014 Alexandre Quercia <alquerci@email.com>
#
# 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));

```