Path Code Style Guide

Here's the place for discussion related to CAM/CNC and the development of the Path module.
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
User avatar
dubstar-04
Posts: 698
Joined: Mon Mar 04, 2013 8:41 pm
Location: Chester, UK
Contact:

Path Code Style Guide

Post by dubstar-04 »

Path coding conventions

General
  • These coding rules apply to the Path Workbench. Other modules or the base system may use different coding guidelines.
  • These coding rules are essentially the same well known PEP 8 guidelines;
  • New code added to the workbench should adhere to these guidelines.
  • All files should have the license header at the beginning.
  • Unix line endings should be used.
  • Use 4 spaces for a single level of indentation. Do not use tabs.
  • Remove trailing white spaces.
  • Keep files at less than 1000 lines in size.
  • Break a module into smaller modules, or into a package (a subdirectory with various modules), as necessary.
  • A big function can be broken into smaller functions.
  • A big class can be broken into smaller classes. Then one class can subclass the other ones in order to inherit their methods.
Code formatting
  • Python code should follow PEP 8 and PEP 257.
  • C++ code should follow PEP 7.
  • Maximum line length should be 80 characters.
  • Find ways to reduce nested blocks of code by using auxiliary variables and functions that encapsulate the operations inside these blocks.
  • If you have more than 3 levels of indentation, this is a sign that the code should be refactored.
  • Use double quotes for `"strings"`.
  • User facing strings should be translated
Imports
  • Imports should be at the beginning of the file, after the license header and module docstring and they should be grouped in three types in order:
    • Standard library imports
    • third party imports
    • FreeCAD specific imports
  • External imports should use lazy loading
  • Import only one module per line.
  • Do not use asterisk imports, `from module import *` as this makes it hard to validate imported functions and classes.
  • Do not import modules inside a function or class.
  • The import of modules that require the graphical interface such as `FreeCADGui` should be guarded by an `if FreeCAD.GuiUp:` test.
  • In general, the code should be structured in such a way that console-only functions are separate from their graphical interface implementations (GuiCommands).
Naming policy
  • `snake_case_names.py` for modules.
  • `variable_names_without_capitals` for variables.
  • `CamelCaseClass` for classes.
  • `CONSTANTS_USE_CAPITALS` for constants.
  • `functions_without_capitals()` for functions and class methods.
  • Functions expected to return a value should indicate what is expected so `is_mesh_valid` is a good name, but `check_mesh` is not a good name.
  • Class names, method names, and variables not part of the public interface should start with an underscore like `_MyInternalClass` or `_my_small_variable`.
Last edited by dubstar-04 on Wed May 27, 2020 1:23 pm, edited 28 times in total.
User avatar
dubstar-04
Posts: 698
Joined: Mon Mar 04, 2013 8:41 pm
Location: Chester, UK
Contact:

Re: Path Code Style Guide

Post by dubstar-04 »

Last edited by dubstar-04 on Wed May 27, 2020 9:47 am, edited 4 times in total.
User avatar
dubstar-04
Posts: 698
Joined: Mon Mar 04, 2013 8:41 pm
Location: Chester, UK
Contact:

Re: Path Code Style Guide

Post by dubstar-04 »

Python code formatting tools
  • Using a code editor that automatically checks compliance with PEP 8 is recommended.
  • For example, Spyder Ide contains code checkers `pylint`, `pyflakes`, `pycodestyle' that automatically test the code as you write it and can provide documentation and hints on the used functions and classes in real time.
  • Compliance should be manually checked with.

    Code: Select all

     flake8 --ignore=E226,E266,W503 file.py 
We may ignore certain errors and warnings.
  • E226: spaces around arithmetic operators `*`, `/`, `+`, `-`; sometimes we don't need a space.
  • E266: only one `#` for comments; we need two `##` for Doxygen documentation.
  • W503: break lines before a binary operator like `and` and `or`. The W503 warning will be changed in the future so we can ignore it for now.
  • See the meaning of the error codes in the pycodestyle documentation.
  • A good way to test entire folders for compliance is to run the following command.

    Code: Select all

    find src/Mod/Path -name '*.py' ! -name InitGui.py -exec flake8 --ignore=E226,E266,W503 --max-line-length=100 '{}' '+' 
  • The online LGTM service is also able to analyze the code and detect problems.
  • Avoid automatic code formaters.

Spelling
  • Take care of spelling mistakes in the default English messages,
    graphical user interfaces, documentation strings, and source code comments.
  • Use codespell to find common errors.
  • The following command tests files in the Path directory, but skips translation files and certain words which could be custom defined variables, functions, and classes.

    Code: Select all

    codespell -q 3 -S '*.ts' -L beginn,childs,eiter,methode,programm src/Mod/Path
    Interactively fix the errors found.

    Code: Select all

    codespell -i 3 -w -S '*.ts' -L beginn,childs,eiter,methode,programm src/Mod/Path
Last edited by dubstar-04 on Wed May 27, 2020 10:01 am, edited 6 times in total.
User avatar
dubstar-04
Posts: 698
Joined: Mon Mar 04, 2013 8:41 pm
Location: Chester, UK
Contact:

Re: Path Code Style Guide

Post by dubstar-04 »

Recommended Reading:

[Book] Writing Idiomatic Python 3 - https://www.amazon.com/Writing-Idiomati ... B00B5VXMRG
Last edited by dubstar-04 on Wed May 27, 2020 1:24 pm, edited 7 times in total.
User avatar
dubstar-04
Posts: 698
Joined: Mon Mar 04, 2013 8:41 pm
Location: Chester, UK
Contact:

Re: Path Code Style Guide

Post by dubstar-04 »

Code Examples

Tranlations:

Code: Select all

def translate(context, text, disambig=None):
    return QtCore.QCoreApplication.translate(context, text, disambig)

translate("Path", "Message")
Lazy Loading:

Code: Select all

# lazily loaded modules
from lazy_loader.lazy_loader import LazyLoader
Part = LazyLoader('Part', globals(), 'Part')
Last edited by dubstar-04 on Wed May 27, 2020 1:26 pm, edited 4 times in total.
User avatar
Wsk8
Posts: 182
Joined: Fri Dec 07, 2018 6:24 pm

Re: Path Code Style Guide

Post by Wsk8 »

- Indentation (Tabs / Spaces)
AFAIK Python only works if this is correct
- Line Length
~120 chars a line
- imports (single / multiline)
python
- Python 2 / 3
3
- Quotes ( " / ' )
???
- Naming Convention
python
- White Space
no unnecessary WS
- Translation of strings
??
- Use of Errors / Warnings / User messages
see other thread
- Comments
COMMENT YOUR CODE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11111111111
- Tools for checking code style / linting
As long as it is python compatible
- imports and lazy loading
??
- Line ending format
Standard UNIX
User avatar
Wsk8
Posts: 182
Joined: Fri Dec 07, 2018 6:24 pm

Re: Path Code Style Guide

Post by Wsk8 »

I especially want to point out to COMMENT YOUR CODE!!! PathWB is mostly a total mystery right now, because nobody comments their code
User avatar
dubstar-04
Posts: 698
Joined: Mon Mar 04, 2013 8:41 pm
Location: Chester, UK
Contact:

Re: Path Code Style Guide

Post by dubstar-04 »

Thank you for the response,

Rightly or wrongly I use a PEP8 formatting checker and I try to stick to the recommendations with the exception of line length.

Here are the PEP8 styles for comparison:

- Indentation (Tabs / Spaces)
AFAIK Python only works if this is correct
Most editors allow tabs to be replaced with spaces. PEP8 states that spaces should be used
do we have a preference for the number of spaces (4/8)?


- Line Length
~120 chars a line
PEP8 states that 79 is the maximum, I generally ignore this.

- imports (single / multiline)
python

Code: Select all

import FreeCAD, Draft # Multiline
import FreeCAD # Single line is PEP8 recommended
import Draft
- Python 2 / 3
3
Are we still maintaining support for python 2 beyond 0.19?

- Quotes ( " / ' )
???
Single quotes are concidered more pythonic? PEP8 has no preference.

Code: Select all

" some text" # double
'some text' # single
- Naming Convention
python
PEP8 suggests:

Code: Select all

UPPERCASE # constants
lowercase
camelCase
CappedWords # class Names
under_scored # variable and function names
_leading_underscore #private functions and variables
- White Space
no unnecessary WS
PEP8 has specific requirements for whitespace.
https://www.python.org/dev/peps/pep-0008/#blank-lines

- Translation of strings
??
The Path workbench is only partially translated. IMO we should translate all user facing strings if possible

- Use of Errors / Warnings / User messages
see other thread
I would like to capture the outcome of that discussion here as a complete reference

- Comments
COMMENT YOUR CODE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11111111111
External Python functions should include the doc comment?

Code: Select all

def functionName():
''' This is a doc comment to provide a description and example to appear in the python console'''
Should we comment code to explain decisions / workarounds for bugs?

- Tools for checking code style / linting
As long as it is python compatible
There are lots of tools available:
-pylint
-flake8
- mypy
- pydocstyle
- pycodestyle

What do you use and what settings are enabled / disabled?

- imports and lazy loading
??
We have lazy loading for python modules:

Code: Select all

ModuleName = LazyLoader('ModuleName', globals(), 'ModuleName')
We should document how, when and why this is used.
[/color]
- Line ending format
Standard UNIX
Now decided based on recent gitter discussions

Thanks,

Dan
Last edited by dubstar-04 on Wed May 27, 2020 1:13 pm, edited 6 times in total.
User avatar
sliptonic
Veteran
Posts: 3460
Joined: Tue Oct 25, 2011 10:46 pm
Location: Columbia, Missouri
Contact:

Re: Path Code Style Guide

Post by sliptonic »

dubstar-04 wrote: Tue May 26, 2020 12:16 pm - Comments
COMMENT YOUR CODE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11111111111
External Python functions should include the doc comment?

Code: Select all

def functionName():
''' This is a doc comment to provide a description and example to appear in the python console'''
This isn't really a comment. It's a docstring. A docstring is a string literal that occurs as the first statement in a module, function, class, or method definition. Such a docstring becomes the __doc__ special attribute of that object.

More details of docstrings on PEP257

For our standard I would agree with the above. As a general rule, every module, function, class and method should have a docstring. I'm ok with omitting them for functions if the function is trivial and private.

Also for comments; They should document WHAT a piece of code does not HOW it does it.
I prefer

Code: Select all

# comments for short one-liners 
and

Code: Select all

"""
multi-line
comments
in triple-double quotes
"""
User avatar
sliptonic
Veteran
Posts: 3460
Joined: Tue Oct 25, 2011 10:46 pm
Location: Columbia, Missouri
Contact:

Re: Path Code Style Guide

Post by sliptonic »

IMPORTS.

Should be alphabetized
should NOT include wildcards ie:

Code: Select all

  from foo import *
For long or relative imports use 'as' to keep subsequent code readable. ie

Code: Select all

import PathScripts.PathGeom as PathGeom
Post Reply