
Un template per domarli tutti: gestire progetti Python con Cookiecutter e Cruft
/ 4 min di lettura
Indice
Crea progetti più in fretta e mantienili coerenti
Iniziare un nuovo progetto Python spesso significa ripetere lo stesso lavoro di configurazione: creare un Dockerfile, configurare Poetry, organizzare le cartelle, aggiungere le regole di linting e collegare gli strumenti di sviluppo. Alcuni progetti hanno bisogno di piccole variazioni, ma la maggior parte della struttura di solito resta la stessa.
Farlo a mano ogni volta è lento e porta facilmente a errori. Qui entra in gioco Cookiecutter. E quando hai tanti progetti generati dallo stesso template, Cruft ti aiuta a tenerli aggiornati.
Cos’è Cookiecutter?
Cookiecutter è uno strumento Python per generare progetti a partire da template, usando la sintassi Jinja. Anche se è un pacchetto Python, puoi usarlo per creare la struttura di progetti in molti linguaggi.
Creare progetti con Cookiecutter
Ci sono due modi comuni di usare Cookiecutter:
- Installare e usare un template esistente.
- Costruire un template personalizzato.
Questo articolo si concentra sul secondo approccio.
Per installare Cookiecutter, esegui uno dei seguenti comandi:
poetry add cookiecutterpip install cookiecutterconda install -c conda-forge cookiecutterUna volta installato, puoi iniziare a costruire il tuo template.
Struttura tipica di un progetto
Ecco un esempio della struttura di progetto Python che riuso spesso:
Questa struttura mi permette di creare un nuovo progetto in pochi secondi. Include:
- Una cartella
packageconscriptseutils, dove vive la logica dell’applicazione. - Una cartella
.devcontainerper la configurazione di Docker e del dev container. - Una cartella
configper i file di configurazione. - Una cartella
dataper dataset, immagini e file di testo. - File a livello di repository come
pyproject.toml,.pre-commit-config.yamle i file di ignore.
Questi elementi compaiono in molti dei miei progetti, e la maggior parte della loro configurazione è condivisa.
Costruire un template Cookiecutter personalizzato
Per creare un template, aggiungi un file cookiecutter.json al repository del template. Questo file definisce i valori che Cookiecutter ti chiederà quando genera un nuovo progetto.
{ "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"}Questo esempio è volutamente semplice, ma basta per molti progetti. Ogni valore fa da predefinito per la domanda mostrata durante la creazione del progetto.
Cookiecutter usa la sintassi Jinja, quindi puoi riferirti ai valori così:
{{ cookiecutter.project_slug }}Nel mio caso, il template usa cartelle come {{ cookiecutter.project_slug }} e {{ cookiecutter.project_name }}. Tutto ciò che sta dentro quelle cartelle diventa parte del progetto generato.
Il mio template Cookiecutter personalizzato, project-wizard, è fatto così:
Per esempio, genero automaticamente un README a partire dai valori definiti in cookiecutter.json:
# {{ cookiecutter.project_name }}
{{ cookiecutter.project_description }}In file come pyproject.toml definisco anche i pacchetti e gli strumenti che voglio in ogni nuovo repository. La cartella scripts può contenere script di utilità che riuso spesso. È qui che Cookiecutter inizia a farti risparmiare tempo sul serio.
Creare un nuovo progetto
Quando il template è pronto, genera un progetto con:
cookiecutter .Se il template è su GitHub, puoi anche eseguire:
cookiecutter https://github.com/simoncraf/project-wizard.gitCookiecutter ti chiederà quindi i valori definiti in cookiecutter.json. I valori predefiniti compaiono tra parentesi.
A questo punto puoi creare tutti i progetti che vuoi dallo stesso template. Il problema successivo è la manutenzione: quando il template evolve, tenere allineati tutti i progetti generati diventa noioso. È il problema che risolve Cruft.
Cos’è Cruft?
Cruft è un pacchetto Python che mantiene i progetti generati sincronizzati con il template Cookiecutter da cui provengono.
Collegare un progetto con Cruft
Inizia installando Cruft:
poetry add cruftpip install cruftconda install -c conda-forge cruftPoi aggiungi un file .cruft.json al tuo template 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}Questo file contiene le informazioni di cui Cruft ha bisogno per seguire il template. I due campi più importanti sono:
template, che punta al repository del template Cookiecutter.commit, che identifica la versione del template usata dal progetto.
Quando il template cambia, cambia anche il suo ultimo commit. Cruft confronta il commit registrato nel progetto con quello del template e ti avvisa quando c’è un aggiornamento disponibile.
Nel mio template personalizzato uso anche uno script di supporto per assicurarmi che il commit salvato in .cruft.json corrisponda all’ultimo commit del template:
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_Se hai già creato un progetto con Cookiecutter ma non include .cruft.json, puoi collegarlo a mano:
cruft link https://github.com/simoncraf/project-wizardPer impostazione predefinita, questo collega il progetto all’ultimo commit del template e crea il file .cruft.json per te.
Aggiornare un progetto
Una volta collegato un progetto, controlla gli aggiornamenti con:
cruft checkSe non ci sono aggiornamenti, vedrai un messaggio di successo:
Se il template è cambiato, Cruft ti mostrerà che c’è un aggiornamento disponibile:
Per applicare gli aggiornamenti del template, esegui:
cruft updateCruft ti permette di esaminare le modifiche, saltarle o applicarle direttamente. Dopo averle applicate, riscrive automaticamente i file corrispondenti.
Se ci sono conflitti, Cruft crea dei file .rej. Funzionano in modo simile ai rifiuti delle patch e ti aiutano a vedere cosa non è stato possibile unire automaticamente. Quando risolvi o scarti le modifiche, il campo commit in .cruft.json viene aggiornato all’ultima versione del template.
Risorse
Link utili:
Template Cookiecutter pronti all’uso che vale la pena esplorare: