Стильний код на Python, або вчимося використовувати Flake8


Автор: Анатолій Соловей, developer

Мова програмування Python дуже затребуваний на сучасному ринку, він розвивається з дня на день, і навколо нього склалося активне співтовариство. Щоб уникнути конфліктів між розробниками-питонистами, творці мови написали угоду PEP 8, описує правила оформлення коду, проте навіть там зазначено, що:
Many projects have their own coding style guidelines. In the event of any conflicts, such project-specific guides take precedence for that project.
В результаті додавання нових правил кількість вимог до оформлення коду збільшилася настільки, що утримати їх в голові стало дуже важко. При цьому звернення до гайдів може займати багато часу і відволікати від процесу розробки.

За довгий час роботи у програмістів виробляється власний стиль написання коду, переваги стайлгайдах та інші дрібниці, які залишають авторську друк на програмах девелопера. Переконати розробників відмовитися від звичних їм кодстайлов дуже складно, але, навіть якщо це вдасться, великий шанс, що у їх коді будуть проскакувати старі фішки, додані в силу звички.

Коли кожен апдейт проходить суворий код рев'ю, що включає в себе перевірку стилів, подібні помилки можуть дуже сильно сповільнювати процес розробки. А якщо помилки в підсумку не помітять навіть в процесі рев'ю, в системі контролю версій проекту дуже скоро з'явиться купа нечитаемого і незрозумілого коду.

На допомогу в цьому випадку приходять линтеры — інструменти, контролюючі оформлення коду у проекті. Саме вони допомагають підтримувати чистоту і, в нашому випадку, запобігати створення комітів, які можуть містити помилки. Я для контролю якості використовую Flake8 і зараз постараюся пояснити, чому вибрав саме його, і розповім, як його налаштувати, щоб отримати максимальний результат. Зацікавилися? Ласкаво просимо під кат.


Flake8: Tool For Your Style Guide Enforcement
Сам Flake8 — інструмент, що дозволяє просканувати код проекту і виявити в ньому стилістичні помилки і порушення різних конвенцій коду на Python.

Flake8 вміє працювати не тільки з PEP 8, але і з іншими правилами, до того ж підтримує кастомні плагіни, тому надалі в цій статті я буду відштовхуватися від правил з Google Python Style Guide.

Чому Flake8?
Flake8: pep8 + pyflakes + more

Творець Flake8 Тарек Зіад ставив перед собою мету об'єднати головні популярні інструменти контролю кодстайла в одній бібліотеці, з чим у підсумку успішно впорався — Flake8 вийшов дійсно універсальним.

Легкість установки і конфігурації

Щоб перевірити, чи відповідає код в вашому проекті основним вимогам PEP 8, досить встановити Flake:

$ pip install flake8

і виконати його — просто ввести в командному рядку:

$ flake8 my_project

після чого ви отримаєте список з іменами файлів і номерами рядків, де були допущені помилки, і докладний опис самих помилок:

$ flake8 my_project
myfile.py:1: 'sys' imported but unused
myfile.py:4:1: E302 expected 2 blank lines, found 1

Чудово, чи не правда? Але і це не все. Якщо ви не любитель працювати з консоллю, то ви можете налаштувати інтеграцію Flake8 з IDE або редактором, який ви віддаєте перевагу використовувати.

Інтеграція Flake8 з редакторами і IDE

Інтеграція з PyCharm
Так само і будь-який інший IDE від JetBrains.
Інтеграція проводиться лише за кілька нескладних кроків.

Відкрийте налаштування External Tools File- > Settings->Tools і натисніть на "+", потім заповніть поля за цим шаблоном:


Після цього натисніть на Output Filters, а потім на "+", щоб додати нове правило для виведення повідомлень від флейка:

тут ми говоримо PyCharm, що хочемо, щоб у висновку рядки з помилками були клікабельними і відкривали в редакторі файл і місце з помилкою

Всі. Інтеграція Flake8 з PyCharm закінчена. Щоб викликати флейк і перевірити свій код, натискаємо правою кнопкою миші на файл/папку, яку ми хочемо перевірити і в контекстному меню вибираємо External Tools -> Flake8.


