flake8-isort 6.1.0
Use isort to check if the imports on your python files are sorted the way you expect.
Add an .isort.cfg to define how you want your imports sorted and run flake8 as you usually do.
See isort documentation for .isort.cfg available options.
Install
Install with pip:
$ pip install flake8-isort
Install with conda:
$ conda install -c conda-forge flake8-isort
Configuration
If using the select option from flake8 be sure to enable the I category as well, see below for the specific error codes reported by flake8-isort .
See flake8 —help for available flake8-isort options.
Error codes
Requirements
- Python 3.8, 3.9, 3.10, 3.11 and pypy3
- flake8
- isort
Relation to flake8-import-order
As an alternative to this flake8 plugin, there’s flake8-import-order that could be worth checking out. In contrast to this plugin that defers all logic to isort, the flake8-import-order comes bundled with it’s own logic.
flake8-import-order comes with a few predefined set of styles meanwhile this plugin can be customized a bit more. But the biggest difference could lie in that flake8-isort actually has the corresponding sorting engine isort that can sort the import orders of your existing python files. Meanwhile flake8-import-order has no such corresponding tool, hence big existing projects who want to adopt either would get a more automized experience choosing flake8-isort.
License
Changelog
6.1.0 (2023-09-15)
- Drop python 3.7 support. [gforcada]
- Add preliminary support to Python 3.12. [gforcada]
6.0.0 (2022-12-22)
- Drop isort 4.x support. [gforcada]
- Add support for flake8 6.0.0. [gforcada]
- Add –isort-no-skip-gitignore option to allow temporarily overriding the set value of isort’s skip_gitignore option with False . This can cause flake8-isort to run significantly faster at the cost of making flake8-isort’s behavior differ slightly from the behavior of isort –check . [gschaffner]
5.0.3 (2022-11-20)
- Fix broken add_options method, again. [casperdcl]
5.0.2 (2022-11-19)
- Fix broken add_options method [casperdcl]
5.0.1 (2022-11-18)
- Improve the config option is added and read back. [gforcada]
- Bump plugin version. [gforcada]
5.0.0 (2022-10-08)
- Update dependencies. [gforcada]
- Revamp GitHub actions. [gforcada]
- Drop python 3.6, and add python 3.10. [gforcada]
- Use linters and formatters to keep code sane and beautiful. [gforcada]
4.2.0 (2022-08-04)
- Fix compatibility with flake8 version 5. [nhymxu]
4.1.2.post0 (2022-07-25)
- Release it as a wheel as well. [gforcada]
4.1.2 (2022-07-25)
- The package no longer depends on testfixtures .
4.1.1 (2021-10-14)
- Release py3 only wheels..
4.1.0 (2021-10-14)
- Support flake8 4.x [g-as]
- Switch from travis-ci to github actions. [g-as]
- Drop python 2.7 support and 3.5 as well [g-as]
4.0.0 (2020-08-11)
- Nothing changed yet.
4.0.0a0 (2020-08-07)
- support isort >= 5 [bnavigator, pkolbus]
3.0.1 (2020-07-08)
- Work around FailedToLoadPlugin exception by requiring isort 4.x. Likewise, pin the major version of all dependencies, to reduce risk of any future incompatibilities. [pkolbus]
3.0.0 (2020-04-15)
- Let isort search the configuration, rather than flake8-isort try to find it. [jnns]
2.9.1 (2020-03-28)
- Fix flake8 warning. [sobolevn]
2.9.0 (2020-03-16)
- Add python3.8 support. [sobolevn]
2.8.0 (2019-12-05)
- Look for isort configuration on .flake8 files as well. [JohnHBrock]
- Document how to install flake8-isort on conda. [marcelotrevisani]
- Look for isort configuration on pyproject.toml files as well. [sanjioh]
2.7.0 (2019-03-19)
- Improve the README. [barbossa]
- Fix isort output when pipes are used. [maerteijn]
2.6.0 (2018-12-01)
- Use pytest to run tests. [gforcada]
- New error code I005 isort foundan unexpected missing import. [charettes]
- Add isort_show_traceback option to show verbose multi-line output from isort , turned off by default [sobolevn]
2.5 (2018-03-15)
- Now requires isort >= 4.3.0. [jleclanche]
2.4 (2018-02-25)
- Fix input handling with flake8’s –stdin-display-name, and simplify it. [blueyed]
- Remove flake8-polyfill dependency. flake8 >= 3.2.1 is required already, and stdin is not read directly anymore. [blueyed]
2.3 (2017-12-22)
- Fix typo. [paltman]
- Add tox.ini and .editorconfig to config search. [cas–]
- Make this plugin compatible with flake8 hook. As the hook copies the files out of tree, flake8-isort never finds the correct configuration. [jaysonsantos]
2.2.2 (2017-08-19)
- Workaround for isort bug when skipping files. [danpalmer]
2.2.1 (2017-05-12)
- Release as universal wheel. [gforcada]
2.2 (2017-03-26)
- Support flake8 git hook. [sergio-alonso]
- Support python 3.6. [gforcada]
- Search configuration on home folder. [gforcada]
2.1.3 (2016-11-25)
- Fix yet another corner case. [gforcada]
2.1.2 (2016-11-25)
- Fix another corner case: ignored files. [cas–]
2.1.1 (2016-11-25)
- Fix corner cases of isort: newlines and grouped imports. [cas–]
2.1.0 (2016-11-24)
- Show the exact line and kind of error, rather than a generic message. [cas–]
2.0.3 (2016-11-22)
- Update trove classifiers. [gforcada]
2.0.2 (2016-11-22)
- Add flake8 classifier. [sigmavirus24]
- Require flake8 3.2.1. flake8 series 3.1.x and 3.2.0 where not reporting flake8-isort errors. [gforcada]
- Test on pypy and pypy3. [gforcada]
- Fix tests and formatting. [gforcada]
2.0.1 (2016-09-22)
- Fix standard input processing. [carljm]
2.0 (2016-09-14)
- Refactor code to handle flake8 version 3. [danpalmer]
- Require flake8 version 3.0. [gforcada]
1.3 (2016-06-20)
- Make error messages clearer. [do3cc]
- Use either pep8 or pycodestyle (new name for pep8). [Maxim Novikov]
- Fix coveralls. [gforcada]
1.2 (2016-03-05)
- Allow stdin processing, this way text editor can pass input to flake8. [mjacksonw]
1.1.1 (2016-02-16)
- Silence isort messages. [gforcada]
- Improve wording. [gforcada]
1.1 (2016-02-16)
- Check for isort configuration on setup.cfg as well. [plumdog]
1.0 (2015-12-16)
- Check for an isort configuration file. [gforcada]
0.2 (2015-09-14)
- Fix entry point. [gforcada]
0.1.post0 (2015-09-13)
- Release wheels as well. [gforcada]
0.1 (2015-09-13)
- Initial release [gforcada]
- Add all boilerplate files. [gforcada]
- Create the flake8 plugin per se. [gforcada]
Простые шаги сделать ваш Python код лучше
У многих из вас есть GIT- репозитории с кодом, в этой заметке я расскажу как сделать ваш Python код лучше.
Форкнем его и попробуем сделать код лучше.
Улучшим читаемость кода
Улучшить читаемость вашего кода очень просто. Мы будем использовать библиотеки для синтаксического форматирования и проверки.
Для начала создадим в репозитории файлы конфигураций для flake8, mypy и black
Установим их для начала:
pip install black flake8 mypy
Разберем flake8. Flake8 — инструмент, позволяющий просканировать код проекта и обнаружить в нем стилистические ошибки и нарушения различных конвенций кода на Python.
Файл setup.cfg для flake8 и mypy
[flake8] max-line-length = 120 exclude =.git,__pycache__,docs/source/conf.py,build,dist,tests ignore = I101,D100,D101,D102,D103,D104,D105,D107,D401,E203,I900,N802,N806,N812,W503,S311,S605,S607,ISC003,ISC001,T101,T000,F541,PL123 per-file-ignores = __init__.py:F401,F403 [mypy] ignore_missing_imports = True disallow_untyped_defs = True check_untyped_defs = True warn_redundant_casts = True no_implicit_optional = True strict_optional = True [mypy-tests.*] ignore_errors = True
- max-line-length — максимальная длина строки
- exclude — список папок, которые исключаются из сканирования flake8
- ignore — список ошибок/ предупреждений, которые так же исключаются. Например: I101: The names in your from import are in the wrong order и D100 — Missing docstring
- per-file-ignores — исключить из сканирования определенный файл
flake8 запустить очень просто:
flake8
Помните, что flake8 не модифицирует код, а просто проверят его. Подправить ошибки придется в ручную.
Теперь поговорим про mypy. У Python нет обязательной статической типизации, но рекомендуется добавлять типы в аргументы функции и возвращаемые типы. Для этого просто запустим mypy и не забудьте подправить ошибки:
mypy .
Создадим файл pyproject.toml для black. black поможет форматировать ваш код в соответствии со стандартом.
Файл pyproject.toml
[tool.black] line-length = 119 target-version = ['py36'] include = '\.pyi?$' exclude = ''' /( \.eggs | \.git | \.hg | \.mypy_cache | \.tox | \.venv | _build | buck-out | build | dist )/ '''
- line-length — длина строки
- target-version — версии Python. py36 — Python 3.6, можно и для других версий.
- include — список того, что включаем в форматирование
- exclude — список того, что исключаем из форматирования
Запуск тоже очень простой:
black .
Рекомендую сохранить отредактированный файл. Так же я уже исправил все ошибки mypy. Взглянем, что же поменялось.
Так выглядел код до правки:

