Python Code Reviews
CSE projects should check Python code with automated tools.
Linting should be added to build validation, and both linting and code formatting can be added to your pre-commit hooks and VS Code.
Code Analysis / Linting
The 2 most popular python linters are Pylint and Flake8. Both check adherence to
PEP8 but vary a bit in what other rules they check. In general
Pylint tends to be a bit more stringent and give more false positives but both are good options for linting python code.
Flake8 can be configured in VS Code using the VS Code
pip install flake8
pip install flake8-docstrings
pip install pep8-naming
flake8 . # lint the whole project
pip install pylint
pylint src # lint the source directory
Automatic Code Formatting
Black is an unapologetic code formatting tool. It removes all need from
pycodestyle nagging about formatting, so the team can focus on content vs style. It's not possible to configure black for your own style needs.
pip install black
Format python code
Autopep8 is more lenient and allows more configuration if you want less stringent formatting.
pip install autopep8
Format python code
autopep8 [file/folder] --in-place
yapf Yet Another Python Formatter is a python formatter from Google based on ideas from gofmt. This is also more configurable, and a good option for automatic code formatting.
pip install yapf
Format python code
yapf [file/folder] --in-place
VS Code Extensions
Python language extension is the base extension you should have installed for python development with VS Code. It enables intellisense, debugging, linting (with the above linters), testing with pytest or unittest, and code formatting with the formatters mentioned above.
Pyright extension augments VS Code with static type checking when you use type hints
def add(first_value: int, second_value: int) -> int: return first_value + second_value
To automate linting with
flake8 and testing with
pytest in Azure Devops you can add the following snippet to you
trigger: branches: include: - develop - master paths: include: - src/* pool: vmImage: 'ubuntu-latest' jobs: - job: LintAndTest displayName: Lint and Test steps: - checkout: self lfs: true - task: UsePythonVersion@0 displayName: 'Set Python version to 3.6' inputs: versionSpec: '3.6' - script: pip3 install --user -r requirements.txt displayName: 'Install dependencies' - script: | # Install Flake8 pip3 install --user flake8 # Install PyTest pip3 install --user pytest displayName: 'Install Flake8 and PyTest' - script: | python3 -m flake8 displayName: 'Run Flake8 linter' - script: | # Run PyTest tester python3 -m pytest --junitxml=./test-results.xml displayName: 'Run PyTest Tester' - task: PublishTestResults@2 displayName: 'Publish PyTest results' condition: succeededOrFailed() inputs: testResultsFiles: '**/test-*.xml' testRunTitle: 'Publish test results for Python $(python.version)'
To perform a PR validation on GitHub you can use a similar YAML configuration with GitHub Actions
Pre-commit hooks allow you to format and lint code locally before submitting the pull request.
Adding pre-commit hooks for your python repository is easy using the pre-commit package
Install pre-commit and add to the requirements.txt
pip install pre-commit
.pre-commit-config.yamlfile in the root of the repository, with the desired pre-commit actions
repos: - repo: https://github.com/ambv/black rev: stable hooks: - id: black language_version: python3.6 - repo: https://github.com/pre-commit/pre-commit-hooks rev: v1.2.3 hooks: - id: flake8
Each individual developer that wants to set up pre-commit hooks can then run
At the next attempted commit any lint failures will block the commit.
Note: Installing pre-commit hooks is voluntary and done by each developer individually. Thus, it's not a replacement for build validation on the server
Code Review Checklist
In addition to the Code Review Checklist you should also look for these python specific code review items
- Are all new packages used included in requirements.txt
- Does the code pass all lint checks?
- Do functions use type hints, and are there any type hint errors?
- Is the code readable and using pythonic constructs wherever possible.