2020-06-09 10:22:20 -04:00
# Cerc Python Style Guide
2020-06-09 12:11:57 -04:00
## What's coding style and why it matters.
2020-06-09 10:22:20 -04:00
Coding style is just how the code looks, it's incredibly personal, and everyone has their style.
2022-04-11 19:29:29 -04:00
Your preferred architectures, variable and function naming style all of then impacts in your code style and how the others read and understand it, so it could become a significant burden if everyone is coding on his or her own.
2020-06-09 10:22:20 -04:00
2020-06-09 12:09:21 -04:00
At CERC, we are following the [PEP8 ](https://www.python.org/dev/peps/pep-0008/ ) with two spaces indentation instead of four.
2020-06-09 10:22:20 -04:00
## Tools.
We use [PyCharm ](https://www.jetbrains.com/pycharm/ ) as an integrated development environment and follow the tool's overall advice but the space indentation, which we set to two spaces instead of default four spaces.
2022-04-11 19:29:29 -04:00
For code analysis, we enforce the usage of [pylint ](https://www.pylint.org/ ) with our own [custom style definition ](pylintrc ). This file will be downloaded with the project the first time you clone it.
2020-06-09 10:22:20 -04:00
2020-06-09 12:11:57 -04:00
## Naming convention.
2020-06-09 10:22:20 -04:00
2022-04-11 19:29:29 -04:00
* Name your folders and files in lowercase and use _ (underscore) to separate words.
2020-06-09 10:22:20 -04:00
* Your class names must start in capital letters and follow the python CapWords pattern.
2022-04-11 19:29:29 -04:00
* Methods and properties that return lists must end in "s". Therefore, those that return single values, must be singular.
2020-06-09 12:09:21 -04:00
* Methods and variables should be lowercase and use _ (underscore) as a word separator.
* Constant names must be all capitals.
2022-04-11 19:29:29 -04:00
* Avoid the usage of "get_" and "set_" methods whenever it is possible, use @property and @variable .setter decorators instead.
* "Private" methods, variables and properties start with _ (underscore).
2020-06-09 11:35:38 -04:00
2020-06-09 12:11:57 -04:00
## Imports.
2020-06-09 12:09:21 -04:00
Place your imports at the top of the file, after the license and contact information
2020-06-09 12:11:57 -04:00
comment.
2020-06-09 11:35:38 -04:00
```python
"""
MyClass module
SPDX - License - Identifier: LGPL - 3.0 - or -later
2022-04-08 09:35:33 -04:00
Copyright © 2022 Concordia CERC group
Project Coder name name@concordia.ca
2020-06-09 11:35:38 -04:00
"""
import sys
```
Ensure that your imports are used and remove any unused.
2020-06-09 12:11:57 -04:00
## Object attributes and methods.
2020-06-09 11:35:38 -04:00
2022-04-11 19:29:29 -04:00
Use properties whenever it is possible. Encapsulate the access to all the calculated object attributes to avoid recalculating each time the property is called.
2020-06-09 11:35:38 -04:00
```python
@property
2023-05-10 17:06:51 -04:00
def object_attribute(cls):
if cls._object_attribute is None:
cls._object_attribute = ...
2020-06-09 11:35:38 -04:00
...
2023-05-10 17:06:51 -04:00
return cls._object_attribute
2020-06-09 11:35:38 -04:00
```
2022-04-11 19:29:29 -04:00
And like in the following example for read and write properties:
2020-06-09 11:35:38 -04:00
```python
@property
2023-05-10 17:06:51 -04:00
def object_changeable_attribute(cls):
return cls._object_changeable_attribute
2020-06-09 11:35:38 -04:00
@object_changeable_attribute .setter
2023-05-10 17:06:51 -04:00
def object_changeable_attribute(cls, value):
cls._object_changeable_attribute = value
2020-06-09 11:35:38 -04:00
```
2022-04-11 19:29:29 -04:00
If your method or attribute returns a complex object, use type hints as in this example:
2020-06-09 11:35:38 -04:00
```python
@property
2023-05-10 17:06:51 -04:00
def complex_object(cls) -> ComplexObject:
return cls._object_changeable_attribute
2020-06-09 11:35:38 -04:00
2023-05-10 17:06:51 -04:00
def new_complex_object(cls, first_param, second_param) -> ComplexObject:
other_needed_property = cls.other_needed_property
2022-04-11 19:29:29 -04:00
return ComplexObject(first_param, second_param, other_needed_property)
2020-06-09 11:35:38 -04:00
```
2020-06-09 12:09:21 -04:00
Always access your variable through the method and avoid to access directly.
2020-06-09 11:35:38 -04:00
```python
@property
2023-05-10 17:06:51 -04:00
def object_attribute(cls):
return cls._object_attribute
2020-06-09 11:35:38 -04:00
2023-05-10 17:06:51 -04:00
def operation(cls, first_param, second_param):
return cls.object_attribute * 2
2020-06-09 11:35:38 -04:00
2020-06-09 11:49:50 -04:00
```
2022-04-11 19:29:29 -04:00
### Comments.
2020-06-09 11:49:50 -04:00
2020-06-09 12:11:57 -04:00
#### Code documentation.
2020-06-09 11:49:50 -04:00
2022-04-11 19:29:29 -04:00
All public classes, properties, and methods must have code comments. Code comments start with capital letters and end without period:
2020-06-09 11:49:50 -04:00
```python
class MyClass
"""
MyClass class perform models class operations
"""
2023-05-10 17:06:51 -04:00
def __init__ (cls):
2020-06-09 11:49:50 -04:00
@property
2023-05-10 17:06:51 -04:00
def object_attribute(cls):
2020-06-09 11:49:50 -04:00
"""
2022-04-11 19:29:29 -04:00
Get my class object attribute
2020-06-09 11:49:50 -04:00
:return: int
"""
2023-05-10 17:06:51 -04:00
return cls._object_attribute
2020-06-09 11:49:50 -04:00
2023-05-10 17:06:51 -04:00
def operation(cls, first_param, second_param):
2020-06-09 11:49:50 -04:00
"""
2022-04-11 19:29:29 -04:00
Multiplies object_attribute by two
2020-06-09 11:49:50 -04:00
:return: int
"""
2023-05-10 17:06:51 -04:00
return cls.object_attribute * 2
2020-06-09 11:49:50 -04:00
```
2022-04-11 19:29:29 -04:00
Comments at getters and setters always start with Get and Set, and identity the type of variable at return (at getter) or the value (at setter):
```python
@property
2023-05-10 17:06:51 -04:00
def object_attribute(cls):
2022-04-11 19:29:29 -04:00
"""
Get object attribute
:return: int
"""
2023-05-10 17:06:51 -04:00
return cls._object_attribute
2022-04-11 19:29:29 -04:00
@object_attribute .setter
2023-05-10 17:06:51 -04:00
def object_attribute(cls, value):
2022-04-11 19:29:29 -04:00
"""
Set object attribute
:param value: int
"""
2023-05-10 17:06:51 -04:00
cls._object_attribute = value
2022-04-11 19:29:29 -04:00
```
2020-06-09 12:09:21 -04:00
Attributes with known units should be explicit in method's comment.
2020-06-09 12:01:47 -04:00
```python
@property
2023-05-10 17:06:51 -04:00
def distance(cls):
2020-06-09 12:01:47 -04:00
"""
My class distance in meters
:return: float
"""
2023-05-10 17:06:51 -04:00
return cls._distance
2020-06-09 12:01:47 -04:00
```
2020-06-09 12:11:57 -04:00
#### To do's.
2020-06-09 11:49:50 -04:00
2022-11-09 11:42:44 -05:00
Pending to implement operations should be indicated with todo comments to highlight the missing functionality.
2020-06-09 11:49:50 -04:00
```python
2022-11-09 11:42:06 -05:00
# todo: right now extracted at the city level, in the future should be extracted also at building level if exist
2020-06-09 11:49:50 -04:00
```