Skip to content

Instantly share code, notes, and snippets.

@Hammer2900
Last active April 14, 2025 12:15
Show Gist options
  • Save Hammer2900/f87ee17f9294001d2794a9ab8b572a63 to your computer and use it in GitHub Desktop.
Save Hammer2900/f87ee17f9294001d2794a9ab8b572a63 to your computer and use it in GitHub Desktop.
fabric config default vars 2025
import os
import sys
from invoke import Config, Local, Context, FailingResponder, StreamWatcher
# --- Демонстрация ВСЕХ стандартных ключей конфигурации Invoke ---
# Создадим словарь, который будет содержать примеры для всех
# стандартных ключей конфигурации. Мы передадим его в `defaults`.
# В реальном приложении эти значения могут быть установлены в файлах
# конфигурации, переменных окружения или через флаги командной строки.
comprehensive_defaults = {
# --- Настройки выполнения команд (run.*) ---
"run": {
# Выполнять ли команду асинхронно (возвращает Promise)
"asynchronous": False,
# Отсоединять ли асинхронный процесс от Invoke (не ждать завершения)
"disown": False,
# "Холостой ход": печатать команды вместо выполнения
"dry": False,
# Печатать ли команду перед выполнением
"echo": True, # Пример: переопределяем стандартное False
# Формат для печати команды при echo=True
"echo_format": ">>> {command}",
# Эхо ввода stdin в stdout (None для автоопределения)
"echo_stdin": None,
# Кодировка для потоков ввода/вывода подпроцесса (None для автоопределения)
"encoding": "utf-8",
# Словарь переменных окружения для подпроцесса (добавляются к os.environ)
"env": {"MY_VAR": "my_value", "OTHER_VAR": "other"},
# Файлоподобный объект для stderr подпроцесса (None = sys.stderr)
"err_stream": None, # Можно указать, например, open('err.log', 'w')
# Использовать ли PTY, если обычный запуск не удался (зависит от Runner'а)
"fallback": True,
# Скрывать ли вывод ('out', 'err', 'both', True, False, None)
"hide": None,
# Файлоподобный объект для stdin подпроцесса (None = sys.stdin, False = отключить)
"in_stream": None,
# Файлоподобный объект для stdout подпроцесса (None = sys.stdout)
"out_stream": None, # Можно указать, например, open('out.log', 'w')
# Использовать ли псевдотерминал (PTY) для запуска команды
"pty": False,
# Заменять ли полностью окружение (`env`), а не обновлять os.environ
"replace_env": False,
# Оболочка для выполнения команды
"shell": "/bin/zsh", # Пример: переопределяем стандартную оболочку
# Предупреждать ли о ненулевом коде выхода вместо падения (False = падать)
"warn": False,
# Список объектов StreamWatcher для автореагирования на вывод
"watchers": [
# Пример: Автоматически вводить 'yes' на вопрос 'Are you sure?'
FailingResponder(pattern=r"Are you sure\?", response="yes\n", sentinel="Incorrect"),
# Можно добавить свои кастомные классы
# MyCustomWatcher(),
],
},
# --- Настройки доступных исполнителей (runners.*) ---
# Определяет, какие классы используются для локального/удаленного выполнения
"runners": {
# Класс для выполнения локальных команд (c.run())
"local": Local,
# Примечание: Fabric добавляет сюда 'remote' и 'remote_shell'
# 'remote': fabric.runners.Remote,
# 'remote_shell': fabric.runners.RemoteShell,
},
# --- Настройки выполнения команд через sudo (sudo.*) ---
"sudo": {
# Пароль для sudo (None = будет запрошен, если терминал интерактивный)
"password": "supersikritpassword", # Пример
# Приглашение для ввода пароля sudo
"prompt": "GIMME SUDO PASSWORD: ", # Пример
# Пользователь для sudo -u (None = root)
"user": "admin", # Пример
},
# --- Настройки, связанные с задачами и их поиском (tasks.*) ---
"tasks": {
# Автоматически заменять подчеркивания на дефисы в именах задач/коллекций для CLI
"auto_dash_names": True,
# Имя файла/директории для поиска задач по умолчанию
"collection_name": "fabfile", # Пример (стандарт Invoke - 'tasks')
# Включить дедупликацию задач (не выполнять одну и ту же задачу дважды в цепочке pre/post)
"dedupe": True,
# Класс Executor для выполнения задач (None = стандартный invoke.executor.Executor)
# Позволяет подменять логику выполнения графа задач
"executor_class": None, # Можно указать строку "my_module.MyExecutor"
# Игнорировать ли ошибки, если в @task(help={...}) указан несуществующий аргумент
"ignore_unknown_help": False,
# Корневая директория для поиска модулей с задачами (None = текущая директория)
"search_root": "/opt/my_project/tasks", # Пример
},
# --- Настройки таймаутов (timeouts.*) ---
"timeouts": {
# Таймаут выполнения команды в секундах (None = без таймаута)
"command": 60, # Пример: 1 минута
# Примечание: Fabric добавляет сюда 'connect'
# 'connect': 10,
},
# --- Дополнительные кастомные настройки ---
# Вы можете добавлять свои собственные разделы и ключи
"my_custom_app": {
"api_key": "12345abcde",
"database_url": "postgresql://user:pass@host/db",
"feature_flags": {
"new_dashboard": True,
"beta_feature": False,
}
}
}
# --- Инициализация Config с полным словарем ---
# Передаем наш детальный словарь как `defaults`. Можно также передать
# его в `overrides` или загрузить из файла.
config = Config(defaults=comprehensive_defaults)
# --- Демонстрация доступа к некоторым значениям ---
print("--- Пример доступа к значениям из полного Config ---")
print(f"Имя коллекции задач по умолчанию: {config.tasks.collection_name}")
print(f"Использовать PTY по умолчанию: {config.run.pty}")
print(f"Оболочка по умолчанию: {config.run.shell}")
print(f"Пароль sudo (если задан): {config.sudo.password}")
print(f"Таймаут команды: {config.timeouts.command}")
print(f"Первый watcher (тип): {type(config.run.watchers[0])}")
print(f"Кастомный API ключ: {config.my_custom_app.api_key}")
print(f"Кастомный флаг фичи: {config.my_custom_app.feature_flags.new_dashboard}")
# Проверка переопределения (если бы мы использовали overrides)
# config_with_override = Config(defaults=comprehensive_defaults, overrides={'run': {'shell': '/bin/bash'}})
# print(f"\nОболочка после переопределения: {config_with_override.run.shell}")
from invoke import task, Context
# Определяем различные типы аргументов для демонстрации
@task(
# --- Словарь help ---
help={
# Строковый аргумент (обязательный, т.к. нет значения по умолчанию)
'string_arg': "Описание для обязательного строкового аргумента.",
# Целочисленный аргумент со значением по умолчанию
'int_arg': "Описание для целочисленного аргумента.",
# Булев флаг (по умолчанию False)
'bool_flag': "Включает определенную опцию (флаг).",
# Булев флаг (по умолчанию True), можно использовать --no-invert-bool
'invert_bool': "Отключает опцию, которая включена по умолчанию.",
# Аргумент со значением по умолчанию None
'maybe_arg': "Необязательный аргумент, может быть None.",
# Списочный аргумент (можно указывать несколько раз)
'list_arg': "Аргумент, который можно указывать много раз.",
# Инкрементный аргумент (например, для уровня verbosity -v, -vv)
'verbose': "Увеличивает уровень подробности вывода.",
# Опциональный аргумент (может быть флагом или принимать значение)
# Используем имя с подчеркиванием в ключе help
'optional_arg': "Аргумент, который может быть флагом или принимать значение.",
# Можно было бы использовать и 'optional-arg': "...", результат был бы тот же
# Позиционный аргумент
'pos_arg': "Обязательный позиционный аргумент.",
# Еще один позиционный
'another_pos': "Второй обязательный позиционный аргумент."
},
# --- Другие параметры @task для полноты картины ---
aliases=['demohelp', 'dh'],
positional=['pos_arg', 'another_pos'], # Указываем, какие аргументы позиционные
optional=['optional_arg'], # Указываем опциональные
iterable=['list_arg'], # Указываем списочные
incrementable=['verbose'] # Указываем инкрементные
)
def demo_help(c: Context,
pos_arg: str,
another_pos: int,
string_arg: str,
int_arg: int = 10,
bool_flag: bool = False,
invert_bool: bool = True,
maybe_arg = None,
list_arg = None, # Значение по умолчанию для iterable должно быть None или []
verbose: int = 0, # Значение по умолчанию для incrementable должно быть int
optional_arg: str = "default_opt"
):
"""
Это демонстрационная задача для показа документации аргументов.
Она принимает множество аргументов разных типов, чтобы показать,
как работает словарь `help`.
"""
print("Демо-задача выполнена!")
print("Аргументы:")
print(f" pos_arg: {pos_arg} (тип: {type(pos_arg).__name__})")
print(f" another_pos: {another_pos} (тип: {type(another_pos).__name__})")
print(f" string_arg: {string_arg} (тип: {type(string_arg).__name__})")
print(f" int_arg: {int_arg} (тип: {type(int_arg).__name__})")
print(f" bool_flag: {bool_flag} (тип: {type(bool_flag).__name__})")
print(f" invert_bool: {invert_bool} (тип: {type(invert_bool).__name__})")
print(f" maybe_arg: {maybe_arg} (тип: {type(maybe_arg).__name__})")
print(f" list_arg: {list_arg} (тип: {type(list_arg).__name__})")
print(f" verbose: {verbose} (тип: {type(verbose).__name__})")
print(f" optional_arg: {optional_arg} (тип: {type(optional_arg).__name__})")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment