Python Coding Conventions
Generally speaking, follow Pythonic coding styles and guidelines.
This document is designed to point you in the right direction and propose a few approaches to coding to maintain consistency.
Project Conventions
Projects must be designed and organized in a specific way to ensure they are both docker compatible and they will continue to function going forward. PEP-518 lays out a new project format to describe project dependencies. In addition PEP-517 describes a very-likely to pass way to handle and build project dependencies.
As part of adapting to the changing landscape we are changing from the pipenv tool to poetry. Pipenv no longer fits in the broader vision of how Python dependencies are managed and never provided much of a deployment vision, either.
Poetry, on the other hand, maintains a somewhat opinioned vision of how to build and deploy Python applications and libraries both that is consistent with the future of Python (already integrates the pyproject.toml) as well as intends to provide standardized hooks for build and deployment.
- Projects must be small and single-purposed.
- Projects should always be hosted in a git repository.
- All projects should follow the below structure replacing app with the name of the package:
.
├── app
│ ├── subpackage
│ │ ├── __init__.py
│ │ └── somefile.py
│ ├── main.py
│ └── __init__.py
└── pyproject.toml
Note that the pyproject sits one level above the actual code. This is very similar to, like, C/C++ projects or Go projects where you’d typically have your project file sitting above the source files. Ideally this should be a more familiar and considerably easier to build format.
- Any Web API service should be exposed through
FastAPI - All developers should use
poetryfor environment creation and management. - All docker images should build from the
python-poetryorpython-poetry-fastapiimages in Harbor - Packages should be deployed and pulled using the Azure Devops artifacts repository
- Sensitive data like passwords and users should be read out of configuration (secrets, files, environment variables) and not be checked in to source control.
Naming and Style Conventions
- Follow the style guidelines as provided in PEP8.
- For purposes of convention, prefer single quotes to double quotes in anything beyond multi-line strings.
- Any time in a project that doesn’t follow convention then follow the general conventions of that project (e.g. Overlord).
Classes vs. Modules vs. Packages
- A single file should not contain more than 1 public class
- Use classes to represent encapsulation of both behavior and state.
- Use classes as a mixin object to inject functionality in to another class.
- Use a single Module when you have a single piece of behavior.
- Use a Package to combine modules or packages based on domain.
- Avoid name-pollution by always having all python in a top-level Package.
- Favor generators, list comprehensions, and iterators over classes if it is clean to do so.
- Prefer readability and usability over dogmatic adherance to rules.
Dependency Injection
- For classes, favor mixins for dependency injection. See here for a discussion on the topic.
- For functions, pass functions as parameters (service injection).
Environment and Setup
- All packages should maintain compatibility with pip
- All python projects must be self-contained and may only rely on
pipandpythonto run. - A library should be just installable through
poetry install {package} - A non-docker runnable app should have a self-contained script that sets up the environment
- A docker app will not require anything special as long as it uses
python-poetryor something based onpython-poetry
Cross Platform
- Assume python projects will be installed cross-platform.
- Always use
osmodule functions to do things like path construction and file manipulation.
Type Annotations
- Functions and methods should be annotated as much as possible
Docstrings
- Docstrings are required for any code being exposed to anyone outside Atlas.
- Docstrings should be used for complex integrations with external tools.
- Docstrings are a nice to have for any internal code.