Commit ·
c13005e
0
Parent(s):
Initial commit
Browse files- .gitignore +26 -0
- .python-version +1 -0
- Dockerfile +25 -0
- README.md +6 -0
- example_inputs/sample.json +72 -0
- example_inputs/senior_ai_mistral.json +161 -0
- generate_resume.py +166 -0
- pydantic_model.py +72 -0
- pyproject.toml +13 -0
- templates/classic.tex.j2 +351 -0
- templates/clean.tex.j2 +199 -0
- templates/template.tex +370 -0
- templates/template_pe.tex +146 -0
- uv.lock +259 -0
.gitignore
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# LaTeX build artifacts
|
| 2 |
+
*.aux
|
| 3 |
+
*.fdb_latexmk
|
| 4 |
+
*.fls
|
| 5 |
+
*.log
|
| 6 |
+
*.out
|
| 7 |
+
*.toc
|
| 8 |
+
*.synctex.gz
|
| 9 |
+
|
| 10 |
+
# Local builds
|
| 11 |
+
build/
|
| 12 |
+
|
| 13 |
+
# Python
|
| 14 |
+
.venv/
|
| 15 |
+
__pycache__/
|
| 16 |
+
*.pyc
|
| 17 |
+
# Python-generated files
|
| 18 |
+
__pycache__/
|
| 19 |
+
*.py[oc]
|
| 20 |
+
build/
|
| 21 |
+
dist/
|
| 22 |
+
wheels/
|
| 23 |
+
*.egg-info
|
| 24 |
+
|
| 25 |
+
# Virtual environments
|
| 26 |
+
.venv
|
.python-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
3.13
|
Dockerfile
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM debian:stable-slim
|
| 2 |
+
|
| 3 |
+
ENV DEBIAN_FRONTEND=noninteractive
|
| 4 |
+
|
| 5 |
+
RUN apt-get update -y && apt-get install -y --no-install-recommends \
|
| 6 |
+
ca-certificates curl git make \
|
| 7 |
+
python3 python3-venv python3-pip \
|
| 8 |
+
texlive-base texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended \
|
| 9 |
+
fonts-lmodern \
|
| 10 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 11 |
+
|
| 12 |
+
WORKDIR /app
|
| 13 |
+
|
| 14 |
+
# Installer uv
|
| 15 |
+
RUN curl -LsSf https://astral.sh/uv/install.sh | sh && \
|
| 16 |
+
ln -s ~/.cargo/bin/uv /usr/local/bin/uv
|
| 17 |
+
|
| 18 |
+
COPY pyproject.toml ./
|
| 19 |
+
RUN uv sync --frozen
|
| 20 |
+
|
| 21 |
+
COPY . .
|
| 22 |
+
|
| 23 |
+
CMD ["uv", "run", "python", "generate_resume.py", "--template", "classic.tex.j2", "--input-json", "example_inputs/sample.json", "--out-dir", "build"]
|
| 24 |
+
|
| 25 |
+
|
README.md
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
cd "/Users/hasanbasbunar/resume-mcp" && uv run python generate_resume.py --template template.tex.j2 --input-json example_inputs/senior_ai_mistral.json --out-tex output.tex --out-pdf output.pdf | cat && test -f output.pdf && open output.pdf
|
| 2 |
+
|
| 3 |
+
uv run python generate_resume.py --template template.tex.j2 --input-json example_inputs/senior_ai_mistral.json --out-dir build
|
| 4 |
+
# ou avec un nom custom
|
| 5 |
+
uv run python generate_resume.py --template template.tex.j2 --input-json example_inputs/senior_ai_mistral.json --out-dir build --basename mistral_senior_fr
|
| 6 |
+
|
example_inputs/sample.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"meta": {
|
| 3 |
+
"pdf_title": "Mon CV",
|
| 4 |
+
"pdf_author": "John Doe",
|
| 5 |
+
"last_updated_text": "Septembre 2025"
|
| 6 |
+
},
|
| 7 |
+
"header": {
|
| 8 |
+
"name": "John Doe",
|
| 9 |
+
"location": "Paris, FR",
|
| 10 |
+
"email": "john@example.com",
|
| 11 |
+
"phone": "+33 6 12 34 56 78",
|
| 12 |
+
"website_url": "https://example.com",
|
| 13 |
+
"website_label": "example.com",
|
| 14 |
+
"linkedin_url": "https://linkedin.com/in/johndoe",
|
| 15 |
+
"linkedin_handle": "johndoe",
|
| 16 |
+
"github_url": "https://github.com/johndoe",
|
| 17 |
+
"github_handle": "johndoe"
|
| 18 |
+
},
|
| 19 |
+
"intro_paragraphs": [
|
| 20 |
+
"Texte d'introduction en une ligne."
|
| 21 |
+
],
|
| 22 |
+
"quick_guide_items": [
|
| 23 |
+
"Point 1",
|
| 24 |
+
"Point 2"
|
| 25 |
+
],
|
| 26 |
+
"education": [
|
| 27 |
+
{
|
| 28 |
+
"degree": "BS",
|
| 29 |
+
"date_range": "2015 - 2019",
|
| 30 |
+
"institution": "Université X",
|
| 31 |
+
"field_of_study": "Informatique",
|
| 32 |
+
"highlights": [
|
| 33 |
+
"Mention Bien",
|
| 34 |
+
"Cours: Algo, Réseaux"
|
| 35 |
+
]
|
| 36 |
+
}
|
| 37 |
+
],
|
| 38 |
+
"experience": [
|
| 39 |
+
{
|
| 40 |
+
"company": "Entreprise A",
|
| 41 |
+
"role": "Software Engineer",
|
| 42 |
+
"location": "Paris",
|
| 43 |
+
"date_range": "2020 - Présent",
|
| 44 |
+
"highlights": [
|
| 45 |
+
"Implémenté X",
|
| 46 |
+
"Réduit Y"
|
| 47 |
+
]
|
| 48 |
+
}
|
| 49 |
+
],
|
| 50 |
+
"publications": [
|
| 51 |
+
{
|
| 52 |
+
"date": "Jan 2024",
|
| 53 |
+
"title": "Titre de la publication",
|
| 54 |
+
"authors": ["Auteur 1", "Auteur 2"],
|
| 55 |
+
"doi_url": "https://doi.org/10.1234/abcd",
|
| 56 |
+
"doi_label": "10.1234/abcd"
|
| 57 |
+
}
|
| 58 |
+
],
|
| 59 |
+
"projects": [
|
| 60 |
+
{
|
| 61 |
+
"title": "Projet 1",
|
| 62 |
+
"repo_url": "https://github.com/name/repo",
|
| 63 |
+
"repo_label": "github.com/name/repo",
|
| 64 |
+
"highlights": ["Feature A", "Tech: Python, Flask"]
|
| 65 |
+
}
|
| 66 |
+
],
|
| 67 |
+
"technologies_section": {
|
| 68 |
+
"languages": ["Python", "TypeScript"],
|
| 69 |
+
"technologies": ["FastAPI", "PostgreSQL", "Docker"]
|
| 70 |
+
}
|
| 71 |
+
}
|
| 72 |
+
|
example_inputs/senior_ai_mistral.json
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"meta": {
|
| 3 |
+
"pdf_title": "CV - Ingénieur IA Sénior",
|
| 4 |
+
"pdf_author": "Alexandre Martin",
|
| 5 |
+
"last_updated_text": "Septembre 2025"
|
| 6 |
+
},
|
| 7 |
+
"header": {
|
| 8 |
+
"name": "Alexandre Martin",
|
| 9 |
+
"location": "Paris, France",
|
| 10 |
+
"email": "alexandre.martin@example.com",
|
| 11 |
+
"phone": "+33 6 12 34 56 78",
|
| 12 |
+
"website_url": "https://alexandre-ml.fr",
|
| 13 |
+
"website_label": "alexandre-ml.fr",
|
| 14 |
+
"linkedin_url": "https://www.linkedin.com/in/alexandre-martin-ai",
|
| 15 |
+
"linkedin_handle": "alexandre-martin-ai",
|
| 16 |
+
"github_url": "https://github.com/alexandre-ml",
|
| 17 |
+
"github_handle": "alexandre-ml"
|
| 18 |
+
},
|
| 19 |
+
"intro_paragraphs": [
|
| 20 |
+
"Ingénieur IA sénior avec dix ans d'expérience en apprentissage profond, modèles de langage et plateformes MLOps. Passionné par les LLM compacts et efficaces, l'optimisation serveur et l'inférence à faible latence.",
|
| 21 |
+
"Motivé pour rejoindre Mistral et contribuer à la recherche appliquée, à l'optimisation et au déploiement massif de modèles en production, avec un souci permanent de qualité et de frugalité."
|
| 22 |
+
],
|
| 23 |
+
"quick_guide_items": [
|
| 24 |
+
"Expertise LLM, optimisation et quantification",
|
| 25 |
+
"Conception d'API d'inférence et observabilité",
|
| 26 |
+
"MLOps de bout en bout, reproductibilité et fiabilité"
|
| 27 |
+
],
|
| 28 |
+
"education": [
|
| 29 |
+
{
|
| 30 |
+
"degree": "Master of Science",
|
| 31 |
+
"date_range": "2013 - 2015",
|
| 32 |
+
"institution": "Ecole Polytechnique",
|
| 33 |
+
"field_of_study": "Mathématiques Appliquées et Informatique",
|
| 34 |
+
"highlights": [
|
| 35 |
+
"Major Projet: optimisation convexe pour réseaux de neurones",
|
| 36 |
+
"Moyenne: 17 sur 20"
|
| 37 |
+
]
|
| 38 |
+
},
|
| 39 |
+
{
|
| 40 |
+
"degree": "Licence",
|
| 41 |
+
"date_range": "2010 - 2013",
|
| 42 |
+
"institution": "Université Paris Saclay",
|
| 43 |
+
"field_of_study": "Informatique",
|
| 44 |
+
"highlights": [
|
| 45 |
+
"Classement top 5 pour le département",
|
| 46 |
+
"Projet open source en vision par ordinateur"
|
| 47 |
+
]
|
| 48 |
+
}
|
| 49 |
+
],
|
| 50 |
+
"experience": [
|
| 51 |
+
{
|
| 52 |
+
"company": "ScaleAI Labs",
|
| 53 |
+
"role": "Senior Staff Machine Learning Engineer",
|
| 54 |
+
"location": "Paris",
|
| 55 |
+
"date_range": "2022 - Présent",
|
| 56 |
+
"highlights": [
|
| 57 |
+
"Conçu une pile d'inférence LLM haute performance avec mise en lots dynamique, gestion des tokens et ordonnanceur mémoire pour réduire la latence p95 de 30 pourcent",
|
| 58 |
+
"Mené la quantification post entraînement et la distillation de modèles 7B vers 3B avec une perte de qualité négligeable sur benchmarks internes",
|
| 59 |
+
"Mis en place une observabilité complète: traces, métriques et journaux corrélés pour la détection d'incidents d'inférence",
|
| 60 |
+
"Piloté l'intégration de modèles Mistral pour des cas d'usage de génération et d'outillage développeur"
|
| 61 |
+
]
|
| 62 |
+
},
|
| 63 |
+
{
|
| 64 |
+
"company": "DeepVision",
|
| 65 |
+
"role": "Lead Machine Learning Engineer",
|
| 66 |
+
"location": "Lyon",
|
| 67 |
+
"date_range": "2018 - 2022",
|
| 68 |
+
"highlights": [
|
| 69 |
+
"Déployé des services de classification et détection en temps réel avec accélération GPU",
|
| 70 |
+
"Industrialisation MLOps: registres de modèles, pipelines d'entraînement et validations",
|
| 71 |
+
"Réduction du coût par prédiction grâce au partage de GPU et à l'optimisation du lot"
|
| 72 |
+
]
|
| 73 |
+
},
|
| 74 |
+
{
|
| 75 |
+
"company": "DataCraft",
|
| 76 |
+
"role": "Machine Learning Engineer",
|
| 77 |
+
"location": "Paris",
|
| 78 |
+
"date_range": "2015 - 2018",
|
| 79 |
+
"highlights": [
|
| 80 |
+
"Mise en place d'un pipeline de traitement de texte pour recherche sémantique",
|
| 81 |
+
"Amélioration continue des modèles avec validation croisée et suivi expérimental"
|
| 82 |
+
]
|
| 83 |
+
}
|
| 84 |
+
],
|
| 85 |
+
"publications": [
|
| 86 |
+
{
|
| 87 |
+
"date": "Juin 2024",
|
| 88 |
+
"title": "Compression pratique de modèles de langage pour inférence frugale",
|
| 89 |
+
"authors": ["Alexandre Martin", "Claire Dupont", "Hugo Leroy"],
|
| 90 |
+
"doi_url": "https://doi.org/10.1234/comp-llm-2024",
|
| 91 |
+
"doi_label": "10.1234/comp-llm-2024"
|
| 92 |
+
},
|
| 93 |
+
{
|
| 94 |
+
"date": "Mars 2022",
|
| 95 |
+
"title": "Optimisation de l'ordonnancement pour services d'inférence",
|
| 96 |
+
"authors": ["Alexandre Martin", "Nina Robert"],
|
| 97 |
+
"doi_url": "https://doi.org/10.2345/sched-infer-2022",
|
| 98 |
+
"doi_label": "10.2345/sched-infer-2022"
|
| 99 |
+
}
|
| 100 |
+
],
|
| 101 |
+
"projects": [
|
| 102 |
+
{
|
| 103 |
+
"title": "Serveur d'inférence LLM minimaliste",
|
| 104 |
+
"repo_url": "https://github.com/alexandre-ml/llm-infer-min",
|
| 105 |
+
"repo_label": "github.com/alexandre-ml/llm-infer-min",
|
| 106 |
+
"highlights": [
|
| 107 |
+
"Planification des requêtes et contrôle du débit",
|
| 108 |
+
"Support pour modèles quantifiés et streaming de tokens"
|
| 109 |
+
]
|
| 110 |
+
},
|
| 111 |
+
{
|
| 112 |
+
"title": "Kit de distillation pour modèles français",
|
| 113 |
+
"repo_url": "https://github.com/alexandre-ml/distill-fr",
|
| 114 |
+
"repo_label": "github.com/alexandre-ml/distill-fr",
|
| 115 |
+
"highlights": [
|
| 116 |
+
"Scripts de distillation assistée pour domaines spécialisés",
|
| 117 |
+
"Evaluation automatique avec corpus français"
|
| 118 |
+
]
|
| 119 |
+
},
|
| 120 |
+
{
|
| 121 |
+
"title": "Observabilité pour pipelines ML",
|
| 122 |
+
"repo_url": "https://github.com/alexandre-ml/ml-observabilite",
|
| 123 |
+
"repo_label": "github.com/alexandre-ml/ml-observabilite",
|
| 124 |
+
"highlights": [
|
| 125 |
+
"Tableau de bord métriques et alertes",
|
| 126 |
+
"Traces distribuées pour étapes d'entraînement et d'inférence"
|
| 127 |
+
]
|
| 128 |
+
}
|
| 129 |
+
],
|
| 130 |
+
"technologies_section": {
|
| 131 |
+
"languages": [
|
| 132 |
+
"Python",
|
| 133 |
+
"C plus plus",
|
| 134 |
+
"Rust",
|
| 135 |
+
"Go",
|
| 136 |
+
"Scala",
|
| 137 |
+
"Bash"
|
| 138 |
+
],
|
| 139 |
+
"technologies": [
|
| 140 |
+
"PyTorch",
|
| 141 |
+
"TensorFlow",
|
| 142 |
+
"JAX",
|
| 143 |
+
"Transformers",
|
| 144 |
+
"Ray",
|
| 145 |
+
"MLflow",
|
| 146 |
+
"Docker",
|
| 147 |
+
"Kubernetes",
|
| 148 |
+
"Airflow",
|
| 149 |
+
"Prometheus",
|
| 150 |
+
"Grafana",
|
| 151 |
+
"NGINX",
|
| 152 |
+
"PostgreSQL",
|
| 153 |
+
"Redis",
|
| 154 |
+
"S3",
|
| 155 |
+
"GCP",
|
| 156 |
+
"Azure"
|
| 157 |
+
]
|
| 158 |
+
}
|
| 159 |
+
}
|
| 160 |
+
|
| 161 |
+
|
generate_resume.py
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
import json
|
| 4 |
+
import subprocess
|
| 5 |
+
import platform
|
| 6 |
+
import sys
|
| 7 |
+
from pathlib import Path
|
| 8 |
+
from typing import Any, Dict
|
| 9 |
+
import uuid
|
| 10 |
+
|
| 11 |
+
from jinja2 import Environment, FileSystemLoader
|
| 12 |
+
from pydantic import ValidationError
|
| 13 |
+
|
| 14 |
+
from pydantic_model import Resume
|
| 15 |
+
|
| 16 |
+
PROJECT_ROOT = Path(__file__).parent
|
| 17 |
+
TEMPLATES_DIR = PROJECT_ROOT / "templates"
|
| 18 |
+
TEMPLATE_NAME = "classic.tex.j2"
|
| 19 |
+
OUTPUT_DIR = PROJECT_ROOT / "build"
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
def render_tex(resume_data: Dict[str, Any], output_tex_path: Path, template_name: str = TEMPLATE_NAME) -> None:
|
| 23 |
+
try:
|
| 24 |
+
resume = Resume.model_validate(resume_data)
|
| 25 |
+
except ValidationError as e:
|
| 26 |
+
print("Erreur de validation Pydantic:")
|
| 27 |
+
print(e)
|
| 28 |
+
sys.exit(1)
|
| 29 |
+
|
| 30 |
+
env = Environment(
|
| 31 |
+
loader=FileSystemLoader(str(TEMPLATES_DIR)),
|
| 32 |
+
autoescape=False,
|
| 33 |
+
trim_blocks=True,
|
| 34 |
+
lstrip_blocks=True,
|
| 35 |
+
)
|
| 36 |
+
# Configure custom delimiters to avoid clashes with LaTeX
|
| 37 |
+
env.block_start_string = "<<%"
|
| 38 |
+
env.block_end_string = "%>>"
|
| 39 |
+
env.variable_start_string = "<<"
|
| 40 |
+
env.variable_end_string = ">>"
|
| 41 |
+
env.comment_start_string = "<#!"
|
| 42 |
+
env.comment_end_string = "!#>"
|
| 43 |
+
template = env.get_template(template_name)
|
| 44 |
+
rendered = template.render(resume=resume.model_dump())
|
| 45 |
+
|
| 46 |
+
output_tex_path.parent.mkdir(parents=True, exist_ok=True)
|
| 47 |
+
output_tex_path.write_text(rendered, encoding="utf-8")
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
def run_tectonic(tex_path: Path, outdir: Path) -> None:
|
| 51 |
+
cmd = [
|
| 52 |
+
"tectonic",
|
| 53 |
+
"--outdir",
|
| 54 |
+
str(outdir),
|
| 55 |
+
str(tex_path),
|
| 56 |
+
]
|
| 57 |
+
subprocess.run(cmd, check=True)
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
def run_latexmk(tex_path: Path, outdir: Path) -> None:
|
| 61 |
+
# latexmk -pdf -synctex=1 -interaction=nonstopmode -output-directory=outdir tex
|
| 62 |
+
cmd = [
|
| 63 |
+
"latexmk",
|
| 64 |
+
"-pdf",
|
| 65 |
+
"-synctex=1",
|
| 66 |
+
"-interaction=nonstopmode",
|
| 67 |
+
f"-output-directory={outdir}",
|
| 68 |
+
str(tex_path),
|
| 69 |
+
]
|
| 70 |
+
subprocess.run(cmd, check=True)
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
def compile_pdf(output_tex_path: Path, output_pdf_path: Path, engine_preference: str = "tectonic") -> None:
|
| 74 |
+
outdir = output_pdf_path.parent
|
| 75 |
+
outdir.mkdir(parents=True, exist_ok=True)
|
| 76 |
+
|
| 77 |
+
if engine_preference == "latexmk":
|
| 78 |
+
try:
|
| 79 |
+
run_latexmk(output_tex_path, outdir)
|
| 80 |
+
except (FileNotFoundError, subprocess.CalledProcessError):
|
| 81 |
+
run_tectonic(output_tex_path, outdir)
|
| 82 |
+
else:
|
| 83 |
+
# default: try tectonic first, then fallback
|
| 84 |
+
try:
|
| 85 |
+
run_tectonic(output_tex_path, outdir)
|
| 86 |
+
except (FileNotFoundError, subprocess.CalledProcessError):
|
| 87 |
+
run_latexmk(output_tex_path, outdir)
|
| 88 |
+
|
| 89 |
+
if not output_pdf_path.exists():
|
| 90 |
+
raise RuntimeError(f"PDF introuvable après compilation: {output_pdf_path}")
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
def main() -> None:
|
| 94 |
+
import argparse
|
| 95 |
+
|
| 96 |
+
parser = argparse.ArgumentParser(description="Générer le CV PDF depuis des données JSON")
|
| 97 |
+
parser.add_argument(
|
| 98 |
+
"--input-json",
|
| 99 |
+
type=Path,
|
| 100 |
+
required=True,
|
| 101 |
+
help="Chemin du fichier JSON d'entrée (conforme au modèle Resume)",
|
| 102 |
+
)
|
| 103 |
+
parser.add_argument(
|
| 104 |
+
"--template",
|
| 105 |
+
type=str,
|
| 106 |
+
default=TEMPLATE_NAME,
|
| 107 |
+
help="Nom du fichier template (dans le dossier templates)",
|
| 108 |
+
)
|
| 109 |
+
parser.add_argument(
|
| 110 |
+
"--out-dir",
|
| 111 |
+
type=Path,
|
| 112 |
+
default=OUTPUT_DIR,
|
| 113 |
+
help="Dossier de sortie pour les fichiers générés (.tex, .pdf, artefacts LaTeX)",
|
| 114 |
+
)
|
| 115 |
+
parser.add_argument(
|
| 116 |
+
"--basename",
|
| 117 |
+
type=str,
|
| 118 |
+
default=None,
|
| 119 |
+
help="Nom de base des fichiers générés (défaut: UUID aléatoire)",
|
| 120 |
+
)
|
| 121 |
+
parser.add_argument(
|
| 122 |
+
"--engine",
|
| 123 |
+
type=str,
|
| 124 |
+
choices=["tectonic", "latexmk"],
|
| 125 |
+
default=None,
|
| 126 |
+
help="Moteur de compilation LaTeX à privilégier (par défaut: latexmk sous Linux, sinon tectonic)",
|
| 127 |
+
)
|
| 128 |
+
parser.add_argument(
|
| 129 |
+
"--out-tex",
|
| 130 |
+
type=Path,
|
| 131 |
+
default=None,
|
| 132 |
+
help="Chemin du fichier .tex rendu (défaut: build/output.tex)",
|
| 133 |
+
)
|
| 134 |
+
parser.add_argument(
|
| 135 |
+
"--out-pdf",
|
| 136 |
+
type=Path,
|
| 137 |
+
default=None,
|
| 138 |
+
help="Chemin du PDF de sortie (défaut: build/output.pdf)",
|
| 139 |
+
)
|
| 140 |
+
args = parser.parse_args()
|
| 141 |
+
|
| 142 |
+
data = json.loads(args.input_json.read_text(encoding="utf-8"))
|
| 143 |
+
|
| 144 |
+
# Résoudre le nom de base (UUID si non fourni)
|
| 145 |
+
base_name = (args.basename or uuid.uuid4().hex).strip()
|
| 146 |
+
if not base_name:
|
| 147 |
+
base_name = uuid.uuid4().hex
|
| 148 |
+
|
| 149 |
+
# Résoudre les chemins de sortie par défaut si non fournis
|
| 150 |
+
out_tex = args.out_tex or (args.out_dir / f"{base_name}.tex")
|
| 151 |
+
out_pdf = args.out_pdf or (args.out_dir / f"{base_name}.pdf")
|
| 152 |
+
|
| 153 |
+
render_tex(data, out_tex, template_name=args.template)
|
| 154 |
+
|
| 155 |
+
# Choix du moteur par défaut selon l'OS
|
| 156 |
+
preferred_engine = args.engine
|
| 157 |
+
if preferred_engine is None:
|
| 158 |
+
preferred_engine = "latexmk" if platform.system() == "Linux" else "tectonic"
|
| 159 |
+
|
| 160 |
+
compile_pdf(out_tex, out_pdf, engine_preference=preferred_engine)
|
| 161 |
+
print(f"PDF généré: {out_pdf}")
|
| 162 |
+
|
| 163 |
+
if __name__ == "__main__":
|
| 164 |
+
main()
|
| 165 |
+
|
| 166 |
+
|
pydantic_model.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import List, Optional
|
| 2 |
+
from pydantic import BaseModel, EmailStr, HttpUrl
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
class DocumentMeta(BaseModel):
|
| 6 |
+
pdf_title: str
|
| 7 |
+
pdf_author: str
|
| 8 |
+
last_updated_text: Optional[str] = None # ex: "September 2024"
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
class Header(BaseModel):
|
| 12 |
+
name: str
|
| 13 |
+
location: str
|
| 14 |
+
email: EmailStr
|
| 15 |
+
phone: str
|
| 16 |
+
website_url: Optional[HttpUrl] = None
|
| 17 |
+
website_label: Optional[str] = None # ex: "yourwebsite.com"
|
| 18 |
+
linkedin_url: Optional[HttpUrl] = None
|
| 19 |
+
linkedin_handle: Optional[str] = None # ex: "yourusername"
|
| 20 |
+
github_url: Optional[HttpUrl] = None
|
| 21 |
+
github_handle: Optional[str] = None # ex: "yourusername"
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
class EducationEntry(BaseModel):
|
| 25 |
+
degree: str # ex: "BS"
|
| 26 |
+
date_range: str # ex: "Sept 2000 – May 2005"
|
| 27 |
+
institution: str # ex: "University of Pennsylvania"
|
| 28 |
+
field_of_study: Optional[str] = None # ex: "Computer Science"
|
| 29 |
+
highlights: List[str] = [] # puces
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
class ExperienceEntry(BaseModel):
|
| 33 |
+
company: str # ex: "Apple"
|
| 34 |
+
role: str # ex: "Software Engineer"
|
| 35 |
+
location: str # ex: "Cupertino, CA"
|
| 36 |
+
date_range: str # ex: "June 2005 – Aug 2007"
|
| 37 |
+
highlights: List[str] = []
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
class PublicationEntry(BaseModel):
|
| 41 |
+
date: str # ex: "Jan 2004"
|
| 42 |
+
title: str # ex: "3D Finite Element Analysis of ..."
|
| 43 |
+
authors: List[str] # ex: ["Frodo Baggins", "John Doe", "Samwise Gamgee"]
|
| 44 |
+
doi_url: Optional[HttpUrl] = None # ex: "https://doi.org/10.1109/..."
|
| 45 |
+
doi_label: Optional[str] = None # ex: "10.1109/TASC.2023.3340648"
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
class ProjectEntry(BaseModel):
|
| 49 |
+
title: str # ex: "Multi-User Drawing Tool"
|
| 50 |
+
repo_url: Optional[HttpUrl] = None # ex: "https://github.com/name/repo"
|
| 51 |
+
repo_label: Optional[str] = None # ex: "github.com/name/repo"
|
| 52 |
+
highlights: List[str] = []
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
class Technologies(BaseModel):
|
| 56 |
+
languages: List[str] = [] # ex: ["C++", "C", "Java", ...]
|
| 57 |
+
technologies: List[str] = [] # ex: [".NET", "SQL Server", "XCode", ...]
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
class Resume(BaseModel):
|
| 61 |
+
meta: DocumentMeta
|
| 62 |
+
header: Header
|
| 63 |
+
|
| 64 |
+
# Sections correspondant au contenu du template fourni
|
| 65 |
+
intro_paragraphs: List[str] = [] # section "Welcome to RenderCV!" (paragraphes)
|
| 66 |
+
quick_guide_items: List[str] = [] # puces "Quick Guide"
|
| 67 |
+
|
| 68 |
+
education: List[EducationEntry] = []
|
| 69 |
+
experience: List[ExperienceEntry] = []
|
| 70 |
+
publications: List[PublicationEntry] = []
|
| 71 |
+
projects: List[ProjectEntry] = []
|
| 72 |
+
technologies_section: Technologies
|
pyproject.toml
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[project]
|
| 2 |
+
name = "resume-mcp"
|
| 3 |
+
version = "0.1.0"
|
| 4 |
+
description = "Génération de CV PDF via LaTeX + Jinja2 + Pydantic"
|
| 5 |
+
readme = "README.md"
|
| 6 |
+
requires-python = ">=3.10"
|
| 7 |
+
dependencies = [
|
| 8 |
+
"jinja2>=3.1",
|
| 9 |
+
"pydantic[email]>=2.7",
|
| 10 |
+
]
|
| 11 |
+
|
| 12 |
+
[tool.uv]
|
| 13 |
+
dev-dependencies = []
|
templates/classic.tex.j2
ADDED
|
@@ -0,0 +1,351 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
\documentclass[10pt, letterpaper]{article}
|
| 2 |
+
|
| 3 |
+
% Packages:
|
| 4 |
+
\usepackage[
|
| 5 |
+
ignoreheadfoot, % set margins without considering header and footer
|
| 6 |
+
top=2 cm, % seperation between body and page edge from the top
|
| 7 |
+
bottom=2 cm, % seperation between body and page edge from the bottom
|
| 8 |
+
left=2 cm, % seperation between body and page edge from the left
|
| 9 |
+
right=2 cm, % seperation between body and page edge from the right
|
| 10 |
+
footskip=1.0 cm, % seperation between body and footer
|
| 11 |
+
% showframe % for debugging
|
| 12 |
+
]{geometry} % for adjusting page geometry
|
| 13 |
+
\usepackage[explicit]{titlesec} % for customizing section titles
|
| 14 |
+
\usepackage{tabularx} % for making tables with fixed width columns
|
| 15 |
+
\usepackage{array} % tabularx requires this
|
| 16 |
+
\usepackage[dvipsnames]{xcolor} % for coloring text
|
| 17 |
+
\definecolor{primaryColor}{RGB}{0, 79, 144} % define primary color
|
| 18 |
+
\usepackage{enumitem} % for customizing lists
|
| 19 |
+
\usepackage{fontawesome5} % for using icons
|
| 20 |
+
\usepackage{amsmath} % for math
|
| 21 |
+
\usepackage[
|
| 22 |
+
pdftitle={John Doe's CV},
|
| 23 |
+
pdfauthor={John Doe},
|
| 24 |
+
pdfcreator={LaTeX with RenderCV},
|
| 25 |
+
colorlinks=true,
|
| 26 |
+
urlcolor=primaryColor
|
| 27 |
+
]{hyperref} % for links, metadata and bookmarks
|
| 28 |
+
\usepackage[pscoord]{eso-pic} % for floating text on the page
|
| 29 |
+
\usepackage{calc} % for calculating lengths
|
| 30 |
+
\usepackage{bookmark} % for bookmarks
|
| 31 |
+
\usepackage{lastpage} % for getting the total number of pages
|
| 32 |
+
\usepackage{changepage} % for one column entries (adjustwidth environment)
|
| 33 |
+
\usepackage{paracol} % for two and three column entries
|
| 34 |
+
\usepackage{ifthen} % for conditional statements
|
| 35 |
+
\usepackage{needspace} % for avoiding page brake right after the section title
|
| 36 |
+
\usepackage{iftex} % check if engine is pdflatex, xetex or luatex
|
| 37 |
+
|
| 38 |
+
% Ensure that generate pdf is machine readable/ATS parsable:
|
| 39 |
+
\ifPDFTeX
|
| 40 |
+
\input{glyphtounicode}
|
| 41 |
+
\pdfgentounicode=1
|
| 42 |
+
\usepackage[T1]{fontenc}
|
| 43 |
+
\usepackage[utf8]{inputenc}
|
| 44 |
+
\usepackage{lmodern}
|
| 45 |
+
\fi
|
| 46 |
+
|
| 47 |
+
\usepackage[default, type1]{sourcesanspro}
|
| 48 |
+
|
| 49 |
+
% Some settings:
|
| 50 |
+
\AtBeginEnvironment{adjustwidth}{\partopsep0pt} % remove space before adjustwidth environment
|
| 51 |
+
\pagestyle{empty} % no header or footer
|
| 52 |
+
\setcounter{secnumdepth}{0} % no section numbering
|
| 53 |
+
\setlength{\parindent}{0pt} % no indentation
|
| 54 |
+
\setlength{\topskip}{0pt} % no top skip
|
| 55 |
+
\setlength{\columnsep}{0.15cm} % set column seperation
|
| 56 |
+
\makeatletter
|
| 57 |
+
\let\ps@customFooterStyle\ps@plain % Copy the plain style to customFooterStyle
|
| 58 |
+
\patchcmd{\ps@customFooterStyle}{\thepage}{
|
| 59 |
+
\color{gray}\textit{\small << resume.header.name >> - Page \thepage{} of \pageref*{LastPage}}
|
| 60 |
+
}{}{} % replace number by desired string
|
| 61 |
+
\makeatother
|
| 62 |
+
\pagestyle{customFooterStyle}
|
| 63 |
+
|
| 64 |
+
\titleformat{\section}{
|
| 65 |
+
% avoid page braking right after the section title
|
| 66 |
+
\needspace{4\baselineskip}
|
| 67 |
+
% make the font size of the section title large and color it with the primary color
|
| 68 |
+
\Large\color{primaryColor}
|
| 69 |
+
}{
|
| 70 |
+
}{
|
| 71 |
+
}{
|
| 72 |
+
% print bold title, give 0.15 cm space and draw a line of 0.8 pt thickness
|
| 73 |
+
% from the end of the title to the end of the body
|
| 74 |
+
\textbf{#1}\hspace{0.15cm}\titlerule[0.8pt]\hspace{-0.1cm}
|
| 75 |
+
}[] % section title formatting
|
| 76 |
+
|
| 77 |
+
\titlespacing{\section}{
|
| 78 |
+
% left space:
|
| 79 |
+
-1pt
|
| 80 |
+
}{
|
| 81 |
+
% top space:
|
| 82 |
+
0.3 cm
|
| 83 |
+
}{
|
| 84 |
+
% bottom space:
|
| 85 |
+
0.2 cm
|
| 86 |
+
} % section title spacing
|
| 87 |
+
|
| 88 |
+
% \renewcommand\labelitemi{$\vcenter{\hbox{\small$\bullet$}}$} % custom bullet points
|
| 89 |
+
\newenvironment{highlights}{
|
| 90 |
+
\begin{itemize}[
|
| 91 |
+
topsep=0.10 cm,
|
| 92 |
+
parsep=0.10 cm,
|
| 93 |
+
partopsep=0pt,
|
| 94 |
+
itemsep=0pt,
|
| 95 |
+
leftmargin=0.4 cm + 10pt
|
| 96 |
+
]
|
| 97 |
+
}{
|
| 98 |
+
\end{itemize}
|
| 99 |
+
} % new environment for highlights
|
| 100 |
+
|
| 101 |
+
\newenvironment{highlightsforbulletentries}{
|
| 102 |
+
\begin{itemize}[
|
| 103 |
+
topsep=0.10 cm,
|
| 104 |
+
parsep=0.10 cm,
|
| 105 |
+
partopsep=0pt,
|
| 106 |
+
itemsep=0pt,
|
| 107 |
+
leftmargin=10pt
|
| 108 |
+
]
|
| 109 |
+
}{
|
| 110 |
+
\end{itemize}
|
| 111 |
+
} % new environment for highlights for bullet entries
|
| 112 |
+
|
| 113 |
+
|
| 114 |
+
\newenvironment{onecolentry}{
|
| 115 |
+
\begin{adjustwidth}{
|
| 116 |
+
0.2 cm + 0.00001 cm
|
| 117 |
+
}{
|
| 118 |
+
0.2 cm + 0.00001 cm
|
| 119 |
+
}
|
| 120 |
+
}{
|
| 121 |
+
\end{adjustwidth}
|
| 122 |
+
} % new environment for one column entries
|
| 123 |
+
|
| 124 |
+
\newenvironment{twocolentry}[2][]{
|
| 125 |
+
\onecolentry
|
| 126 |
+
\def\secondColumn{#2}
|
| 127 |
+
\setcolumnwidth{\fill, 4.5 cm}
|
| 128 |
+
\begin{paracol}{2}
|
| 129 |
+
}{
|
| 130 |
+
\switchcolumn \raggedleft \secondColumn
|
| 131 |
+
\end{paracol}
|
| 132 |
+
\endonecolentry
|
| 133 |
+
} % new environment for two column entries
|
| 134 |
+
|
| 135 |
+
\newenvironment{threecolentry}[3][]{
|
| 136 |
+
\onecolentry
|
| 137 |
+
\def\thirdColumn{#3}
|
| 138 |
+
\setcolumnwidth{1 cm, \fill, 4.5 cm}
|
| 139 |
+
\begin{paracol}{3}
|
| 140 |
+
{\raggedright #2} \switchcolumn
|
| 141 |
+
}{
|
| 142 |
+
\switchcolumn \raggedleft \thirdColumn
|
| 143 |
+
\end{paracol}
|
| 144 |
+
\endonecolentry
|
| 145 |
+
} % new environment for three column entries
|
| 146 |
+
|
| 147 |
+
\newenvironment{header}{
|
| 148 |
+
\setlength{\topsep}{0pt}\par\kern\topsep\centering\color{primaryColor}\linespread{1.5}
|
| 149 |
+
}{
|
| 150 |
+
\par\kern\topsep
|
| 151 |
+
} % new environment for the header
|
| 152 |
+
|
| 153 |
+
\newcommand{\placelastupdatedtext}{ % \placetextbox{<horizontal pos>}{<vertical pos>}{<stuff>}
|
| 154 |
+
\AddToShipoutPictureFG*{ % Add <stuff> to current page foreground
|
| 155 |
+
\put(
|
| 156 |
+
\LenToUnit{\paperwidth-2 cm-0.2 cm+0.05cm},
|
| 157 |
+
\LenToUnit{\paperheight-1.0 cm}
|
| 158 |
+
){\vtop{{\null}\makebox[0pt][c]{
|
| 159 |
+
\small\color{gray}\textit{Last updated in << resume.meta.last_updated_text | default('') >>}\hspace{\widthof{Last updated in << resume.meta.last_updated_text | default('') >> }}
|
| 160 |
+
}}}%
|
| 161 |
+
}%
|
| 162 |
+
}%
|
| 163 |
+
|
| 164 |
+
% save the original href command in a new command:
|
| 165 |
+
\let\hrefWithoutArrow\href
|
| 166 |
+
|
| 167 |
+
% new command for external links:
|
| 168 |
+
\renewcommand{\href}[2]{\hrefWithoutArrow{#1}{\ifthenelse{\equal{#2}{}}{ }{#2 }\raisebox{.15ex}{\footnotesize \faExternalLink*}}}
|
| 169 |
+
|
| 170 |
+
|
| 171 |
+
\begin{document}
|
| 172 |
+
\newcommand{\AND}{\unskip
|
| 173 |
+
\cleaders\copy\ANDbox\hskip\wd\ANDbox
|
| 174 |
+
\ignorespaces
|
| 175 |
+
}
|
| 176 |
+
\newsavebox\ANDbox
|
| 177 |
+
\sbox\ANDbox{}
|
| 178 |
+
|
| 179 |
+
\hypersetup{
|
| 180 |
+
pdftitle=<< '{' >><< resume.meta.pdf_title >><< '}' >>,
|
| 181 |
+
pdfauthor=<< '{' >><< resume.meta.pdf_author >><< '}' >>
|
| 182 |
+
}
|
| 183 |
+
\placelastupdatedtext
|
| 184 |
+
\begin{header}
|
| 185 |
+
\fontsize{30 pt}{30 pt}
|
| 186 |
+
\textbf{ << resume.header.name >> }
|
| 187 |
+
|
| 188 |
+
\vspace{0.3 cm}
|
| 189 |
+
|
| 190 |
+
\normalsize
|
| 191 |
+
\mbox{{\footnotesize\faMapMarker*}\hspace*{0.13cm}<< resume.header.location >>}%
|
| 192 |
+
\kern 0.25 cm%
|
| 193 |
+
\AND%
|
| 194 |
+
\kern 0.25 cm%
|
| 195 |
+
\mbox{\hrefWithoutArrow{mailto:<< resume.header.email >>}{{\footnotesize\faEnvelope[regular]}\hspace*{0.13cm}<< resume.header.email >>}}%
|
| 196 |
+
\kern 0.25 cm%
|
| 197 |
+
\AND%
|
| 198 |
+
\kern 0.25 cm%
|
| 199 |
+
\mbox{\hrefWithoutArrow{tel:<< resume.header.phone | replace(' ', '') | replace('-', '') >>}{{\footnotesize\faPhone*}\hspace*{0.13cm}<< resume.header.phone >>}}%
|
| 200 |
+
<<% if resume.header.website_url %>>
|
| 201 |
+
\kern 0.25 cm%
|
| 202 |
+
\AND%
|
| 203 |
+
\kern 0.25 cm%
|
| 204 |
+
\mbox{\hrefWithoutArrow{ << resume.header.website_url >> }{{\footnotesize\faLink}\hspace*{0.13cm}<< resume.header.website_label or resume.header.website_url >>}}%
|
| 205 |
+
<<% endif %>>
|
| 206 |
+
<<% if resume.header.linkedin_url %>>
|
| 207 |
+
\kern 0.25 cm%
|
| 208 |
+
\AND%
|
| 209 |
+
\kern 0.25 cm%
|
| 210 |
+
\mbox{\hrefWithoutArrow{ << resume.header.linkedin_url >> }{{\footnotesize\faLinkedinIn}\hspace*{0.13cm}<< resume.header.linkedin_handle or resume.header.linkedin_url >>}}%
|
| 211 |
+
<<% endif %>>
|
| 212 |
+
<<% if resume.header.github_url %>>
|
| 213 |
+
\kern 0.25 cm%
|
| 214 |
+
\AND%
|
| 215 |
+
\kern 0.25 cm%
|
| 216 |
+
\mbox{\hrefWithoutArrow{ << resume.header.github_url >> }{{\footnotesize\faGithub}\hspace*{0.13cm}<< resume.header.github_handle or resume.header.github_url >>}}%
|
| 217 |
+
<<% endif %>>
|
| 218 |
+
\end{header}
|
| 219 |
+
|
| 220 |
+
\vspace{0.3 cm - 0.3 cm}
|
| 221 |
+
|
| 222 |
+
|
| 223 |
+
\section{About}
|
| 224 |
+
|
| 225 |
+
<<% for p in resume.intro_paragraphs %>>
|
| 226 |
+
\begin{onecolentry}
|
| 227 |
+
<< p >>
|
| 228 |
+
\end{onecolentry}
|
| 229 |
+
<<% if not loop.last %>>
|
| 230 |
+
\vspace{0.2 cm}
|
| 231 |
+
<<% endif %>>
|
| 232 |
+
<<% endfor %>>
|
| 233 |
+
|
| 234 |
+
|
| 235 |
+
|
| 236 |
+
|
| 237 |
+
\section{Highlights}
|
| 238 |
+
|
| 239 |
+
\begin{onecolentry}
|
| 240 |
+
\begin{highlightsforbulletentries}
|
| 241 |
+
<<% for item in resume.quick_guide_items %>>
|
| 242 |
+
\item << item >>
|
| 243 |
+
<<% endfor %>>
|
| 244 |
+
\end{highlightsforbulletentries}
|
| 245 |
+
\end{onecolentry}
|
| 246 |
+
|
| 247 |
+
\section{Education}
|
| 248 |
+
|
| 249 |
+
|
| 250 |
+
<<% for edu in resume.education %>>
|
| 251 |
+
\begin{threecolentry}{\textbf{ << edu.degree >> }}{
|
| 252 |
+
<< edu.date_range >>
|
| 253 |
+
}
|
| 254 |
+
\textbf{ << edu.institution >> }<<% if edu.field_of_study %>>, << edu.field_of_study >><<% endif %>>
|
| 255 |
+
<<% if edu.highlights %>>
|
| 256 |
+
\begin{highlights}
|
| 257 |
+
<<% for h in edu.highlights %>>
|
| 258 |
+
\item << h >>
|
| 259 |
+
<<% endfor %>>
|
| 260 |
+
\end{highlights}
|
| 261 |
+
<<% endif %>>
|
| 262 |
+
\end{threecolentry}
|
| 263 |
+
<<% endfor %>>
|
| 264 |
+
|
| 265 |
+
|
| 266 |
+
\section{Experience}
|
| 267 |
+
|
| 268 |
+
|
| 269 |
+
<<% for exp in resume.experience %>>
|
| 270 |
+
\begin{twocolentry}{
|
| 271 |
+
<< exp.location >>
|
| 272 |
+
|
| 273 |
+
<< exp.date_range >>
|
| 274 |
+
}
|
| 275 |
+
\textbf{ << exp.company >> }, << exp.role >>
|
| 276 |
+
<<% if exp.highlights %>>
|
| 277 |
+
\begin{highlights}
|
| 278 |
+
<<% for h in exp.highlights %>>
|
| 279 |
+
\item << h >>
|
| 280 |
+
<<% endfor %>>
|
| 281 |
+
\end{highlights}
|
| 282 |
+
<<% endif %>>
|
| 283 |
+
\end{twocolentry}
|
| 284 |
+
<<% if not loop.last %>>
|
| 285 |
+
\vspace{0.2 cm}
|
| 286 |
+
<<% endif %>>
|
| 287 |
+
<<% endfor %>>
|
| 288 |
+
|
| 289 |
+
|
| 290 |
+
|
| 291 |
+
\section{Publications}
|
| 292 |
+
|
| 293 |
+
|
| 294 |
+
<<% for pub in resume.publications %>>
|
| 295 |
+
\begin{samepage}
|
| 296 |
+
\begin{twocolentry}{
|
| 297 |
+
<< pub.date >>
|
| 298 |
+
}
|
| 299 |
+
\textbf{ << pub.title >> }
|
| 300 |
+
|
| 301 |
+
\vspace{0.10 cm}
|
| 302 |
+
|
| 303 |
+
<< pub.authors | join(', ') >>
|
| 304 |
+
\vspace{0.10 cm}
|
| 305 |
+
<<% if pub.doi_url %>>
|
| 306 |
+
\href{ << pub.doi_url >> }{ << pub.doi_label or pub.doi_url >> }
|
| 307 |
+
<<% endif %>>
|
| 308 |
+
\end{twocolentry}
|
| 309 |
+
\end{samepage}
|
| 310 |
+
<<% endfor %>>
|
| 311 |
+
|
| 312 |
+
|
| 313 |
+
\section{Projects}
|
| 314 |
+
|
| 315 |
+
|
| 316 |
+
<<% for pr in resume.projects %>>
|
| 317 |
+
\begin{twocolentry}{
|
| 318 |
+
<<% if pr.repo_url %>>\href{ << pr.repo_url >> }{ << pr.repo_label or pr.repo_url >> }<<% endif %>>
|
| 319 |
+
}
|
| 320 |
+
\textbf{ << pr.title >> }
|
| 321 |
+
<<% if pr.highlights %>>
|
| 322 |
+
\begin{highlights}
|
| 323 |
+
<<% for h in pr.highlights %>>
|
| 324 |
+
\item << h >>
|
| 325 |
+
<<% endfor %>>
|
| 326 |
+
\end{highlights}
|
| 327 |
+
<<% endif %>>
|
| 328 |
+
\end{twocolentry}
|
| 329 |
+
<<% if not loop.last %>>
|
| 330 |
+
\vspace{0.2 cm}
|
| 331 |
+
<<% endif %>>
|
| 332 |
+
<<% endfor %>>
|
| 333 |
+
|
| 334 |
+
|
| 335 |
+
\section{Technologies}
|
| 336 |
+
|
| 337 |
+
|
| 338 |
+
\begin{onecolentry}
|
| 339 |
+
\textbf{Languages:} << resume.technologies_section.languages | join(', ') >>
|
| 340 |
+
\end{onecolentry}
|
| 341 |
+
|
| 342 |
+
\vspace{0.2 cm}
|
| 343 |
+
|
| 344 |
+
\begin{onecolentry}
|
| 345 |
+
\textbf{Technologies:} << resume.technologies_section.technologies | join(', ') >>
|
| 346 |
+
\end{onecolentry}
|
| 347 |
+
|
| 348 |
+
|
| 349 |
+
\end{document}
|
| 350 |
+
|
| 351 |
+
|
templates/clean.tex.j2
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
% Clean CV/Resume Template adapted for Jinja2 (Resume schema)
|
| 2 |
+
\documentclass[oneside]{article}
|
| 3 |
+
|
| 4 |
+
\usepackage{wallpaper}
|
| 5 |
+
\usepackage{geometry}
|
| 6 |
+
\usepackage[
|
| 7 |
+
unicode=true,
|
| 8 |
+
bookmarks=true,
|
| 9 |
+
bookmarksnumbered=false,
|
| 10 |
+
bookmarksopen=true,
|
| 11 |
+
bookmarksopenlevel=1,
|
| 12 |
+
breaklinks=false,
|
| 13 |
+
pdfborder={0 0 0},
|
| 14 |
+
backref=false,
|
| 15 |
+
colorlinks=false
|
| 16 |
+
]{hyperref}
|
| 17 |
+
\usepackage{lastpage}
|
| 18 |
+
\usepackage{hyphenat}
|
| 19 |
+
\usepackage{hyphsubst}
|
| 20 |
+
\usepackage{tabularx}
|
| 21 |
+
\usepackage{moresize}
|
| 22 |
+
\usepackage[document]{ragged2e}
|
| 23 |
+
% \usepackage{parskip}
|
| 24 |
+
|
| 25 |
+
\usepackage[scaled]{helvet}
|
| 26 |
+
\usepackage{fontawesome5}
|
| 27 |
+
\usepackage[defaultfam,tabular,oldstyle]{montserrat}
|
| 28 |
+
\usepackage[T1]{fontenc}
|
| 29 |
+
\renewcommand*\oldstylenums[1]{{\fontfamily{Montserrat-TOsF}\selectfont #1}}
|
| 30 |
+
|
| 31 |
+
\usepackage{titlesec}
|
| 32 |
+
\usepackage{xcolor}
|
| 33 |
+
\usepackage{tikz}
|
| 34 |
+
|
| 35 |
+
\setlength{\parindent}{0pt}
|
| 36 |
+
\titleformat{\section}{\normalfont}{}{0pt}{}
|
| 37 |
+
|
| 38 |
+
\renewcommand{\arraystretch}{1.4}
|
| 39 |
+
|
| 40 |
+
\setlength\fboxrule{0pt}
|
| 41 |
+
\setlength\fboxsep{12pt}
|
| 42 |
+
% \setlength{\parskip}{.5\baselineskip plus 2pt}
|
| 43 |
+
% \renewcommand{\baselinestretch}{1.1}
|
| 44 |
+
|
| 45 |
+
\titlespacing{\section}{0pt}{1.5ex plus .1ex minus .2ex}{1pc}
|
| 46 |
+
|
| 47 |
+
\newcolumntype{Y}{>{\RaggedRight\arraybackslash}X}
|
| 48 |
+
|
| 49 |
+
% PDF Meta Info
|
| 50 |
+
\hypersetup{
|
| 51 |
+
pdftitle=<< '{' >><< resume.meta.pdf_title >><< '}' >>,
|
| 52 |
+
pdfauthor=<< '{' >><< resume.meta.pdf_author >><< '}' >>,
|
| 53 |
+
pdfsubject={CV}
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
+
% Paper size
|
| 57 |
+
\geometry{
|
| 58 |
+
a4paper,
|
| 59 |
+
left=0pt,
|
| 60 |
+
right=0pt,
|
| 61 |
+
top=0pt,
|
| 62 |
+
bottom=0pt,
|
| 63 |
+
nohead,
|
| 64 |
+
% includefoot,
|
| 65 |
+
nomarginpar
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
% Colors
|
| 69 |
+
\definecolor{sidebg}{cmyk}{1, 0.02, 0, 0.56}
|
| 70 |
+
\definecolor{mainbg}{cmyk}{0, 0, 0.07, 0.04}
|
| 71 |
+
\definecolor{maintext}{cmyk}{1, 0.02, 0, 0.8}
|
| 72 |
+
\definecolor{sidetext}{cmyk}{0, 0, 0.07, 0.04}
|
| 73 |
+
|
| 74 |
+
\pagecolor{mainbg}
|
| 75 |
+
|
| 76 |
+
\begin{document}
|
| 77 |
+
\setlength{\topskip}{0pt}\setlength{\footskip}{0pt}%
|
| 78 |
+
\fcolorbox{red}{sidebg}{%
|
| 79 |
+
\begin{minipage}[t][\textheight-2\fboxsep-2\fboxrule][t]{\dimexpr0.40\textwidth-2\fboxrule-2\fboxsep\relax}
|
| 80 |
+
\color{sidetext}
|
| 81 |
+
% Name
|
| 82 |
+
{\bfseries\scshape\HUGE << resume.header.name >>} \\
|
| 83 |
+
\vspace{.5cm}
|
| 84 |
+
% Contact
|
| 85 |
+
\phantomsection{}
|
| 86 |
+
\addcontentsline{toc}{section}{Contact}
|
| 87 |
+
\section*{\large Contact}
|
| 88 |
+
\begin{tabularx}{\textwidth}{cY}
|
| 89 |
+
\faMapMarker{} & << resume.header.location >> \\
|
| 90 |
+
\faPhone{} & << resume.header.phone >> \\
|
| 91 |
+
\faEnvelope{} & \href{mailto:<< resume.header.email >>}{<< resume.header.email >>} \\
|
| 92 |
+
<<% if resume.header.website_url %>>\faLink{} & \href{ << resume.header.website_url >> }{ << resume.header.website_label or resume.header.website_url >> } \\<<% endif %>>
|
| 93 |
+
\end{tabularx}
|
| 94 |
+
\vspace{.3cm} \\
|
| 95 |
+
\rule{\linewidth}{0.4pt} \\
|
| 96 |
+
% Links
|
| 97 |
+
\phantomsection{}
|
| 98 |
+
\addcontentsline{toc}{section}{Links}
|
| 99 |
+
\section*{\large Links}
|
| 100 |
+
\begin{tabular}{cl}
|
| 101 |
+
<<% if resume.header.github_url %>>\faGithub{} & \href{ << resume.header.github_url >> }{ << resume.header.github_handle or resume.header.github_url >> } \\<<% endif %>>
|
| 102 |
+
<<% if resume.header.linkedin_url %>>\faLinkedin{} & \href{ << resume.header.linkedin_url >> }{ << resume.header.linkedin_handle or resume.header.linkedin_url >> } \\<<% endif %>>
|
| 103 |
+
\end{tabular}
|
| 104 |
+
\vspace{10pt} \\
|
| 105 |
+
\rule{\linewidth}{0.4pt} \\
|
| 106 |
+
% Technologies
|
| 107 |
+
\phantomsection{}
|
| 108 |
+
\addcontentsline{toc}{section}{Technologies}
|
| 109 |
+
\section*{\large Technologies}
|
| 110 |
+
\begin{tabularx}{\textwidth}{cY}
|
| 111 |
+
\faCode{} & \textbf{Languages:} << resume.technologies_section.languages | join(', ') >> \\
|
| 112 |
+
\faCogs{} & \textbf{Technologies:} << resume.technologies_section.technologies | join(', ') >> \\
|
| 113 |
+
\end{tabularx}
|
| 114 |
+
\vspace{1pt} \\
|
| 115 |
+
\rule{\linewidth}{0.4pt}
|
| 116 |
+
\vfill
|
| 117 |
+
{\tiny Last updated in << resume.meta.last_updated_text | default('') >>}
|
| 118 |
+
\end{minipage}
|
| 119 |
+
}
|
| 120 |
+
\hfill
|
| 121 |
+
\fcolorbox{red}{mainbg}{%
|
| 122 |
+
\begin{minipage}[t][\dimexpr\textheight-2\fboxrule-2\fboxsep\relax][t]{\dimexpr0.6\textwidth-2\fboxrule-2\fboxsep\relax}
|
| 123 |
+
\color{maintext}
|
| 124 |
+
% About
|
| 125 |
+
\phantomsection{}
|
| 126 |
+
\addcontentsline{toc}{section}{About}
|
| 127 |
+
\section*{\scshape\Large About \rule{\linewidth}{0.4pt}}
|
| 128 |
+
<<% for p in resume.intro_paragraphs %>><< p >>\\<<% endfor %>>
|
| 129 |
+
|
| 130 |
+
% Highlights
|
| 131 |
+
\phantomsection{}
|
| 132 |
+
\addcontentsline{toc}{section}{Highlights}
|
| 133 |
+
\section*{\scshape\Large Highlights \rule{\linewidth}{0.4pt}}
|
| 134 |
+
\begin{itemize}
|
| 135 |
+
<<% for item in resume.quick_guide_items %>>\item << item >>
|
| 136 |
+
<<% endfor %>>
|
| 137 |
+
\end{itemize}
|
| 138 |
+
|
| 139 |
+
% Work Experience
|
| 140 |
+
\phantomsection{}
|
| 141 |
+
\addcontentsline{toc}{section}{Experience}
|
| 142 |
+
\section*{\scshape\Large Experience \rule{\linewidth}{0.4pt}}
|
| 143 |
+
<<% for exp in resume.experience %>>
|
| 144 |
+
{\large \textbf{ << exp.company >> }} \\
|
| 145 |
+
{\fontseries{medium}\selectfont << exp.role >>} \\
|
| 146 |
+
{\scshape\fontseries{light}\selectfont\footnotesize << exp.location >> \qquad << exp.date_range >>}
|
| 147 |
+
\begin{itemize}
|
| 148 |
+
\setlength{\itemsep}{-3pt}
|
| 149 |
+
<<% for h in exp.highlights %>>\item << h >>
|
| 150 |
+
<<% endfor %>>
|
| 151 |
+
\end{itemize}
|
| 152 |
+
<<% endfor %>>
|
| 153 |
+
|
| 154 |
+
% Education
|
| 155 |
+
\phantomsection{}
|
| 156 |
+
\addcontentsline{toc}{section}{Education}
|
| 157 |
+
\section*{\scshape\Large Education \rule{\linewidth}{0.4pt}}
|
| 158 |
+
<<% for edu in resume.education %>>
|
| 159 |
+
{\large \textbf{ << edu.institution >> }} \\
|
| 160 |
+
{\fontseries{medium}\selectfont << edu.degree >><<% if edu.field_of_study %>>, << edu.field_of_study >><<% endif %>>} \\
|
| 161 |
+
{\scshape\fontseries{light}\selectfont\footnotesize << edu.date_range >>} \\
|
| 162 |
+
<<% if edu.highlights %>><<% for h in edu.highlights %>>{\footnotesize << h >>} \\<<% endfor %>><<% endif %>>
|
| 163 |
+
\vspace{1ex}
|
| 164 |
+
<<% endfor %>>
|
| 165 |
+
|
| 166 |
+
% Publications
|
| 167 |
+
<<% if resume.publications %>>
|
| 168 |
+
\phantomsection{}
|
| 169 |
+
\addcontentsline{toc}{section}{Publications}
|
| 170 |
+
\section*{\scshape\Large Publications \rule{\linewidth}{0.4pt}}
|
| 171 |
+
<<% for pub in resume.publications %>>
|
| 172 |
+
{\large \textbf{ << pub.title >> }} \\
|
| 173 |
+
{\scshape\fontseries{light}\selectfont\footnotesize << pub.authors | join(', ') >> \qquad << pub.date >>} \\
|
| 174 |
+
<<% if pub.doi_url %>>\href{ << pub.doi_url >> }{ << pub.doi_label or pub.doi_url >> }<<% endif %>>
|
| 175 |
+
\vspace{1ex}
|
| 176 |
+
<<% endfor %>>
|
| 177 |
+
<<% endif %>>
|
| 178 |
+
|
| 179 |
+
% Projects
|
| 180 |
+
<<% if resume.projects %>>
|
| 181 |
+
\phantomsection{}
|
| 182 |
+
\addcontentsline{toc}{section}{Projects}
|
| 183 |
+
\section*{\scshape\Large Projects \rule{\linewidth}{0.4pt}}
|
| 184 |
+
<<% for pr in resume.projects %>>
|
| 185 |
+
{\large \textbf{ << pr.title >> }} \\
|
| 186 |
+
<<% if pr.repo_url %>>\href{ << pr.repo_url >> }{ << pr.repo_label or pr.repo_url >> }\\<<% endif %>>
|
| 187 |
+
\begin{itemize}
|
| 188 |
+
\setlength{\itemsep}{-3pt}
|
| 189 |
+
<<% for h in pr.highlights %>>\item << h >>
|
| 190 |
+
<<% endfor %>>
|
| 191 |
+
\end{itemize}
|
| 192 |
+
<<% endfor %>>
|
| 193 |
+
<<% endif %>>
|
| 194 |
+
|
| 195 |
+
\vfill% footer
|
| 196 |
+
{\hfill\small\fontseries{extralight}\selectfont Page \thepage~of~\pageref{LastPage}\hfill}
|
| 197 |
+
\end{minipage}
|
| 198 |
+
}%
|
| 199 |
+
\end{document}
|
templates/template.tex
ADDED
|
@@ -0,0 +1,370 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
\documentclass[10pt, letterpaper]{article}
|
| 2 |
+
|
| 3 |
+
% Packages:
|
| 4 |
+
\usepackage[
|
| 5 |
+
ignoreheadfoot, % set margins without considering header and footer
|
| 6 |
+
top=2 cm, % seperation between body and page edge from the top
|
| 7 |
+
bottom=2 cm, % seperation between body and page edge from the bottom
|
| 8 |
+
left=2 cm, % seperation between body and page edge from the left
|
| 9 |
+
right=2 cm, % seperation between body and page edge from the right
|
| 10 |
+
footskip=1.0 cm, % seperation between body and footer
|
| 11 |
+
% showframe % for debugging
|
| 12 |
+
]{geometry} % for adjusting page geometry
|
| 13 |
+
\usepackage[explicit]{titlesec} % for customizing section titles
|
| 14 |
+
\usepackage{tabularx} % for making tables with fixed width columns
|
| 15 |
+
\usepackage{array} % tabularx requires this
|
| 16 |
+
\usepackage[dvipsnames]{xcolor} % for coloring text
|
| 17 |
+
\definecolor{primaryColor}{RGB}{0, 79, 144} % define primary color
|
| 18 |
+
\usepackage{enumitem} % for customizing lists
|
| 19 |
+
\usepackage{fontawesome5} % for using icons
|
| 20 |
+
\usepackage{amsmath} % for math
|
| 21 |
+
\usepackage[
|
| 22 |
+
pdftitle={John Doe's CV},
|
| 23 |
+
pdfauthor={John Doe},
|
| 24 |
+
pdfcreator={LaTeX with RenderCV},
|
| 25 |
+
colorlinks=true,
|
| 26 |
+
urlcolor=primaryColor
|
| 27 |
+
]{hyperref} % for links, metadata and bookmarks
|
| 28 |
+
\usepackage[pscoord]{eso-pic} % for floating text on the page
|
| 29 |
+
\usepackage{calc} % for calculating lengths
|
| 30 |
+
\usepackage{bookmark} % for bookmarks
|
| 31 |
+
\usepackage{lastpage} % for getting the total number of pages
|
| 32 |
+
\usepackage{changepage} % for one column entries (adjustwidth environment)
|
| 33 |
+
\usepackage{paracol} % for two and three column entries
|
| 34 |
+
\usepackage{ifthen} % for conditional statements
|
| 35 |
+
\usepackage{needspace} % for avoiding page brake right after the section title
|
| 36 |
+
\usepackage{iftex} % check if engine is pdflatex, xetex or luatex
|
| 37 |
+
|
| 38 |
+
% Ensure that generate pdf is machine readable/ATS parsable:
|
| 39 |
+
\ifPDFTeX
|
| 40 |
+
\input{glyphtounicode}
|
| 41 |
+
\pdfgentounicode=1
|
| 42 |
+
\usepackage[T1]{fontenc}
|
| 43 |
+
\usepackage[utf8]{inputenc}
|
| 44 |
+
\usepackage{lmodern}
|
| 45 |
+
\fi
|
| 46 |
+
|
| 47 |
+
\usepackage[default, type1]{sourcesanspro}
|
| 48 |
+
|
| 49 |
+
% Some settings:
|
| 50 |
+
\AtBeginEnvironment{adjustwidth}{\partopsep0pt} % remove space before adjustwidth environment
|
| 51 |
+
\pagestyle{empty} % no header or footer
|
| 52 |
+
\setcounter{secnumdepth}{0} % no section numbering
|
| 53 |
+
\setlength{\parindent}{0pt} % no indentation
|
| 54 |
+
\setlength{\topskip}{0pt} % no top skip
|
| 55 |
+
\setlength{\columnsep}{0.15cm} % set column seperation
|
| 56 |
+
\makeatletter
|
| 57 |
+
\let\ps@customFooterStyle\ps@plain % Copy the plain style to customFooterStyle
|
| 58 |
+
\patchcmd{\ps@customFooterStyle}{\thepage}{
|
| 59 |
+
\color{gray}\textit{\small {{ resume.header.name }} - Page \thepage{} of \pageref*{LastPage}}
|
| 60 |
+
}{}{} % replace number by desired string
|
| 61 |
+
\makeatother
|
| 62 |
+
\pagestyle{customFooterStyle}
|
| 63 |
+
|
| 64 |
+
\titleformat{\section}{
|
| 65 |
+
% avoid page braking right after the section title
|
| 66 |
+
\needspace{4\baselineskip}
|
| 67 |
+
% make the font size of the section title large and color it with the primary color
|
| 68 |
+
\Large\color{primaryColor}
|
| 69 |
+
}{
|
| 70 |
+
}{
|
| 71 |
+
}{
|
| 72 |
+
% print bold title, give 0.15 cm space and draw a line of 0.8 pt thickness
|
| 73 |
+
% from the end of the title to the end of the body
|
| 74 |
+
\textbf{#1}\hspace{0.15cm}\titlerule[0.8pt]\hspace{-0.1cm}
|
| 75 |
+
}[] % section title formatting
|
| 76 |
+
|
| 77 |
+
\titlespacing{\section}{
|
| 78 |
+
% left space:
|
| 79 |
+
-1pt
|
| 80 |
+
}{
|
| 81 |
+
% top space:
|
| 82 |
+
0.3 cm
|
| 83 |
+
}{
|
| 84 |
+
% bottom space:
|
| 85 |
+
0.2 cm
|
| 86 |
+
} % section title spacing
|
| 87 |
+
|
| 88 |
+
% \renewcommand\labelitemi{$\vcenter{\hbox{\small$\bullet$}}$} % custom bullet points
|
| 89 |
+
\newenvironment{highlights}{
|
| 90 |
+
\begin{itemize}[
|
| 91 |
+
topsep=0.10 cm,
|
| 92 |
+
parsep=0.10 cm,
|
| 93 |
+
partopsep=0pt,
|
| 94 |
+
itemsep=0pt,
|
| 95 |
+
leftmargin=0.4 cm + 10pt
|
| 96 |
+
]
|
| 97 |
+
}{
|
| 98 |
+
\end{itemize}
|
| 99 |
+
} % new environment for highlights
|
| 100 |
+
|
| 101 |
+
\newenvironment{highlightsforbulletentries}{
|
| 102 |
+
\begin{itemize}[
|
| 103 |
+
topsep=0.10 cm,
|
| 104 |
+
parsep=0.10 cm,
|
| 105 |
+
partopsep=0pt,
|
| 106 |
+
itemsep=0pt,
|
| 107 |
+
leftmargin=10pt
|
| 108 |
+
]
|
| 109 |
+
}{
|
| 110 |
+
\end{itemize}
|
| 111 |
+
} % new environment for highlights for bullet entries
|
| 112 |
+
|
| 113 |
+
|
| 114 |
+
\newenvironment{onecolentry}{
|
| 115 |
+
\begin{adjustwidth}{
|
| 116 |
+
0.2 cm + 0.00001 cm
|
| 117 |
+
}{
|
| 118 |
+
0.2 cm + 0.00001 cm
|
| 119 |
+
}
|
| 120 |
+
}{
|
| 121 |
+
\end{adjustwidth}
|
| 122 |
+
} % new environment for one column entries
|
| 123 |
+
|
| 124 |
+
\newenvironment{twocolentry}[2][]{
|
| 125 |
+
\onecolentry
|
| 126 |
+
\def\secondColumn{#2}
|
| 127 |
+
\setcolumnwidth{\fill, 4.5 cm}
|
| 128 |
+
\begin{paracol}{2}
|
| 129 |
+
}{
|
| 130 |
+
\switchcolumn \raggedleft \secondColumn
|
| 131 |
+
\end{paracol}
|
| 132 |
+
\endonecolentry
|
| 133 |
+
} % new environment for two column entries
|
| 134 |
+
|
| 135 |
+
\newenvironment{threecolentry}[3][]{
|
| 136 |
+
\onecolentry
|
| 137 |
+
\def\thirdColumn{#3}
|
| 138 |
+
\setcolumnwidth{1 cm, \fill, 4.5 cm}
|
| 139 |
+
\begin{paracol}{3}
|
| 140 |
+
{\raggedright #2} \switchcolumn
|
| 141 |
+
}{
|
| 142 |
+
\switchcolumn \raggedleft \thirdColumn
|
| 143 |
+
\end{paracol}
|
| 144 |
+
\endonecolentry
|
| 145 |
+
} % new environment for three column entries
|
| 146 |
+
|
| 147 |
+
\newenvironment{header}{
|
| 148 |
+
\setlength{\topsep}{0pt}\par\kern\topsep\centering\color{primaryColor}\linespread{1.5}
|
| 149 |
+
}{
|
| 150 |
+
\par\kern\topsep
|
| 151 |
+
} % new environment for the header
|
| 152 |
+
|
| 153 |
+
\newcommand{\placelastupdatedtext}{ % \placetextbox{<horizontal pos>}{<vertical pos>}{<stuff>}
|
| 154 |
+
\AddToShipoutPictureFG*{ % Add <stuff> to current page foreground
|
| 155 |
+
\put(
|
| 156 |
+
\LenToUnit{\paperwidth-2 cm-0.2 cm+0.05cm},
|
| 157 |
+
\LenToUnit{\paperheight-1.0 cm}
|
| 158 |
+
){\vtop{{\null}\makebox[0pt][c]{
|
| 159 |
+
\small\color{gray}\textit{Last updated in {{ resume.meta.last_updated_text | default('') }}}\hspace{\widthof{Last updated in {{ resume.meta.last_updated_text | default('') }} }}
|
| 160 |
+
}}}%
|
| 161 |
+
}%
|
| 162 |
+
}%
|
| 163 |
+
|
| 164 |
+
% save the original href command in a new command:
|
| 165 |
+
\let\hrefWithoutArrow\href
|
| 166 |
+
|
| 167 |
+
% new command for external links:
|
| 168 |
+
\renewcommand{\href}[2]{\hrefWithoutArrow{#1}{\ifthenelse{\equal{#2}{}}{ }{#2 }\raisebox{.15ex}{\footnotesize \faExternalLink*}}}
|
| 169 |
+
|
| 170 |
+
|
| 171 |
+
\begin{document}
|
| 172 |
+
\newcommand{\AND}{\unskip
|
| 173 |
+
\cleaders\copy\ANDbox\hskip\wd\ANDbox
|
| 174 |
+
\ignorespaces
|
| 175 |
+
}
|
| 176 |
+
\newsavebox\ANDbox
|
| 177 |
+
\sbox\ANDbox{}
|
| 178 |
+
|
| 179 |
+
\hypersetup{
|
| 180 |
+
pdftitle={{ '{' }}{{ resume.meta.pdf_title }}{{ '}' }},
|
| 181 |
+
pdfauthor={{ '{' }}{{ resume.meta.pdf_author }}{{ '}' }}
|
| 182 |
+
}
|
| 183 |
+
\placelastupdatedtext
|
| 184 |
+
\begin{header}
|
| 185 |
+
\fontsize{30 pt}{30 pt}
|
| 186 |
+
\textbf{ {{ resume.header.name }} }
|
| 187 |
+
|
| 188 |
+
\vspace{0.3 cm}
|
| 189 |
+
|
| 190 |
+
\normalsize
|
| 191 |
+
\mbox{{\footnotesize\faMapMarker*}\hspace*{0.13cm}{{ resume.header.location }}}%
|
| 192 |
+
\kern 0.25 cm%
|
| 193 |
+
\AND%
|
| 194 |
+
\kern 0.25 cm%
|
| 195 |
+
\mbox{\hrefWithoutArrow{mailto:{{ resume.header.email }}}{{\footnotesize\faEnvelope[regular]}\hspace*{0.13cm}{{ resume.header.email }}}}%
|
| 196 |
+
\kern 0.25 cm%
|
| 197 |
+
\AND%
|
| 198 |
+
\kern 0.25 cm%
|
| 199 |
+
\mbox{\hrefWithoutArrow{tel:{{ resume.header.phone | replace(' ', '') | replace('-', '') }}}{{\footnotesize\faPhone*}\hspace*{0.13cm}{{ resume.header.phone }}}}%
|
| 200 |
+
{% if resume.header.website_url %}
|
| 201 |
+
\kern 0.25 cm%
|
| 202 |
+
\AND%
|
| 203 |
+
\kern 0.25 cm%
|
| 204 |
+
\mbox{\hrefWithoutArrow{ {{ resume.header.website_url }} }{{\footnotesize\faLink}\hspace*{0.13cm}{{ resume.header.website_label or resume.header.website_url }}}}%
|
| 205 |
+
{% endif %}
|
| 206 |
+
{% if resume.header.linkedin_url %}
|
| 207 |
+
\kern 0.25 cm%
|
| 208 |
+
\AND%
|
| 209 |
+
\kern 0.25 cm%
|
| 210 |
+
\mbox{\hrefWithoutArrow{ {{ resume.header.linkedin_url }} }{{\footnotesize\faLinkedinIn}\hspace*{0.13cm}{{ resume.header.linkedin_handle or resume.header.linkedin_url }}}}%
|
| 211 |
+
{% endif %}
|
| 212 |
+
{% if resume.header.github_url %}
|
| 213 |
+
\kern 0.25 cm%
|
| 214 |
+
\AND%
|
| 215 |
+
\kern 0.25 cm%
|
| 216 |
+
\mbox{\hrefWithoutArrow{ {{ resume.header.github_url }} }{{\footnotesize\faGithub}\hspace*{0.13cm}{{ resume.header.github_handle or resume.header.github_url }}}}%
|
| 217 |
+
{% endif %}
|
| 218 |
+
\end{header}
|
| 219 |
+
|
| 220 |
+
\vspace{0.3 cm - 0.3 cm}
|
| 221 |
+
|
| 222 |
+
|
| 223 |
+
\section{Welcome to RenderCV!}
|
| 224 |
+
|
| 225 |
+
{% for p in resume.intro_paragraphs %}
|
| 226 |
+
\begin{onecolentry}
|
| 227 |
+
{{ p }}
|
| 228 |
+
\end{onecolentry}
|
| 229 |
+
{% if not loop.last %}
|
| 230 |
+
\vspace{0.2 cm}
|
| 231 |
+
{% endif %}
|
| 232 |
+
{% endfor %}
|
| 233 |
+
|
| 234 |
+
|
| 235 |
+
|
| 236 |
+
|
| 237 |
+
|
| 238 |
+
\section{Quick Guide}
|
| 239 |
+
|
| 240 |
+
\begin{onecolentry}
|
| 241 |
+
\begin{highlightsforbulletentries}
|
| 242 |
+
{% for item in resume.quick_guide_items %}
|
| 243 |
+
\item {{ item }}
|
| 244 |
+
{% endfor %}
|
| 245 |
+
\end{highlightsforbulletentries}
|
| 246 |
+
\end{onecolentry}
|
| 247 |
+
|
| 248 |
+
\section{Education}
|
| 249 |
+
|
| 250 |
+
|
| 251 |
+
|
| 252 |
+
|
| 253 |
+
{% for edu in resume.education %}
|
| 254 |
+
\begin{threecolentry}{\textbf{ {{ edu.degree }} }}{
|
| 255 |
+
{{ edu.date_range }}
|
| 256 |
+
}
|
| 257 |
+
\textbf{ {{ edu.institution }} }{% if edu.field_of_study %}, {{ edu.field_of_study }}{% endif %}
|
| 258 |
+
{% if edu.highlights %}
|
| 259 |
+
\begin{highlights}
|
| 260 |
+
{% for h in edu.highlights %}
|
| 261 |
+
\item {{ h }}
|
| 262 |
+
{% endfor %}
|
| 263 |
+
\end{highlights}
|
| 264 |
+
{% endif %}
|
| 265 |
+
\end{threecolentry}
|
| 266 |
+
{% endfor %}
|
| 267 |
+
|
| 268 |
+
|
| 269 |
+
|
| 270 |
+
\section{Experience}
|
| 271 |
+
|
| 272 |
+
|
| 273 |
+
|
| 274 |
+
|
| 275 |
+
{% for exp in resume.experience %}
|
| 276 |
+
\begin{twocolentry}{
|
| 277 |
+
{{ exp.location }}
|
| 278 |
+
|
| 279 |
+
{{ exp.date_range }}
|
| 280 |
+
}
|
| 281 |
+
\textbf{ {{ exp.company }} }, {{ exp.role }}
|
| 282 |
+
{% if exp.highlights %}
|
| 283 |
+
\begin{highlights}
|
| 284 |
+
{% for h in exp.highlights %}
|
| 285 |
+
\item {{ h }}
|
| 286 |
+
{% endfor %}
|
| 287 |
+
\end{highlights}
|
| 288 |
+
{% endif %}
|
| 289 |
+
\end{twocolentry}
|
| 290 |
+
{% if not loop.last %}
|
| 291 |
+
\vspace{0.2 cm}
|
| 292 |
+
{% endif %}
|
| 293 |
+
{% endfor %}
|
| 294 |
+
|
| 295 |
+
|
| 296 |
+
|
| 297 |
+
|
| 298 |
+
\section{Publications}
|
| 299 |
+
|
| 300 |
+
|
| 301 |
+
|
| 302 |
+
|
| 303 |
+
{% for pub in resume.publications %}
|
| 304 |
+
\begin{samepage}
|
| 305 |
+
\begin{twocolentry}{
|
| 306 |
+
{{ pub.date }}
|
| 307 |
+
}
|
| 308 |
+
\textbf{ {{ pub.title }} }
|
| 309 |
+
|
| 310 |
+
\vspace{0.10 cm}
|
| 311 |
+
|
| 312 |
+
{{ pub.authors | join(', ') }}
|
| 313 |
+
\vspace{0.10 cm}
|
| 314 |
+
{% if pub.doi_url %}
|
| 315 |
+
\href{ {{ pub.doi_url }} }{ {{ pub.doi_label or pub.doi_url }} }
|
| 316 |
+
{% endif %}
|
| 317 |
+
\end{twocolentry}
|
| 318 |
+
\end{samepage}
|
| 319 |
+
{% endfor %}
|
| 320 |
+
|
| 321 |
+
|
| 322 |
+
|
| 323 |
+
\section{Projects}
|
| 324 |
+
|
| 325 |
+
|
| 326 |
+
|
| 327 |
+
|
| 328 |
+
{% for pr in resume.projects %}
|
| 329 |
+
\begin{twocolentry}{
|
| 330 |
+
{% if pr.repo_url %}\href{ {{ pr.repo_url }} }{ {{ pr.repo_label or pr.repo_url }} }{% endif %}
|
| 331 |
+
}
|
| 332 |
+
\textbf{ {{ pr.title }} }
|
| 333 |
+
{% if pr.highlights %}
|
| 334 |
+
\begin{highlights}
|
| 335 |
+
{% for h in pr.highlights %}
|
| 336 |
+
\item {{ h }}
|
| 337 |
+
{% endfor %}
|
| 338 |
+
\end{highlights}
|
| 339 |
+
{% endif %}
|
| 340 |
+
\end{twocolentry}
|
| 341 |
+
{% if not loop.last %}
|
| 342 |
+
\vspace{0.2 cm}
|
| 343 |
+
{% endif %}
|
| 344 |
+
{% endfor %}
|
| 345 |
+
|
| 346 |
+
|
| 347 |
+
|
| 348 |
+
|
| 349 |
+
|
| 350 |
+
|
| 351 |
+
|
| 352 |
+
\section{Technologies}
|
| 353 |
+
|
| 354 |
+
|
| 355 |
+
|
| 356 |
+
|
| 357 |
+
\begin{onecolentry}
|
| 358 |
+
\textbf{Languages:} {{ resume.technologies_section.languages | join(', ') }}
|
| 359 |
+
\end{onecolentry}
|
| 360 |
+
|
| 361 |
+
\vspace{0.2 cm}
|
| 362 |
+
|
| 363 |
+
\begin{onecolentry}
|
| 364 |
+
\textbf{Technologies:} {{ resume.technologies_section.technologies | join(', ') }}
|
| 365 |
+
\end{onecolentry}
|
| 366 |
+
|
| 367 |
+
|
| 368 |
+
|
| 369 |
+
|
| 370 |
+
\end{document}
|
templates/template_pe.tex
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
%%%%%%%%%%%%%%%%%
|
| 2 |
+
% * <shrabanipanigrahi@gmail.com> 2018-06-25T16:57:48.502Z:
|
| 3 |
+
%
|
| 4 |
+
% ^.
|
| 5 |
+
% This is an sample CV template created using altacv.cls
|
| 6 |
+
% (v1.1.3, 30 April 2017) written by LianTze Lim (liantze@gmail.com). Now compiles with pdfLaTeX, XeLaTeX and LuaLaTeX.
|
| 7 |
+
%
|
| 8 |
+
%% It may be distributed and/or modified under the
|
| 9 |
+
%% conditions of the LaTeX Project Public License, either version 1.3
|
| 10 |
+
%% of this license or (at your option) any later version.
|
| 11 |
+
%% The latest version of this license is in
|
| 12 |
+
%% http://www.latex-project.org/lppl.txt
|
| 13 |
+
%% and version 1.3 or later is part of all distributions of LaTeX
|
| 14 |
+
%% version 2003/12/01 or later.
|
| 15 |
+
%%%%%%%%%%%%%%%%
|
| 16 |
+
|
| 17 |
+
%% If you need to pass whatever options to xcolor
|
| 18 |
+
\PassOptionsToPackage{dvipsnames}{xcolor}
|
| 19 |
+
|
| 20 |
+
%% If you are using \orcid or academicons
|
| 21 |
+
%% icons, make sure you have the academicons
|
| 22 |
+
%% option here, and compile with XeLaTeX
|
| 23 |
+
%% or LuaLaTeX.
|
| 24 |
+
% \documentclass[10pt,a4paper,academicons]{altacv}
|
| 25 |
+
|
| 26 |
+
%% Use the "normalphoto" option if you want a normal photo instead of cropped to a circle
|
| 27 |
+
% \documentclass[10pt,a4paper,normalphoto]{altacv}
|
| 28 |
+
|
| 29 |
+
\documentclass[10pt,a4paper]{altacv}
|
| 30 |
+
|
| 31 |
+
%% AltaCV uses the fontawesome and academicon fonts
|
| 32 |
+
%% and packages.
|
| 33 |
+
%% See texdoc.net/pkg/fontawecome and http://texdoc.net/pkg/academicons for full list of symbols.
|
| 34 |
+
%%
|
| 35 |
+
%% Compile with LuaLaTeX for best results. If you
|
| 36 |
+
%% want to use XeLaTeX, you may need to install
|
| 37 |
+
%% Academicons.ttf in your operating system's font
|
| 38 |
+
%% folder.
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
% Change the page layout if you need to
|
| 42 |
+
\geometry{left=1cm,right=9cm,marginparwidth=6.8cm,marginparsep=1.2cm,top=1.25cm,bottom=1.25cm,footskip=2\baselineskip}
|
| 43 |
+
|
| 44 |
+
% Change the font if you want to.
|
| 45 |
+
|
| 46 |
+
% If using pdflatex:
|
| 47 |
+
\usepackage[utf8]{inputenc}
|
| 48 |
+
\usepackage[T1]{fontenc}
|
| 49 |
+
\usepackage[default]{lato}
|
| 50 |
+
\usepackage{hyperref}
|
| 51 |
+
|
| 52 |
+
% If using xelatex or lualatex:
|
| 53 |
+
% \setmainfont{Lato}
|
| 54 |
+
|
| 55 |
+
% Change the colours if you want to
|
| 56 |
+
\definecolor{darkblue}{HTML}{00394d}
|
| 57 |
+
\definecolor{Mulberry}{HTML}{005c99}
|
| 58 |
+
\definecolor{SlateGrey}{HTML}{000000}
|
| 59 |
+
\definecolor{LightGrey}{HTML}{333333}
|
| 60 |
+
\colorlet{heading}{darkblue}
|
| 61 |
+
\colorlet{accent}{Mulberry}
|
| 62 |
+
\colorlet{emphasis}{SlateGrey}
|
| 63 |
+
\colorlet{body}{LightGrey}
|
| 64 |
+
|
| 65 |
+
% Change the bullets for itemize and rating marker
|
| 66 |
+
% for \cvskill if you want to
|
| 67 |
+
\renewcommand{\itemmarker}{{\small\textbullet}}
|
| 68 |
+
\renewcommand{\ratingmarker}{\faCircle}
|
| 69 |
+
|
| 70 |
+
%% sample.bib contains your publications
|
| 71 |
+
\addbibresource{sample.bib}
|
| 72 |
+
|
| 73 |
+
\begin{document}
|
| 74 |
+
\name{Pierre-Emmanuel DIOT}
|
| 75 |
+
\tagline{Data Scientist \& Founder}
|
| 76 |
+
\photo{3cm}{photo_cv}
|
| 77 |
+
\personalinfo{%
|
| 78 |
+
% Not all of these are required!
|
| 79 |
+
% You can add your own with \printinfo{symbol}{detail}
|
| 80 |
+
\mailaddress{p.emmanuel.diot@gmail.com}
|
| 81 |
+
\linkedin{\href{https://www.linkedin.com/in/pierre-emmanuel-diot/}{pierre-emmanuel diot}}
|
| 82 |
+
\github{\href{https://github.com/PeDiot}{github}}
|
| 83 |
+
% \homepage{\href{https://fr.pinterest.com/shoprecove/}{pinterest}}
|
| 84 |
+
%% You MUST add the academicons option to \documentclass, then compile with LuaLaTeX or XeLaTeX, if you want to use \orcid or other academicons commands.
|
| 85 |
+
% \orcid{orcid.org/0000-0000-0000-0000}
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
%% Make the header extend all the way to the right, if you want.
|
| 89 |
+
\begin{fullwidth}
|
| 90 |
+
\makecvheader
|
| 91 |
+
\end{fullwidth}
|
| 92 |
+
|
| 93 |
+
%% Provide the file name containing the sidebar contents as an optional parameter to \cvsection.
|
| 94 |
+
%% You can always just use \marginpar{...} if you do
|
| 95 |
+
%% not need to align the top of the contents to any
|
| 96 |
+
%% \cvsection title in the "main" bar.
|
| 97 |
+
|
| 98 |
+
\cvsection[page1sidebar]{Work Experience}
|
| 99 |
+
|
| 100 |
+
\vspace{.2cm}
|
| 101 |
+
|
| 102 |
+
\cvevent{\textbf{Co-Founder \& CTO}}{\href{https://shoprecove.com}{Recove}, Paris}{Since January 2025}
|
| 103 |
+
|
| 104 |
+
\vspace{.1cm}
|
| 105 |
+
|
| 106 |
+
\textit{Co-founded and scaled a fashion discovery application that connects Pinterest inspiration with Vinted's marketplace, growing the platform to 80,000+ total users and driving over 600,000 clicks to Vinted.}
|
| 107 |
+
|
| 108 |
+
\vspace{.1cm}
|
| 109 |
+
|
| 110 |
+
\begin{itemize}
|
| 111 |
+
\item[--] Engineered and deployed a production-grade multimodal search engine, implementing retrieval and ranking algorithms to query a vector database of over 20 million Vinted listings.
|
| 112 |
+
\item[--] Designed and built the data infrastructure on Google Cloud Platform \& Pinecone, creating automated ETL pipelines to ingest, process, and continuously update listings data.
|
| 113 |
+
\item[--] Developed a scalable REST API with Django to serve model predictions and data to both web and mobile clients.
|
| 114 |
+
\item[--] Owned the full product lifecycle, from technical architecture and model development to deployment and iteration based on user feedback.
|
| 115 |
+
\item[--] \textbf{Tech Stack}: Python, Vector Database (Pinecone), Google Cloud Platform (BigQuery, Cloud Run), Docker, Django, React, Git.
|
| 116 |
+
\end{itemize}
|
| 117 |
+
|
| 118 |
+
\divider
|
| 119 |
+
|
| 120 |
+
\cvevent{\textbf{Lead Data Science}}{HelloSafe, Paris}{June 2023 -- August 2024}
|
| 121 |
+
|
| 122 |
+
\vspace{.1cm}
|
| 123 |
+
|
| 124 |
+
\textit{Built the company's core data infrastructure and developed key machine learning models to drive product strategy and marketing efficiency.}
|
| 125 |
+
|
| 126 |
+
\vspace{.1cm}
|
| 127 |
+
|
| 128 |
+
\begin{itemize}
|
| 129 |
+
\item[--] Architected and built the company's first central data warehouse, integrating multiple sources (website analytics, Typeform conversions, revenue data) to create a single source of truth for all product and business reporting.
|
| 130 |
+
\item[--] Developed a classification model to predict user conversion based on web behavior, providing actionable insights that improved marketing campaign retargeting.
|
| 131 |
+
\item[--] \textbf{Tech Stack}: Python (Scikit-learn, Pandas), SQL (Google BigQuery)
|
| 132 |
+
\end{itemize}
|
| 133 |
+
|
| 134 |
+
\divider
|
| 135 |
+
|
| 136 |
+
\cvevent{\textbf{Data Scientist R\&D}}{Epsilon France (Publicis Groupe), Paris}{April 2022 -- Aug. 2022}
|
| 137 |
+
|
| 138 |
+
\vspace{.1cm}
|
| 139 |
+
|
| 140 |
+
\begin{itemize}
|
| 141 |
+
\item[--] Led an R\&D project to design and build a standardized toolkit in R for Marketing Mix Modeling (MMM), a key method for measuring marketing impact.
|
| 142 |
+
\item[--] The tool automated the end-to-end modeling process, from data transformation and econometric modeling to parameter optimization, ensuring scientific rigor and reproducibility for future analyses.
|
| 143 |
+
\item[--] \textbf{Tech Stack}: R, Git.
|
| 144 |
+
\end{itemize}
|
| 145 |
+
|
| 146 |
+
\end{document}
|
uv.lock
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version = 1
|
| 2 |
+
revision = 3
|
| 3 |
+
requires-python = ">=3.10"
|
| 4 |
+
|
| 5 |
+
[[package]]
|
| 6 |
+
name = "annotated-types"
|
| 7 |
+
version = "0.7.0"
|
| 8 |
+
source = { registry = "https://pypi.org/simple" }
|
| 9 |
+
sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" }
|
| 10 |
+
wheels = [
|
| 11 |
+
{ url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" },
|
| 12 |
+
]
|
| 13 |
+
|
| 14 |
+
[[package]]
|
| 15 |
+
name = "dnspython"
|
| 16 |
+
version = "2.8.0"
|
| 17 |
+
source = { registry = "https://pypi.org/simple" }
|
| 18 |
+
sdist = { url = "https://files.pythonhosted.org/packages/8c/8b/57666417c0f90f08bcafa776861060426765fdb422eb10212086fb811d26/dnspython-2.8.0.tar.gz", hash = "sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f", size = 368251, upload-time = "2025-09-07T18:58:00.022Z" }
|
| 19 |
+
wheels = [
|
| 20 |
+
{ url = "https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af", size = 331094, upload-time = "2025-09-07T18:57:58.071Z" },
|
| 21 |
+
]
|
| 22 |
+
|
| 23 |
+
[[package]]
|
| 24 |
+
name = "email-validator"
|
| 25 |
+
version = "2.3.0"
|
| 26 |
+
source = { registry = "https://pypi.org/simple" }
|
| 27 |
+
dependencies = [
|
| 28 |
+
{ name = "dnspython" },
|
| 29 |
+
{ name = "idna" },
|
| 30 |
+
]
|
| 31 |
+
sdist = { url = "https://files.pythonhosted.org/packages/f5/22/900cb125c76b7aaa450ce02fd727f452243f2e91a61af068b40adba60ea9/email_validator-2.3.0.tar.gz", hash = "sha256:9fc05c37f2f6cf439ff414f8fc46d917929974a82244c20eb10231ba60c54426", size = 51238, upload-time = "2025-08-26T13:09:06.831Z" }
|
| 32 |
+
wheels = [
|
| 33 |
+
{ url = "https://files.pythonhosted.org/packages/de/15/545e2b6cf2e3be84bc1ed85613edd75b8aea69807a71c26f4ca6a9258e82/email_validator-2.3.0-py3-none-any.whl", hash = "sha256:80f13f623413e6b197ae73bb10bf4eb0908faf509ad8362c5edeb0be7fd450b4", size = 35604, upload-time = "2025-08-26T13:09:05.858Z" },
|
| 34 |
+
]
|
| 35 |
+
|
| 36 |
+
[[package]]
|
| 37 |
+
name = "idna"
|
| 38 |
+
version = "3.10"
|
| 39 |
+
source = { registry = "https://pypi.org/simple" }
|
| 40 |
+
sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" }
|
| 41 |
+
wheels = [
|
| 42 |
+
{ url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" },
|
| 43 |
+
]
|
| 44 |
+
|
| 45 |
+
[[package]]
|
| 46 |
+
name = "jinja2"
|
| 47 |
+
version = "3.1.6"
|
| 48 |
+
source = { registry = "https://pypi.org/simple" }
|
| 49 |
+
dependencies = [
|
| 50 |
+
{ name = "markupsafe" },
|
| 51 |
+
]
|
| 52 |
+
sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" }
|
| 53 |
+
wheels = [
|
| 54 |
+
{ url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" },
|
| 55 |
+
]
|
| 56 |
+
|
| 57 |
+
[[package]]
|
| 58 |
+
name = "markupsafe"
|
| 59 |
+
version = "3.0.2"
|
| 60 |
+
source = { registry = "https://pypi.org/simple" }
|
| 61 |
+
sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537, upload-time = "2024-10-18T15:21:54.129Z" }
|
| 62 |
+
wheels = [
|
| 63 |
+
{ url = "https://files.pythonhosted.org/packages/04/90/d08277ce111dd22f77149fd1a5d4653eeb3b3eaacbdfcbae5afb2600eebd/MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8", size = 14357, upload-time = "2024-10-18T15:20:51.44Z" },
|
| 64 |
+
{ url = "https://files.pythonhosted.org/packages/04/e1/6e2194baeae0bca1fae6629dc0cbbb968d4d941469cbab11a3872edff374/MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158", size = 12393, upload-time = "2024-10-18T15:20:52.426Z" },
|
| 65 |
+
{ url = "https://files.pythonhosted.org/packages/1d/69/35fa85a8ece0a437493dc61ce0bb6d459dcba482c34197e3efc829aa357f/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579", size = 21732, upload-time = "2024-10-18T15:20:53.578Z" },
|
| 66 |
+
{ url = "https://files.pythonhosted.org/packages/22/35/137da042dfb4720b638d2937c38a9c2df83fe32d20e8c8f3185dbfef05f7/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d", size = 20866, upload-time = "2024-10-18T15:20:55.06Z" },
|
| 67 |
+
{ url = "https://files.pythonhosted.org/packages/29/28/6d029a903727a1b62edb51863232152fd335d602def598dade38996887f0/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb", size = 20964, upload-time = "2024-10-18T15:20:55.906Z" },
|
| 68 |
+
{ url = "https://files.pythonhosted.org/packages/cc/cd/07438f95f83e8bc028279909d9c9bd39e24149b0d60053a97b2bc4f8aa51/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b", size = 21977, upload-time = "2024-10-18T15:20:57.189Z" },
|
| 69 |
+
{ url = "https://files.pythonhosted.org/packages/29/01/84b57395b4cc062f9c4c55ce0df7d3108ca32397299d9df00fedd9117d3d/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c", size = 21366, upload-time = "2024-10-18T15:20:58.235Z" },
|
| 70 |
+
{ url = "https://files.pythonhosted.org/packages/bd/6e/61ebf08d8940553afff20d1fb1ba7294b6f8d279df9fd0c0db911b4bbcfd/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171", size = 21091, upload-time = "2024-10-18T15:20:59.235Z" },
|
| 71 |
+
{ url = "https://files.pythonhosted.org/packages/11/23/ffbf53694e8c94ebd1e7e491de185124277964344733c45481f32ede2499/MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50", size = 15065, upload-time = "2024-10-18T15:21:00.307Z" },
|
| 72 |
+
{ url = "https://files.pythonhosted.org/packages/44/06/e7175d06dd6e9172d4a69a72592cb3f7a996a9c396eee29082826449bbc3/MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a", size = 15514, upload-time = "2024-10-18T15:21:01.122Z" },
|
| 73 |
+
{ url = "https://files.pythonhosted.org/packages/6b/28/bbf83e3f76936960b850435576dd5e67034e200469571be53f69174a2dfd/MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d", size = 14353, upload-time = "2024-10-18T15:21:02.187Z" },
|
| 74 |
+
{ url = "https://files.pythonhosted.org/packages/6c/30/316d194b093cde57d448a4c3209f22e3046c5bb2fb0820b118292b334be7/MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93", size = 12392, upload-time = "2024-10-18T15:21:02.941Z" },
|
| 75 |
+
{ url = "https://files.pythonhosted.org/packages/f2/96/9cdafba8445d3a53cae530aaf83c38ec64c4d5427d975c974084af5bc5d2/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832", size = 23984, upload-time = "2024-10-18T15:21:03.953Z" },
|
| 76 |
+
{ url = "https://files.pythonhosted.org/packages/f1/a4/aefb044a2cd8d7334c8a47d3fb2c9f328ac48cb349468cc31c20b539305f/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84", size = 23120, upload-time = "2024-10-18T15:21:06.495Z" },
|
| 77 |
+
{ url = "https://files.pythonhosted.org/packages/8d/21/5e4851379f88f3fad1de30361db501300d4f07bcad047d3cb0449fc51f8c/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca", size = 23032, upload-time = "2024-10-18T15:21:07.295Z" },
|
| 78 |
+
{ url = "https://files.pythonhosted.org/packages/00/7b/e92c64e079b2d0d7ddf69899c98842f3f9a60a1ae72657c89ce2655c999d/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798", size = 24057, upload-time = "2024-10-18T15:21:08.073Z" },
|
| 79 |
+
{ url = "https://files.pythonhosted.org/packages/f9/ac/46f960ca323037caa0a10662ef97d0a4728e890334fc156b9f9e52bcc4ca/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e", size = 23359, upload-time = "2024-10-18T15:21:09.318Z" },
|
| 80 |
+
{ url = "https://files.pythonhosted.org/packages/69/84/83439e16197337b8b14b6a5b9c2105fff81d42c2a7c5b58ac7b62ee2c3b1/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4", size = 23306, upload-time = "2024-10-18T15:21:10.185Z" },
|
| 81 |
+
{ url = "https://files.pythonhosted.org/packages/9a/34/a15aa69f01e2181ed8d2b685c0d2f6655d5cca2c4db0ddea775e631918cd/MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d", size = 15094, upload-time = "2024-10-18T15:21:11.005Z" },
|
| 82 |
+
{ url = "https://files.pythonhosted.org/packages/da/b8/3a3bd761922d416f3dc5d00bfbed11f66b1ab89a0c2b6e887240a30b0f6b/MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b", size = 15521, upload-time = "2024-10-18T15:21:12.911Z" },
|
| 83 |
+
{ url = "https://files.pythonhosted.org/packages/22/09/d1f21434c97fc42f09d290cbb6350d44eb12f09cc62c9476effdb33a18aa/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", size = 14274, upload-time = "2024-10-18T15:21:13.777Z" },
|
| 84 |
+
{ url = "https://files.pythonhosted.org/packages/6b/b0/18f76bba336fa5aecf79d45dcd6c806c280ec44538b3c13671d49099fdd0/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", size = 12348, upload-time = "2024-10-18T15:21:14.822Z" },
|
| 85 |
+
{ url = "https://files.pythonhosted.org/packages/e0/25/dd5c0f6ac1311e9b40f4af06c78efde0f3b5cbf02502f8ef9501294c425b/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", size = 24149, upload-time = "2024-10-18T15:21:15.642Z" },
|
| 86 |
+
{ url = "https://files.pythonhosted.org/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", size = 23118, upload-time = "2024-10-18T15:21:17.133Z" },
|
| 87 |
+
{ url = "https://files.pythonhosted.org/packages/d5/da/f2eeb64c723f5e3777bc081da884b414671982008c47dcc1873d81f625b6/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", size = 22993, upload-time = "2024-10-18T15:21:18.064Z" },
|
| 88 |
+
{ url = "https://files.pythonhosted.org/packages/da/0e/1f32af846df486dce7c227fe0f2398dc7e2e51d4a370508281f3c1c5cddc/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", size = 24178, upload-time = "2024-10-18T15:21:18.859Z" },
|
| 89 |
+
{ url = "https://files.pythonhosted.org/packages/c4/f6/bb3ca0532de8086cbff5f06d137064c8410d10779c4c127e0e47d17c0b71/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", size = 23319, upload-time = "2024-10-18T15:21:19.671Z" },
|
| 90 |
+
{ url = "https://files.pythonhosted.org/packages/a2/82/8be4c96ffee03c5b4a034e60a31294daf481e12c7c43ab8e34a1453ee48b/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", size = 23352, upload-time = "2024-10-18T15:21:20.971Z" },
|
| 91 |
+
{ url = "https://files.pythonhosted.org/packages/51/ae/97827349d3fcffee7e184bdf7f41cd6b88d9919c80f0263ba7acd1bbcb18/MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", size = 15097, upload-time = "2024-10-18T15:21:22.646Z" },
|
| 92 |
+
{ url = "https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", size = 15601, upload-time = "2024-10-18T15:21:23.499Z" },
|
| 93 |
+
{ url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274, upload-time = "2024-10-18T15:21:24.577Z" },
|
| 94 |
+
{ url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352, upload-time = "2024-10-18T15:21:25.382Z" },
|
| 95 |
+
{ url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122, upload-time = "2024-10-18T15:21:26.199Z" },
|
| 96 |
+
{ url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085, upload-time = "2024-10-18T15:21:27.029Z" },
|
| 97 |
+
{ url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978, upload-time = "2024-10-18T15:21:27.846Z" },
|
| 98 |
+
{ url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208, upload-time = "2024-10-18T15:21:28.744Z" },
|
| 99 |
+
{ url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357, upload-time = "2024-10-18T15:21:29.545Z" },
|
| 100 |
+
{ url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344, upload-time = "2024-10-18T15:21:30.366Z" },
|
| 101 |
+
{ url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101, upload-time = "2024-10-18T15:21:31.207Z" },
|
| 102 |
+
{ url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603, upload-time = "2024-10-18T15:21:32.032Z" },
|
| 103 |
+
{ url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510, upload-time = "2024-10-18T15:21:33.625Z" },
|
| 104 |
+
{ url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486, upload-time = "2024-10-18T15:21:34.611Z" },
|
| 105 |
+
{ url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480, upload-time = "2024-10-18T15:21:35.398Z" },
|
| 106 |
+
{ url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914, upload-time = "2024-10-18T15:21:36.231Z" },
|
| 107 |
+
{ url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796, upload-time = "2024-10-18T15:21:37.073Z" },
|
| 108 |
+
{ url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473, upload-time = "2024-10-18T15:21:37.932Z" },
|
| 109 |
+
{ url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114, upload-time = "2024-10-18T15:21:39.799Z" },
|
| 110 |
+
{ url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098, upload-time = "2024-10-18T15:21:40.813Z" },
|
| 111 |
+
{ url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208, upload-time = "2024-10-18T15:21:41.814Z" },
|
| 112 |
+
{ url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739, upload-time = "2024-10-18T15:21:42.784Z" },
|
| 113 |
+
]
|
| 114 |
+
|
| 115 |
+
[[package]]
|
| 116 |
+
name = "pydantic"
|
| 117 |
+
version = "2.11.9"
|
| 118 |
+
source = { registry = "https://pypi.org/simple" }
|
| 119 |
+
dependencies = [
|
| 120 |
+
{ name = "annotated-types" },
|
| 121 |
+
{ name = "pydantic-core" },
|
| 122 |
+
{ name = "typing-extensions" },
|
| 123 |
+
{ name = "typing-inspection" },
|
| 124 |
+
]
|
| 125 |
+
sdist = { url = "https://files.pythonhosted.org/packages/ff/5d/09a551ba512d7ca404d785072700d3f6727a02f6f3c24ecfd081c7cf0aa8/pydantic-2.11.9.tar.gz", hash = "sha256:6b8ffda597a14812a7975c90b82a8a2e777d9257aba3453f973acd3c032a18e2", size = 788495, upload-time = "2025-09-13T11:26:39.325Z" }
|
| 126 |
+
wheels = [
|
| 127 |
+
{ url = "https://files.pythonhosted.org/packages/3e/d3/108f2006987c58e76691d5ae5d200dd3e0f532cb4e5fa3560751c3a1feba/pydantic-2.11.9-py3-none-any.whl", hash = "sha256:c42dd626f5cfc1c6950ce6205ea58c93efa406da65f479dcb4029d5934857da2", size = 444855, upload-time = "2025-09-13T11:26:36.909Z" },
|
| 128 |
+
]
|
| 129 |
+
|
| 130 |
+
[package.optional-dependencies]
|
| 131 |
+
email = [
|
| 132 |
+
{ name = "email-validator" },
|
| 133 |
+
]
|
| 134 |
+
|
| 135 |
+
[[package]]
|
| 136 |
+
name = "pydantic-core"
|
| 137 |
+
version = "2.33.2"
|
| 138 |
+
source = { registry = "https://pypi.org/simple" }
|
| 139 |
+
dependencies = [
|
| 140 |
+
{ name = "typing-extensions" },
|
| 141 |
+
]
|
| 142 |
+
sdist = { url = "https://files.pythonhosted.org/packages/ad/88/5f2260bdfae97aabf98f1778d43f69574390ad787afb646292a638c923d4/pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", size = 435195, upload-time = "2025-04-23T18:33:52.104Z" }
|
| 143 |
+
wheels = [
|
| 144 |
+
{ url = "https://files.pythonhosted.org/packages/e5/92/b31726561b5dae176c2d2c2dc43a9c5bfba5d32f96f8b4c0a600dd492447/pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8", size = 2028817, upload-time = "2025-04-23T18:30:43.919Z" },
|
| 145 |
+
{ url = "https://files.pythonhosted.org/packages/a3/44/3f0b95fafdaca04a483c4e685fe437c6891001bf3ce8b2fded82b9ea3aa1/pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d", size = 1861357, upload-time = "2025-04-23T18:30:46.372Z" },
|
| 146 |
+
{ url = "https://files.pythonhosted.org/packages/30/97/e8f13b55766234caae05372826e8e4b3b96e7b248be3157f53237682e43c/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d", size = 1898011, upload-time = "2025-04-23T18:30:47.591Z" },
|
| 147 |
+
{ url = "https://files.pythonhosted.org/packages/9b/a3/99c48cf7bafc991cc3ee66fd544c0aae8dc907b752f1dad2d79b1b5a471f/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572", size = 1982730, upload-time = "2025-04-23T18:30:49.328Z" },
|
| 148 |
+
{ url = "https://files.pythonhosted.org/packages/de/8e/a5b882ec4307010a840fb8b58bd9bf65d1840c92eae7534c7441709bf54b/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02", size = 2136178, upload-time = "2025-04-23T18:30:50.907Z" },
|
| 149 |
+
{ url = "https://files.pythonhosted.org/packages/e4/bb/71e35fc3ed05af6834e890edb75968e2802fe98778971ab5cba20a162315/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b", size = 2736462, upload-time = "2025-04-23T18:30:52.083Z" },
|
| 150 |
+
{ url = "https://files.pythonhosted.org/packages/31/0d/c8f7593e6bc7066289bbc366f2235701dcbebcd1ff0ef8e64f6f239fb47d/pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2", size = 2005652, upload-time = "2025-04-23T18:30:53.389Z" },
|
| 151 |
+
{ url = "https://files.pythonhosted.org/packages/d2/7a/996d8bd75f3eda405e3dd219ff5ff0a283cd8e34add39d8ef9157e722867/pydantic_core-2.33.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a", size = 2113306, upload-time = "2025-04-23T18:30:54.661Z" },
|
| 152 |
+
{ url = "https://files.pythonhosted.org/packages/ff/84/daf2a6fb2db40ffda6578a7e8c5a6e9c8affb251a05c233ae37098118788/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac", size = 2073720, upload-time = "2025-04-23T18:30:56.11Z" },
|
| 153 |
+
{ url = "https://files.pythonhosted.org/packages/77/fb/2258da019f4825128445ae79456a5499c032b55849dbd5bed78c95ccf163/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a", size = 2244915, upload-time = "2025-04-23T18:30:57.501Z" },
|
| 154 |
+
{ url = "https://files.pythonhosted.org/packages/d8/7a/925ff73756031289468326e355b6fa8316960d0d65f8b5d6b3a3e7866de7/pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b", size = 2241884, upload-time = "2025-04-23T18:30:58.867Z" },
|
| 155 |
+
{ url = "https://files.pythonhosted.org/packages/0b/b0/249ee6d2646f1cdadcb813805fe76265745c4010cf20a8eba7b0e639d9b2/pydantic_core-2.33.2-cp310-cp310-win32.whl", hash = "sha256:0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22", size = 1910496, upload-time = "2025-04-23T18:31:00.078Z" },
|
| 156 |
+
{ url = "https://files.pythonhosted.org/packages/66/ff/172ba8f12a42d4b552917aa65d1f2328990d3ccfc01d5b7c943ec084299f/pydantic_core-2.33.2-cp310-cp310-win_amd64.whl", hash = "sha256:b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640", size = 1955019, upload-time = "2025-04-23T18:31:01.335Z" },
|
| 157 |
+
{ url = "https://files.pythonhosted.org/packages/3f/8d/71db63483d518cbbf290261a1fc2839d17ff89fce7089e08cad07ccfce67/pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7", size = 2028584, upload-time = "2025-04-23T18:31:03.106Z" },
|
| 158 |
+
{ url = "https://files.pythonhosted.org/packages/24/2f/3cfa7244ae292dd850989f328722d2aef313f74ffc471184dc509e1e4e5a/pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246", size = 1855071, upload-time = "2025-04-23T18:31:04.621Z" },
|
| 159 |
+
{ url = "https://files.pythonhosted.org/packages/b3/d3/4ae42d33f5e3f50dd467761304be2fa0a9417fbf09735bc2cce003480f2a/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f", size = 1897823, upload-time = "2025-04-23T18:31:06.377Z" },
|
| 160 |
+
{ url = "https://files.pythonhosted.org/packages/f4/f3/aa5976e8352b7695ff808599794b1fba2a9ae2ee954a3426855935799488/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc", size = 1983792, upload-time = "2025-04-23T18:31:07.93Z" },
|
| 161 |
+
{ url = "https://files.pythonhosted.org/packages/d5/7a/cda9b5a23c552037717f2b2a5257e9b2bfe45e687386df9591eff7b46d28/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de", size = 2136338, upload-time = "2025-04-23T18:31:09.283Z" },
|
| 162 |
+
{ url = "https://files.pythonhosted.org/packages/2b/9f/b8f9ec8dd1417eb9da784e91e1667d58a2a4a7b7b34cf4af765ef663a7e5/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a", size = 2730998, upload-time = "2025-04-23T18:31:11.7Z" },
|
| 163 |
+
{ url = "https://files.pythonhosted.org/packages/47/bc/cd720e078576bdb8255d5032c5d63ee5c0bf4b7173dd955185a1d658c456/pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef", size = 2003200, upload-time = "2025-04-23T18:31:13.536Z" },
|
| 164 |
+
{ url = "https://files.pythonhosted.org/packages/ca/22/3602b895ee2cd29d11a2b349372446ae9727c32e78a94b3d588a40fdf187/pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e", size = 2113890, upload-time = "2025-04-23T18:31:15.011Z" },
|
| 165 |
+
{ url = "https://files.pythonhosted.org/packages/ff/e6/e3c5908c03cf00d629eb38393a98fccc38ee0ce8ecce32f69fc7d7b558a7/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d", size = 2073359, upload-time = "2025-04-23T18:31:16.393Z" },
|
| 166 |
+
{ url = "https://files.pythonhosted.org/packages/12/e7/6a36a07c59ebefc8777d1ffdaf5ae71b06b21952582e4b07eba88a421c79/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30", size = 2245883, upload-time = "2025-04-23T18:31:17.892Z" },
|
| 167 |
+
{ url = "https://files.pythonhosted.org/packages/16/3f/59b3187aaa6cc0c1e6616e8045b284de2b6a87b027cce2ffcea073adf1d2/pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf", size = 2241074, upload-time = "2025-04-23T18:31:19.205Z" },
|
| 168 |
+
{ url = "https://files.pythonhosted.org/packages/e0/ed/55532bb88f674d5d8f67ab121a2a13c385df382de2a1677f30ad385f7438/pydantic_core-2.33.2-cp311-cp311-win32.whl", hash = "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51", size = 1910538, upload-time = "2025-04-23T18:31:20.541Z" },
|
| 169 |
+
{ url = "https://files.pythonhosted.org/packages/fe/1b/25b7cccd4519c0b23c2dd636ad39d381abf113085ce4f7bec2b0dc755eb1/pydantic_core-2.33.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab", size = 1952909, upload-time = "2025-04-23T18:31:22.371Z" },
|
| 170 |
+
{ url = "https://files.pythonhosted.org/packages/49/a9/d809358e49126438055884c4366a1f6227f0f84f635a9014e2deb9b9de54/pydantic_core-2.33.2-cp311-cp311-win_arm64.whl", hash = "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65", size = 1897786, upload-time = "2025-04-23T18:31:24.161Z" },
|
| 171 |
+
{ url = "https://files.pythonhosted.org/packages/18/8a/2b41c97f554ec8c71f2a8a5f85cb56a8b0956addfe8b0efb5b3d77e8bdc3/pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc", size = 2009000, upload-time = "2025-04-23T18:31:25.863Z" },
|
| 172 |
+
{ url = "https://files.pythonhosted.org/packages/a1/02/6224312aacb3c8ecbaa959897af57181fb6cf3a3d7917fd44d0f2917e6f2/pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7", size = 1847996, upload-time = "2025-04-23T18:31:27.341Z" },
|
| 173 |
+
{ url = "https://files.pythonhosted.org/packages/d6/46/6dcdf084a523dbe0a0be59d054734b86a981726f221f4562aed313dbcb49/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025", size = 1880957, upload-time = "2025-04-23T18:31:28.956Z" },
|
| 174 |
+
{ url = "https://files.pythonhosted.org/packages/ec/6b/1ec2c03837ac00886ba8160ce041ce4e325b41d06a034adbef11339ae422/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011", size = 1964199, upload-time = "2025-04-23T18:31:31.025Z" },
|
| 175 |
+
{ url = "https://files.pythonhosted.org/packages/2d/1d/6bf34d6adb9debd9136bd197ca72642203ce9aaaa85cfcbfcf20f9696e83/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f", size = 2120296, upload-time = "2025-04-23T18:31:32.514Z" },
|
| 176 |
+
{ url = "https://files.pythonhosted.org/packages/e0/94/2bd0aaf5a591e974b32a9f7123f16637776c304471a0ab33cf263cf5591a/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88", size = 2676109, upload-time = "2025-04-23T18:31:33.958Z" },
|
| 177 |
+
{ url = "https://files.pythonhosted.org/packages/f9/41/4b043778cf9c4285d59742281a769eac371b9e47e35f98ad321349cc5d61/pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1", size = 2002028, upload-time = "2025-04-23T18:31:39.095Z" },
|
| 178 |
+
{ url = "https://files.pythonhosted.org/packages/cb/d5/7bb781bf2748ce3d03af04d5c969fa1308880e1dca35a9bd94e1a96a922e/pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b", size = 2100044, upload-time = "2025-04-23T18:31:41.034Z" },
|
| 179 |
+
{ url = "https://files.pythonhosted.org/packages/fe/36/def5e53e1eb0ad896785702a5bbfd25eed546cdcf4087ad285021a90ed53/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1", size = 2058881, upload-time = "2025-04-23T18:31:42.757Z" },
|
| 180 |
+
{ url = "https://files.pythonhosted.org/packages/01/6c/57f8d70b2ee57fc3dc8b9610315949837fa8c11d86927b9bb044f8705419/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6", size = 2227034, upload-time = "2025-04-23T18:31:44.304Z" },
|
| 181 |
+
{ url = "https://files.pythonhosted.org/packages/27/b9/9c17f0396a82b3d5cbea4c24d742083422639e7bb1d5bf600e12cb176a13/pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea", size = 2234187, upload-time = "2025-04-23T18:31:45.891Z" },
|
| 182 |
+
{ url = "https://files.pythonhosted.org/packages/b0/6a/adf5734ffd52bf86d865093ad70b2ce543415e0e356f6cacabbc0d9ad910/pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290", size = 1892628, upload-time = "2025-04-23T18:31:47.819Z" },
|
| 183 |
+
{ url = "https://files.pythonhosted.org/packages/43/e4/5479fecb3606c1368d496a825d8411e126133c41224c1e7238be58b87d7e/pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2", size = 1955866, upload-time = "2025-04-23T18:31:49.635Z" },
|
| 184 |
+
{ url = "https://files.pythonhosted.org/packages/0d/24/8b11e8b3e2be9dd82df4b11408a67c61bb4dc4f8e11b5b0fc888b38118b5/pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab", size = 1888894, upload-time = "2025-04-23T18:31:51.609Z" },
|
| 185 |
+
{ url = "https://files.pythonhosted.org/packages/46/8c/99040727b41f56616573a28771b1bfa08a3d3fe74d3d513f01251f79f172/pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", size = 2015688, upload-time = "2025-04-23T18:31:53.175Z" },
|
| 186 |
+
{ url = "https://files.pythonhosted.org/packages/3a/cc/5999d1eb705a6cefc31f0b4a90e9f7fc400539b1a1030529700cc1b51838/pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", size = 1844808, upload-time = "2025-04-23T18:31:54.79Z" },
|
| 187 |
+
{ url = "https://files.pythonhosted.org/packages/6f/5e/a0a7b8885c98889a18b6e376f344da1ef323d270b44edf8174d6bce4d622/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", size = 1885580, upload-time = "2025-04-23T18:31:57.393Z" },
|
| 188 |
+
{ url = "https://files.pythonhosted.org/packages/3b/2a/953581f343c7d11a304581156618c3f592435523dd9d79865903272c256a/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", size = 1973859, upload-time = "2025-04-23T18:31:59.065Z" },
|
| 189 |
+
{ url = "https://files.pythonhosted.org/packages/e6/55/f1a813904771c03a3f97f676c62cca0c0a4138654107c1b61f19c644868b/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", size = 2120810, upload-time = "2025-04-23T18:32:00.78Z" },
|
| 190 |
+
{ url = "https://files.pythonhosted.org/packages/aa/c3/053389835a996e18853ba107a63caae0b9deb4a276c6b472931ea9ae6e48/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", size = 2676498, upload-time = "2025-04-23T18:32:02.418Z" },
|
| 191 |
+
{ url = "https://files.pythonhosted.org/packages/eb/3c/f4abd740877a35abade05e437245b192f9d0ffb48bbbbd708df33d3cda37/pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", size = 2000611, upload-time = "2025-04-23T18:32:04.152Z" },
|
| 192 |
+
{ url = "https://files.pythonhosted.org/packages/59/a7/63ef2fed1837d1121a894d0ce88439fe3e3b3e48c7543b2a4479eb99c2bd/pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", size = 2107924, upload-time = "2025-04-23T18:32:06.129Z" },
|
| 193 |
+
{ url = "https://files.pythonhosted.org/packages/04/8f/2551964ef045669801675f1cfc3b0d74147f4901c3ffa42be2ddb1f0efc4/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", size = 2063196, upload-time = "2025-04-23T18:32:08.178Z" },
|
| 194 |
+
{ url = "https://files.pythonhosted.org/packages/26/bd/d9602777e77fc6dbb0c7db9ad356e9a985825547dce5ad1d30ee04903918/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", size = 2236389, upload-time = "2025-04-23T18:32:10.242Z" },
|
| 195 |
+
{ url = "https://files.pythonhosted.org/packages/42/db/0e950daa7e2230423ab342ae918a794964b053bec24ba8af013fc7c94846/pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", size = 2239223, upload-time = "2025-04-23T18:32:12.382Z" },
|
| 196 |
+
{ url = "https://files.pythonhosted.org/packages/58/4d/4f937099c545a8a17eb52cb67fe0447fd9a373b348ccfa9a87f141eeb00f/pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", size = 1900473, upload-time = "2025-04-23T18:32:14.034Z" },
|
| 197 |
+
{ url = "https://files.pythonhosted.org/packages/a0/75/4a0a9bac998d78d889def5e4ef2b065acba8cae8c93696906c3a91f310ca/pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", size = 1955269, upload-time = "2025-04-23T18:32:15.783Z" },
|
| 198 |
+
{ url = "https://files.pythonhosted.org/packages/f9/86/1beda0576969592f1497b4ce8e7bc8cbdf614c352426271b1b10d5f0aa64/pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", size = 1893921, upload-time = "2025-04-23T18:32:18.473Z" },
|
| 199 |
+
{ url = "https://files.pythonhosted.org/packages/a4/7d/e09391c2eebeab681df2b74bfe6c43422fffede8dc74187b2b0bf6fd7571/pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", size = 1806162, upload-time = "2025-04-23T18:32:20.188Z" },
|
| 200 |
+
{ url = "https://files.pythonhosted.org/packages/f1/3d/847b6b1fed9f8ed3bb95a9ad04fbd0b212e832d4f0f50ff4d9ee5a9f15cf/pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", size = 1981560, upload-time = "2025-04-23T18:32:22.354Z" },
|
| 201 |
+
{ url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777, upload-time = "2025-04-23T18:32:25.088Z" },
|
| 202 |
+
{ url = "https://files.pythonhosted.org/packages/30/68/373d55e58b7e83ce371691f6eaa7175e3a24b956c44628eb25d7da007917/pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa", size = 2023982, upload-time = "2025-04-23T18:32:53.14Z" },
|
| 203 |
+
{ url = "https://files.pythonhosted.org/packages/a4/16/145f54ac08c96a63d8ed6442f9dec17b2773d19920b627b18d4f10a061ea/pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29", size = 1858412, upload-time = "2025-04-23T18:32:55.52Z" },
|
| 204 |
+
{ url = "https://files.pythonhosted.org/packages/41/b1/c6dc6c3e2de4516c0bb2c46f6a373b91b5660312342a0cf5826e38ad82fa/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d", size = 1892749, upload-time = "2025-04-23T18:32:57.546Z" },
|
| 205 |
+
{ url = "https://files.pythonhosted.org/packages/12/73/8cd57e20afba760b21b742106f9dbdfa6697f1570b189c7457a1af4cd8a0/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e", size = 2067527, upload-time = "2025-04-23T18:32:59.771Z" },
|
| 206 |
+
{ url = "https://files.pythonhosted.org/packages/e3/d5/0bb5d988cc019b3cba4a78f2d4b3854427fc47ee8ec8e9eaabf787da239c/pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c", size = 2108225, upload-time = "2025-04-23T18:33:04.51Z" },
|
| 207 |
+
{ url = "https://files.pythonhosted.org/packages/f1/c5/00c02d1571913d496aabf146106ad8239dc132485ee22efe08085084ff7c/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec", size = 2069490, upload-time = "2025-04-23T18:33:06.391Z" },
|
| 208 |
+
{ url = "https://files.pythonhosted.org/packages/22/a8/dccc38768274d3ed3a59b5d06f59ccb845778687652daa71df0cab4040d7/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052", size = 2237525, upload-time = "2025-04-23T18:33:08.44Z" },
|
| 209 |
+
{ url = "https://files.pythonhosted.org/packages/d4/e7/4f98c0b125dda7cf7ccd14ba936218397b44f50a56dd8c16a3091df116c3/pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c", size = 2238446, upload-time = "2025-04-23T18:33:10.313Z" },
|
| 210 |
+
{ url = "https://files.pythonhosted.org/packages/ce/91/2ec36480fdb0b783cd9ef6795753c1dea13882f2e68e73bce76ae8c21e6a/pydantic_core-2.33.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808", size = 2066678, upload-time = "2025-04-23T18:33:12.224Z" },
|
| 211 |
+
{ url = "https://files.pythonhosted.org/packages/7b/27/d4ae6487d73948d6f20dddcd94be4ea43e74349b56eba82e9bdee2d7494c/pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8", size = 2025200, upload-time = "2025-04-23T18:33:14.199Z" },
|
| 212 |
+
{ url = "https://files.pythonhosted.org/packages/f1/b8/b3cb95375f05d33801024079b9392a5ab45267a63400bf1866e7ce0f0de4/pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593", size = 1859123, upload-time = "2025-04-23T18:33:16.555Z" },
|
| 213 |
+
{ url = "https://files.pythonhosted.org/packages/05/bc/0d0b5adeda59a261cd30a1235a445bf55c7e46ae44aea28f7bd6ed46e091/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612", size = 1892852, upload-time = "2025-04-23T18:33:18.513Z" },
|
| 214 |
+
{ url = "https://files.pythonhosted.org/packages/3e/11/d37bdebbda2e449cb3f519f6ce950927b56d62f0b84fd9cb9e372a26a3d5/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7", size = 2067484, upload-time = "2025-04-23T18:33:20.475Z" },
|
| 215 |
+
{ url = "https://files.pythonhosted.org/packages/8c/55/1f95f0a05ce72ecb02a8a8a1c3be0579bbc29b1d5ab68f1378b7bebc5057/pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e", size = 2108896, upload-time = "2025-04-23T18:33:22.501Z" },
|
| 216 |
+
{ url = "https://files.pythonhosted.org/packages/53/89/2b2de6c81fa131f423246a9109d7b2a375e83968ad0800d6e57d0574629b/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8", size = 2069475, upload-time = "2025-04-23T18:33:24.528Z" },
|
| 217 |
+
{ url = "https://files.pythonhosted.org/packages/b8/e9/1f7efbe20d0b2b10f6718944b5d8ece9152390904f29a78e68d4e7961159/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf", size = 2239013, upload-time = "2025-04-23T18:33:26.621Z" },
|
| 218 |
+
{ url = "https://files.pythonhosted.org/packages/3c/b2/5309c905a93811524a49b4e031e9851a6b00ff0fb668794472ea7746b448/pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb", size = 2238715, upload-time = "2025-04-23T18:33:28.656Z" },
|
| 219 |
+
{ url = "https://files.pythonhosted.org/packages/32/56/8a7ca5d2cd2cda1d245d34b1c9a942920a718082ae8e54e5f3e5a58b7add/pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1", size = 2066757, upload-time = "2025-04-23T18:33:30.645Z" },
|
| 220 |
+
]
|
| 221 |
+
|
| 222 |
+
[[package]]
|
| 223 |
+
name = "resume-mcp"
|
| 224 |
+
version = "0.1.0"
|
| 225 |
+
source = { virtual = "." }
|
| 226 |
+
dependencies = [
|
| 227 |
+
{ name = "jinja2" },
|
| 228 |
+
{ name = "pydantic", extra = ["email"] },
|
| 229 |
+
]
|
| 230 |
+
|
| 231 |
+
[package.metadata]
|
| 232 |
+
requires-dist = [
|
| 233 |
+
{ name = "jinja2", specifier = ">=3.1" },
|
| 234 |
+
{ name = "pydantic", extras = ["email"], specifier = ">=2.7" },
|
| 235 |
+
]
|
| 236 |
+
|
| 237 |
+
[package.metadata.requires-dev]
|
| 238 |
+
dev = []
|
| 239 |
+
|
| 240 |
+
[[package]]
|
| 241 |
+
name = "typing-extensions"
|
| 242 |
+
version = "4.15.0"
|
| 243 |
+
source = { registry = "https://pypi.org/simple" }
|
| 244 |
+
sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" }
|
| 245 |
+
wheels = [
|
| 246 |
+
{ url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
|
| 247 |
+
]
|
| 248 |
+
|
| 249 |
+
[[package]]
|
| 250 |
+
name = "typing-inspection"
|
| 251 |
+
version = "0.4.1"
|
| 252 |
+
source = { registry = "https://pypi.org/simple" }
|
| 253 |
+
dependencies = [
|
| 254 |
+
{ name = "typing-extensions" },
|
| 255 |
+
]
|
| 256 |
+
sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726, upload-time = "2025-05-21T18:55:23.885Z" }
|
| 257 |
+
wheels = [
|
| 258 |
+
{ url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552, upload-time = "2025-05-21T18:55:22.152Z" },
|
| 259 |
+
]
|