From b5fe854fecc29b7143e956afe992a0ed8d9b098c Mon Sep 17 00:00:00 2001 From: ThatGenZGamer48 Date: Wed, 19 Jan 2022 13:18:50 +0530 Subject: [PATCH 01/10] Added Business Card Generator and Resume Generator script. --- .gitignore | 10 + pyproject.toml | 8 + src/LICENSE.txt | 19 + src/MANIFEST.in | 1 + src/README.md | 1 - src/README.rst | 69 ++ src/VERSION.txt | 1 + src/businesstemplates/__init__.py | 18 + .../business_card_generator.py | 136 +++ src/businesstemplates/resume_generator.py | 813 ++++++++++++++++++ .../templates/Business Card Template.jpg | Bin 0 -> 35040 bytes .../templates/Email Icon Template.png | Bin 0 -> 1470 bytes .../templates/Phone Icon Template.png | Bin 0 -> 1055 bytes .../templates/Resume Template.docx | Bin 0 -> 14434 bytes src/businesstemplates/utils.py | 76 ++ src/requirements.txt | 17 + src/setup.cfg | 41 + src/setup.py | 42 + 18 files changed, 1251 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 pyproject.toml create mode 100644 src/LICENSE.txt create mode 100644 src/MANIFEST.in delete mode 100644 src/README.md create mode 100644 src/README.rst create mode 100644 src/VERSION.txt create mode 100644 src/businesstemplates/__init__.py create mode 100644 src/businesstemplates/business_card_generator.py create mode 100644 src/businesstemplates/resume_generator.py create mode 100644 src/businesstemplates/templates/Business Card Template.jpg create mode 100644 src/businesstemplates/templates/Email Icon Template.png create mode 100644 src/businesstemplates/templates/Phone Icon Template.png create mode 100644 src/businesstemplates/templates/Resume Template.docx create mode 100644 src/businesstemplates/utils.py create mode 100644 src/requirements.txt create mode 100644 src/setup.cfg create mode 100644 src/setup.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..37b717a --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +dist +colorconverters.egg-info +build +*.egg-info +venv +.venv +.idea/ +.vs/slnx.sqlite +env/ +test.py \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..2d5bec4 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,8 @@ +[tool.documatic] +name="businesstemplates" +docdir="." +srcdir="src/businesstemplates" + +[tool.doculog] +changelog="CHANGELOG" +project="businesstemplates" \ No newline at end of file diff --git a/src/LICENSE.txt b/src/LICENSE.txt new file mode 100644 index 0000000..f6cbbf9 --- /dev/null +++ b/src/LICENSE.txt @@ -0,0 +1,19 @@ +Copyright (c) 2022 That GenZ Gamer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the “Software”), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/src/MANIFEST.in b/src/MANIFEST.in new file mode 100644 index 0000000..1515a6a --- /dev/null +++ b/src/MANIFEST.in @@ -0,0 +1 @@ +global-include *.txt *.md *.py *.docx *.jpg *.png *.cfg *.toml *.rst \ No newline at end of file diff --git a/src/README.md b/src/README.md deleted file mode 100644 index 3fd786d..0000000 --- a/src/README.md +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/README.rst b/src/README.rst new file mode 100644 index 0000000..79e87f2 --- /dev/null +++ b/src/README.rst @@ -0,0 +1,69 @@ +businesstemplates +================= + +.. image:: https://img.shields.io/pypi/v/businesstemplates.svg + :target: https://pypi.python.org/pypi/businesstemplates + :alt: PyPI Version Info +.. image:: https://img.shields.io/pypi/pyversions/businesstemplates.svg + :target: https://pypi.python.org/pypi/businesstemplates + :alt: PyPI Supported Python Versions + +An efficient command line tool to create resumes and business cards on the go! + +Notable Features +---------------- + +- Modern pythonic syntax. +- Easy to run scripts. +- Covers all important information. +- Lightweight module. + +Installing +---------- + +**"Python 3.7" or higher is required to install this module.** + +Installing this module is quite simple, + +... code:: sh + + # Linux/MacOS + python3 -m pip install -U businesstemplates + + # Windows + py -3 -m pip install -U businesstemplates + +Other Required Packages +~~~~~~~~~~~~~~~~~~~~~~~~ + +* `python-docx `__ +* `pathlib` + +How to run? +----------- + +Resume Generator +~~~~~~~~~~~~~~~~ + +Now you can design your own impressive resume + +Open your favourite terminal and enter this + +... code:: sh + + resume_generator + +Enter the information through the inputs and you're done! + +Business Card Generator +~~~~~~~~~~~~~~~~~~~~~~~ + +Design your sparkling business card in just under a minute. + +Open your favourite terminal and enter this + +... code:: sh + business_card_generator + +Enter the information through the inputs and you're done! + diff --git a/src/VERSION.txt b/src/VERSION.txt new file mode 100644 index 0000000..6c6aa7c --- /dev/null +++ b/src/VERSION.txt @@ -0,0 +1 @@ +0.1.0 \ No newline at end of file diff --git a/src/businesstemplates/__init__.py b/src/businesstemplates/__init__.py new file mode 100644 index 0000000..f0a40e1 --- /dev/null +++ b/src/businesstemplates/__init__.py @@ -0,0 +1,18 @@ +""" +Business Templates +=================== + +An efficient command line tool to create resumes and business cards on the go! + +Copyright 2022 (c) That GenZ Gamer +This project uses the MIT license. +""" + +__title__ = "businesstemplates" +__author__ = "That GenZ Gamer" +__license__ = "MIT" +__copyright__ = "Copyright 2022 (c) That GenZ Gamer" +__version__ = "0.1.0" + +from .resume_generator import * +from .business_card_generator import * diff --git a/src/businesstemplates/business_card_generator.py b/src/businesstemplates/business_card_generator.py new file mode 100644 index 0000000..5e80b46 --- /dev/null +++ b/src/businesstemplates/business_card_generator.py @@ -0,0 +1,136 @@ +""" +Copyright (c) 2022 That GenZ Gamer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the “Software”), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +""" + +from easy_pil import Editor, Canvas, Font, Text +from pathlib import Path + + +def main(): + + print("--------------------------------") + print(" Business Card Generator ") + print(" ----------------------- ") + print(" Get your sparkling ") + print(" business card ready. ") + print("--------------------------------\n") + + # Getting the path of all the icons and template. + template_dir = Path(__file__).parent / "templates" + email_icon_path = template_dir / "Email Icon Template.png" + phone_icon_path = template_dir / "Phone Icon Template.png" + card_template_path = template_dir / "Business Card Template.jpg" + + # Asking for the inputs + company = input("What company are you working for?: ") + name = input("What's your name?: ") + designation = input("What is your current designation?: ") + department = input("What department are you working in?: ") + phone = input("What's your phone number?: ") + email = input("What's your Email ID?: ") + + # Preparing a while loop to check if the address (Line 1) is below or above 30 characters + address_loop_one = True + + # Resuming if address is below 30 characters. + while address_loop_one: + address_line_1 = input("What's your address? (Line 1) [Max: 30 chars]: ") + if len(address_line_1) <= 30: + address_loop_one = False + else: + print("Limit the length of the address below 30 characters!") + + # Preparing a while loop to check if the address (Line 2) is below or above 30 characters + address_loop_two = True + + # Resuming if address is below 30 characters. + while address_loop_two: + address_line_2 = input("What's your address? (Line 2) [Max: 30 chars]: ") + if len(address_line_2) <= 30: + address_loop_two = False + else: + print("Limit the length of the address below 30 characters!") + + # Combing the designation and department inputs with a comma. + designation_and_department = designation + ", " + department + + # Background of the canvas. + # Open the background as a new Editor to work on it. + background = Editor(str(card_template_path)) + + # Setting up all the fonts required. + bold_50 = Font.poppins(variant="bold", size=50) + regular_40 = Font.poppins(variant="regular", size=40) + light_25 = Font.poppins(variant="light", size=25) + bold_35 = Font.poppins(variant="bold", size=35) + light_15 = Font.poppins(variant="light", size=15) + + # Loading all the images + phone_icon = Editor(str(phone_icon_path)).resize((50, 50)) + email_icon = Editor(str(email_icon_path)).resize((50, 50)) + + # Adding the texts. + background.text( + (800, 50), company, font=bold_35, color="#000000", align="right" + ) + + background.text( + (800, 90), address_line_1, font=light_15, color="#000000", align="right" + ) + + background.text( + (800, 110), address_line_2, font=light_15, color="#000000", align="right" + ) + + background.text((94, 50), name, font=bold_50, color="#000000") + + background.text( + (94, 196), designation_and_department, font=light_25, color="#000000" + ) + + # Adding a line for aesthetics. + background.rectangle((94, 159), width=754, height=3, color="#000000") + + # Adding the phone icon + background.paste(phone_icon, (94, 267)) + + # Adding the phone number as text + background.text((153, 270), phone, font=regular_40, color="#000000") + + # Adding the email icon + background.paste(email_icon, (94, 337)) + + # Adding the email ID as text + background.text((153, 344), email, font=regular_40, color="#000000") + + # Asking for the path to save the resulting file. + path_to_save = input( + "Where do you want to save the file? (Eg: C:/path/to/save/filename.png) [Note: Relative paths are also allowed]: " + ) + try: + background.save(path_to_save) + except: + print("You have entered an incorrect path! Try again") + exit() + +# Running the script with the __name__ == "__main__" check. +if __name__ == "__main__": + main() diff --git a/src/businesstemplates/resume_generator.py b/src/businesstemplates/resume_generator.py new file mode 100644 index 0000000..927d7f2 --- /dev/null +++ b/src/businesstemplates/resume_generator.py @@ -0,0 +1,813 @@ +""" +Copyright (c) 2022 That GenZ Gamer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the “Software”), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +""" + +from docx import Document +from docx.text.paragraph import Paragraph +from docx.shared import Pt +from .utils import change_text, find_paragraph, insert_paragraph_after +from pathlib import Path + + +def main(): + # Prepare a nice (custom) ASCII art to show before the start of the inputs. + print("--------------------------------") + print("| Python Resume Generator |") + print("| ----------------------- |") + print("| Now, you can design your own |") + print("| impressive resume. |") + print("--------------------------------\n") + + template_directory = Path(__file__).parent / "templates" + resume_template = template_directory / "Resume Template.docx" + + # Reading the document containing the resume template. + document = Document(resume_template) + + # The following set of inputs is to get enough information to prepare the resume. + + # Getting the user's name + name = input("What is your full name?: ") + + # Changing the text of the user's name and setting the font size using an helper function. + if len(name) != 0: + change_text(document.paragraphs[0], name, 18, True) + else: + print("You haven't mentioned a name!") + exit() + + # Getting the information table from the word document. + information_table = document.tables[0] + + # Asking for the user's age + age = input("What is your age?: ") + + # Changing the text of the user's age and setting the font size using an helper function. + if len(age) != 0: + age_cell = information_table.columns[0].cells[0].paragraphs[0] + + change_text(age_cell, f"Age: {age}", 12) + else: + print("You haven't mentioned an age!") + exit() + + # Asking for the user's gender + gender = input("What is your gender?: ") + + # Changing the text of the user's gender and setting the font size using an helper function. + if len(gender) != 0: + gender_cell = information_table.columns[0].cells[1].paragraphs[0] + + change_text(gender_cell, f"Gender: {gender}", 12) + else: + print("You haven't mentioned a gender!") + exit() + + # Asking for the user's nationality + nationality = input("Which country do you belong to?: ") + + # Changing the text of the user's nationality and setting the font size using an helper function. + if len(nationality) != 0: + nationality_cell = information_table.columns[0].cells[2].paragraphs[0] + + change_text(nationality_cell, f"Nationality: {nationality}", 12) + else: + print("You haven't mentioned a nationality!") + exit() + + # Asking for the user's Email ID + email = input("What is your Email ID?: ") + + # Changing the text of the user's Email ID and setting the font size using an helper function. + if len(email) != 0: + email_cell = information_table.columns[1].cells[0].paragraphs[0] + + change_text(email_cell, f"Email ID: {email}", 12) + else: + print("You haven't mentioned an Email ID!") + exit() + + # Asking for the user's Mobile no + mobile_number = input("What is your mobile number?: ") + + # Changing the text of the user's mobile no and setting the font size using an helper function. + if len(mobile_number) != 0: + mobile_number_cell = information_table.columns[1].cells[1].paragraphs[0] + + change_text(mobile_number_cell, f"Mobile No: {mobile_number}", 12) + else: + print("You haven't entered a mobile number") + exit() + + # Asking for the user's city + city = input("Which city are you from?: ") + + # Changing the text of the user's mobile no and setting the font size using an helper function. + if len(city) != 0: + city_cell = information_table.columns[1].cells[2].paragraphs[0] + + change_text(city_cell, f"City: {city}", 12) + else: + print("You haven't mentioned a city!") + exit() + + # Asking for the user's introduction + objective = input("Write your objective to be mentioned in the resume: ") + + # Changing the text of the user's introduction and setting the font size using an helper function. + if len(objective) != 0: + change_text(document.paragraphs[3], objective, 12) + else: + print("You haven't mentioned your objective!") + exit() + + # Getting the course details table + course_details = document.tables[1] + + # Asking for the highest qualification + highest_qualification = input( + "What is your highest qualification? [Employee/Post Graduation/Graduation/Class 12]: " + ).lower() + + qualifications = [ + "employee", + "post graduation", + "graduation", + "class 12", + ] + + # Exitting if the qualification selected does not exist in options. + if highest_qualification not in qualifications: + print("Pick an option from the given options!") + exit() + # Exitting if the user hasn't entered anything. + elif len(highest_qualification) == 0: + print("You haven't mentioned your highest qualification!") + else: + # Asking for post graduation, graduation, 12th and 10th details + # if the user is an employee. + if highest_qualification == "employee": + employee_pg_institute = input( + "Which institute did you pursue your post graduation in?: " + ) + + change_text( + course_details.columns[1].cells[1].paragraphs[0], + employee_pg_institute, + 12, + ) + + employee_pg_year = input( + "Which year did you complete your post graduation?: " + ) + + change_text( + course_details.columns[2].cells[1].paragraphs[0], + employee_pg_year, + 12, + ) + + employee_pg_percentage = input( + "What was your post graduation percentage obtained?: " + ) + + change_text( + course_details.columns[3].cells[1].paragraphs[0], + employee_pg_percentage, + 12, + ) + + employee_grad_institute = input( + "Which institute did you pursue your graduation in?: " + ) + + change_text( + course_details.columns[1].cells[2].paragraphs[0], + employee_grad_institute, + 12, + ) + + employee_grad_year = input( + "Which year did you complete your graduation?: " + ) + + change_text( + course_details.columns[2].cells[2].paragraphs[0], + employee_grad_year, + 12, + ) + + employee_grad_percentage = input( + "What was your graduation percentage obtained?: " + ) + + change_text( + course_details.columns[3].cells[2].paragraphs[0], + employee_grad_percentage, + 12, + ) + + employee_12th_institute = input( + "Which institute did you pursue your 12th grade in?: " + ) + + change_text( + course_details.columns[1].cells[3].paragraphs[0], + employee_12th_institute, + 12, + ) + + employee_12th_year = input( + "Which year did you complete your 12th grade?: " + ) + + change_text( + course_details.columns[2].cells[3].paragraphs[0], + employee_12th_year, + 12, + ) + + employee_12th_percentage = input( + "What was your 12th grade percentage obtained?: " + ) + + change_text( + course_details.columns[3].cells[3].paragraphs[0], + employee_12th_percentage, + 12, + ) + + employee_10th_institute = input( + "Which institute did you pursue your 10th grade in?: " + ) + + change_text( + course_details.columns[1].cells[4].paragraphs[0], + employee_10th_institute, + 12, + ) + + employee_10th_year = input( + "Which year did you complete your 10th grade?: " + ) + + change_text( + course_details.columns[2].cells[4].paragraphs[0], + employee_10th_year, + 12, + ) + + employee_10th_percentage = input( + "What was your 10th grade percentage obtained?: " + ) + + change_text( + course_details.columns[3].cells[4].paragraphs[0], + employee_10th_percentage, + 12, + ) + + # Asking for pg, ug, 12th and 10th details if user is an post graduate. + elif highest_qualification == "post graduation": + postgraduate_pg_institute = input( + "Which institute did you pursue your post graduation in?: " + ) + + change_text( + course_details.columns[1].cells[1].paragraphs[0], + postgraduate_pg_institute, + 12, + ) + + postgraduate_pg_year = input( + "Which year did you complete your post graduation?: " + ) + + change_text( + course_details.columns[2].cells[1].paragraphs[0], + postgraduate_pg_year, + 12, + ) + + postgraduate_pg_percentage = input( + "What was your post graduation percentage obtained?: " + ) + + change_text( + course_details.columns[3].cells[1].paragraphs[0], + postgraduate_pg_percentage, + 12, + ) + + postgraduate_grad_institute = input( + "Which institute did you pursue your graduation in?: " + ) + + change_text( + course_details.columns[1].cells[2].paragraphs[0], + postgraduate_grad_institute, + 12, + ) + + postgraduate_grad_year = input( + "Which year did you complete your graduation?: " + ) + + change_text( + course_details.columns[2].cells[2].paragraphs[0], + postgraduate_grad_year, + 12, + ) + + postgraduate_grad_percentage = input( + "What was your graduation percentage obtained?: " + ) + + change_text( + course_details.columns[3].cells[2].paragraphs[0], + postgraduate_grad_percentage, + 12, + ) + + postgraduate_12th_institute = input( + "Which institute did you pursue your 12th grade in?: " + ) + + change_text( + course_details.columns[1].cells[3].paragraphs[0], + postgraduate_12th_institute, + 12, + ) + + postgraduate_12th_year = input( + "Which year did you complete your 12th grade?: " + ) + + change_text( + course_details.columns[2].cells[3].paragraphs[0], + postgraduate_12th_year, + 12, + ) + + postgraduate_12th_percentage = input( + "What was your 12th grade percentage obtained?: " + ) + + change_text( + course_details.columns[3].cells[3].paragraphs[0], + postgraduate_12th_percentage, + 12, + ) + + postgraduate_10th_institute = input( + "Which institute did you pursue your 10th grade in?: " + ) + + change_text( + course_details.columns[1].cells[4].paragraphs[0], + postgraduate_10th_institute, + 12, + ) + + postgraduate_10th_year = input( + "Which year did you complete your 10th grade?: " + ) + + change_text( + course_details.columns[2].cells[4].paragraphs[0], + postgraduate_10th_year, + 12, + ) + + postgraduate_10th_percentage = input( + "What was your 10th grade percentage obtained?: " + ) + + change_text( + course_details.columns[3].cells[4].paragraphs[0], + postgraduate_10th_percentage, + 12, + ) + + # Asking for ug, 12th and 10th details if user is an graduate. + elif highest_qualification == "graduation": + change_text(course_details.columns[1].cells[1].paragraphs[0], "NA", 12) + change_text(course_details.columns[2].cells[1].paragraphs[0], "NA", 12) + change_text(course_details.columns[3].cells[1].paragraphs[0], "NA", 12) + + graduate_grad_institute = input( + "Which institute did you pursue your graduation in?: " + ) + + change_text( + course_details.columns[1].cells[2].paragraphs[0], + graduate_grad_institute, + 12, + ) + + graduate_grad_year = input( + "Which year did you complete your graduation?: " + ) + + change_text( + course_details.columns[2].cells[2].paragraphs[0], + graduate_grad_year, + 12, + ) + + graduate_grad_percentage = input( + "What was your graduation percentage obtained?: " + ) + + change_text( + course_details.columns[3].cells[2].paragraphs[0], + graduate_grad_percentage, + 12, + ) + + graduate_12th_institute = input( + "Which institute did you pursue your 12th grade in?: " + ) + + change_text( + course_details.columns[1].cells[3].paragraphs[0], + graduate_12th_institute, + 12, + ) + + graduate_12th_year = input( + "Which year did you complete your 12th grade?: " + ) + + change_text( + course_details.columns[2].cells[3].paragraphs[0], + graduate_12th_year, + 12, + ) + + graduate_12th_percentage = input( + "What was your 12th grade percentage obtained?: " + ) + + change_text( + course_details.columns[3].cells[3].paragraphs[0], + graduate_12th_percentage, + 12, + ) + + graduate_10th_institute = input( + "Which institute did you pursue your 10th grade in?: " + ) + + change_text( + course_details.columns[1].cells[4].paragraphs[0], + graduate_10th_institute, + 12, + ) + + graduate_10th_year = input( + "Which year did you complete your 10th grade?: " + ) + + change_text( + course_details.columns[2].cells[4].paragraphs[0], + graduate_10th_year, + 12, + ) + + graduate_10th_percentage = input( + "What was your 10th grade percentage obtained?: " + ) + + change_text( + course_details.columns[3].cells[4].paragraphs[0], + graduate_10th_percentage, + 12, + ) + + # Asking for 12th and 10th details if user is a 12th grader. + elif highest_qualification == "class 12": + change_text(course_details.columns[1].cells[1].paragraphs[0], "NA", 12) + change_text(course_details.columns[2].cells[1].paragraphs[0], "NA", 12) + change_text(course_details.columns[3].cells[1].paragraphs[0], "NA", 12) + + change_text(course_details.columns[1].cells[2].paragraphs[0], "NA", 12) + change_text(course_details.columns[2].cells[2].paragraphs[0], "NA", 12) + change_text(course_details.columns[3].cells[2].paragraphs[0], "NA", 12) + + class12_12th_institute = input( + "Which institute did you pursue your 12th grade in?: " + ) + + change_text( + course_details.columns[1].cells[3].paragraphs[0], + class12_12th_institute, + 12, + ) + + class12_12th_year = input( + "Which year did you complete your 12th grade?: " + ) + + change_text( + course_details.columns[2].cells[3].paragraphs[0], + class12_12th_year, + 12, + ) + + class12_12th_percentage = input( + "What was your 12th grade percentage obtained?: " + ) + change_text( + course_details.columns[3].cells[3].paragraphs[0], + class12_12th_percentage, + 12, + ) + + class12_10th_institute = input( + "Which institute did you pursue your 10th grade in?: " + ) + + change_text( + course_details.columns[1].cells[4].paragraphs[0], + class12_10th_institute, + 12, + ) + + class12_10th_year = input( + "Which year did you complete your 10th grade?: " + ) + + change_text( + course_details.columns[2].cells[4].paragraphs[0], + class12_10th_year, + 12, + ) + + class12_10th_percentage = input( + "What was your 10th grade percentage obtained?: " + ) + + change_text( + course_details.columns[3].cells[4].paragraphs[0], + class12_10th_percentage, + 12, + ) + else: + pass + + # Asking the user whether he/she has previous work experience + has_work_experience = input( + "Do you have any previous work experience? [Yes/No]: " + ).lower() + + # Checking if he/she has work experience or not + if has_work_experience == "yes": + # Asking for the number of work experiences. + number_of_work_experiences = input( + "How many companies have you worked for?: " + ) + + # Checking if the user has provided a valid number. + if number_of_work_experiences.isnumeric(): + number_of_work_experiences = int(number_of_work_experiences) + else: + print( + "You haven't entered a valid number. Check if the number you have entered doesn't contain negative values or decimals and try again!" + ) + exit() + + # Getting the first paragraph using an helper tool. + work_experience_previous_paragraph = find_paragraph(document, "WORK EXPERIENCE") + + # Adding the paragraphs after one another containing the work experience information. + for _ in range(0, number_of_work_experiences): + work_experience = input( + "Mention a suitable description for your previous work experience: " + ) + + work_experience_inserted_paragraph = insert_paragraph_after( + document, + work_experience_previous_paragraph, + 12, + work_experience, + ) + work_experience_previous_paragraph = work_experience_inserted_paragraph + + # Passing if the user doesn't have any work experience + elif has_work_experience == "no": + insert_paragraph_after( + document, + find_paragraph(document, "WORK EXPERIENCE"), + 12, + "NA" + ) + else: + print("You haven't mentioned if you have previous work experience or not!") + exit() + + # Asking the user whether he/she has previous internship experience. + has_internship_experience = input( + "Do you have any previous Internship experience? [Yes/No]: " + ).lower() + + # Checking if he/she has previous internship experience or not. + if has_internship_experience == "yes": + # Asking for the number of internship experience(s). + number_of_internship_experiences = input( + "How many internships have you attended?: " + ) + + # Checking if the user has provided a valid number. + if number_of_internship_experiences.isnumeric(): + number_of_internship_experiences = int( + number_of_internship_experiences + ) + else: + print( + "You haven't entered a valid number. Check if the number you have entered doesn't contain negative values or decimals and try again!" + ) + exit() + + # Getting the first paragraph using an helper tool. + internship_experience_previous_paragraph = find_paragraph( + document, "INTERNSHIP EXPERIENCE(S) (IF ANY)" + ) + + # Adding the paragraphs after one another containing the internship experience information. + for _ in range(0, number_of_internship_experiences): + internship_experience = input( + "Mention a description for your previous work experience: " + ) + + internship_experience_inserted_paragraph = insert_paragraph_after( + document, + internship_experience_previous_paragraph, + 12, + internship_experience, + ) + internship_experience_previous_paragraph = ( + internship_experience_inserted_paragraph + ) + + # Passing if the user doesn't have any previous internship experience + elif has_internship_experience == "no": + insert_paragraph_after( + document, + find_paragraph( + document, "INTERNSHIP EXPERIENCE(S) (IF ANY)" + ), + 12, + "NA" + ) + else: + print("You haven't mentioned if you have an internship experience or not!") + exit() + + # Asking the user whether he/she has certificates/courses. + has_certificates_courses = input( + "Do you have any previous Certificates/Courses to your name? [Yes/No]: " + ).lower() + + # Checking if he/she has any certificates/courses or not. + if has_certificates_courses == "yes": + # Splitting the certificates and courses with a "," + certificates_courses = input( + "Mention all the certificates/courses' name seperated by commas (,). Make sure to not include a space after each comma: " + ).split(",") + + # Getting the first paragraph using a helper tool. + certificates_courses_previous_paragraph = find_paragraph( + document, "CERTIFICATIONS/COURSES COMPLETED (IF ANY)" + ) + + # Adding the paragraphs after one another containing the certificate/course information. + for certificate_course in certificates_courses: + certificates_courses_inserted_paragraph = insert_paragraph_after( + document=document, + paragraph=certificates_courses_previous_paragraph, + font_size=12, + description=certificate_course, + ) + + certificates_courses_previous_paragraph = ( + certificates_courses_inserted_paragraph + ) + + # Passing if the user doesn't have any certificate/course + elif has_certificates_courses == "no": + insert_paragraph_after( + document, + find_paragraph( + document, "CERTIFICATIONS/COURSES COMPLETED (IF ANY)" + ), + 12, + "NA" + ) + else: + print("You haven't mentioned if you have a certificate/course or not!") + exit() + + # Asking the user whether he/she has any hobby. + has_skillsets = input("Do you have any skillsets? [Yes/No]: ").lower() + + # Checking if he/she has any skillsets or not. + if has_skillsets == "yes": + # Asking for the skillsets and seperating it by a "," + skillsets = input( + "Mention all the skillsets' name seperated by commas (,). Make sure to not include a space after each comma: " + ).split(",") + + # Getting the first paragraph. + skillsets_previous_paragraph = find_paragraph(document, "SKILL SETS") + + # Adding the paragraphs after one another containing the skillset information. + for skillset in skillsets: + skillsets_inserted_paragraph = insert_paragraph_after( + document=document, + paragraph=skillsets_previous_paragraph, + font_size=12, + description=skillset, + ) + + skillsets_previous_paragraph = skillsets_inserted_paragraph + + # Passing if the user doesn't have any skillset + elif has_skillsets == "no": + insert_paragraph_after( + document, + find_paragraph(document, "SKILL SETS"), + 12, + "NA" + ) + else: + print("You haven't mentioned if you have a skillset or not!") + exit() + + # Asking the user whether he/she has any hobbies. + has_hobbies = input("Do you have any hobbies? [Yes/No]: ").lower() + + # Checking if he/she has any hobby or not. + if has_hobbies == "yes": + # Asking for the hobbies + hobbies = input( + "Mention all the hobbies' name seperated by commas (,). Make sure to not include a space after each comma: " + ).split(",") + + # Getting the first paragraph. + hobbies_previous_paragraph = find_paragraph(document, "HOBBIES AND INTERESTS") + + # Adding the paragraphs after one another containing the hobbies information. + for hobby in hobbies: + hobbies_inserted_paragraph = insert_paragraph_after( + document=document, + paragraph=hobbies_previous_paragraph, + font_size=12, + description=hobby, + ) + + hobbies_previous_paragraph = hobbies_inserted_paragraph + + # Passing if the user doesn't have any hobby + elif has_hobbies == "no": + insert_paragraph_after( + document, + find_paragraph(document, "HOBBIES AND INTERESTS"), + 12, + "NA" + ) + else: + print("You haven't mentioned if you have a hobby or not!") + exit() + + # Asking for the path to save the end document. + path_to_save = input( + "Where do you want to save the file? (Eg: C:/path/to/save/filename.docx) [Note: Relative paths are also allowed]: " + ) + try: + document.save(path_to_save) + except: + print("You have entered an incorrect path. Try again") + exit() + +# Running the script with the __name__ == "__main__" check. +if __name__ == "__main__": + main() diff --git a/src/businesstemplates/templates/Business Card Template.jpg b/src/businesstemplates/templates/Business Card Template.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bf3bb2e3c4e8f559d50a0ec6a01bd29ea4a757f0 GIT binary patch literal 35040 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

04N2@Y^7wdZg0QrB7 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 literal 0 HcmV?d00001 diff --git a/src/businesstemplates/templates/Email Icon Template.png b/src/businesstemplates/templates/Email Icon Template.png new file mode 100644 index 0000000000000000000000000000000000000000..1419ce15b7d14f97da15f91d7bed847d226ebd9d GIT binary patch literal 1470 zcmV;v1ws0WP)*rECRo z5P<124;DXLT{a8AQl-=&LPCU<$TZD`0Qylb;#edS=`;+(Wae+(;Q*|7JbqVL^+Q=B z#r3ckzzroE5p4&sER{-~JAL}}Sa)~#?vas^MgZN#kZYOwv9Q*S@6?J$qw|Ci8v#t4 zB*!!&idWdqGIPqaU?H|FXEFBdgpCrNaU5quI-UO2%OCL@D1_KZL=R1rd;+EsQQ&Fg z@ke-K7zO}5?B(-aBSbVkXd{=9Tl^fpSEPbn%-k1JGgU!E2>?$_78gheGat1qYgf%( z{R>Rf%n{L~LPFbq|7)%ax!mwvBZ)+!IhV`L@bYzZbllI(JN(8L`C2Kp+%@JXGcO3( zQ=XYuS(f#shi^tAk!bGg>l>?dT+~cgSJ#|uHhX}G=KB;f0o)2;7ZK$uoy>eUfMkX3 z3nKbChze%bLWo~{-1Bp}-1nWGoe%c+_y6uI#5B!?`Fwsq5zU;epyN2}(&_Y>O1qTu zAb_abrj*(`xrD$(9mh$<+Db))AkwhZVoXuuGBBB+pz%c-$06f=8wGhz=Gmiv}bqvGE__+T9&;pnnUi0D37@F0Mt0Jb0`Axf#WVdMeu6Mz>`xaVmF03up3K0bb9 z1i(G6z{6VWM{V04mQsdP8<0}I4&V+iA2WYrS=P>=xs*~?EEek!LhJ>wsF>s42we9h zj^nIMr_;kh5;in6%#Fw6=PK=5>+3w4jS|tFUU`VNRMhJ1NwzjILY9Y354+D6o4!zXG z6?4|QD&%q_kPsr8Q}0GIfQZ&G^Wz?Q zbIiO~2(f8kVBklOp60raD8Yo3=<4d4={U}_%={dHn>|8KFmtbESzn?2Dpm^U2JkX~ zCAj#p?I?hqLWs?&RO*ypj+%s&XlrY`zNx8c6@YaBZu1EFfrz#;^B&j6AWYL-LPW0t z==2yfL`2*3`TVqVex7?hfXxKT;!^|99aecQJG47(;!2O%Yj4Zi|lL(!z`RST%25Epe7P~!h}`ke|~6>_<8 z#Rw_ewTP%S9*<86aru0{?9Q=Fh!Ena)|X_rtQjH7|8D`n@5%R6VoU&d3sYN6hKSz$ Y2Lb&L!NzlWjsO4v07*qoM6N<$f;UvYegFUf literal 0 HcmV?d00001 diff --git a/src/businesstemplates/templates/Phone Icon Template.png b/src/businesstemplates/templates/Phone Icon Template.png new file mode 100644 index 0000000000000000000000000000000000000000..5147ddd184ca4a03487616508820c4b275d6d06c GIT binary patch literal 1055 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 literal 0 HcmV?d00001 diff --git a/src/businesstemplates/utils.py b/src/businesstemplates/utils.py new file mode 100644 index 0000000..cef3311 --- /dev/null +++ b/src/businesstemplates/utils.py @@ -0,0 +1,76 @@ +""" +Copyright (c) 2022 That GenZ Gamer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the “Software”), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +""" + +from docx import Document +from docx.text.paragraph import Paragraph +from docx.shared import Pt +from docx.oxml.xmlchemy import OxmlElement +from docx.enum.text import WD_ALIGN_PARAGRAPH + +def change_text( + paragraph: Paragraph, text_to_change: str, font_size: int, is_bold: bool = False +) -> None: + ''' Helper function to change text and font size of a paragraph ''' + + # Changing the text + paragraph.text = text_to_change + + # Changing the font size of each of the runs in the paragraph. + for run in paragraph.runs: + run.font.size = Pt(font_size) + run.font.name = "Times New Roman" + run.bold = is_bold + +def find_paragraph(document: Document, text: str) -> Paragraph: + ''' Helper function to find paragraph with text ''' + + for para in document.paragraphs: + if text in para.text: + return para + +def insert_paragraph_after( + document: Document, + paragraph: Paragraph, + font_size: int, + description: str = None, +) -> Paragraph: + ''' Helper function to insert a paragraph after another paragrapoh ''' + + # Adding a new XML paragraph element. + new_paragraph_element = OxmlElement("w:p") + + # Adding the XML paragraph element after the previous paragraph. + paragraph._p.addnext(new_paragraph_element) + + # Create a Paragraph instance using the created XML paragraph element and + # appending it to the parent of the previous paragraph. + new_paragraph = Paragraph(new_paragraph_element, paragraph._parent) + + # Adding text to the paragraph. + new_paragraph.add_run(f"• {description} ") + + # Changing the font size of the paragraph text. + new_paragraph.style.font.size = Pt(font_size) + new_paragraph.style.font.name = "Times New Roman" + + # Returning the created paragraph + return new_paragraph diff --git a/src/requirements.txt b/src/requirements.txt new file mode 100644 index 0000000..65de0b7 --- /dev/null +++ b/src/requirements.txt @@ -0,0 +1,17 @@ +aiohttp==3.8.1 +aiosignal==1.2.0 +async-timeout==4.0.2 +attrs==21.4.0 +certifi==2021.10.8 +charset-normalizer==2.0.10 +easy-pil==0.1.4 +frozenlist==1.2.0 +idna==3.3 +lxml==4.7.1 +multidict==5.2.0 +Pillow==8.4.0 +python-docx==0.8.11 +requests==2.27.1 +typing_extensions==4.0.1 +urllib3==1.26.8 +yarl==1.7.2 diff --git a/src/setup.cfg b/src/setup.cfg new file mode 100644 index 0000000..38b60cc --- /dev/null +++ b/src/setup.cfg @@ -0,0 +1,41 @@ +[metadata] +name = businesstemplates +author = That GenZ Gamer +author_email = thatgenzgamer@gmail.com +description = An efficient command line tool to create resumes and business cards on the go! +long_description = file: README.md +long_description_content_type = text/markdown +license = MIT +keywords = Resume, Resume Generator, Business Card, Business Template, template, card +classifiers = + Programming Language :: Python :: 3 + License :: OSI Approved :: MIT License + Operating System :: OS Independent + +[options] +packages = find: +python_requires = >=3.7 +include_package_data = true +install_requires = + aiohttp==3.8.1 + aiosignal==1.2.0 + async-timeout==4.0.2 + attrs==21.4.0 + certifi==2021.10.8 + charset-normalizer==2.0.10 + easy-pil==0.1.4 + frozenlist==1.2.0 + idna==3.3 + lxml==4.7.1 + multidict==5.2.0 + Pillow==8.4.0 + python-docx==0.8.11 + requests==2.27.1 + typing_extensions==4.0.1 + urllib3==1.26.8 + yarl==1.7.2 + +[options.entry_points] +console_scripts = + resume_generator = businesstemplates.resume_generator:main + business_card_generator = businesstemplates.business_card_generator:main \ No newline at end of file diff --git a/src/setup.py b/src/setup.py new file mode 100644 index 0000000..8b8bfb7 --- /dev/null +++ b/src/setup.py @@ -0,0 +1,42 @@ +from setuptools import setup, find_packages + +version = "" +with open("VERSION.txt", "r") as version_file: + version = version_file.read() + +with open("README.rst", "r") as fh: + long_description = fh.read() + +with open("requirements.txt", "r") as requirements_file: + requirements = requirements_file.read().splitlines() + +setup( + name="businesstemplates", + version=version, + author="That GenZ Gamer", + author_email="thatgenzgamer@gmail.com", + license="MIT", + description="An efficient command line tool to create resumes and business cards on the go!", + long_description=long_description, + long_description_content_type="text/x-rst", + packages=find_packages(), + classifiers=[ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT License", + "Natural Language :: English", + "Topic :: Internet", + "Topic :: Utilities", + "Typing :: Typed", + "Operating System :: OS Independent", + ], + entry_points={ + "console_scripts": [ + "resume_generator=businesstemplates.resume_generator:main", + "business_card_generator=businesstemplates.business_card_generator:main", + ], + }, + install_requires=requirements, + keywords="Resume, Resume Generator, Business Card, Business Template, template, card", + python_requires=">=3.7", + include_package_data=True +) From 658ed1c01a9f76a07e3e9c762fcf8a4a39fd4fb8 Mon Sep 17 00:00:00 2001 From: ThatGenZGamer48 Date: Wed, 19 Jan 2022 13:28:02 +0530 Subject: [PATCH 02/10] Fixed bug in README.rst. --- src/README.rst | 6 +++--- src/VERSION.txt | 2 +- src/businesstemplates/__init__.py | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/README.rst b/src/README.rst index 79e87f2..7505ad7 100644 --- a/src/README.rst +++ b/src/README.rst @@ -25,7 +25,7 @@ Installing Installing this module is quite simple, -... code:: sh +.. code:: sh # Linux/MacOS python3 -m pip install -U businesstemplates @@ -49,7 +49,7 @@ Now you can design your own impressive resume Open your favourite terminal and enter this -... code:: sh +.. code:: sh resume_generator @@ -62,7 +62,7 @@ Design your sparkling business card in just under a minute. Open your favourite terminal and enter this -... code:: sh +.. code:: sh business_card_generator Enter the information through the inputs and you're done! diff --git a/src/VERSION.txt b/src/VERSION.txt index 6c6aa7c..6da28dd 100644 --- a/src/VERSION.txt +++ b/src/VERSION.txt @@ -1 +1 @@ -0.1.0 \ No newline at end of file +0.1.1 \ No newline at end of file diff --git a/src/businesstemplates/__init__.py b/src/businesstemplates/__init__.py index f0a40e1..9ffb602 100644 --- a/src/businesstemplates/__init__.py +++ b/src/businesstemplates/__init__.py @@ -12,7 +12,7 @@ __author__ = "That GenZ Gamer" __license__ = "MIT" __copyright__ = "Copyright 2022 (c) That GenZ Gamer" -__version__ = "0.1.0" +__version__ = "0.1.1" from .resume_generator import * from .business_card_generator import * From 67c4b9442707d217c8c57e8c8caf5f6d6f8ed9eb Mon Sep 17 00:00:00 2001 From: ThatGenZGamer48 Date: Wed, 19 Jan 2022 14:05:54 +0530 Subject: [PATCH 03/10] Fixed some bugs --- src/MANIFEST.in | 2 +- src/README.rst | 17 +++++++++-------- src/VERSION.txt | 2 +- src/businesstemplates/__init__.py | 2 +- src/setup.cfg | 8 ++++++++ src/setup.py | 10 ++++++++++ 6 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/MANIFEST.in b/src/MANIFEST.in index 1515a6a..b4f4ca7 100644 --- a/src/MANIFEST.in +++ b/src/MANIFEST.in @@ -1 +1 @@ -global-include *.txt *.md *.py *.docx *.jpg *.png *.cfg *.toml *.rst \ No newline at end of file +global-include *.txt *.py *.docx *.jpg *.png *.cfg *.rst \ No newline at end of file diff --git a/src/README.rst b/src/README.rst index 7505ad7..1fd14fc 100644 --- a/src/README.rst +++ b/src/README.rst @@ -3,10 +3,10 @@ businesstemplates .. image:: https://img.shields.io/pypi/v/businesstemplates.svg :target: https://pypi.python.org/pypi/businesstemplates - :alt: PyPI Version Info + :alt: PyPI version info .. image:: https://img.shields.io/pypi/pyversions/businesstemplates.svg :target: https://pypi.python.org/pypi/businesstemplates - :alt: PyPI Supported Python Versions + :alt: PyPI supported Python versions An efficient command line tool to create resumes and business cards on the go! @@ -27,11 +27,11 @@ Installing this module is quite simple, .. code:: sh - # Linux/MacOS - python3 -m pip install -U businesstemplates + # Linux/macOS + python3 -m pip install -U businesstemplates - # Windows - py -3 -m pip install -U businesstemplates + # Windows + py -3 -m pip install -U businesstemplates Other Required Packages ~~~~~~~~~~~~~~~~~~~~~~~~ @@ -51,7 +51,7 @@ Open your favourite terminal and enter this .. code:: sh - resume_generator + resume_generator Enter the information through the inputs and you're done! @@ -63,7 +63,8 @@ Design your sparkling business card in just under a minute. Open your favourite terminal and enter this .. code:: sh - business_card_generator + + business_card_generator Enter the information through the inputs and you're done! diff --git a/src/VERSION.txt b/src/VERSION.txt index 6da28dd..7693c96 100644 --- a/src/VERSION.txt +++ b/src/VERSION.txt @@ -1 +1 @@ -0.1.1 \ No newline at end of file +0.1.3 \ No newline at end of file diff --git a/src/businesstemplates/__init__.py b/src/businesstemplates/__init__.py index 9ffb602..35681cf 100644 --- a/src/businesstemplates/__init__.py +++ b/src/businesstemplates/__init__.py @@ -12,7 +12,7 @@ __author__ = "That GenZ Gamer" __license__ = "MIT" __copyright__ = "Copyright 2022 (c) That GenZ Gamer" -__version__ = "0.1.1" +__version__ = "0.1.3" from .resume_generator import * from .business_card_generator import * diff --git a/src/setup.cfg b/src/setup.cfg index 38b60cc..ecface3 100644 --- a/src/setup.cfg +++ b/src/setup.cfg @@ -5,10 +5,18 @@ author_email = thatgenzgamer@gmail.com description = An efficient command line tool to create resumes and business cards on the go! long_description = file: README.md long_description_content_type = text/markdown +url = https://github.com/ThatGenZGamer48/Hackathon +project_urls = + Bug Tracker = https://github.com/ThatGenZGamer48/Hackathon/issues + Source Code = https://github.com/ThatGenZGamer48/Hackathon license = MIT keywords = Resume, Resume Generator, Business Card, Business Template, template, card classifiers = Programming Language :: Python :: 3 + Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 License :: OSI Approved :: MIT License Operating System :: OS Independent diff --git a/src/setup.py b/src/setup.py index 8b8bfb7..5fdb912 100644 --- a/src/setup.py +++ b/src/setup.py @@ -4,6 +4,7 @@ with open("VERSION.txt", "r") as version_file: version = version_file.read() +long_description = '' with open("README.rst", "r") as fh: long_description = fh.read() @@ -19,9 +20,18 @@ description="An efficient command line tool to create resumes and business cards on the go!", long_description=long_description, long_description_content_type="text/x-rst", + url="https://github.com/ThatGenZGamer48/Hackathon", + project_urls={ + "Bug Tracker": "https://github.com/ThatGenZGamer48/Hackathon/issues", + "Source Code": "https://github.com/ThatGenZGamer48/Hackathon", + }, packages=find_packages(), classifiers=[ "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", "License :: OSI Approved :: MIT License", "Natural Language :: English", "Topic :: Internet", From 6f25dbaed9e298f38673f61d62137dd58cd9fdd5 Mon Sep 17 00:00:00 2001 From: ThatGenZGamer48 Date: Wed, 19 Jan 2022 16:16:24 +0530 Subject: [PATCH 04/10] Edited business card looks --- .env | 1 + src/VERSION.txt | 2 +- src/businesstemplates/__init__.py | 2 +- .../business_card_generator.py | 22 ++++++++++--------- 4 files changed, 15 insertions(+), 12 deletions(-) create mode 100644 .env diff --git a/.env b/.env new file mode 100644 index 0000000..ecefbcc --- /dev/null +++ b/.env @@ -0,0 +1 @@ +DOCUMATIC_API_KEY = d88cac5226b3452e812a3ba33f434464 \ No newline at end of file diff --git a/src/VERSION.txt b/src/VERSION.txt index 7693c96..341cf11 100644 --- a/src/VERSION.txt +++ b/src/VERSION.txt @@ -1 +1 @@ -0.1.3 \ No newline at end of file +0.2.0 \ No newline at end of file diff --git a/src/businesstemplates/__init__.py b/src/businesstemplates/__init__.py index 35681cf..3121e0a 100644 --- a/src/businesstemplates/__init__.py +++ b/src/businesstemplates/__init__.py @@ -12,7 +12,7 @@ __author__ = "That GenZ Gamer" __license__ = "MIT" __copyright__ = "Copyright 2022 (c) That GenZ Gamer" -__version__ = "0.1.3" +__version__ = "0.2.0" from .resume_generator import * from .business_card_generator import * diff --git a/src/businesstemplates/business_card_generator.py b/src/businesstemplates/business_card_generator.py index 5e80b46..aa4901b 100644 --- a/src/businesstemplates/business_card_generator.py +++ b/src/businesstemplates/business_card_generator.py @@ -69,9 +69,6 @@ def main(): else: print("Limit the length of the address below 30 characters!") - # Combing the designation and department inputs with a comma. - designation_and_department = designation + ", " + department - # Background of the canvas. # Open the background as a new Editor to work on it. background = Editor(str(card_template_path)) @@ -79,13 +76,14 @@ def main(): # Setting up all the fonts required. bold_50 = Font.poppins(variant="bold", size=50) regular_40 = Font.poppins(variant="regular", size=40) + regular_30 = Font.poppins(variant="regular", size=30) light_25 = Font.poppins(variant="light", size=25) bold_35 = Font.poppins(variant="bold", size=35) light_15 = Font.poppins(variant="light", size=15) # Loading all the images - phone_icon = Editor(str(phone_icon_path)).resize((50, 50)) - email_icon = Editor(str(email_icon_path)).resize((50, 50)) + phone_icon = Editor(str(phone_icon_path)).resize((30, 30)) + email_icon = Editor(str(email_icon_path)).resize((30, 30)) # Adding the texts. background.text( @@ -103,23 +101,27 @@ def main(): background.text((94, 50), name, font=bold_50, color="#000000") background.text( - (94, 196), designation_and_department, font=light_25, color="#000000" + (94, 196), f"{designation},", font=light_25, color="#000000" + ) + + background.text( + (94, 225), f"{department}", font=light_25, color="#000000" ) # Adding a line for aesthetics. background.rectangle((94, 159), width=754, height=3, color="#000000") # Adding the phone icon - background.paste(phone_icon, (94, 267)) + background.paste(phone_icon, (94, 287)) # Adding the phone number as text - background.text((153, 270), phone, font=regular_40, color="#000000") + background.text((148, 290), phone, font=regular_30, color="#000000") # Adding the email icon - background.paste(email_icon, (94, 337)) + background.paste(email_icon, (94, 330)) # Adding the email ID as text - background.text((153, 344), email, font=regular_40, color="#000000") + background.text((148, 335), email, font=regular_30, color="#000000") # Asking for the path to save the resulting file. path_to_save = input( From a108f3bb0743d99cc93ad9826d98478446602ed3 Mon Sep 17 00:00:00 2001 From: That GenZ Gamer <78960084+ThatGenZGamer48@users.noreply.github.com> Date: Wed, 19 Jan 2022 16:25:47 +0530 Subject: [PATCH 05/10] Delete .env --- .env | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .env diff --git a/.env b/.env deleted file mode 100644 index ecefbcc..0000000 --- a/.env +++ /dev/null @@ -1 +0,0 @@ -DOCUMATIC_API_KEY = d88cac5226b3452e812a3ba33f434464 \ No newline at end of file From 6717f5c821cdac4802cbcf1bab9d8a9a68cdccc6 Mon Sep 17 00:00:00 2001 From: ThatGenZGamer48 Date: Wed, 19 Jan 2022 17:41:16 +0530 Subject: [PATCH 06/10] Fixed path bug and changed resume generator a bit --- .gitignore | 3 +- src/VERSION.txt | 2 +- src/businesstemplates/__init__.py | 2 +- src/businesstemplates/resume_generator.py | 185 ++++++------------ .../templates/Resume Template.docx | Bin 14434 -> 14519 bytes 5 files changed, 62 insertions(+), 130 deletions(-) diff --git a/.gitignore b/.gitignore index 37b717a..de12afb 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ venv .idea/ .vs/slnx.sqlite env/ -test.py \ No newline at end of file +test.py +.env \ No newline at end of file diff --git a/src/VERSION.txt b/src/VERSION.txt index 341cf11..7dff5b8 100644 --- a/src/VERSION.txt +++ b/src/VERSION.txt @@ -1 +1 @@ -0.2.0 \ No newline at end of file +0.2.1 \ No newline at end of file diff --git a/src/businesstemplates/__init__.py b/src/businesstemplates/__init__.py index 3121e0a..e26eeae 100644 --- a/src/businesstemplates/__init__.py +++ b/src/businesstemplates/__init__.py @@ -12,7 +12,7 @@ __author__ = "That GenZ Gamer" __license__ = "MIT" __copyright__ = "Copyright 2022 (c) That GenZ Gamer" -__version__ = "0.2.0" +__version__ = "0.2.1" from .resume_generator import * from .business_card_generator import * diff --git a/src/businesstemplates/resume_generator.py b/src/businesstemplates/resume_generator.py index 927d7f2..7cff1b9 100644 --- a/src/businesstemplates/resume_generator.py +++ b/src/businesstemplates/resume_generator.py @@ -129,10 +129,21 @@ def main(): print("You haven't mentioned a city!") exit() + # Asking for the user's address + address = input("What's your address?: ") + + # Changing the text of the user's address and setting the font size using an helper function. + if len(address) != 0: + address_cell = information_table.rows[3].cells[0].paragraphs[0] + + change_text(address_cell, f"Address: {address}", 12) + else: + print("You haven't mentioned an address!") + # Asking for the user's introduction objective = input("Write your objective to be mentioned in the resume: ") - # Changing the text of the user's introduction and setting the font size using an helper function. + # Changing the text of the user's objective and setting the font size using an helper function. if len(objective) != 0: change_text(document.paragraphs[3], objective, 12) else: @@ -144,14 +155,14 @@ def main(): # Asking for the highest qualification highest_qualification = input( - "What is your highest qualification? [Employee/Post Graduation/Graduation/Class 12]: " + "What is your highest qualification? [Post Graduation/Graduation/Class 12/Class 10]: " ).lower() qualifications = [ - "employee", "post graduation", "graduation", "class 12", + "class 10", ] # Exitting if the qualification selected does not exist in options. @@ -162,131 +173,8 @@ def main(): elif len(highest_qualification) == 0: print("You haven't mentioned your highest qualification!") else: - # Asking for post graduation, graduation, 12th and 10th details - # if the user is an employee. - if highest_qualification == "employee": - employee_pg_institute = input( - "Which institute did you pursue your post graduation in?: " - ) - - change_text( - course_details.columns[1].cells[1].paragraphs[0], - employee_pg_institute, - 12, - ) - - employee_pg_year = input( - "Which year did you complete your post graduation?: " - ) - - change_text( - course_details.columns[2].cells[1].paragraphs[0], - employee_pg_year, - 12, - ) - - employee_pg_percentage = input( - "What was your post graduation percentage obtained?: " - ) - - change_text( - course_details.columns[3].cells[1].paragraphs[0], - employee_pg_percentage, - 12, - ) - - employee_grad_institute = input( - "Which institute did you pursue your graduation in?: " - ) - - change_text( - course_details.columns[1].cells[2].paragraphs[0], - employee_grad_institute, - 12, - ) - - employee_grad_year = input( - "Which year did you complete your graduation?: " - ) - - change_text( - course_details.columns[2].cells[2].paragraphs[0], - employee_grad_year, - 12, - ) - - employee_grad_percentage = input( - "What was your graduation percentage obtained?: " - ) - - change_text( - course_details.columns[3].cells[2].paragraphs[0], - employee_grad_percentage, - 12, - ) - - employee_12th_institute = input( - "Which institute did you pursue your 12th grade in?: " - ) - - change_text( - course_details.columns[1].cells[3].paragraphs[0], - employee_12th_institute, - 12, - ) - - employee_12th_year = input( - "Which year did you complete your 12th grade?: " - ) - - change_text( - course_details.columns[2].cells[3].paragraphs[0], - employee_12th_year, - 12, - ) - - employee_12th_percentage = input( - "What was your 12th grade percentage obtained?: " - ) - - change_text( - course_details.columns[3].cells[3].paragraphs[0], - employee_12th_percentage, - 12, - ) - - employee_10th_institute = input( - "Which institute did you pursue your 10th grade in?: " - ) - - change_text( - course_details.columns[1].cells[4].paragraphs[0], - employee_10th_institute, - 12, - ) - - employee_10th_year = input( - "Which year did you complete your 10th grade?: " - ) - - change_text( - course_details.columns[2].cells[4].paragraphs[0], - employee_10th_year, - 12, - ) - - employee_10th_percentage = input( - "What was your 10th grade percentage obtained?: " - ) - - change_text( - course_details.columns[3].cells[4].paragraphs[0], - employee_10th_percentage, - 12, - ) - # Asking for pg, ug, 12th and 10th details if user is an post graduate. - elif highest_qualification == "post graduation": + if highest_qualification == "post graduation": postgraduate_pg_institute = input( "Which institute did you pursue your post graduation in?: " ) @@ -571,6 +459,49 @@ def main(): class12_10th_percentage, 12, ) + # Asking for 10th details if user is a 10th grader. + elif highest_qualification == "class 10": + change_text(course_details.columns[1].cells[1].paragraphs[0], "NA", 12) + change_text(course_details.columns[2].cells[1].paragraphs[0], "NA", 12) + change_text(course_details.columns[3].cells[1].paragraphs[0], "NA", 12) + + change_text(course_details.columns[1].cells[2].paragraphs[0], "NA", 12) + change_text(course_details.columns[2].cells[2].paragraphs[0], "NA", 12) + change_text(course_details.columns[3].cells[2].paragraphs[0], "NA", 12) + + change_text(course_details.columns[1].cells[3].paragraphs[0], "NA", 12) + change_text(course_details.columns[2].cells[3].paragraphs[0], "NA", 12) + change_text(course_details.columns[3].cells[3].paragraphs[0], "NA", 12) + + class10_10th_institute = input( + "Which institute did you pursue your 10th grade in?: " + ) + + change_text( + course_details.columns[1].cells[4].paragraphs[0], + class10_10th_institute, + 12, + ) + + class10_10th_year = input( + "Which year did you complete your 10th grade?: " + ) + + change_text( + course_details.columns[2].cells[4].paragraphs[0], + class10_10th_year, + 12, + ) + + class10_10th_percentage = input( + "What was your 10th grade percentage obtained?: " + ) + + change_text( + course_details.columns[3].cells[4].paragraphs[0], + class10_10th_percentage, + 12, + ) else: pass diff --git a/src/businesstemplates/templates/Resume Template.docx b/src/businesstemplates/templates/Resume Template.docx index 37d835cf106bc1e72614233a5a65ba72860536ea..18928e8b292518d1d40321dc91335fc312008005 100644 GIT binary patch delta 4419 zcmY+IRa6v=7KLdTa%cqUF6p5`l#y;2kdl_}6vjaW1nC*1q#LBmp+Q1QYG|Z}?vO^{ z{{PEe_nybS&e>1CaC_)Ao17bX*-l}3AH((T&8ap!V%25B9w0&&y}BOE;+>IFeRZPhse zDz;!!D6svH1p};rKxin~!nM8h(dpP35MvbSa5Jyx{b`E#eVMr<}VV0-hNA z?)DR$kQ33po5G_~_K`H#v3=v#;GNC$+Wl+qbMXAK zXOn)9VNr{yH;5q>>(BU@=#c9n`RjG4a9ZFL+n#7depO8kWQ=EBGtuW)RbHL5e!urC zK_e93rZcR>!hmuDC}v&oegQRHRzp-`wMGsxK=GTlW=s*Mt5zGwnPw#bNkv-!);Qf$ z1PV?U0|2$AR{8>bUSzl&`6R9~yS4j0s=Ga3L|-TnDE9y!W8En@8{vs6k}~^0?ThLX zgILlyMd>m_n$nO!GKi|+kLEwaCVs&qC}+q-IZSP|f1Hf>rBV@D$bfTHDQ(XQh*GGd z7s{0lu98pNc`DYKX*)|^jM}Si_{>$>f5I`#>PK$^OoqH+^ZnvGGvv1Hx`&R61s)pN zfysJ{{EFh+BE}#Eg$m>+T$n98;}<-FQ1T)hxuuHJ5kr630^{ zFd}L-9XNVa*CUnx%ey;B>4kHVvk*zCNNOKRGoD#U|EqZso8Ojkl&V@yK3EA3BT#yHxUZG{dMq#J(@l?W zNwMR$aZfsmfI&@fVKwQ9@Q|iObY#S?#}i3cec#Q{mPGAPs6+vg zI91ihjs8a`)7bwm}hEu8x&*y(rwl)EjhT5vUJRe|+( zStrMNg7VB#V3DQ`e)Vu5eDLQNbC-WE$BjJPT6FIyMg|&;T zwat!yZX2sa+8@tA2*P~*;iSxTX|mTm3~3F;Q-OtDZDI=x@gJ?J-0+^hq_n8b3XH)R z(e*+tJy|uNdXQCN%$Nt9ZxU+_kEB!uf6FTV6C+fMVmyy6gHO+DPu=#G$lju5zOOUN20LVtA|b9W9LS`H2n0-P=j_JQlXUK|+=06^~Jjm-=NCFE0sfL{>lCofcU(PmuGfPz0O5&rslh-F1z*W5QX4%4daKo1|$+1)QCLOs06?Y!CA!)qP zuw$CX8IFL}(P*3(SV=_TFpl8@o6dKjx@0-tT_r5mApNrq|LiIG+o6gOF)cL&oRI?v z=i=0I&r?%_!x=b$cS#(rPv5a|D=7UWnIF%e=CiL%E3v2iRzVZr%~hlFF!{J|b*?AU zK@ykbbbi68UE4P5lyP4xvS&uSB`h{CIb*gNH*c_Tf9!FbbB&FHvEav9wwuge-klwt z&U~|F<`a2kTmN?NuvU7<4A-l_SO2`bWUWX9)G~>wbAYj55EN8q(l7O>oS=Md6)uFA z6|ZL7vUJRs`IdN}w1(XgVeNbXjq(A$rMXiRmnAZCt$`8MI*;x`8{eBIq~^|ZcZpL_ z=?68BjLDs@x9{hxNeQ++tFQmLKlv03f6~jvG>f`~AW74!iKT5or@3m*+6qtiZycvf zPakRBJUMsqBFXAF=Vj)7xU4ii|JE;$K95zReORa0r6S^yfV!Ta41xy`U)SMvz`?*k zAwE;n!xrNgK|rX`I86B5yqYt;#UzSypl;f=M*DN%9cHrfVy}APbNx#hrN{OHBI9Ke zN>_%B!KuvVu|%==e~xPTxVhOlHeH>hC7UEz1-5bRKNVeEL1joPqYcxjksGlBl|)H1 zt=~HzFSnkm7Z49nvk#L}77U=f=n)c|bIF>nNR$mgDlALzWY66tE^ z3ddI(<@^4$Q@uQCWPzfP*97!{)0MDx?tAz?nqS`8eY*92#g2v9)24Z?Kj5YDIWexF^?Y z(gn@J8PWFi#?xu#4PAyEr^O}*LES`ocXhvn`Yg0WO{VZQ5Q&}1T-(*mW@EhmbTY-W z7)MCrO}C==m*5vshjo)4(D8uHz${HNChFf>`dt8z={_Ur=@hhRkX*m*Ou3kUAz0o*T;RISDc6fdt zVR~ZoVV_F@zKv@Dj>gE^CC7;v6fU2}jfvm{#2ELKh^Hcs`xV+30Bc?nl^h$F8P z@PfUr30qNu)rIzUDDC3~mnW#d%`KB9K5lyXIrWQzCX(wE`qlshl7B31Lfmty?+U0W z!JbFCkd^hCth=%@-yi#0W5?hQN2lD9t=ou;C);(A(R#+)4s8ui?-#>@y-YA?Z{~Hx-Mj>m|Vgj`8kN&~J z+hkWSi>qocf6o+%8kx!_tbwdFtQre4c*HJ?#NP5xTeMxmA6*;>4VH=(H%3)mZ)Jd( zom5fds(-|PF*tP;-v}NO_~<4l%Xe9g|4ixFwjUfT3{*s~B;IliuvZPXth~-`57ePc zp_7&dZ;&@J=P1?aJFL>a3gg-s|W6m1Q9*o`N5f=`is%N8jC&l@;rc+;^ z%)^Zd)6@AO4E(vG^_Ns*MdiB^@iSWv=RkO`a%}(i1t#73g<^TSkl@xh6561X!>X&+ zM~g={kYWnh6Jx&+B1VzGMiGiORc%a9`aaE;3GZSx2%|Rbj?L^!3VI)m@IrXIt@Sx$ z({LiY_<2*k#n{c15&C=AH0oQgvUNL@phVY>zzVy$Y` zQFz!D+`%K})pJim+~nNxi9jk8QH+&FKx1CnUp9?sZfxU;syUPjcW_O4xt@f(ZYNAr zF=ed!m(j~I=W3}$IZ8QjH15We_HYI7yK0ZsIi{=Vgl62xg)NQ2O8<9pnCs@p)F3;U zaV2!6yKE97RV^|g$JOP1D3HKh9f0E1I)r>L6|D? znEOysxkKoN1^Aip%h2<3@k1N8Mi<-6Ueg208#?`mdu;{BPoV(u#%UV<&pz?@TN@L> zAwG8%L>}yde8QA8msneB>{dmZAZwk3m~Z5N#=Yv%xOCFiX3+=!w>Ky)3GHsFbH~o^ zS{lj}S>t#pGx(XrPp0HaU6?5Dx8?%luQwTsIs0eoq0gEPG>mw@Ulg#=)oJ%<7hpM+ zhyTU0sVwsP^?qe2jH=tJO8s}4(RQhkm2nX+EBS7Y-^89%)kusc9W#LwrvOV~m5L(D zXi9bBQrOXpvwPY6~*8n}DjISU)KJGJ%keJ za#VYLRm5WwD4jaauVBhshCbqN1T3RRc;K;k0r<*QkIIEXBxYHEqDQRUzBEW6D8(t* zJePFKoO)>|#%ti0bn%Ar!_zkc=!f8%Yb8d@9M`~n1JWuYnTTq}zc1rN*CR|#{eDoy z^b=l04L+R!r*x^aTF$VXiWn$+ojoHtV-ZVSM%@Fb0xXOhB$=~lm_u!txLXGnv#Be2 z+p777m(*OQBCmBSC$v0oiT+t+94pL?je1Q{E=*Xr`=T&$JK3BfU5n&rRD&ZnxG&LW z$Jz|L*KI6AllzCATB1q8{A@xKgU-BvhR$))6pEcUruF*_4P&oen_0a#=q;|)q09QE z%cUW-18EI@vFU8z{!v2qg-yWOI(}`O!gFQpG8RDU%t0s}B$FE&3MqP0#Ar{?Y!;!s zo(;Pz7NI|CfA7}K`etN%_USUvoa6$WhBIG^+&h7RU8;j&yUj9qlZgB2qeqBU2^}jd+&$bdtQ(L7FBd=C4z()18&PIUzgq_HAFNt8WXum{WgT6=g!rv5 z=05$EsuP9xmt8($XywXd9U8ga?Yb|7N7kAvezIEoRRR~(@&n~sJ4AQROz zTT<^%c2Tx1hxYl6;u02zg01hJSG%go%N1`ww6Ke_#XgPEr9g8PP1s u`Sia80$^ZJ{I4s9oG{{6l7r#j#4Y|~v-A(bfdAK!fRL7A$IF%YSNsou?m<@o delta 4387 zcmZ9QcQhM}*T-XT4Y6udY6~@6L}S&SF;aW)*dvsvO;Dt?rFN@!5v?et_G;}JN*kjn zHEXN4&wJkAdEWE8f8BHMJ@>DBzTeNe%>e}edL}Arn#u^O4Ke_rABy3o5B5kAdA{YuF~G>1nJH_|of#s)Rd85PX5=t@c68>>=Fyzl z1JR;WLHTU3YtV;At;!w!bUdjj_m(CbAS2SMFIn!ix_)$iVqfGI!m2b0(leePQyQaIDIg!6Kcwqckt-aDK!0oWnz#XZOrMbp zYTk?Wk$KBGp#ucUtW(lHr(^2{sphpdRLjpO>f|ie1rg+FC!(>!_9#45U-P%RPa`Ak`z%{47^9JTzX2baOPaZ`6WZ>Zum`4 z>^*1ku(2_^GMlQVJe0W#^KUBFb?aV4Z4Q-^KW#bDn#6SIyobd^E`;@+H#7DjNJb;7 z3(Z6C-9ZLb51WgP*BA{D$x45PW=MxqB;8dxQfKp4QJf@KB-IY(Oc_0en44DVARjHS zuf*3FXEy?P!8y?2VBeqs$rs|!-~y_va+XEM&!;yxfr$)dDDH~i_bHJyIXi)E8#2_{ z{5NH&eIi&t1rzuvF4Ioyno{IYt_D79H#vnPSQ|WIM0(+eWPJ*o4rNnJU;7{_n*gi{ z(vI%FX}-ey04cgNdCdDa#N%Y&4_OvG8u1;CxkdoEY+?QoSjFNF*TjtJ>xWOtCDCX> zzFg6Xtf%7ZC}S*4ayIWqV1=~=>;t@IV_r*3^zZhO1hwP=9&sQD~(DV_dX&&m5Nq&yT>569=hk?|+or*GPKKi=N;Wk~C# zwL#3Iz$857Ii;dGbWdE=y9C-Y!>AOn9<9zWG5%Lz&)=7jtzR}DCVr{U@d{sVML6U? z?B|rPrHLea=APNH%YjW$yZdQN9M68}}IqqeZgHGvZ8UMTV8sGaU3Y zVU(0Nav#JfF{=icH!UHW{*3P>6Z1e%_J#M=LM>Yf$57b?*miM@v23MBAf16|Hf*sN z6*HGEfNa<)TVIYz(PCTPI|2GqQwn*jMw(KqvCLeL_|qsVn7ZO;H4rmqqRda?p6zWg z9n=yAXToa~KQ-M?O>%L|S~+aauG3O2R=--9etTP@#RoPlc&lTm)wLrbET!9N$TgGx z^5yl<>2GMa=%4u{!`tt^oNSd(bL7PpqM{JLSzlf`pr#;JwzcyYe*&;8Mm7Yov5lDn zxw4SGr_tu$7SUJZyh&zf`tx^4_T){*!Q5R!I~9<^)`zLjp?X*ZqIGrmas!)38!KaLQyNS`Xukkp*IQA?bcX?{|C;r+!1|HQ_C-%JzPmW#FG-UHX^IF(k=VhCKIX@UYCl#KfkG}IzXhG z!E^vo+jdGS@*;eQBE5iwJkROXJ-@ntE+M(*J=SuDa!|Y?%cf$&zPMpQj+%IzbPz}i z0JP8o01N;CAj~h&1svoW9PEj350VV`^=Y#7^;?h!{((4LcaHtIo9prsUST!>erVRS zW9+UPlkJgDDM&5g+Rt^o9QLYbPN#+6dfce|S4$Z8?#S+v>U3~$j}36{sA|P_^di8GPOg?KT3%>ShREqB_5j{mDg4%THQlE;lfX-q9k4%-y&dzToo^Ae zGL7xAUNj??a2I4DmaHi6gHG7cQY;HcypJMzp9Fj-3Ouoi`f#j#=|_EONlhB1C!i8+ zM4b_CFQm>E@?vR+qt66dBFguYA$)aF4Ib@U!(A}Ja>)3L+zTI4kV4FR%cnU<+bKp9 zEi$cXXPS2ZyU15m5KJA(o|;>^M;`)%6g!E*Y4jhEM)&_IZdB&Y&`mjeuPNwZ-KZ6) zMQ7g&k#31M{oxOaiK{do(@ z6gk)>3W{_rw8nzK>I&E;8%7+mzKIVGOw@7HZ1nK$*wI`cC9eK_CuJtUNz($sxhC(j zrvBUNmTj%GpYN9uJR18s;*Iw}h|~0YyL0qd9;!h3xNI>)z>cu>q3{UUhP`JV^ydb` zu*x%I%g!lfD;6Y+uP|^ZRiyrd<4y0Rp)I4czqL>&^(}mnq*Uwax|BI>F}TD~j33Xu zv?=qIx4mP7OA(ht4ccD8O3E=vUl(BOcE&*ue3xnI(5$3!0-mcXm2|ejy))W!QfY6C zQFWCNo|chGL6tW!HM2?eHSW#z3S@vx`^A({>#IlA>^w`w?{_ZT8&1~g1ux=`V8fU_ z^Ukgc)zpuw4()xH+><;Nuq>hzf85w3^;SYYJN`(GhE@VMrlw8|WGa9Q+3$(!OE-h%VA}jL8g`UF8BuF!e6%j{8ct=l*R`@`lk1Jfr*Gbl*I8*C z+Y0H(61%ij64?GNn{C!MYu?AzMAcSE%gT`2XJ_7WhjCK*5i73s+I`TCq!j^{B8mRO z=Fc;ZgmpOZN~KNhuxRC&2Y~fwkEJK2lg#SJ9t#T*p*jt_rDzj(wcFHlBA=D3OI6ir z$AmgDGOF_;`1ZA|@-o4UHU= zFV_z_NJIOh7@fYylm+zKP`S6koq7_aIQ}9xsz$#3t)o4MP}CTk3lZj9f*DJU;|>QH1pP!Hk0-0}4(hO`OG{cAR~bndCk$Qo$5 zS$riG&%J8ne21v4qT3R4o|>ns8Qpt-Z7L-vv&;8Nm@@HIj`WX;``MIzD1aE#Y~9i> zholKZ(-#dynAh4}FTv*_h?oHH{m;7c5vkNyqM$wsHC-tZ7RK4`?k47GQ=AGdYU@R| zA8{Olc)U8s36lhiD-lcCYhb+5J5cj_HwR?Ee4D%3i>xu@2P|%luUsBxs3Y}>f!y4@ z%prLcD#aiDF4J|&%Fa`krtJ1hW5Lx>R=MH|1Y?W8_(HG3RB~1MZCB0Il&(7BDNpc( zhMMejw7@;9$>k^Y58c~%sFrIxQGVxiF(g2}65Q|T{fP@(%jh)icxSewERD3VclFi<QaBt?u=x|FUW}p9_D!_b0)9$8_c!c zl>Jf5vRd5*vtS9uRdnO!z<1`(X=D3@l+5(BpY+$ynvOrrJ}ay;Ji9#~&b zjCeh%{f4oGap%3MBC?ysA#&ZS_=+NRX9&D zqnz zo%42e)VmtinkS9D4o!|UzCwfz9i88^2`e7&=YLVu^p#Aky_)oDO1{QyTsX-`pCg@U zAyaB-s95mVAh$zdu5-{=G-szP!GV^Y(!PpA^i@(~L^mqA;D-|hUD=erVcoXP$_rUN>WLpr`kDXe8m_TDNFyf^j2~PDo=icT zR8&8PP*jZGMNyoiBiOGk?%I#&o+pCtU2Fi$m$m;8WAfzi|NpfREpJ4`g&C0-=J;>; z{3|H`7eN>X1qcxn##jML59jy~mIfnzTrs=~%pCtX1Cj^;IR7g}|4{3{5sMjBfDqpi z!_KgIt6P^J-- From 27d0d8ae7a8cbb102ac0fcedba11e0d9589143fd Mon Sep 17 00:00:00 2001 From: ThatGenZGamer48 Date: Wed, 19 Jan 2022 21:01:18 +0530 Subject: [PATCH 07/10] Added CHANGELOG.md and technical_doc.md --- CHANGELOG.md | 30 ++++++ src/VERSION.txt | 2 +- src/businesstemplates/__init__.py | 2 +- technical_doc.md | 162 ++++++++++++++++++++++++++++++ 4 files changed, 194 insertions(+), 2 deletions(-) create mode 100644 CHANGELOG.md create mode 100644 technical_doc.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..f1938fa --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,30 @@ +# Changelog + +Based on KeepAChangelog. +Generated by **Documatic.** + +## Unreleased + +## 0.2.1 - 2022-01-19 + +## 0.1.3 - 2022-01-19 + +## 0.1.1 - 2022-01-19 + +## 0.1.0 - 2022-01-19 + +## show - 2022-01-19 + +### Added + +* Business card generator and resume generator script. + +### Fixed + +* Bug in readme.rst. +* Some bugs +* Path bug and changed resume generator a bit + +### Removed + +* .env diff --git a/src/VERSION.txt b/src/VERSION.txt index 7dff5b8..afaf360 100644 --- a/src/VERSION.txt +++ b/src/VERSION.txt @@ -1 +1 @@ -0.2.1 \ No newline at end of file +1.0.0 \ No newline at end of file diff --git a/src/businesstemplates/__init__.py b/src/businesstemplates/__init__.py index e26eeae..b5c5998 100644 --- a/src/businesstemplates/__init__.py +++ b/src/businesstemplates/__init__.py @@ -12,7 +12,7 @@ __author__ = "That GenZ Gamer" __license__ = "MIT" __copyright__ = "Copyright 2022 (c) That GenZ Gamer" -__version__ = "0.2.1" +__version__ = "1.0.0" from .resume_generator import * from .business_card_generator import * diff --git a/technical_doc.md b/technical_doc.md new file mode 100644 index 0000000..c210700 --- /dev/null +++ b/technical_doc.md @@ -0,0 +1,162 @@ +# businesstemplates Technical Documentation + +**Last updated:** 2022-01-19\ +_Document generation aided by **Documatic**_ + +An efficient command line tool to create resumes and business cards on the go! + +* [Introduction](#introduction) +* [Code Overview](#code-overview) + +## Introduction + +This is a technical document detailing + at a high-level + what businesstemplates does, how it operates, + and how it is built. + +The outline of this document was generated + by **Documatic**. + + + +## Project Architecture + + + + + + + +## Code Overview + +The codebase has a flat structure, with 4 code files. + +The codebase is compatible with Python 3.6 and above, because of f-string 3.6 in /home/tom/Documents/documatic/test_projects/Hackathon/src/businesstemplates/resume_generator.py. + + + + + +`businesstemplates.resume_generator` has a `__main__` entrypoint, which calls: + +* `businesstemplates.resume_generator.main` + +`businesstemplates.business_card_generator` has a `__main__` entrypoint, which calls: + +* `businesstemplates.business_card_generator.main` + + + + + +## Entrypoints + +There are 0 source code entrypoints in top-level `__main__`/`__init__` files. + + + + + +## Concepts + + + + + + + +## Developers + + + + + + + + + +No CI/CD config files were detected. + + + + + + +### **Hackathon/** + + + +#### resume_generator.py + + +File has 871 lines added and 127 lines removed + in the past 4 weeks. ThatGenZGamer48 is the inferred code owner. + + +resume_generator.py has 1 functions. + +```python +main() + +Prepare a nice (custom) ASCII art to show before the start of the inputs. +Does not raise. +The function is complex so cannot be summarised easily. +``` + + + +#### utils.py + + +File has 76 lines added and 0 lines removed + in the past 4 weeks. ThatGenZGamer48 is the inferred code owner. + + +utils.py has 3 functions. + +```python +change_text(paragraph: Paragraph, text_to_change: str, font_size: int, is_bold: bool = False) -> None + +This function takes a paragraph and a string of text to change. It then changes the text in the paragraph to the new text. It then loops through each run in the paragraph and sets the font size and font name to the new values. It then sets the bold property to the new value. + +Helper function to change text and font size of a paragraph. +Does not raise. +``` + +```python +find_paragraph(document: Document, text: str) -> Paragraph + +Helper function to find paragraph with text. +Does not raise. +``` + +```python +insert_paragraph_after(document: Document, paragraph: Paragraph, font_size: int, description: str = None,) -> Paragraph + +This function inserts a paragraph after the paragraph passed as the first argument. +The font size of the inserted paragraph is the font size of the paragraph passed as the first argument. +The inserted paragraph is a copy of the paragraph passed as the first argument. +The inserted paragraph has a line that + +Helper function to insert a paragraph after another paragrapoh. +Does not raise. +``` + + + +#### business_card_generator.py + + +File has 148 lines added and 10 lines removed + in the past 4 weeks. ThatGenZGamer48 is the inferred code owner. + + +business_card_generator.py has 1 functions. + +```python +main() + +Does not raise. +The function is complex so cannot be summarised easily. +``` \ No newline at end of file From a6dd54c5032e798e7ba45076871f6cd4a910ed5e Mon Sep 17 00:00:00 2001 From: That GenZ Gamer <78960084+ThatGenZGamer48@users.noreply.github.com> Date: Sun, 3 Dec 2023 19:11:43 +0530 Subject: [PATCH 08/10] Delete examples directory --- examples/doculog.md | 241 ------------------------------------- examples/technical-docs.md | 125 ------------------- 2 files changed, 366 deletions(-) delete mode 100644 examples/doculog.md delete mode 100644 examples/technical-docs.md diff --git a/examples/doculog.md b/examples/doculog.md deleted file mode 100644 index 3e9ab0f..0000000 --- a/examples/doculog.md +++ /dev/null @@ -1,241 +0,0 @@ -# doculog - -## [Demo Video](https://youtu.be/zpPjkhckFMQ) - - -_README generated with **Documatic**_. - -Quickly generate changelogs -and release notes -by analysing your git history. -A tool written in python, -but works on any language. - -## Getting started - -### Requirements - -* python >= 3.8 -* git -* "good" commit messages -* Git version tags - -Minimum python 3.8. -Project actively supports python 3.8, -3.9, -3.10. -To install, -clone the repository -and run `pip install -e .` -to package locally -OR -`pip install doculog`. - -`Doculog` works by reading git commit messages -and inferring what changes are being made. -It assumes that you are writing -your commit messages as actions: -e.g. "_Add_ some feature", -"_Fix_ a particular bug". -While it's good practice to have the action -in the present, -imperitive tense, -`doculog` accepts past verbs. -See [git best practices](https://cbea.ms/git-commit/#imperative) -for more information -on this git commit writing style. -Standard `doculog` looks through a list -of expected verbs -(open an issue/contribute a PR if there are some missing!), -but the [extended version](#api-key) -includes additional logic -for classifying commit message, -which allows you to be more lax -with your commit messages. - -### API key - -To generate a changelog -with a full feature-set, -doculog requires a (free) -API key. -Join the waitlist -for an API key -by joining our [discord server](https://discord.gg/BcbY3GXtUZ) -In the meantime, -doculog **works without an API key** -(you just won't have access to advanced features). - -`doculog` uses `python-dotenv` -to load environment variables -stored in a `.env` file. -To use your API key, -create a `.env` file -in your project root directory -with the following fields: - -``` -DOCUMATIC_API_KEY = -``` - -**IMPORTANT: DO NOT ADD `.env` TO VERSION CONTROL. -YOUR API KEY MUST BE KEPT SECRET.** - - -### Generate a Changelog - -In a terminal, -run `doculog` -to create -a `CHANGELOG.md` -from your git commit history, -or update an existing changelog. -The "Unreleased" section corresponds to updates -not attached to a version. -Each changelog update version -may contain the following sections: -"Added", -"Removed", -"Deprecated", -"Fixed", -"Changed". -Each section header will only appear -in the version -if it has at least one update. -**Note:** `doculog` will overwrite changes made -to the "Unreleased" section -every time it is run, -however tagged versions are not overwritten. -Therefore, -you can manually edit -and add updates -to a version release. - -To get the best out of the changelog, -read the concepts below -for information on -[configuration](#configuration), -[git commits](#git-commit-parsing) -and [version tags](#version-tags). - -## Concepts - -### Git commit parsing - -The initial logic for generating a changelog -comes from reading -your git commit messages. -`doculog` -expects -commit messages to begin with an imperitive verb, -and to written passively. -`doculog` parses the message for signalling words -and phrases. - -E.g. `Rename 'my_func' to 'my_awesome_func'` -will get interpreted as a "Changed" feature. -Whereas `'my_func' -> 'my_awesome_func'` -will not. - -### Version tags - -Changelogs break down your project's featureset -by each release. -Currently, -`doculog` infers a release has been made -by reading the git tags of your project. -If you don't have any git tags, -your changelog will only have an "Unreleased" section. -To make a git tag, -run `git tag -a v--` -(and `git push --tags` to push to your remote); -This assumes you're using [semver](https://www.mariokandut.com/what-is-semantic-versioning-semver/) -versioning system. - -**Note:** not using semver or git tags to release your project? -Open an issue on the `doculog` repo -detailing your method to get it supported -by `doculog`. - -### Configuration - -You can configure how `doculog` runs -by adding a `tool.doculog` section -to `pyproject.toml`. - -| Field | Purpose | Required | Default value | -|:------|:--------|:---------|:--------------| -| changelog | Name of changelog file generated. ".md" suffix added if not present. | No | CHANGELOG.md | -| project | The name of your project. Used to title the changelog | No | The name of your root project folder | -| local | If `true`, use a local sever for advanced features. Only used for project development | No | false | - -For example, -your `pyproject.toml` file _might_ be: - -``` -[tool.doculog] -changelog = "CHANGELOG" -project = "My Cool Project" -``` - -## Developers - -Read the [contributing guide](CONTRIBUTING.md) -for information on coding styles -and workflow. - -Run `pip install -r requirements-dev.txt` -to get developer requirements. - -| CI file | Purpose | -|:--------|:--------| -| `test.yml` | Linting and unit testing. Runs on every pull request | - -## FAQ - -### I want more intelligent featureset generation. What can I do? - -Request access to the free Documatic API -to generate a changelog -driven by machine learning. -Follow `Documatic` on GitHub -and socials -to stay up to date -with the latest features -and releases. - -### How do I get my API key? - -Once you've joined the waitlist, -we will be in touch shortly -with your API key. - -### The changelog is great, but I want more! - -Get in touch - `info@documatic.com`. - -### I'm not getting a complete changelog. What's gone wrong? - -Check that you have appropriate [version tags](#version-tags) -and [commit messages](#git-commit-parsing). -If you have the advanced featureset -(i.e. have an API key) -then you will get better changelog updates -which don't require you to follow -the commit process -so strictly. -If you're still not getting good results, -please open a bug report. - -### Can I contribute to doculog? - -Absolutely: -feature requests, -bug fixes, -bug reports -and PRs of all shapes and sizes -are welcome. -See the [developers](#developers) -section. - -_Generated by **Documatic**._ \ No newline at end of file diff --git a/examples/technical-docs.md b/examples/technical-docs.md deleted file mode 100644 index 6e8fccb..0000000 --- a/examples/technical-docs.md +++ /dev/null @@ -1,125 +0,0 @@ -# Technical Docs - -## [Demo video](https://www.youtube.com/watch?v=m6Oo3HRY9IY) - -# API key - -To use all features of Documatic tools, you will need to get a (free) API key. All hackathon participants get a free key, join our [discord server](https://discord.gg/BcbY3GXtUZ) - -To use your API key, create a “.env” file in the root of a project you wish to document, and give it the following field: -``` - DOCUMATIC_API_KEY = -``` -**DO NOT ADD THE .env FILE TO SOURCE CONTROL. DO NOT SHARE YOUR API KEY WITH ANYONE.** - -
- -# Technical Docs - -Documatic automatically generates technical documentation for your codebase. For parts of your documentation which have not yet been automated, Documatic provides helpful features to streamline how you create and maintain great documentation. Documents are currently generated in a markdown format, however other formats and hosting options are coming soon. - -
- -# Configuration - -Create a “pyproject.toml” file in the root directory. -Give it a section “tool.documatic”. The following fields must be filled: - -- name -- - The name of your project -- docdir -- - The path to the folder in which you want documentation to be generated. The folder must exist. Set as “.” to be your project root -- srcdir -- - The path to the source code directory. E.g. if your project structure is “root/src/mypackage/init.py”, then “srcdir” would be “src/mypackage” - -Additionally, there are some optional fields you may use: - -- package -- - The name of your codebase as a python package, as it would be imported around the codebase or in other projects -- - Only relevant if codebase is pip-installable and you don’t use relative imports -- - Defaults to “srcdir”, so only necessary if import package name differs -- - E.g. if structure is “root/src/mypackage/__init__.py” then srcdir would be “src/mypackage” and package would probably be “mypackage” -- docname -- - The name of the technical document to be generated -- - Defaults to “technical_doc” -- - “.md” extension will be appended to the end if not provided - -
- -## Getting the tool - -If you use VSCode, search for and install the “Documatic” extension. Otherwise, install the “documatic” python package with “pip install documatic”. - -The VSCode extension is the preferred method as it provides additional features for generating documentation. - -
- -## Generating Documentation - -### If using the VSCode extension: - -- 1. In a terminal, navigate to the directory of the project - -- 2. you wish to document - -- 3. Open it with “code .” - -- 4. Press “ctrl + shift + p” to open the command pane - -- 5. Search for and run “Generate Technical Documentation” -(Depending on the size of your codebase) Your documentation will be generated in seconds - -N.b. it’s necessary to close all existing VScode windows before using the tool and to navigate directly to your project because of a known bug. This is in the process of being fixed, which will give you more freedom in using the extension. - -### If using the python package: -- 1. In a terminal, navigate to the directory of the project you wish to document -- 2. Run “documatic” -- 3. (Depending on the size of your codebase) Your documentation will be generated in seconds - -
- -## Adding manually edited sections -To include custom sections in your documentation that are not changed by the doc generation process, write the text in your document, highlight it and run the command “Fix Section to Top” (to pin the section to the top of the document) or “Fix Section to Bottom”. Fixing custom sections to anyplace in the document is coming soon. N.b. that if you have at least 1 top-fixed section, Documatic will not generate the intro header when you next run the tool as it assumes that the top fixed section is an intro. You can have as many fixed sections as you like. - -If you don’t have the extension, you can achieve this functionality manually by wrapping the section in markdown comments of the form: -``` -