Preferred packages ================== We have preferences for :doc:`requirements` in order to: - Limit the number of packages with which developers need to be familiar. - Reuse code (like Click) instead of writing new code (with argparse). For applications, we prefer all-inclusive and opinionated packages, because they: - Promote greater similarity and code reuse across projects. Django encourages developers to use its authentication mechanism. With Flask, each developer can choose a different mechanism. - Are more robust to changes in scope. For example, you might not need the `Django admin site `__ on day one, but you'll be happy to have it when it becomes a requirement. Maintainers can find dependencies with: .. code-block:: bash find . \( -name 'pyproject.toml' -or -name 'requirements.in' \) -exec echo {} \; -exec cat {} \; Preferences ----------- Web framework `Django LTS `__, unless a newer version has desirable features. Do not use `Flask `__, except in limited circumstances like generating a static site with `Frozen-Flask `__. API `Django REST Framework `__ or `FastAPI `__. Do not use `Django Tastypie `__, which has at times fallen behind on Django and Python versions. Command-line interface `Click `__, unless a framework has its own, like `Django `__, `Scrapy `__ or `Typer `__ with FastAPI. Do not use `argparse `__. DataFrames `Polars `__, unless end-users are unfamiliar (`pandas `__). Object Relational Mapper (ORM) Django. If you don't need an ORM, use `psycopg2 `__. Do not use `SQLAlchemy `__, except with FastAPI or in low-level libraries with limited scope *where an ORM is needed*. .. note:: Use ``psycopg2`` in production, not ``psycopg2-binary``, `as recommended `__. :ref:`See instructions`. HTTP client `Requests `__ for synchronous code and `niquests `__ for asynchronous code, unless a framework uses another, like Scrapy (Twisted). HTML parsing `lxml `__. Do not use `BeautifulSoup `__. Templating `Jinja `__. Do not use CSS framework integration packages like ``django-bootstrap*``, as they tend to lag the most recent releases. See :doc:`../htmlcss/index`. Asset management Do not use `django-compressor `__ or `django-pipeline `__, which are always behind NPM packages. See :ref:`javascript-preferences` for JavaScript. Internationalization (i18n) `gettext `__ and `Babel `__, unless a framework provides an interface to these, like `Django `__ or `Sphinx `__. Logging `logging `__ Testing `pytest `__, unless a framework uses another, like `Django `__ (unittest). Documentation `Sphinx `__. Its Markdown extensions should only be used for OCDS documentation. .. tip:: `Jazzband `__ packages are a good choice. Criteria -------- A preferred package should meet the following criteria: - It is properly released: its readme is rendered on PyPI, a changelog is maintained, tags are used, etc. - It supports the most recent version of Python and frameworks (if relevant), like Django or Sphinx. - Simple libraries might not need new releases for new Python versions. - It meets the `QASP criteria `__ of published, tested and documented. - *Published*: Find its repository and check its open source license. - *Tested*: Check its CI badges, GitHub Actions tab, or CI configuration. - *Documented*: Check its documentation website. - Its issue tracker demonstrates that the maintainers are responsive. - The repository is not described as archived or unmaintained. - The maintainer's other repositories can be considered if the repository is new or unpopular. `Snyk Open Source Advisor `__ might also be used to answer the above. License compliance ------------------ To ease license compliance and code reuse, avoid software distributed under `strong copyleft `__ licenses. - Use an alternative dependency. - `rfc3339-validator `__, not `strict-rfc3339 `__ - `rfc3986-validator `__, not `rfc3987 `__ - `text-unidecode `__, not `unidecode `__ - Make the dependency optional. .. code-block:: python try: import some_gpl_package using_some_gpl_package = True except ImportError: using_some_gpl_package = False if using_some_gpl_package: print("Some optional behavior") .. note:: This does not apply to software that is only used as a utility and is not linked to the code, like `libsass `__. To list the licenses under which installed packages are distributed: - Install the packages - Install `pip-licenses `__: .. code-block:: bash pip install pip-licenses - List the licenses: .. code-block:: bash pip-licenses --with-urls If you have virtual environments for multiple repositories in the same directory, you can do a bulk operation: - Install `pip-licenses `__. For example: .. code-block:: bash uv tool install pip-licenses - Initialize a CSV file as the output file: .. code-block:: bash echo Venv,Name,Version,License,URL > licenses.csv - Append licenses to the output file: .. code-block:: bash find . -name .venv -maxdepth 2 -exec sh -c \ 'pip-licenses --python="$0"/bin/python --format=csv --with-urls | tail -n +2 | sed "s@^@$(basename $(dirname $0)),@" >> licenses.csv' '{}' \; - Run this script from the `standard-maintenance-scripts `__ repository: .. code-block:: bash ./manage.py check-licenses licenses.csv