А так после правки:

Код стал читабельнее и теперь у нас статическая типизация. Особое внимание обратите на тип Union. Использовать его необходимо когда допускается использование не любых типов, а только некоторых. Перечислить их нужно в квадратных скобках.
isort
isort — это библиотека Python для сортировки импорта по алфавиту с автоматическим разделением на разделы и по типу.
pip install isort
isort .
Так выглядели наши импорты до правки:

А так после применения isort:

Так же рекомендую сохранить отредактированный файл.
pre-commit hook
Мы можем запускать black, flake8 и mypy вручную, но это не удобно. Мы можем автоматизировать процесс с помощью pre-commit hook.
Файл .pre-commit-config.yaml
repos: - repo: https://github.com/asottile/pyupgrade rev: v2.19.4 hooks: - id: pyupgrade args: [ "--py38-plus" ] - repo: https://github.com/pre-commit/mirrors-isort rev: 1ba6bfc # Use the revision sha / tag you want to point at hooks: - id: isort args: ["--profile", "black"] - repo: https://github.com/psf/black rev: 21.6b0 hooks: - id: black - repo: https://gitlab.com/pycqa/flake8 rev: 3.9.2 hooks: - id: flake8 language_version: python3 - repo: https://github.com/pre-commit/pre-commit-hooks rev: v4.0.1 hooks: - id: check-docstring-first - id: check-json - id: check-merge-conflict - id: check-yaml - id: debug-statements - id: end-of-file-fixer - id: trailing-whitespace - id: requirements-txt-fixer - repo: https://github.com/pre-commit/mirrors-pylint rev: 56b3cb4 hooks: - id: pylint args: - --max-line-length=120 - --ignore-imports=yes - -d duplicate-code - repo: https://github.com/pre-commit/pygrep-hooks rev: v1.9.0 hooks: - id: python-check-mock-methods - id: python-use-type-annotations - id: python-check-blanket-noqa - id: python-use-type-annotations - id: text-unicode-replacement-char - repo: https://github.com/pre-commit/mirrors-mypy rev: 9feadeb hooks: - id: mypy exclude: ^tests/ args: [ --disallow-untyped-defs, --check-untyped-defs, --warn-redundant-casts, --no-implicit-optional, --strict-optional ]
Теперь каждый коммит будет запускаться наше форматирование и проверки. Теперь сделаем, что бы Github запускал их при каждом pull request.
Github Actions
Для наших целей будем использовать Github Action. Создадим файл ci.yaml
Файл .github/workflows/ci.yaml
name: Python package on: push: branches: [ master ] pull_request: branches: [ master ] jobs: build: runs-on: ubuntu-latest strategy: matrix: python-version: [3.6] steps: - uses: actions/checkout@v2 - name: Set up Python uses: actions/setup-python@v2 with: python-version: $> # You can test your matrix by printing the current Python version - name: Display Python version run: python -c "import sys; print(sys.version)" - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements_dev.txt - name: Run black run: black --check . - name: Run flake8 run: flake8 - name: Run Mypy run: mypy pandaseda
Основное внимание обратите на:
- name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements_dev.txt - name: Run black run: black --check . - name: Run flake8 run: flake8 - name: Run Mypy run: mypy pandaseda
Тут указаны наши проверки. Black тут запускаем с флагом check. Black не будет редактировать код, но выполнит проверку. Именно поэтому лучше сохранить файл после запуска black заранее.
Action теперь готов, его можно запустить при любом коммите. После запуска можно посмотреть ход выполнения и результат во вкладке Action.

