HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-03-10
1 <p>Теги: python, bash, программирование на python, fabric, веб-пайтон, локальная автоматизация</p>
1 <p>Теги: python, bash, программирование на python, fabric, веб-пайтон, локальная автоматизация</p>
2 <p>Чаще всего<strong>Fabric</strong>вспоминают, когда речь идёт об автоматизации деплоя и работы с удалёнными нодами. Но на самом деле он так же прекрасно справляется и с автоматизацией локальных задач. Он удобнее обычного<em>баша</em>тем, что в нём есть<strong>вся гибкость Python</strong>, и круче чистого Python множеством готовых админских функций.</p>
2 <p>Чаще всего<strong>Fabric</strong>вспоминают, когда речь идёт об автоматизации деплоя и работы с удалёнными нодами. Но на самом деле он так же прекрасно справляется и с автоматизацией локальных задач. Он удобнее обычного<em>баша</em>тем, что в нём есть<strong>вся гибкость Python</strong>, и круче чистого Python множеством готовых админских функций.</p>
3 <p>Лично я пользуюсь им для<strong>локальной автоматизации</strong>довольно часто. Один из примеров - проверка домашних заданий в OTUS. С его помощью я ускоряю проверку стилей и статического анализа кода.</p>
3 <p>Лично я пользуюсь им для<strong>локальной автоматизации</strong>довольно часто. Один из примеров - проверка домашних заданий в OTUS. С его помощью я ускоряю проверку стилей и статического анализа кода.</p>
4 <h2>Давайте посмотрим, как это выглядит</h2>
4 <h2>Давайте посмотрим, как это выглядит</h2>
5 <p>Прежде всего, у меня создана папка ~/otus/homeworks/, в которой лежит<strong>fabfile.py</strong>и виртуальное окружение otus с установленными и настроенными линтерами.</p>
5 <p>Прежде всего, у меня создана папка ~/otus/homeworks/, в которой лежит<strong>fabfile.py</strong>и виртуальное окружение otus с установленными и настроенными линтерами.</p>
6 <p>Работаем мы локально, так что нам нужна функция local из состава Fabric.</p>
6 <p>Работаем мы локально, так что нам нужна функция local из состава Fabric.</p>
7 import os from fabric.api import local, lcd, task, settings<p>Поскольку ДЗ студенты сдают в виде git-репозиториев, мне нужна функция, которая будет клонировать их в локальные папки.</p>
7 import os from fabric.api import local, lcd, task, settings<p>Поскольку ДЗ студенты сдают в виде git-репозиториев, мне нужна функция, которая будет клонировать их в локальные папки.</p>
8 def prepare_repo(repo, pull=True): project_path = repo.split(':')[1] if project_path.endswith('.git'): project_path = project_path[:-4] if not os.path.exists(project_path): os.makedirs(project_path) local('git clone {} {}'.format(repo, project_path)) elif pull: with lcd(project_path): local('git pull') return project_path<p>Часто проекты проходят несколько этапов проверок, функция может проверять, есть ли уже репозиторий, и если есть - вытягивать обновления.</p>
8 def prepare_repo(repo, pull=True): project_path = repo.split(':')[1] if project_path.endswith('.git'): project_path = project_path[:-4] if not os.path.exists(project_path): os.makedirs(project_path) local('git clone {} {}'.format(repo, project_path)) elif pull: with lcd(project_path): local('git pull') return project_path<p>Часто проекты проходят несколько этапов проверок, функция может проверять, есть ли уже репозиторий, и если есть - вытягивать обновления.</p>
9 <p>А дальше у меня есть несколько тасков:<strong>flake, pylint, mccabe</strong>и т.д. Они все примерно одинаковые, так что приведу в пример только одну:</p>
9 <p>А дальше у меня есть несколько тасков:<strong>flake, pylint, mccabe</strong>и т.д. Они все примерно одинаковые, так что приведу в пример только одну:</p>
10 @task @task def flake8(repo, pull=True): project_path = prepare_repo(repo, pull) with lcd(project_path): with settings(warn_only=True): result = local('/path/to/venv/otus/bin/flake8 .') return result.return_code == 0<p>Получив из функции подготовки репозитория путь до папки, мы переключаемся в неё, используя<strong>lcd</strong>. Это аналог<strong>cd</strong>, только для работы локально. После мы включаем режим warn_only. Он нужен, чтобы выполнение скрипта не прекратилось, если<strong>flake8</strong>вернёт код, отличный от нуля. А он именно так и сделает, если в коде есть хоть одно замечание. Как результат, функция вернёт булево значение - были ли замечания.</p>
10 @task @task def flake8(repo, pull=True): project_path = prepare_repo(repo, pull) with lcd(project_path): with settings(warn_only=True): result = local('/path/to/venv/otus/bin/flake8 .') return result.return_code == 0<p>Получив из функции подготовки репозитория путь до папки, мы переключаемся в неё, используя<strong>lcd</strong>. Это аналог<strong>cd</strong>, только для работы локально. После мы включаем режим warn_only. Он нужен, чтобы выполнение скрипта не прекратилось, если<strong>flake8</strong>вернёт код, отличный от нуля. А он именно так и сделает, если в коде есть хоть одно замечание. Как результат, функция вернёт булево значение - были ли замечания.</p>
11 <p>Аналогично устроены и остальные проверки. Но на практике я редко запускаю их отдельно. Кроме отдельных проверок, у меня есть одна общая:</p>
11 <p>Аналогично устроены и остальные проверки. Но на практике я редко запускаю их отдельно. Кроме отдельных проверок, у меня есть одна общая:</p>
12 @task def all(repo): prepare_repo(repo, True) checks = [] checks.append(flake8(repo, False)) checks.append(pylint(repo, False)) checks.append(mccabe(repo, False)) … if all(checks): print('Perfect!')<p>Таким образом, чаще всего я запускаю именно одну эту задачу, которая проверяет весь код, выводя основные нарушения, если они есть.</p>
12 @task def all(repo): prepare_repo(repo, True) checks = [] checks.append(flake8(repo, False)) checks.append(pylint(repo, False)) checks.append(mccabe(repo, False)) … if all(checks): print('Perfect!')<p>Таким образом, чаще всего я запускаю именно одну эту задачу, которая проверяет весь код, выводя основные нарушения, если они есть.</p>
13 <p>Разумеется, проверка кода на этом не заканчивается. Стилистические замечания лишь малая часть процесса. Но благодаря автоматизации, эта часть делается быстро и оставляет больше времени на остальной анализ.</p>
13 <p>Разумеется, проверка кода на этом не заканчивается. Стилистические замечания лишь малая часть процесса. Но благодаря автоматизации, эта часть делается быстро и оставляет больше времени на остальной анализ.</p>
14  
14