Skip to content

Commit

Permalink
Initial commit done with a working code
Browse files Browse the repository at this point in the history
  • Loading branch information
MohitR1999 committed Aug 5, 2023
0 parents commit 4312534
Show file tree
Hide file tree
Showing 16 changed files with 351 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
env
.vscode
output.pdf
config.ini
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2023 Mohit Ranjan

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.
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Resume in python (using reportlab) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

This is an attempt to create an ATS friendly resume in python. I'm intending to maintain and enhance it as per my needs, or in case I get any feedback from the community. I'm trying to keep the code simple and easy to comprehend, and separating the data from the PDF generation logic. All the data that needs to be put in the resume is present in the ```data.json``` file

## Steps to run
- Make sure you have python version 3 installed
- Clone this repository
- Create a virtual environment by running the command ```python3 -m venv env```
- Activate the virtual environment by running the ```activate``` script for your respective operating system
- Install all the required libraries by running ```pip install requirements.txt```
- Create a ```config.ini``` file as follows:

```
[global]
debug = false
author = <Your name>
email = <Your email>
address = <Your address>
phone = <Your phone number>
```
This will set the debug configuration as false, which will generate the resume without any grid lines. If debug is set to true it will generate the resume with gridlines
- Run the ```main.py``` file by executing the command ```python3 main.py```. This will generate a resume in PDF format with the name ```output.pdf``` in the project directory
- To customize the information in resume, just modify the ```data.json``` file with your required information
- Personal information would be picked up from the ```config.ini``` file that is present in the project root
94 changes: 94 additions & 0 deletions data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
{
"education": [
{
"degree": "B.Tech (Computer Engineering), CGPA: 8.36",
"university": "Delhi Technological University",
"location": "Delhi, India",
"year": "July 2021"
},
{
"degree": "AISSCE (Class XII), Percentage: 95.2%",
"university": "Vanasthali Public School",
"location": "Delhi, India",
"year": "July 2017"
},
{
"degree": "AISSE (Class X), CGPA: 10.0",
"university": "Vanasthali Public School",
"location": "Delhi, India",
"year": "July 2015"
}
],
"experience": [
{
"title": "Research and Development Engineer",
"company": "Tejas Networks Ltd.",
"location": "Gurugram, Haryana, India",
"duration": "July 2021 - Present",
"description": [
"Developed and implemented new features, including Circuit Emulation and QoS Enhancements, for carrier Ethernet Networks in TejNMS (Tejas Network Management System) app",
"Installed and configured multiple network element simulators, providing a realistic testing environment, using Docker",
"Utilized Selenium and TestNG to automate regression testing, resulting in improved efficiency and reduced testing time by 60%",
"Developed test scripts and executed automated tests to verify system functionality, identify bugs, and ensure product quality",
"Played a key role in migrating the existing codebase of the TejNMS from CVS to Git, enhancing version control and collaboration processes",
"Currently involved in the development of a user-friendly Border Gateway Protocol (BGP) configuration UI for Layer 3 provisioning in TejNMS"
]
},
{
"title": "R & D Engineer Intern",
"company": "Tejas Networks Ltd.",
"location": "Gurugram, Haryana, India",
"duration": "January 2021 - July 2021",
"description": [
"Achieved enhanced code quality through in-depth analysis and optimized flow by leveraging library functions of DHTMLX, minimizing redundancy",
"Significantly improved TejNMS UI by implementing modern JavaScript practices and asynchronous operations, resulting in shorter development time and highly predictable code behavior."
]
},
{
"title": "Front-end Developer Intern",
"company": "Stepswatch",
"location": "India",
"duration": "March 2020 - May 2020",
"description": [
"Designed and developed the Stepswatch mobile app from scratch using React Native, Redux, and Node.js",
"Implemented authentication and state management using Redux and JWT (JSON Web Tokens), ensuring secure user sessions and data protection",
"Integrated real-time chat functionality using socket.io, allowing users to engage in seamless and instant communication within the app"
]
},
{
"title": "University Student Intern",
"company": "Delhi Technological University",
"location": "Delhi, India",
"duration": "August 2019 - March 2020",
"description": [
"Designed and developed the website for Intellectual Property Rights Cell, DTU <a href=\"https://mohitr1999.github.io/iprCellWebsite/\" color=\"blue\">(Link)</a>",
"Developed the website for International Summit on Quality Indices in Higher Education"
]
}
],
"skills": [
"Programming Languages: Javascript, C++, Python",
"Version control systems: Git, CVS",
"Frameworks and Libraries: React.js, React Native, Redux"
],

"projects" : [
{
"title" : "C Compiler in Javascript",
"description" : "A C compiler, written purely in Javascript from scratch <a href=\"https://github.com/MohitR1999/compiler-in-javascript\" color=\"blue\">(GitHub)</a>",
"link" : "<a href=\"https://github.com/MohitR1999/compiler-in-javascript\" color=\"blue\">(GitHub)</a>"
},

{
"title" : "Vitarit File Pranali",
"description" : "A distributed file system implemented using python and rpyc <a href=\"https://github.com/MohitR1999/vitarit-file-pranali\" color=\"blue\">(GitHub)</a>",
"link" : "<a href=\"https://github.com/MohitR1999/vitarit-file-pranali\" color=\"blue\">(GitHub)</a>"
},

{
"title" : "Maestro-bot",
"description" : "A Discord bot, that shows you memes and pictures as you say <a href=\"https://github.com/MohitR1999/maestro-bot\" color=\"blue\">(GitHub)</a>",
"link" : "<a href=\"https://github.com/MohitR1999/maestro-bot\" color=\"blue\">(GitHub)</a>"
}
]
}
206 changes: 206 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
from reportlab.pdfbase import pdfmetrics, ttfonts
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import inch
from reportlab.lib import colors
from reportlab.platypus import SimpleDocTemplate, Paragraph, Table, TableStyle
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_RIGHT
import json
import configparser
import os

PAGE_WIDTH, PAGE_HEIGHT = A4
FULL_COLUMN_WIDTH = (PAGE_WIDTH - 1 * inch)
GARAMOND_REGULAR_FONT_PATH = './res/fonts/EBGaramond-Regular.ttf'
GARAMOND_REGULAR = 'Garamond_Regular'

GARAMOND_BOLD_FONT_PATH = './res/fonts/EBGaramond-Bold.ttf'
GARAMOND_BOLD = 'Garamond_Bold'

GARAMOND_SEMIBOLD_FONT_PATH = './res/fonts/EBGaramond-SemiBold.ttf'
GARAMOND_SEMIBOLD = 'Garamond_Semibold'

pdfmetrics.registerFont(ttfonts.TTFont(GARAMOND_REGULAR, GARAMOND_REGULAR_FONT_PATH))
pdfmetrics.registerFont(ttfonts.TTFont(GARAMOND_BOLD, GARAMOND_BOLD_FONT_PATH))
pdfmetrics.registerFont(ttfonts.TTFont(GARAMOND_SEMIBOLD, GARAMOND_SEMIBOLD_FONT_PATH))

JOB_DETAILS_PARAGRAPH_STYLE = ParagraphStyle('job_details_paragraph', leftIndent=12, fontName = GARAMOND_REGULAR, fontSize = 12, leading = 14)
NAME_PARAGRAPH_STYLE = ParagraphStyle('name_paragraph', fontName = GARAMOND_SEMIBOLD, fontSize=16)
CONTACT_PARAGRAPH_STYLE = ParagraphStyle('contact_paragraph', fontName = GARAMOND_REGULAR, fontSize=12)
SECTION_PARAGRAPH_STYLE = ParagraphStyle('section_paragraph', fontName = GARAMOND_SEMIBOLD, fontSize=13, textTransform = 'uppercase')
COMPANY_HEADING_PARAGRAPH_STYLE = ParagraphStyle('company_heading_paragraph', fontName = GARAMOND_SEMIBOLD, fontSize=13)
COMPANY_TITLE_PARAGRAPH_STYLE = ParagraphStyle('company_title_paragraph', fontName = GARAMOND_REGULAR, fontSize=12)
COMPANY_DURATION_PARAGRAPH_STYLE = ParagraphStyle('company_duration_paragraph', fontName = GARAMOND_SEMIBOLD, fontSize=13, alignment = TA_RIGHT)
COMPANY_LOCATION_PARAGRAPH_STYLE = ParagraphStyle('company_location_paragraph', fontName = GARAMOND_REGULAR, fontSize=12, alignment = TA_RIGHT)

def appendSectionTableStyle(table_styles, running_row_index):
table_styles.append(('TOPPADDING', (0, running_row_index), (1, running_row_index), 5))
table_styles.append(('BOTTOMPADDING', (0, running_row_index), (1, running_row_index), 5))
table_styles.append(('LINEBELOW', (0, running_row_index), (-1, running_row_index), 1, colors.black))


def generate_resume(file_path, json_file_path):
config = None
debug = 'false'
author = 'anonymous'
email = '[email protected]'
address = 'XXX'
phone = '00-0000000000'

if (os.path.isfile('./config.ini')):
config = configparser.ConfigParser()
config.read('./config.ini')
# Check if debug option is present
if (config.has_option('global', 'debug')):
debug = config.get('global', 'debug')

# Check if author is present
if (config.has_option('global', 'author')):
author = config.get('global', 'author')

# Check if email address is present
if (config.has_option('global', 'email')):
email = config.get('global', 'email')

# Check if address is present
if (config.has_option('global', 'address')):
address = config.get('global', 'address')

# Check if author is present
if (config.has_option('global', 'phone')):
phone = config.get('global', 'phone')

doc = SimpleDocTemplate(file_path, pagesize=A4, showBoundary=0, leftMargin = 0.5 * inch, rightMargin= 0.5 * inch, topMargin = 0.2 * inch, bottomMargin = 0.1 * inch, title = f"Resume of {author}", author = author)
with open(json_file_path, 'r') as file:
data = json.load(file)
# data for the table
table_data = []
table_styles = []
running_row_index = 0

# Append some basic styles to the table styles array only in debug mode
if (debug == 'true'):
table_styles.append(('GRID', (0, 0), (-1, -1), 0, colors.black))

table_styles.append(('ALIGN', (0, 0), (0, -1), 'LEFT'))
table_styles.append(('ALIGN', (1, 0), (1, -1), 'RIGHT'))
table_styles.append(('LEFTPADDING', (0, 0), (-1, -1), 0))
table_styles.append(('RIGHTPADDING', (0, 0), (-1, -1), 0))
# Add name and basic contact

table_styles.append(('BOTTOMPADDING', (0, running_row_index), (1, running_row_index), 6))
table_data.append([
Paragraph(author, NAME_PARAGRAPH_STYLE)
])
running_row_index += 1

table_data.append([
Paragraph(f"{email} | {phone} | {address}", CONTACT_PARAGRAPH_STYLE),
])
table_styles.append(('BOTTOMPADDING', (0, running_row_index), (1, running_row_index), 1))
running_row_index += 1

# Add experience heading
table_data.append(
[Paragraph("Experience", SECTION_PARAGRAPH_STYLE)]
)
appendSectionTableStyle(table_styles, running_row_index)
running_row_index += 1


# Append experience
for job_experience in data['experience']:
table_data.append([
Paragraph(job_experience['company'], COMPANY_HEADING_PARAGRAPH_STYLE),
Paragraph(job_experience['duration'], COMPANY_DURATION_PARAGRAPH_STYLE),
])
table_styles.append(('TOPPADDING', (0, running_row_index), (1, running_row_index), 5))
running_row_index += 1

table_data.append([
Paragraph(job_experience['title'], COMPANY_TITLE_PARAGRAPH_STYLE),
Paragraph(job_experience['location'], COMPANY_LOCATION_PARAGRAPH_STYLE),
])
table_styles.append(('TOPPADDING', (0, running_row_index), (1, running_row_index), 1))
running_row_index += 1

for line in job_experience['description']:
table_data.append([
Paragraph(line, bulletText='•', style=JOB_DETAILS_PARAGRAPH_STYLE)
])
table_styles.append(('TOPPADDING', (0, running_row_index), (1, running_row_index), 1))
table_styles.append(('BOTTOMPADDING', (0, running_row_index), (1, running_row_index), 0))
table_styles.append(('SPAN', (0, running_row_index), (1, running_row_index)))
running_row_index += 1

# Append education heading
table_data.append(
[Paragraph("Education", SECTION_PARAGRAPH_STYLE)]
)
appendSectionTableStyle(table_styles, running_row_index)
running_row_index += 1

# Append education
for education in data['education']:
table_data.append([
Paragraph(education['university'], COMPANY_HEADING_PARAGRAPH_STYLE),
Paragraph(education['year'], COMPANY_DURATION_PARAGRAPH_STYLE),
])
table_styles.append(('TOPPADDING', (0, running_row_index), (1, running_row_index), 5))
running_row_index += 1

table_data.append([
Paragraph(education['degree'], COMPANY_TITLE_PARAGRAPH_STYLE),
Paragraph(education['location'], COMPANY_LOCATION_PARAGRAPH_STYLE),
])
table_styles.append(('TOPPADDING', (0, running_row_index), (1, running_row_index), 1))
running_row_index += 1

# Append projects heading
table_data.append(
[Paragraph("Projects", SECTION_PARAGRAPH_STYLE)]
)
appendSectionTableStyle(table_styles, running_row_index)
running_row_index += 1

for project in data['projects']:
table_data.append([
Paragraph(project['description'], bulletText='•', style=COMPANY_TITLE_PARAGRAPH_STYLE),
])
table_styles.append(('TOPPADDING', (0, running_row_index), (1, running_row_index), 1))
table_styles.append(('SPAN', (0, running_row_index), (1, running_row_index)))
running_row_index += 1

# Append skills heading
table_data.append(
[Paragraph("Skills", SECTION_PARAGRAPH_STYLE)]
)
appendSectionTableStyle(table_styles, running_row_index)
running_row_index += 1

# Append skills
for skill in data['skills']:
table_data.append([
Paragraph(skill, bulletText='•', style=JOB_DETAILS_PARAGRAPH_STYLE)
])
table_styles.append(('TOPPADDING', (0, running_row_index), (1, running_row_index), 1))
table_styles.append(('BOTTOMPADDING', (0, running_row_index), (1, running_row_index), 0))
table_styles.append(('SPAN', (0, running_row_index), (1, running_row_index)))
running_row_index += 1

table_style = TableStyle(table_styles)

# Create the table and apply the style
table = Table(table_data, colWidths=[FULL_COLUMN_WIDTH * 0.7, FULL_COLUMN_WIDTH * 0.3], spaceBefore=0, spaceAfter=0)
table.setStyle(table_style)

# Add the table to the elements list
elements = [table]

# Build the PDF document
doc.build(elements)

if __name__ == "__main__":
OUTPUT_PDF_PATH = "./output.pdf"
JSON_PATH = "./data.json"
generate_resume(OUTPUT_PDF_PATH, JSON_PATH)
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Pillow==10.0.0
reportlab==4.0.4
Binary file added res/fonts/EBGaramond-Bold.ttf
Binary file not shown.
Binary file added res/fonts/EBGaramond-BoldItalic.ttf
Binary file not shown.
Binary file added res/fonts/EBGaramond-ExtraBold.ttf
Binary file not shown.
Binary file added res/fonts/EBGaramond-ExtraBoldItalic.ttf
Binary file not shown.
Binary file added res/fonts/EBGaramond-Italic.ttf
Binary file not shown.
Binary file added res/fonts/EBGaramond-Medium.ttf
Binary file not shown.
Binary file added res/fonts/EBGaramond-MediumItalic.ttf
Binary file not shown.
Binary file added res/fonts/EBGaramond-Regular.ttf
Binary file not shown.
Binary file added res/fonts/EBGaramond-SemiBold.ttf
Binary file not shown.
Binary file added res/fonts/EBGaramond-SemiBoldItalic.ttf
Binary file not shown.

0 comments on commit 4312534

Please sign in to comment.