Python#
Guidelines for setting up and working in Python projects.
Dependencies#
If your project is a application, e.g. a CLI or a deployed service such as a AWS Lambda function, you should pin all your dependencies to exact versions. Tools such as pip-tools can help with the process; this documentation uses pip-tools to defines its dependencies.
If you are building a library that is meant to be imported and used by other projects, then the correct way to specify dependencies is a little trickier. We recommended the following setup, if possible:
Specify direct dependencies with
>=
in your setup file (usuallysetup.cfg
)Keep a
requirements-min.txt
file at the top level of your repo with all direct dependencies, but this time with==
version specificationsIn CI, test with both a standard install and with
requirements-min.txt
Specify development dependencies with
~=
version specifications on the MINOR version when appropriate, otherwise==
Examples#
Let’s say you have a spam package that depends on eggs, and uses
milk and coffee as development packages. Your setup.cfg
should
include something like this:
install_requires =
eggs >= 2.3.4
Then, in your requirements-min.txt
file:
eggs == 2.3.4
If you keep your development dependencies in requirements-dev.txt
(recommended), that might look like:
milk ~= 5.4
coffee == 2023.03.16
For an example of this setup in a real-life package, check out stactools.
Tooling#
For Python projects, the following linters, formatters, and checkers are recommended. Each should be included in requirements file(s) as well as added as pre-commit hooks:
Style#
Warning
This style guide is a work in progress
There’s quite a few Python packages in the stac-utils organization. PySTAC is the “base” repository that includes classes for all the main STAC data structures (Item, Catalog, and Collection) as well as reading, writing, and convenience functionality. Before the creation of this this developer guide, we had a de facto policy of “do what PySTAC does” for the rest of the stac-utils Python packages. Now, we use this document as the source of truth.
Using datetime
#
Following the lead of the datetime documentation, prefer import the
datetime
class (and other classes, e.g. timedelta
), and don’t rename it:
# DO
from datetime import datetime
# DON't
import datetime
import datetime as dt
The exception to this rule is when datetime
is only imported for type checking and
using the class directly interferes with another variable name. In this case, in the
TYPE_CHECKING block you should do from datetime import datetime as Datetime
.