2025, Dec 14 00:01

Как подставлять имя и email из git в cookiecutter без обёртки

Как получить динамические значения по умолчанию в cookiecutter.json без Python-обёртки: подставляем author_name и email из git config выражениями Jinja

Cookiecutter упрощает создание каркасов проектов из терминала, включая работу с удалёнными шаблонами, но возникает очевидное неудобство, когда значения по умолчанию в cookiecutter.json жёстко привязаны к конкретному автору. Хочется простого: продолжать пользоваться штатной командой cookiecutter, по‑прежнему поддерживать удалённые репозитории и подставлять разумные значения по умолчанию из локальной конфигурации git — без отдельного Python-раннера.

Постановка задачи

Представьте шаблон, где имя автора и email заданы статически. Очевидный способ сделать их динамическими — программно подставлять контекст. Но это быстро приводит к появлению входной точки на Python, что нивелирует удобство запуска cookiecutter напрямую из оболочки.

Очерк минимального варианта выглядит так:

import os as sys_os
from cookiecutter.main import cookiecutter as bake_template

bake_template(
  'cookiecutter-pypackage',
  extra_context={
    'author_name': sys_os.popen('git config --get user.name').read().strip(),
    'author_email': sys_os.popen('git config --get user.email').read().strip(),
  }
)

А значения по умолчанию в шаблоне будут ссылаться на те же ключи, чтобы подставленные данные заранее заполняли подсказки:

{
  "author_name": "{{ cookiecutter.author_name }}",
  "author_email": "{{ cookiecutter.author_email }}"
}

Это работает, но ценой отказа от штатной команды и возможности запускать инструмент прямо по URL репозитория. Хуки в этой ситуации тоже не выручают.

Что здесь по сути

Суть проблемы в том, что cookiecutter.json вычисляется, чтобы определить значения по умолчанию для подсказок. Если там жёсткие строки, все увидят одинаковые данные об авторе. Если нужны динамические значения, остаются два пути: подмешивать их из обёртки через extra_context или научиться вычислять их в момент оценки прямо внутри шаблона — не меняя способ вызова cookiecutter.

Решение: вычислять значения по умолчанию внутри cookiecutter.json

Подход ниже переносит динамику прямо в cookiecutter.json, используя выражения Jinja, которые вычисляются во время рендеринга шаблона. Это намеренно «кустарный» proof of concept, про который сообщалось, что он работает с Python 3.13.3.

{
  "full_name" : "{{ ''.__class__.__mro__[1].__subclasses__()[116].__init__.__globals__['__builtins__']['__import__']('subprocess').getoutput('git config --get user.name' ) }}",
  "email"     : "{{ ''.__class__.__mro__[1].__subclasses__()[116].__init__.__globals__['__builtins__']['__import__']('subprocess').getoutput('git config --get user.email') }}"
}

Эти выражения выполняются при оценке шаблона, обращаются к git config и возвращают локальные user.name и user.email. В итоге вы продолжаете использовать cookiecutter <template> или даже cookiecutter https://github.com/audreyr/cookiecutter-pypackage, а значения по умолчанию больше не привязаны к конкретному автору.

Почему это важно

Так шаблон остаётся универсальным и нейтральным — без вшитых персональных данных — и при этом сразу предлагает удобные значения по умолчанию для большинства пользователей. Сохраняется привычная работа из командной строки и поддержка URL удалённых репозиториев — зачастую именно ради этого команды и выбирают Cookiecutter.

Выводы

Если вам нужны динамические значения по умолчанию, но не хочется городить собственную точку входа на Python, вычисление их внутри cookiecutter.json — рабочий proof of concept. Он избавляет публичные шаблоны от жёстко зашитых данных автора и всё же даёт удобные дефолты, подтягивая информацию из локальной git‑конфигурации пользователя. Относитесь к этому как к прагматичному обходному решению, проверьте его в своей среде и постарайтесь сохранить опыт использования максимально близким к привычному потоку cookiecutter.