В случае ошибок на почту будет отправлен email:

Саму ошибку можно так же посмотреть в Action:

Заключение
В этой заметке получилось рассмотреть несколько библиотек для работы с вашим кодом. Отдельно рассмотрели pre-commit hook и Github Actions.
Дополнительный материал
- Документация по GitHub Actions
- isort
- Документация по mypy
- Стильный код на Python, или учимся использовать Flake8
- black
Линтинг — Python: Настройка окружения
У кода есть множество разных характеристик, по которым можно судить, насколько хорошо он написан. Среди них есть одна базовая, с которой начинают все разработчики — это стиль написания.
Сравните два варианта оформления кода:
## Без форматирования def find_sum(a,b): c = a+b; return c ## С форматированием def find_sum(a, b): sum = a + b return sum
Второй вариант читается значительно проще. Чем больше будет кода, тем больше будет различий. Хороший стиль кодирования — базовое требование к коду в коммерческой разработке, потому что он упрощает командную разработку. В одном проекте может работать несколько десятков программистов. Важно, чтобы им было легко читать код друг друга, не спотыкаясь о неправильное форматирование.
Для отслеживания подобных ситуаций существуют линтеры — особый класс программ. Линтеры содержат большое количество правил, по которым они могут выдать рекомендации по коду. Другими словами, они подсказывают, как стоит писать код, а как — не стоит. Более того, часто линтеры расширяются плагинами под конкретные фреймворки, что позволяет отслеживать специфичные ошибки и давать рекомендации по кодированию в этих фреймворках.
В Python особой популярностью пользуется линтер flake8 . Количество правил, по которым он проверяет код, исчисляется десятками . Посмотрите на этот небольшой участок кода:
from math import sqrt def sum(a, b): c = 5 return a + b
С точки зрения форматирования здесь все хорошо, а что скажет линтер flake8?
Он выдаст два предупреждения:
- F401 ‘math.sqrt’ imported but unused . Модуль импортируется, но не используется — либо он не нужен, либо в коде есть ошибка
- F841 local variable ‘c’ is assigned to but never used . Переменная не используется — либо она не нужна, либо в коде ошибка
Ссылки выше ведут на страницы конкретных правил. Там подробно объясняется, почему так код писать не нужно. Изучать правила flake8 очень полезно, они прививают хорошие практики написания кода.
Установка и настройка flake8
Линтер flake8 устанавливается как dev зависимость прямо в проект:
--group=dev flake8
После установки его можно настроить под набор ваших правил и ограничений. Для этого нужно создать файл конфигурации setup.cfg, который нужно добавить в репозиторий. Ниже пример такого файла, который используется для настройки линтера в наших практиках:
Выше настраивается максимальная сложность функций, максимальная длина строчки кода и другие параметры. Так же мы можем указать, какие файлы не нужно проверять линтером или какие правила можно игнорировать. Список всех опций вы можете изучить в документации .
И последний шаг — запуск flake8:
# Обратите внимание на точку # Это указание текущей директории и всех поддиректорий poetry run flake8 .
Открыть доступ
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно
- 130 курсов, 2000+ часов теории
- 1000 практических заданий в браузере
- 360 000 студентов
Наши выпускники работают в компаниях:
Лучшие практики разработки на Python
Цель этой статьи — поделиться лучшими практиками разработки на Python. Вы узнаете, как настроить и использовать репозиторий Github. Я познакомлю вас с полезными инструментами для поддержания чистоты и правильности кода, покажу, как настроить репозиторий и включить в него ранее представленные инструменты для автоматизированной проверки CI (непрерывной интеграции).
В завершение мы соберем все это вместе в образце проекта. Заметьте, я не утверждаю, что список рекомендуемых практик Python-разработки является полным и единственно возможным. Просто хочу поделиться собственным профессиональным опытом работы инженером-программистом. Могу подтвердить, что многие крупные компании, которые разрабатывают ПО, следуют аналогичной схеме.
С учетом сказанного, перейдем непосредственно к содержательной части. Полный код можно найти здесь.
Используемые инструменты
В этом разделе перечислим инструменты, необходимые для разработки Python-репозитория.
poetry
Poetry — это удобный инструмент для управления версиями и зависимостями Python. С его помощью легко контролировать и корректировать версии, а также централизованно управлять зависимостями. Из всех способов сделать это рекомендую poetry. Теперь кратко о том, как использовать этот инструмент.
Основой управления зависимостями в poetry является файл pyproject.toml . В нашем проекте он начинается следующим образом:
[tool.poetry]
name = "Sample Python Project"
version = "0.1.0"
description = "Sample Python repository"
authors = ["hermanmichaels "]
[tool.poetry.dependencies]
python = "3.10"
matplotlib = "3.5.1"
mypy = "0.910"
numpy = "1.22.3"
pytest = "7.1.2"
black = "22.3.0"
flake8 = "4.0.1"
isort = "^5.10.1"
Как видите, заголовок определяет и раскрывает основные свойства проекта. За ним следует абзац, определяющий необходимые зависимости.
Нужно просто выполнить poetry install в терминале, и poetry автоматически создаст среду Python со всеми установленными зависимостями. Затем можно войти в него через poetry shell .
После добавления новой зависимости нужно запустить poetry update . Это создаст или обновит файл poetry.lock , который можно представить как двоичное представление вышеуказанных зависимостей. Его также нужно будет добавить в репозиторий, и описанный выше процесс установки требований использует этот файл.
isort
PEP 8, руководство по стилю для Python, определяет, как упорядочить импорты. Рекомендуется создавать следующие группы.
- Импорт стандартных библиотек (например, os и sys ).
- Импорт сторонних производителей (например, numpy ).
- Локальный, специфический для проекта импорт (например, различные файлы одного проекта).
Внутри этих групп импортированные инструменты должны быть отсортированы в алфавитном порядке.
isort — это инструмент, который позволяет не запоминать и не выполнять все это самостоятельно. Удобно то, что isort и большинство инструментов, представленных в следующих разделах, отлично работают с poetry. Можно даже задать их настройки в файле pyproject.toml . Для нашего случая установим следующее:
[tool.isort]
profile = "black"
py_version = 310
multi_line_output = 3
В дополнение к версии Python сообщаем isort, что будем работать с форматером black (см. следующий раздел), и определяем, как будут переформатироваться импорты, которые слишком длинны для одной строки.
black
black — это форматер Python-кода. Его запуск приводит к форматированию кода в соответствии с действующими соглашениями. Призывая всех разработчиков использовать его, мы обеспечиваем определенный, единый стиль кода. Подумайте об отступах строк, количестве пустых строк после функций и т. д.
Настройками также управляет poetry, а мы просто задаем:
[tool.black]
line-length = 80
target_version = ["py310"]
Т.е. указываем максимальную длину строки (80) и целевую версию Python.
flake8
flake8 — это линтер кода. Линтеры и форматеры кода близки по своему назначению, однако линтеры проверяют соблюдение определенных стилей и рекомендаций, но не форматируют код. flake8 выполняет несколько функций, одна из которых — проверка на соответствие ранее упомянутому стандарту PEP 8.
mypy
mypy — это статическая проверка типов Python. Как вы (наверняка) знаете, Python — динамически типизированный язык, то есть типы переменных определяются во время выполнения (в отличие от, например, C++). Эта гибкость, которую мы все ценим, имеет свои недостатки, такие как большая вероятность совершения ошибок без компилятора или аналогичного средства, выступающего в качестве первой линии обороны.
Поэтому в последние годы многие усилия направлены на то, чтобы сделать проверку типов в Python более строгой. mypy является такой программой проверки типов, следящей за правильным использованием переменных. В основном это происходит автоматически, но вы также можете сделать определенные типы явными, аннотировав их (что для наглядности рекомендуется выполнять в любом случае в отношении параметров функций и возвращаемых типов).
Можно аннотировать аргументы функций и возвращаемые типы следующим образом:
def foo(x: int, y: int) -> int:
return x + y
Тогда mypy будет сигнализировать о нарушении, если вы попытаетесь вызвать функцию с неправильными аргументами, например:
foo("a", "b")
Управлять настройками mypy будем в отдельном файле mypy.ini . Это необходимо главным образом потому, что некоторые внешние зависимости не могут быть проверены на тип, и нужно исключить их из проверки (хотя какие-то из них можно настроить).
pytest
Модульное тестирование необходимо любому профессиональному программному продукту, хотя желательно тестировать каждый проект. Мы будем использовать pytest, который предпочитают многие разработчики Python.
Модульное тестирование помогает отлавливать ошибки и тем самым поддерживать качество кода на высоком уровне.
Github Actions
Github Actions позволяет автоматизировать и запускать определенные шаги в репозитории — в духе непрерывной интеграции. С помощью этого инструмента можно создавать рабочие процессы, которые будут выполняться для определенных событий, таких как запросы на включение изменений (PR).
Рабочий процесс, который будет использован здесь, фактически является совокупной деятельностью вышеупомянутых инструментов: для каждого открытого PR будут выполняться форматирование, линтинг, проверка типов и модульные тесты. И все это должно осуществляться перед слиянием, чтобы защитить основную ветку от коммита любого нечистого и ошибочного кода!
Настройка репозитория
В этой статье не будут рассматриваться с нуля системы контроля версий и настройка репозиториев Github. Предполагается наличие у читателей определенных базовых знаний. При необходимости можно обратиться к туториалам, например к официальному руководству Github. Здесь же поговорим только о настройках в Git, которые есть практически в любом профессиональном репозитории программного обеспечения.
Собственно говоря, нужно установить лишь одну настройку — защиту основной ветки. Чтобы кто-то не попал в нее без проверок, необходимо обеспечить выполнение ваших требований, в частности одобрения другими разработчиками и прохождения установленных вами CI-тестов. Для этого зайдите в репозиторий и выберите “Settings” (“Настройки”), а затем “Branches” (“Ветки”):
Потом добавьте правила защиты основной ветки.
- Требовать запрос на добавление изменений перед слиянием.
- Требовать одобрения (можно выбрать количество необходимых одобрений).
- Требовать прохождения проверки состояния перед слиянием.
Соберем все вместе
Мы подготовили все необходимые инструменты. Теперь соберем их вместе, создадим образец репозитория и запустим рабочий процесс, которому должен следовать каждый разработчик.
Образец проекта
Проект будет иметь папку utils , содержащую файл math_utils.py и связанный с ним файл модульного теста ( math_utils_test.py ). В math_utils повторно реализуем функцию экспоненциализации в демонстрационных целях:
import numpy.typing as npt
def exponentiate(base: int, exponent: npt.NDArray) -> npt.NDArray:
return base**exponent
Таким образом, exponentiate(2, [1, 2, 3]) вернет [2, 4, 8] .
Проверим корректность функции в тестовом файле:
import numpy as np
import numpy.typing as npt
import pytest
from utils.math_utils import exponentiate
@pytest.mark.parametrize(
"base, exponent, expected",
[
(2, np.zeros(3), np.ones(3)),
(2, np.linspace(1, 4, 4), np.asarray([2, 4, 8, 16])),
],
)
def test_exponentiate(base: int, exponent: npt.NDArray, expected: npt.NDArray) -> None:
assert np.allclose(exponentiate(base, exponent), expected)
В основном файле ( main.py ) будем использовать эту функцию для генерации первых 10 значений степени 2 и построения графика с помощью matplotlib :
import matplotlib.pyplot as plt
import numpy as np
from utils.math_utils import exponentiate
def main() -> None:
x = np.linspace(0, 10, 10)
y = exponentiate(2, x)
plt.plot(x, y, "ro")
plt.savefig("plot.png")
if __name__ == "__main__":
main()
Файл pyproject.toml для этого проекта выглядит следующим образом:
[tool.poetry]
name = "Sample Python Project"
version = "0.1.0"
description = "Sample Python repository"
authors = ["hermanmichaels "]
[tool.poetry.dependencies]
python = "3.10"
matplotlib = "3.5.1"
mypy = "0.910"
numpy = "1.22.3"
pytest = "7.1.2"
black = "22.3.0"
flake8 = "4.0.1"
isort = "^5.10.1"
[tool.poetry.dev-dependencies]
[tool.black]
line-length = 80
target_version = ["py310"]
[tool.isort]
profile = "black"
py_version = 310
multi_line_output = 3
Кроме того, исключаем matplotlib из проверки mypy для предотвращения ошибок, создав следующий файл mypy.ini :
[mypy]
python_version = 3.10
[mypy-matplotlib.*]
ignore_missing_imports = True
ignore_errors = True
Рабочий процесс Github
Теперь определим следующий рабочий процесс Github Actions:
name: Sample CI Check
on:
pull_request:
branches: [main]
push:
branches: [main]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- name: Set up Python 3.10.0
uses: actions/setup-python@v3
with:
python-version: "3.10.0"
- name: Install poetry dependencies
run: |
curl -sSL https://install.python-poetry.org | python3 -
poetry install
- name: Sort imports with isort
run: poetry run python -m isort .
- name: Format with black
run: poetry run python -m black .
- name: Lint with flake8
run: poetry run python -m flake8 .
- name: Check types with mypy
run: poetry run python -m mypy .
- name: Run unit tests
run: poetry run python -m py.test
Таким образом, этот рабочий процесс запускается для каждого нового PR и для каждого PR, объединенного с основным.
Он состоит из следующих шагов.
- Проверка репозитория.
- Установка Python 3.10.
- Установка poetry и зависимостей.
- Запуск всех установленных проверок (обратите внимание, что poetry run X идентичен входу в среду poetry через poetry shell и последующему выполнению X ). В частности, осуществляется запуск сортировки импорта с помощью isort, форматирования кода с помощью black, линтинга с помощью flake8, проверки типов с помощью mypy и модульного тестирования с помощью pytest.
Локальный рабочий процесс разработчика
Теперь опишем рабочий процесс, который каждый разработчик должен выполнять время от времени, особенно перед тем, как генерировать PR. В предыдущем разделе выражение “рабочий процесс” обозначало концепцию Github по группировке шагов в рабочем процессе, а здесь оно просто описывает шаги, которые должен выполнить разработчик.
Не стоит полагаться на CI и нагружать его поиском всех ошибок. Необходимо отправлять PR как можно более “чистыми”. Это означает, что следует проделывать все шаги, выполняемые на CI, самостоятельно локально перед отправкой. Это достигается следующим образом:
- запуск isort для сортировки импорта: isort ;
- запуск black для форматирования кода: black ;
- запуск flake8 для проверки кода: python -m flake8 ;
- запуск mypy для проверки типов: mypy (в первый раз это может занять довольно много времени);
- запуск всех модульных тестов: python -m pytest .
Заключение
В этой статье описаны полезные инструменты, помогающие организовывать и поддерживать код Python в хорошем состоянии в соответствии с профессиональными стандартами. Мы также показали, как создать Git-репозиторий для версионирования и обмена этим кодом и, в частности, как использовать ранее представленные инструменты в CI (выполнение определенных проверок для предотвращения любых нечистых и ошибочных коммитов в основную ветку). Наконец, мы показали, как запустить все эти инструменты локально, чтобы минимизировать риск сбоя CI.
- 5 приемов Python, которые отличают профессионалов от новичков
- Как развернуть пакет Cython в PyPI
- Зачем Python столько знаков подчеркивания?
Читайте нас в Telegram, VK и Дзен