|
2 | 2 |
|
3 | 3 | Style Guide Enforcement
|
4 | 4 | =======================
|
| 5 | +The following sections will describe the use of flake8 for `PEP8`_ style |
| 6 | +enforcement and the minimum standards expected. The PyAnsys libraries |
| 7 | +will be consistent with these basic guidelines. |
| 8 | + |
| 9 | +.. _PEP8: https://www.python.org/dev/peps/pep-0008/ |
| 10 | + |
| 11 | +Flake8 |
| 12 | +~~~~~~ |
| 13 | +`Flake8`_ is a python tool for enforcing code styling. It is a wrapper |
| 14 | +around the following three tools: `PyFlakes`_, `pycodestyle`_, and |
| 15 | +`Ned Batchelder's McCabe script for complexity`_. Flake8 runs all three tools at once, |
| 16 | +checking the code against a variety of style rules, such as line length, |
| 17 | +code complexity, whitespace, etc. |
| 18 | + |
| 19 | +.. _Flake8: https://flake8.pycqa.org/en/latest/index.html |
| 20 | +.. _PyFlakes: https://pypi.org/project/pyflakes/ |
| 21 | +.. _pycodestyle: https://pypi.org/project/pycodestyle/ |
| 22 | +.. _`Ned Batchelder's McCabe script for complexity`: https://github.com/PyCQA/mccabe |
| 23 | + |
| 24 | +.. _configuring-flake8: |
| 25 | + |
| 26 | +Configuring Flake8 |
| 27 | +------------------ |
| 28 | +Flake8 supports configuring a specific set of style rules to |
| 29 | +enforce. This configuration can be stored in your project in a |
| 30 | +``setup.cfg``, ``tox.ini``, or ``.flake8`` file. The PyAnsys libraries |
| 31 | +store the flake8 configuration in a ``.flake8`` file at the root of the |
| 32 | +repository. |
| 33 | + |
| 34 | +Here is an example of a ``.flake8`` configuration file from one of the |
| 35 | +PyAnsys libraries: |
| 36 | + |
| 37 | +.. code:: |
| 38 | +
|
| 39 | + [flake8] |
| 40 | + exclude = venv, __init__.py, doc/_build |
| 41 | + select = W191, W291, W293, W391, E115, E117, E122, E124, E125, E225, E231, E301, E303, E501, F401, F403 |
| 42 | + count = True |
| 43 | + max-complexity = 10 |
| 44 | + max-line-length = 100 |
| 45 | + statistics = True |
| 46 | +
|
| 47 | +Flake8 has many options that can be set within the configuration file. |
| 48 | +A list of possible options can be found `here <https://flake8.pycqa.org/en/latest/user/options.html>`__. |
| 49 | + |
| 50 | +The above configuration defines the following options: |
| 51 | + |
| 52 | +- ``exclude`` |
| 53 | + This denotes subdirectories and ``doc/_build``, along with all |
| 54 | + ``__init__.py`` files to be excluded from the check. |
| 55 | + |
| 56 | +- ``select`` |
| 57 | + This is a sequence of error codes that flake8 will report errors |
| 58 | + for. The set in the above configuration is a basic set of errors to |
| 59 | + check for and is not an exhaustive list. |
| 60 | + |
| 61 | + A full list of error codes and their descriptions can be found `here <https://flake8.pycqa.org/en/3.9.2/user/error-codes.html>`__. |
| 62 | + |
| 63 | +- ``count`` |
| 64 | + The total number of errors is printed at the end of the check. |
| 65 | + |
| 66 | +- ``max-complexity`` |
| 67 | + This sets the maximum allowed McCabe complexity value for a block of code. |
| 68 | + The value of 10 was chosen because it is a common default. |
| 69 | + |
| 70 | +- ``max-line-length`` |
| 71 | + This denotes the maximum line length for any one line of code. |
| 72 | + The `PEP8`_ standard advises a line length of 79. Since this is a bit |
| 73 | + limiting in some cases, a maximum line length of 100 is suggested. |
| 74 | + |
| 75 | +- ``statistics`` |
| 76 | + This enables the number of occurrences of each error or warning code |
| 77 | + to be printed as a report at the end of the check. |
| 78 | + |
| 79 | + |
| 80 | +Running Flake8 |
| 81 | +-------------- |
| 82 | +First, to install flake8, run: |
| 83 | + |
| 84 | +.. code:: |
| 85 | +
|
| 86 | + python -m pip install flake8 |
| 87 | +
|
| 88 | +Then, flake8 can be run from inside your project directory by executing: |
| 89 | + |
| 90 | +.. code:: |
| 91 | +
|
| 92 | + flake8 . |
| 93 | +
|
| 94 | +This will use the configuration defined in the ``.flake8`` file to |
| 95 | +run the style checks on the appropriate files within the project and |
| 96 | +report any errors. |
| 97 | + |
| 98 | +In PyAnsys libraries, flake8 is run as part of the CI/CD for code style. |
| 99 | +This action is run as a required check on pull requests, preventing |
| 100 | +code in violation of these style rules from being merged into the code |
| 101 | +base. |
| 102 | + |
| 103 | + |
| 104 | +Utilizing Black |
| 105 | +~~~~~~~~~~~~~~~ |
| 106 | +Manually checking for code styling can be a tedious task. Luckily, |
| 107 | +there are several python tools for autoformatting code to meet PEP8 |
| 108 | +standards to help with this. The PyAnsys project suggests the use of the |
| 109 | +the formatting tool `black`_. |
| 110 | + |
| 111 | + |
| 112 | +Upon completing a code change, and before committing, `black`_ can be |
| 113 | +run to reformat the code, following the PEP8 guidelines enforced through |
| 114 | +flake8. This will limit any manual code changes needed to address style |
| 115 | +rules. |
| 116 | + |
| 117 | +.. _black: https://black.readthedocs.io/en/stable/ |
| 118 | + |
| 119 | +Optionally, it is possible to automate the use of ``black`` as well. |
| 120 | +This can be done with the tool `pre-commit`_. Setting up a `pre-commit hook |
| 121 | +to run black <https://black.readthedocs.io/en/stable/integrations/source_version_control.html>`_ |
| 122 | +will automatically format the code before committing. This is the |
| 123 | +simplest way to incorporate code style checks into the development |
| 124 | +workflow with the least amount of manual effort to maintain PEP8 guidelines. |
| 125 | + |
| 126 | +.. _pre-commit: https://pre-commit.com/ |
| 127 | + |
| 128 | + |
| 129 | +Minimum Standards |
| 130 | +~~~~~~~~~~~~~~~~~ |
| 131 | +The following section describes the minimum set of code style standards |
| 132 | +expected in an PyAnsys library. |
| 133 | + |
| 134 | +* `W191`_ - **Indentation contains tabs.** |
| 135 | + |
| 136 | + Indentations should be composed of four spaces, not tabs. |
| 137 | + |
| 138 | +* `W291`_ - **Trailing whitespace.** |
| 139 | + |
| 140 | + There should be no trailing whitespace after the final character |
| 141 | + on a line. |
| 142 | + |
| 143 | +* `W293`_ - **Blank line contains whitespace.** |
| 144 | + |
| 145 | + Blank lines should not have any tabs or spaces. |
| 146 | + |
| 147 | +* `W391`_ - **Blank line at the end of every file.** |
| 148 | + |
| 149 | + There should be only one blank line at the end of each file. This |
| 150 | + warning will occur when there are zero, two, or more than two blank |
| 151 | + lines. |
| 152 | + |
| 153 | +* `E115`_ - **Comment block expected an indent.** |
| 154 | + |
| 155 | + An indented block comment was expected but a non-indented block |
| 156 | + comment was found instead. |
| 157 | + |
| 158 | +* `E117`_ - **Line over-indented.** |
| 159 | + |
| 160 | + Lines should be consistently indented in increments of two or four. |
| 161 | + |
| 162 | +* `E122`_ - **Continuation line missing indentation or outdented.** |
| 163 | + |
| 164 | + Continuation line is not indented as far as it should be or is |
| 165 | + indented too far. |
| 166 | + |
| 167 | +* `E124`_ - **Closing bracket does not match indentation.** |
| 168 | + |
| 169 | + Closing bracket does not match the indentation of the opening bracket. |
| 170 | + |
| 171 | +* `E125`_ - **Continuation line with same indent as next logical line.** |
| 172 | + |
| 173 | + Continuation line is indented at the same level as the next logical |
| 174 | + line. It should be indented to one more level to distinguish it from |
| 175 | + the next line. |
| 176 | + |
| 177 | +* `E225`_ - **Missing whitespace around operator.** |
| 178 | + |
| 179 | + There should be one space before and after all operators. |
| 180 | + |
| 181 | +* `E231`_ - **Missing whitespace after certain special characters.** |
| 182 | + |
| 183 | + There should be one space after the characters ``,``, ``;``, or ``:``. |
| 184 | + |
| 185 | +* `E301`_ - **Expected a blank line, found none.** |
| 186 | + |
| 187 | + All methods of a class should have a single line between them. |
| 188 | + |
| 189 | +* `E303`_ - **Too many blank lines.** |
| 190 | + |
| 191 | + There should be one line between methods and two lines between |
| 192 | + methods and classes. |
| 193 | + |
| 194 | +* `E501`_ - **Line too long.** |
| 195 | + |
| 196 | + All code lines should not exceed 100 characters. The |
| 197 | + `PEP8 line length <https://www.python.org/dev/peps/pep-0008/#maximum-line-length>`_ |
| 198 | + guidelines suggest a maximum line length of 79. Following this limit |
| 199 | + is not as necessary due to modern screen sizes. The suggested maximum |
| 200 | + length of 100 can be easier to accommodate and can still support |
| 201 | + viewing files side-by-side in code editors. |
| 202 | + |
| 203 | +* `F401`_ - **Module imported but unused.** |
| 204 | + |
| 205 | + Modules should only be imported if they are actually used. |
| 206 | + |
| 207 | +* `F403`_ - **'from module import *' used.** |
| 208 | + |
| 209 | + Importing everything from a module should never be done. Importing |
| 210 | + modules this way leads to uncertainty and pollutes the code. You |
| 211 | + cannot know exactly what is being imported and it can often lead to |
| 212 | + name clashes. It is best to import the exact modules to be used. |
| 213 | + |
| 214 | +* **Limit complexity of code to 10.** |
| 215 | + |
| 216 | + This is enforced by the ``max-complexity`` option described in |
| 217 | + :ref:`configuring-flake8`. Limiting code complexity leads to code that |
| 218 | + is easier to understand and less risky to modify. Writing low |
| 219 | + complexity code when possible is preferred. |
| 220 | + |
| 221 | + |
| 222 | +Your ``.flake8`` file should be: |
| 223 | + |
| 224 | +.. code:: |
| 225 | +
|
| 226 | + [flake8] |
| 227 | + exclude = venv, __init__.py, doc/_build |
| 228 | + select = W191, W291, W293, W391, E115, E117, E122, E124, E125, E225, E231, E301, E303, E501, F401, F403 |
| 229 | + count = True |
| 230 | + max-complexity = 10 |
| 231 | + max-line-length = 100 |
| 232 | + statistics = True |
| 233 | +
|
| 234 | +
|
| 235 | +.. _W191: https://www.flake8rules.com/rules/W191.html |
| 236 | +.. _W291: https://www.flake8rules.com/rules/W291.html |
| 237 | +.. _W293: https://www.flake8rules.com/rules/W293.html |
| 238 | +.. _W391: https://www.flake8rules.com/rules/W391.html |
| 239 | +.. _E115: https://www.flake8rules.com/rules/E115.html |
| 240 | +.. _E117: https://www.flake8rules.com/rules/E117.html |
| 241 | +.. _E122: https://www.flake8rules.com/rules/E122.html |
| 242 | +.. _E124: https://www.flake8rules.com/rules/E124.html |
| 243 | +.. _E125: https://www.flake8rules.com/rules/E125.html |
| 244 | +.. _E225: https://www.flake8rules.com/rules/E225.html |
| 245 | +.. _E231: https://www.flake8rules.com/rules/E231.html |
| 246 | +.. _E301: https://www.flake8rules.com/rules/E301.html |
| 247 | +.. _E303: https://www.flake8rules.com/rules/E303.html |
| 248 | +.. _E501: https://www.flake8rules.com/rules/E501.html |
| 249 | +.. _F401: https://www.flake8rules.com/rules/F401.html |
| 250 | +.. _F403: https://www.flake8rules.com/rules/F403.html |
| 251 | + |
0 commit comments