
Una plantilla per governar-los a tots: gestionar projectes Python amb Cookiecutter i Cruft
/ 5 min de lectura
Índex
Crea projectes més de pressa i mantén-los coherents
Començar un projecte Python nou sovint vol dir repetir la mateixa feina de configuració: crear un Dockerfile, configurar Poetry, organitzar les carpetes, afegir regles de linting i connectar les eines de desenvolupament. Alguns projectes necessiten petites variacions, però la major part de l’estructura normalment és la mateixa.
Fer-ho a mà cada vegada és lent i és fàcil equivocar-se. Aquí és on Cookiecutter ajuda. I quan tens molts projectes generats a partir de la mateixa plantilla, Cruft t’ajuda a mantenir-los actualitzats.
Què és Cookiecutter?
Cookiecutter és una eina de Python per generar projectes a partir de plantilles amb la sintaxi de Jinja. Tot i que és un paquet de Python, el pots fer servir per crear l’estructura de projectes en molts llenguatges.
Crear projectes amb Cookiecutter
Hi ha dues maneres habituals de fer servir Cookiecutter:
- Instal·lar i fer servir una plantilla existent.
- Construir la teva pròpia plantilla.
Aquest article se centra en la segona opció.
Per instal·lar Cookiecutter, executa una d’aquestes ordres:
poetry add cookiecutterpip install cookiecutterconda install -c conda-forge cookiecutterUn cop instal·lat, pots començar a construir la teva plantilla.
Estructura típica d’un projecte
Aquí tens un exemple de l’estructura de projecte Python que reutilitzo sovint:
Aquesta estructura em permet crear un projecte nou en pocs segons. Inclou:
- Una carpeta
packageambscriptsiutils, on viu la lògica de l’aplicació. - Una carpeta
.devcontainerper a la configuració de Docker i del contenidor de desenvolupament. - Una carpeta
configper als fitxers de configuració. - Una carpeta
dataper a conjunts de dades, imatges i fitxers de text. - Fitxers a nivell de repositori com
pyproject.toml,.pre-commit-config.yamli els fitxers d’ignore.
Aquests elements apareixen en molts dels meus projectes, i la major part de la configuració és compartida.
Construir una plantilla de Cookiecutter pròpia
Per crear una plantilla, afegeix un fitxer cookiecutter.json al repositori de la plantilla. Aquest fitxer defineix els valors que Cookiecutter et demanarà quan generi un projecte nou.
{ "project_name": "Name of the project", "project_slug": "Slug of the project", "package_name": "Name of the package", "repository_url": "URL of the project", "project_description": "Description of the project"}Aquest exemple és senzill a propòsit, però n’hi ha prou per a molts projectes. Cada valor fa de valor per defecte de la pregunta que es mostra en crear el projecte.
Cookiecutter fa servir la sintaxi de Jinja, així que pots fer referència als valors d’aquesta manera:
{{ cookiecutter.project_slug }}En el meu cas, la plantilla fa servir carpetes com {{ cookiecutter.project_slug }} i {{ cookiecutter.project_name }}. Tot el que hi ha dins d’aquestes carpetes passa a formar part del projecte generat.
La meva plantilla de Cookiecutter, project-wizard, és així:
Per exemple, genero automàticament un README a partir dels valors definits a cookiecutter.json:
# {{ cookiecutter.project_name }}
{{ cookiecutter.project_description }}En fitxers com pyproject.toml també defineixo els paquets i les eines que vull a cada repositori nou. La carpeta scripts pot incloure scripts d’utilitat que reutilitzo sovint. És aquí on Cookiecutter comença a estalviar-te temps de veritat.
Crear un projecte nou
Quan la plantilla estigui a punt, genera un projecte amb:
cookiecutter .Si la plantilla és a GitHub, també pots executar:
cookiecutter https://github.com/simoncraf/project-wizard.gitLlavors Cookiecutter et demanarà els valors definits a cookiecutter.json. Els valors per defecte apareixen entre claudàtors.
En aquest punt pots crear tants projectes com vulguis a partir de la mateixa plantilla. El següent problema és el manteniment: quan la plantilla evoluciona, mantenir alineats tots els projectes generats es fa feixuc. Aquest és el problema que resol Cruft.
Què és Cruft?
Cruft és un paquet de Python que manté els projectes generats sincronitzats amb la plantilla de Cookiecutter de què provenen.
Vincular un projecte amb Cruft
Comença instal·lant Cruft:
poetry add cruftpip install cruftconda install -c conda-forge cruftDesprés afegeix un fitxer .cruft.json a la teva plantilla de Cookiecutter:
{ "template": "https://github.com/simoncraf/project-wizard", "commit": "069a78495a5d0cbffc8245f42bd190adaa1df698", "checkout": "null", "context": { "cookiecutter": { "project_name": "{{cookiecutter.project_name }}", "project_slug": "{{cookiecutter.project_slug }}", "package_name": "{{cookiecutter.package_name }}", "project_short_description": "{{cookiecutter.project_description }}", "repository_url": "{{cookiecutter.repository_url }}", "_template": "https://github.com/simoncraf/project-wizard" } }, "directory": null}Aquest fitxer guarda la informació que Cruft necessita per seguir la plantilla. Els dos camps més importants són:
template, que apunta al repositori de la plantilla de Cookiecutter.commit, que identifica la versió de la plantilla que fa servir el projecte.
Quan la plantilla canvia, també canvia el seu últim commit. Cruft compara el commit registrat al projecte amb el de la plantilla i t’avisa quan hi ha una actualització disponible.
A la meva plantilla també faig servir un script auxiliar per assegurar-me que el commit guardat a .cruft.json coincideix amb l’últim commit de la plantilla:
def get_last_commit_hash(): """ Update the commit hash in `.cruft.json` to the latest commit. """ result = subprocess.run(["git", "log", "-n", "1", "--format=%H"], stdout=subprocess.PIPE) hash_ = result.stdout.decode().strip() file_path = Path("{{cookiecutter.project_slug}}") / ".cruft.json" with file_path.open("r", encoding="utf-8") as f: data = json.load(f) data["commit"] = hash_ with file_path.open("w", encoding="utf-8") as f: json.dump(data, f, indent=4) return hash_Si ja has creat un projecte amb Cookiecutter però no inclou .cruft.json, el pots vincular manualment:
cruft link https://github.com/simoncraf/project-wizardPer defecte, això vincula el projecte a l’últim commit de la plantilla i et crea el fitxer .cruft.json.
Actualitzar un projecte
Un cop vinculat el projecte, comprova si hi ha actualitzacions amb:
cruft checkSi no n’hi ha, veuràs un missatge d’èxit:
Si la plantilla ha canviat, Cruft et mostrarà que hi ha una actualització disponible:
Per aplicar les actualitzacions de la plantilla, executa:
cruft updateCruft et permet revisar els canvis, saltar-los o aplicar-los directament. Després d’aplicar-los, reescriu automàticament els fitxers corresponents.
Si hi ha conflictes, Cruft crea fitxers .rej. Funcionen de manera semblant als rebuigs dels pedaços i t’ajuden a revisar el que no s’ha pogut fusionar automàticament. Quan resols o descartes els canvis, el camp commit de .cruft.json s’actualitza a l’última versió de la plantilla.
Recursos
Enllaços útils:
Plantilles de Cookiecutter a punt per fer servir que val la pena explorar: