Code Standards ============== General ------- In order to provide a code base that is easy to maintain, as well as easy to contribute to, **Robottelo** has adopted a set of code standards that all contributers are held to. Violations to our strictly held standards will result in a rejected pull request until all violations have been resolved. While not adhering to our recomended standards isn't a show stopper, keeping to them will help our code base to stay great! Strictly Held ------------- Black * Robottelo uses the code formatting tool black. * This tool will handle most of the general formatting regarding indentation and others. * In general, if black makes a change to your code, that is what we also desire. * Black is integrated into our CI process, so make sure it is run via pre-commit hook or manually before submitting a pull request. Linting * All code will be linted to black-compatible `PEP8`_ standards using `flake8`_. * In the root of the **Robottelo** directory, run :code:`flake8 .` * If flake8 returns errors, make corrections before submitting a pull request. * pre-commit configuration is available, and its use is strongly encouraged in local development. Docstrings * Every class, method and function will have a `properly formatted`_ docstring. * Docstring will also contain `testimony`_ and `sphinx`_ directives, as appropriate. * testimony docstrings are specific to foreman tests, so every test in tests/foreman/* should have the testimony tags. * In the root of the **Robottelo** directory, run :code:`make test-docstrings` to ensure you did not miss adding a docstring. Strings * Use string methods instead of the string module. * Use f-strings for string formatting whenever possible. * Use the string's format method when an f-string would become too complex. * When using format, leave out indices, unless absolutely necessary (variable re-use). Examples ::code:: simple_example = f'This is a {simple_var} example' moderate_example = f'{some_var}: {some_func(arg="foo")}' multi_line_example = f'You can also do {"larger"} ' 'f-strings. Only using the f notation when a ' f'string requires it like this one: {some_func()}' complex_formatting = 'This {} contains both {} and {}'.format( 'string', '"layered"', ' '.join(['a', 'non-trivial list', 'converted to', 'a', 'string']) ) indices_needed = ( 'this {var1} is a {var1} that has the {var2} {var1} {var3}'.format( var1='sentence', var2='word', var3='multiple times' ) ) Naming Variable names must follow the standard below in addition to Python's own language requirements for valid variable names. * module_name * method_name * function_name * instance_variable_name * local_variable_name * function_parameter_name * ClassName * ExceptionName * GLOBAL_CONSTANT_NAME * _private_method * _private_variable * _PrivateClass Furthermore, when writing fixtures, make their scope clear at the beginning of the fixture function's name. An unspecified scope is assumed to be function-level * org * module_org * session_org Style * Absolutely no semicolons. * Lines are not to exceed 99 characters in length. * Code will be indented with **4 spaces** instead of tabs. Recommended ----------- Importing * Import modules in alphabetical order. * Each non-module import should be on their own line. * Import order is: * standard library * third-party * application-specific * Put a blank line between groups of imports. General * Avoid global variables. * Use :code:`.join()` for non-trivial string concatenation. * Trivial string concatenation can be done either via f-strings or `+`, though f-strings are preferred. * string to string concatenation is faster with `+`. * if one or more values need to be converted to a string, f-strings are faster. [jake] - i agree because of course * Handle data aggregation inside of functions when able. Style * Use single quotes instead of double quotes whenever possible. Single quotes are less visually noisy, and they are easier to type. * When mixing nested strings, and you have exhausted both single and double quotes, use triple quotes on the outer string. ::code:: bad = f'This "quoted \'string\' is \'messy\''.''' good = f'''This 'quoted "string" reads "better"'.''' * One statement per line. Read More! ---------- `Python Style Guide`_ `pre-commit Tutorial`_ `Code Like a Pythonista`_ Todo ---- Compile a list of standards used by the **Robottelo** team Categorize each standard into how strictly they are enforced .. _PEP8: http://legacy.python.org/dev/peps/pep-0008/ .. _flake8: http://flake8.readthedocs.org/ .. _testimony: https://github.com/SatelliteQE/testimony .. _sphinx: http://sphinx-doc.org/markup/para.html .. _properly format strings: https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting .. _Python Style Guide: http://docs.python-guide.org/en/latest/writing/style/ .. _pre-commit Tutorial: https://pre-commit.com/#usage .. _Code Like a Pythonista: http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html