Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,294 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
from fpdf import FPDF
|
3 |
+
import re
|
4 |
+
from docx import Document
|
5 |
+
from docx.shared import Pt, RGBColor
|
6 |
+
from docx.enum.text import WD_ALIGN_PARAGRAPH
|
7 |
+
|
8 |
+
class CustomPDF(FPDF):
|
9 |
+
def header(self):
|
10 |
+
if self.page_no() == 1: # Only add image and personal details on the first page
|
11 |
+
if self.image_path:
|
12 |
+
self.image(self.image_path, x=150, y=20, w=40)
|
13 |
+
|
14 |
+
self.set_font("Arial", 'B', 20)
|
15 |
+
self.set_text_color(31, 73, 125) # Set text color to the specific blue from the template
|
16 |
+
self.cell(0, 10, 'Katrin Winter', ln=True, align='L')
|
17 |
+
self.set_text_color(0, 0, 0) # Reset text color to black
|
18 |
+
self.set_font("Arial", '', 12)
|
19 |
+
self.cell(0, 8, '10. Oktober 1991', ln=True, align='L')
|
20 |
+
self.cell(0, 8, 'Kaiserstraße 1, 1010 Wien', ln=True, align='L')
|
21 |
+
self.cell(0, 8, 'T +43 650 123 45 67', ln=True, align='L')
|
22 |
+
self.cell(0, 8, 'E [email protected]', ln=True, align='L')
|
23 |
+
self.ln(10)
|
24 |
+
|
25 |
+
def section_title(self, title):
|
26 |
+
self.set_font("Arial", 'B', 14)
|
27 |
+
self.cell(0, 10, title, ln=True)
|
28 |
+
self.ln(2)
|
29 |
+
|
30 |
+
def add_experience(self, dates, role_company, description):
|
31 |
+
self.set_font("Arial", '', 12) # Regular font for dates
|
32 |
+
|
33 |
+
# Clean up the text to ensure no excessive spaces
|
34 |
+
dates = self.clean_text(dates)
|
35 |
+
role_company = self.clean_text(role_company)
|
36 |
+
description = self.clean_text(description)
|
37 |
+
|
38 |
+
# Print the dates in template-specific blue color and move the cursor 5 cm from the left margin
|
39 |
+
self.set_text_color(31, 73, 125) # Set text color to the specific blue from the template
|
40 |
+
self.cell(40, 8, dates, ln=False)
|
41 |
+
self.set_text_color(0, 0, 0) # Reset text color to black
|
42 |
+
self.set_x(70) # Move to 5 cm (50 mm) from the left margin
|
43 |
+
self.set_font("Arial", 'B', 12) # Bold for role and company
|
44 |
+
self.cell(0, 8, role_company, ln=True)
|
45 |
+
|
46 |
+
self.set_x(70) # Move to 5 cm (50 mm) from the left margin for the description
|
47 |
+
self.set_font("Arial", '', 12) # Regular font for description
|
48 |
+
self.multi_cell(0, 8, description)
|
49 |
+
self.ln(3)
|
50 |
+
|
51 |
+
def add_education(self, dates, degree_institution, details):
|
52 |
+
self.set_font("Arial", '', 12) # Regular font for dates
|
53 |
+
|
54 |
+
# Clean up the text to ensure no excessive spaces
|
55 |
+
dates = self.clean_text(dates)
|
56 |
+
degree_institution = self.clean_text(degree_institution)
|
57 |
+
details = self.clean_text(details)
|
58 |
+
|
59 |
+
self.set_text_color(31, 73, 125) # Set text color to the specific blue from the template
|
60 |
+
self.cell(40, 8, dates, ln=False)
|
61 |
+
self.set_text_color(0, 0, 0) # Reset text color to black
|
62 |
+
self.set_x(70)
|
63 |
+
self.set_font("Arial", 'B', 12) # Bold for degree and institution
|
64 |
+
self.cell(0, 8, degree_institution, ln=True)
|
65 |
+
self.set_font("Arial", '', 12) # Regular font for details
|
66 |
+
self.set_x(70)
|
67 |
+
self.multi_cell(0, 8, details)
|
68 |
+
self.ln(3)
|
69 |
+
|
70 |
+
def add_qualification(self, year, qualification_institution, details):
|
71 |
+
self.set_font("Arial", '', 12) # Regular font for dates
|
72 |
+
|
73 |
+
# Clean up the text to ensure no excessive spaces
|
74 |
+
year = self.clean_text(year)
|
75 |
+
qualification_institution = self.clean_text(qualification_institution)
|
76 |
+
details = self.clean_text(details)
|
77 |
+
|
78 |
+
self.set_text_color(31, 73, 125) # Set text color to the specific blue from the template
|
79 |
+
self.cell(40, 8, year, ln=False)
|
80 |
+
self.set_text_color(0, 0, 0) # Reset text color to black
|
81 |
+
self.set_x(70)
|
82 |
+
self.set_font("Arial", 'B', 12) # Bold for qualification and institution
|
83 |
+
self.cell(0, 8, qualification_institution, ln=True)
|
84 |
+
self.set_font("Arial", '', 12) # Regular font for details
|
85 |
+
self.set_x(70)
|
86 |
+
self.multi_cell(0, 8, details)
|
87 |
+
self.ln(2)
|
88 |
+
|
89 |
+
def add_skills(self, skills):
|
90 |
+
self.set_font("Arial", '', 12)
|
91 |
+
for skill in skills:
|
92 |
+
self.set_x(70)
|
93 |
+
self.cell(0, 8, f"{skill}", ln=True)
|
94 |
+
self.ln(3)
|
95 |
+
|
96 |
+
def add_languages(self, languages):
|
97 |
+
self.set_font("Arial", '', 12)
|
98 |
+
for language in languages:
|
99 |
+
self.set_x(70)
|
100 |
+
self.cell(0, 8, f"{language}", ln=True)
|
101 |
+
self.ln(3)
|
102 |
+
|
103 |
+
def add_interests(self, interests):
|
104 |
+
self.set_font("Arial", '', 12)
|
105 |
+
self.set_x(70)
|
106 |
+
self.multi_cell(0, 8, f"{interests}")
|
107 |
+
self.ln(3)
|
108 |
+
|
109 |
+
def set_image(self, image_path):
|
110 |
+
self.image_path = image_path
|
111 |
+
|
112 |
+
def clean_text(self, text):
|
113 |
+
# Replace multiple spaces with a single space and strip the text
|
114 |
+
text = re.sub(r'\s+', ' ', text).strip()
|
115 |
+
return text
|
116 |
+
|
117 |
+
def replace_special_characters(text):
|
118 |
+
# Replace problematic characters with simpler ones
|
119 |
+
return text.replace("–", "-").replace("’", "'").replace("‘", "'").replace("“", '"').replace("”", '"')
|
120 |
+
|
121 |
+
def create_resume(image, name, contact_info,
|
122 |
+
experience_dates_1, experience_role_company_1, experience_description_1,
|
123 |
+
experience_dates_2, experience_role_company_2, experience_description_2,
|
124 |
+
education_dates_1, education_degree_institution_1, education_details_1,
|
125 |
+
education_dates_2, education_degree_institution_2, education_details_2,
|
126 |
+
qualification_year_1, qualification_institution_1, qualification_details_1,
|
127 |
+
qualification_year_2, qualification_institution_2, qualification_details_2,
|
128 |
+
skills, languages, interests):
|
129 |
+
|
130 |
+
# Create PDF
|
131 |
+
pdf = CustomPDF(orientation='P', unit='mm', format='A4')
|
132 |
+
pdf.set_left_margin(20)
|
133 |
+
pdf.set_right_margin(20)
|
134 |
+
pdf.set_top_margin(20)
|
135 |
+
pdf.set_auto_page_break(auto=True, margin=20)
|
136 |
+
|
137 |
+
pdf.set_image(image)
|
138 |
+
pdf.add_page()
|
139 |
+
|
140 |
+
# Replace special characters in all fields
|
141 |
+
name = replace_special_characters(name)
|
142 |
+
contact_info = replace_special_characters(contact_info)
|
143 |
+
experience_dates_1 = replace_special_characters(experience_dates_1)
|
144 |
+
experience_role_company_1 = replace_special_characters(experience_role_company_1)
|
145 |
+
experience_description_1 = replace_special_characters(experience_description_1)
|
146 |
+
experience_dates_2 = replace_special_characters(experience_dates_2)
|
147 |
+
experience_role_company_2 = replace_special_characters(experience_role_company_2)
|
148 |
+
experience_description_2 = replace_special_characters(experience_description_2)
|
149 |
+
education_dates_1 = replace_special_characters(education_dates_1)
|
150 |
+
education_degree_institution_1 = replace_special_characters(education_degree_institution_1)
|
151 |
+
education_details_1 = replace_special_characters(education_details_1)
|
152 |
+
education_dates_2 = replace_special_characters(education_dates_2)
|
153 |
+
education_degree_institution_2 = replace_special_characters(education_degree_institution_2)
|
154 |
+
education_details_2 = replace_special_characters(education_details_2)
|
155 |
+
qualification_year_1 = replace_special_characters(qualification_year_1)
|
156 |
+
qualification_institution_1 = replace_special_characters(qualification_institution_1)
|
157 |
+
qualification_details_1 = replace_special_characters(qualification_details_1)
|
158 |
+
qualification_year_2 = replace_special_characters(qualification_year_2)
|
159 |
+
qualification_institution_2 = replace_special_characters(qualification_institution_2)
|
160 |
+
qualification_details_2 = replace_special_characters(qualification_details_2)
|
161 |
+
skills = replace_special_characters(skills)
|
162 |
+
languages = replace_special_characters(languages)
|
163 |
+
interests = replace_special_characters(interests)
|
164 |
+
|
165 |
+
# Experience
|
166 |
+
pdf.section_title('Berufserfahrung')
|
167 |
+
pdf.add_experience(experience_dates_1, experience_role_company_1, experience_description_1)
|
168 |
+
pdf.add_experience(experience_dates_2, experience_role_company_2, experience_description_2)
|
169 |
+
|
170 |
+
# Education
|
171 |
+
pdf.section_title('Ausbildung')
|
172 |
+
pdf.add_education(education_dates_1, education_degree_institution_1, education_details_1)
|
173 |
+
pdf.add_education(education_dates_2, education_degree_institution_2, education_details_2)
|
174 |
+
|
175 |
+
# Qualifications
|
176 |
+
pdf.section_title('Qualifikationen')
|
177 |
+
pdf.add_qualification(qualification_year_1, qualification_institution_1, qualification_details_1)
|
178 |
+
pdf.add_qualification(qualification_year_2, qualification_institution_2, qualification_details_2)
|
179 |
+
|
180 |
+
# Skills
|
181 |
+
pdf.section_title('Kenntnisse')
|
182 |
+
pdf.add_skills(["Microsoft Office: Ausgezeichnet", "Adobe Creative Suite: Ausgezeichnet", "HTML / CSS / CMS: Fortgeschritten"])
|
183 |
+
|
184 |
+
# Languages
|
185 |
+
pdf.section_title('Sprachen')
|
186 |
+
pdf.add_languages(["Englisch: C1", "Spanisch: B2", "Italienisch: B2"])
|
187 |
+
|
188 |
+
# Interests
|
189 |
+
pdf.section_title('Interessen')
|
190 |
+
pdf.add_interests("Fotografie, Reisen, Bergsteigen, Höhlentauchen")
|
191 |
+
|
192 |
+
# Save the PDF to a file
|
193 |
+
pdf_file = "resume_with_image.pdf"
|
194 |
+
pdf.output(pdf_file)
|
195 |
+
|
196 |
+
# Create Word Document
|
197 |
+
doc = Document()
|
198 |
+
doc.add_heading('Katrin Winter', 0).alignment = WD_ALIGN_PARAGRAPH.LEFT
|
199 |
+
|
200 |
+
# Add contact info
|
201 |
+
p = doc.add_paragraph()
|
202 |
+
p.add_run('10. Oktober 1991\nKaiserstraße 1, 1010 Wien\nT +43 650 123 45 67\nE [email protected]')
|
203 |
+
|
204 |
+
# Add sections with content
|
205 |
+
doc.add_heading('Berufserfahrung', level=1)
|
206 |
+
doc.add_paragraph(f'{experience_dates_1} - {experience_role_company_1}\n{experience_description_1}')
|
207 |
+
doc.add_paragraph(f'{experience_dates_2} - {experience_role_company_2}\n{experience_description_2}')
|
208 |
+
|
209 |
+
doc.add_heading('Ausbildung', level=1)
|
210 |
+
doc.add_paragraph(f'{education_dates_1} - {education_degree_institution_1}\n{education_details_1}')
|
211 |
+
doc.add_paragraph(f'{education_dates_2} - {education_degree_institution_2}\n{education_details_2}')
|
212 |
+
|
213 |
+
doc.add_heading('Qualifikationen', level=1)
|
214 |
+
doc.add_paragraph(f'{qualification_year_1} - {qualification_institution_1}\n{qualification_details_1}')
|
215 |
+
doc.add_paragraph(f'{qualification_year_2} - {qualification_institution_2}\n{qualification_details_2}')
|
216 |
+
|
217 |
+
doc.add_heading('Kenntnisse', level=1)
|
218 |
+
doc.add_paragraph(skills)
|
219 |
+
|
220 |
+
doc.add_heading('Sprachen', level=1)
|
221 |
+
doc.add_paragraph(languages)
|
222 |
+
|
223 |
+
doc.add_heading('Interessen', level=1)
|
224 |
+
doc.add_paragraph(interests)
|
225 |
+
|
226 |
+
doc_file = "resume_with_image.docx"
|
227 |
+
doc.save(doc_file)
|
228 |
+
|
229 |
+
return pdf_file, doc_file
|
230 |
+
|
231 |
+
# Gradio Interface
|
232 |
+
inputs = [
|
233 |
+
gr.Image(type="filepath", label="Profile Picture"),
|
234 |
+
gr.Textbox(label="Name", placeholder="Katrin Winter", value="Katrin Winter"),
|
235 |
+
gr.Textbox(label="Contact Information", placeholder="Address, Phone, Email", lines=4, value="10. Oktober 1991\nKaiserstraße 1, 1010 Wien\nT +43 650 123 45 67\nE [email protected]"),
|
236 |
+
|
237 |
+
# Experience 1
|
238 |
+
gr.Textbox(label="Experience 1 Dates", placeholder="02/2019 - jetzt", value="02/2019 - jetzt"),
|
239 |
+
gr.Textbox(label="Experience 1 Role & Company", placeholder="B2B Marketing Manager\nStepcompany, Wien", value="B2B Marketing Manager\nStepcompany, Wien"),
|
240 |
+
gr.Textbox(label="Experience 1 Description", placeholder="Selbstständige Organisation und Betreuung von Messen und Kundenevents, Aufbereitung von Sales- und Marketing-Materialien", lines=3, value="Selbstständige Organisation und Betreuung von Messen und Kundenevents, Aufbereitung von Sales- und Marketing-Materialien"),
|
241 |
+
|
242 |
+
# Experience 2
|
243 |
+
gr.Textbox(label="Experience 2 Dates", placeholder="02/2018 - 01/2019", value="02/2018 - 01/2019"),
|
244 |
+
gr.Textbox(label="Experience 2 Role & Company", placeholder="Marketing Assistenz\nStepcompany, Wien", value="Marketing Assistenz\nStepcompany, Wien"),
|
245 |
+
gr.Textbox(label="Experience 2 Description", placeholder="Abwicklung und Durchführung diverser Kundenprojekte, Einholung von Angeboten und Recherche von Give-Aways", lines=3, value="Abwicklung und Durchführung diverser Kundenprojekte, Einholung von Angeboten und Recherche von Give-Aways"),
|
246 |
+
|
247 |
+
# Education 1
|
248 |
+
gr.Textbox(label="Education 1 Dates", placeholder="02/2011 - 09/2016", value="02/2011 - 09/2016"),
|
249 |
+
gr.Textbox(label="Education 1 Degree & Institution", placeholder="Wirtschafts- und Sozialwissenschaften, WU Wien", value="Wirtschafts- und Sozialwissenschaften, WU Wien"),
|
250 |
+
gr.Textbox(label="Education 1 Details", placeholder="Schwerpunkt Marketing, Abschlussarbeit: Marktorientiertes Business Development", lines=3, value="Schwerpunkt Marketing, Abschlussarbeit: Marktorientiertes Business Development"),
|
251 |
+
|
252 |
+
# Education 2
|
253 |
+
gr.Textbox(label="Education 2 Dates", placeholder="02/2006 - 05/2011", value="02/2006 - 05/2011"),
|
254 |
+
gr.Textbox(label="Education 2 Degree & Institution", placeholder="Marketingmanagement, HAK I, Vienna Business School", value="Marketingmanagement, HAK I, Vienna Business School"),
|
255 |
+
gr.Textbox(label="Education 2 Details", placeholder="Details about this degree", lines=3, value=""),
|
256 |
+
|
257 |
+
# Qualification 1
|
258 |
+
gr.Textbox(label="Qualification 1 Year", placeholder="2019", value="2019"),
|
259 |
+
gr.Textbox(label="Qualification 1 Institution", placeholder="Ausbildung Grafikdesign, Webeakademie Wien", value="Ausbildung Grafikdesign, Webeakademie Wien"),
|
260 |
+
gr.Textbox(label="Qualification 1 Details", placeholder="Details about this qualification", lines=3, value=""),
|
261 |
+
|
262 |
+
# Qualification 2
|
263 |
+
gr.Textbox(label="Qualification 2 Year", placeholder="2018", value="2018"),
|
264 |
+
gr.Textbox(label="Qualification 2 Institution", placeholder="Online-Marketing Basis-Lehrgang, Online Marketing Forum, Wien", value="Online-Marketing Basis-Lehrgang, Online Marketing Forum, Wien"),
|
265 |
+
gr.Textbox(label="Qualification 2 Details", placeholder="Details about this qualification", lines=3, value=""),
|
266 |
+
|
267 |
+
# Other sections
|
268 |
+
gr.TextArea(label="Kenntnisse", placeholder="Enter skills here", lines=3, value="""
|
269 |
+
Microsoft Office: Ausgezeichnet
|
270 |
+
Adobe Creative Suite: Ausgezeichnet
|
271 |
+
HTML / CSS / CMS: Fortgeschritten
|
272 |
+
"""),
|
273 |
+
gr.TextArea(label="Sprachen", placeholder="Enter languages here", lines=3, value="""
|
274 |
+
Englisch: C1
|
275 |
+
Spanisch: B2
|
276 |
+
Italienisch: B2
|
277 |
+
"""),
|
278 |
+
gr.TextArea(label="Interessen", placeholder="Enter interests here", lines=2, value="Fotografie, Reisen, Bergsteigen, Höhlentauchen")
|
279 |
+
]
|
280 |
+
|
281 |
+
outputs = [
|
282 |
+
gr.File(label="Download Your Resume as PDF"),
|
283 |
+
gr.File(label="Download Your Resume as DOCX")
|
284 |
+
]
|
285 |
+
|
286 |
+
gr_interface = gr.Interface(
|
287 |
+
fn=create_resume,
|
288 |
+
inputs=inputs,
|
289 |
+
outputs=outputs,
|
290 |
+
title="Resume Creator",
|
291 |
+
description="Create a resume similar to the provided template.",
|
292 |
+
)
|
293 |
+
|
294 |
+
gr_interface.launch()
|