У висновку PyCharm з'явиться клікабельний список порушень у вибраному файлі/директорії:


Інтеграція з Atom
Щоб встановити інструмент Flake8 для Atom, використовуйте Atom package manager Settings і знайдіть там linter-flake8:


або викличте

apm install flake8

з командного рядка.

Потім перейдіть в linter-flake8 settings і вкажіть шлях до директорії, де встановлено flake8:


У linter-flake8 є власний ReadMe по налаштуванню, з яким при бажанні ви можете ознайомитися на сторінці самого linter-flake8 в Atom.

Наявність Version Control Hooks
Саме це я вважаю головним достоїнством Flake8, яка виділяє його серед інших лінтер. На відміну від більшості подібних інструментів, де для налаштування VCS-хуків використовуються цілі окремі бібліотеки і модулі (як, наприклад, у Pylint), налаштування хуків в флейке проводиться буквально в два рядки.

На момент написання цієї статті, Flake8 вміє використовувати pre-commit-хуки для Git і Mercurial. Ці хуки дозволяють, наприклад, не допускати створення коміта при порушенні будь-яких правил оформлення.

Встановити хук для Git:

$ flake8 --install-hook git

І налаштувати сам гіт, щоб враховувати правила Flake8:

$ git config --bool flake8.strict true

Я продемонструю, як Git hook працює на проекті, який я використовував для прикладу інтеграції Flake8 з PyCharm. У модулі flake8tutorial.py ми бачимо очевидні помилки: імпортовані та невикористані модулі, остсутствие докстринга і порожній рядок в кінці файлу.

Першим ділом проинициализируем в цьому проекті git-0репозиторий, встановимо flake8 хук і скажемо нашому git, що він повинен проганяти флейк перед коммитами:


Потім спробуємо провести перший комміт:


Як бачите, flake8 був викликаний перед комітом і не дозволив нам закоммитить невалідні зміни.

Тепер фиксим помилки, зазначені флейком, і намагаємося закоммитить валідний код:


Комміт успішно створений. Відмінно!

Налаштування Flake8 для Mercurial практично ідентична. Для початку потрібно встановити Flake8 Mercurial Hook:
$ flake8 --install-hook mercurial


І налаштувати сам Mercurial:
$ hg config flake8.strict true


Ось і все, хук для Меrcurial встановлено, налаштований і готовий до використання!

Докладніше про конфігурації Flake8
Базова конфігурація
Список додаткових опцій і правил можна передати прямо при виклику з командного рядка таким чином:

flake8 --select E123

(у цьому прикладі опцією select ми говоримо, щоб Flake повідомляв про порушення правила E123 (це код правила «closing bracket does not match indentation opening of bracket's line»)).

До речі, повний список опцій з описом ви можете знайти на документації до самої бібліотеці.

На мій погляд, куди краще налаштовувати Flake за допомогою конфігураційних файлів, ви можете зберігати налаштування в одному з файлів setup.cfg, tox.ini або.flake8. Для ясності я віддаю перевагу використовувати останній варіант.

Файл з настройками дозволяє контролювати використання бібліотекою тих же опцій, що налаштовуються для командного рядка, базовий конфігураційний файл виглядає так:

[flake8]
ignore = D203
exclude = .git__pycache__,docs/source/conf.py,old,build,dist

У цьому файлі ми повідомляємо Flake, що він не повинен сповіщати нас про порушення правила D203 («1 blank line required before class docstring»), а також не повинен перевіряти файли .git__pycache__,docs/source/conf.py і директорії old, build, dist.

У конфігураційних файлах можна залишати коментарі, це корисно, якщо ви надаєте великий список правил, які Flake повинен ігнорувати:

[flake8]
# it's not a bug that we aren't using all of hacking
ignore =
# F812: list comprehension redefines ...
F812,
# H101: Use TODO(NAME)
H101,
# H202: assertRaises Exception too broad
H202,
# H233: Python 3.x incompatible use of print operator
H233,
# H301: one import per line
H301,
# H306: imports not in alphabetical order (time, os)
H306,
# H401: docstring should not start with a space
H401,
# H403: multi line docstrings should end on a new line
H403,
# H404: multi line docstring should start without a new leading line
H404,
# H405: multi line docstring summary not separated with an empty-line
H405,
# H501: Do not use self.__dict__ for string formatting
H501


Також можна додати до виключення окремий рядок у вашому модулі, просто залишивши на цій рядку коментар noqa. Тоді при перевірці модуля Flake8 буде ігнорувати помилки, знайдені у рядках, позначених цим коментарем:

import sys # noqa


Модулі, що розширюють функціональність
Так як Flake дозволяє створювати і використовувати кастомні плагіни, для нього можна знайти велику кількість open-source плагінів. Я опишу тільки ті, які використовую сам і вважаю особливо корисними:

flake8-import-order

Плагін, перевіряючий порядок импортов у проекті: в стандартній конфігурації першими повинні йти імпорти стандартних бібліотек (stdlib), потім імпорти сторонніх бібліотек, а потім локальні пакети, причому кожна група відокремлена порожнім рядком і відсортована в алфавітному порядку.

Цей плагін розширює список попереджень Flake, додаючи туди три нових:

  • I100: import Your statements are in the wrong order.
  • I101: The names in your import from are in the wrong order.
  • I201: Missing newline between sections or imports.
Установка:

pip install flake8-import-order

Конфігурація:

[flake8]
application-import-names = my_project, tests # Вказуємо флейку директорії, в яких зберігаються локальні пакети.
import-order-style = google # Вказуємо флейку на те, в якому порядку повинні йти імпорти. Як я вже говорив вище, я віддаю перевагу використовувати Google Style Guide.

Більш докладно про налаштування flake8-import-order можна прочитати на сторінці бібліотеки на Github.

flake8-docstrings

Плагін, який додає підтримку функціоналу з pydocstyle — перевірку докстрингов на відповідність конвенціям Пітона.

Установка:

pip install flake8_docstrings

Список доданих цією бібліотекою правил можна знайти на документації pydocstyle.

Конфігурація:

Сама по собі ця бібліотека ніяк не налаштовується, проте додані правила можна внести до виключення, якщо якийсь із них неактуально для вашого проекту:

[flake8]
ignore = D101 # Ігнорувати docstrings попередження "Missing docstring in public class"

Сторінка бібліотеки на Github тут.

flake8-builtins

Плагін, перевіряючий код на використання вбудованих імен в якості змінних або параметрів.

Установка:

pip install flake8-builtins

Конфігурація:

Як і у випадку з flake8-docstrings, у плагіна немає додаткових налаштувань, але додані їм правила можна, наприклад, внести до виключення флейка:

[flake8]
ignore = B001 # Ігнорувати builtins попередження "<some_builtin> is a python builtin and is being shadowed, consider renaming the variable"

Більш детальну інформацію про цьому плагіні можна знайти на сторінці цього плагіна на Github.

flake8-quotes

Плагін, що дозволяє контролювати тип лапок, які будуть використовуватися в проекті.

Установка:

pip install flake8-quotes

Конфігурація:

[flake8]
inline-quotes = " # Вказуємо, який тип лапок повинен використовуватись у вашому проекті

Більш детальну інформацію про цьому плагіні можна знайти на сторінці цього плагіна на Github.

Післямова
Хоча параметри, описані вище, в 97,5 % випадків зможуть запобігти появу неякісного коду в репозиторії, він так чи інакше може виявитися запушенным (наприклад, якщо діву було лінь вводити дві строчки для налаштування pre-commit hook). Тому я настійно рекомендую додати виклик Flake8 на етапі білду пул-реквестов в використовуваної вами системі continuous integration, щоб запобігти мердж валідних пул-реквестов і потрапляння помилок у майстер.

Сподіваюся, ця стаття була вам корисна і дозволить надалі максимально гнучко і якісно налаштувати робочий процес і стайлгайды у ваших Python-проектах. Всіх благ.

Список джерел:

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.