diff --git a/.github/workflows/resume.yml b/.github/workflows/resume.yml index b58871a..834536b 100644 --- a/.github/workflows/resume.yml +++ b/.github/workflows/resume.yml @@ -25,7 +25,9 @@ jobs: uses: actions/checkout@v4 - name: Run resume generation script run: | - python3 example.py + cd ./src/ + python3 -m resume.builder ../example.py -o ../assets + cd ../ - name: Check for resume changes id: check_updates run: | diff --git a/example.py b/example.py index 73cd80f..8dbfa8e 100755 --- a/example.py +++ b/example.py @@ -1,121 +1,115 @@ -#!/usr/bin/env python3 +from src.resume.components import * -from src.resume import * - - -# TODO: edit author object as required -me: Author = Author( - name="Sheikh Saad Abdullah", - address=Address("2060 Quingate Place", "B3L 4P7"), - phone="+1 (902) 818-0048", - email="sheikh@cybar.dev", - website="www.cybar.dev", - social="cybardev", - skills=[ - Skill( - name="Skills", - attributes=[ - "Python", - "HTML", - "CSS", - "Bootstrap", - "JavaScript", - "jQuery", - "ReactJS", - "NodeJS", - "ExpressJS", - "MongoDB", - "Java", - "C/C++", - "Git", - ], - ), - Skill( - name="Interests", - attributes=[ - "Linux", - "Open-source", - "Shell Scripting", - "Automation", - "Cloud", - "Front-end Web Development", - "Data Analytics", - ], - ), - ], - experiences=[ - Experience( - name="ReelData AI", - address="Halifax, Nova Scotia", - role="Junior Software Developer", - start="Sept 2023", - end="Dec 2023", - attributes=[ - "Collaborated with a dynamic Agile team on ReelAppetite, a key product, demonstrating strong teamwork and interpersonal skills", - "Successfully integrated into a large existing codebase, showcasing adaptability and quick learning", - "Implemented features using test-driven development and containerization, contributing to the software’s robustness", - "Experienced the deployment of code to production, highlighting practical application and impact of contributions", - ], - ), - Experience( - name="Sensor Technology LTD (COVE)", - address="Dartmouth, Nova Scotia", - role="Research Intern", - start="May 2023", - end="Aug 2023", - attributes=[ - "Configured Raspberry Pi SBCs with OpenPlotter Marine OS for the purpose of developing and testing the Acoustic Projector Control and Logging System", - "Developed Python script for generation and playback of audio files from given wavelength and duration", - "Implemented module to connect to private Signal K server and utilize its API to effectively retrieve sensor data", - "Created a script for logging data from sensors, consuming it via API calls, and storing it in an SQLite database", - ], - ), - ], - projects=[ - Project( - name="Cy | Pass - Secure Password Generator", - address="https://pypi.org/project/cybarpass", - role="Software Developer", - start="Apr 2022", - end="Apr 2023", - attributes=[ - "Modularized code by splitting up project into multiple scripts and using proper object-oriented techniques to ensure separation of concerns", - "Designed and implemented simple and elegant tkinter GUI and robust CLI for convenience and ease of access", - "Packaged and published project to Python Package Index (PyPI), making it easy and convenient for users to install", - "Created companion tool [CheckPass](https://checkpass.cybar.dev) to allow users to test the security of generated passphrase", - ], - ), - Project( - name="Cy | Search - Search Engine Frontend", - address="https://search.cybar.dev", - role="Full-stack Developer", - start="Jan 2022", - end="Apr 2022", - attributes=[ - "Designed a search engine frontend that uses NodeJS functions to request and fetch search results from a public API", - "Successfully displayed the fetched results in a clear and concise format", - "Secured the API key by encrypting it as a repository secret and using code obfuscation techniques", - "Implemented progressive web app functionality to allow users to install it as an app", +def main(): + # TODO: edit author object as required + return Author( + name="Sheikh Saad Abdullah", + address=Address("2060 Quingate Place", "B3L 4P7"), + phone="+1 (902) 818-0048", + email="sheikh@cybar.dev", + website="www.cybar.dev", + social="cybardev", + skills=[ + Skill( + name="Skills", + attributes=[ + "Python", + "HTML", + "CSS", + "Bootstrap", + "JavaScript", + "jQuery", + "ReactJS", + "NodeJS", + "ExpressJS", + "MongoDB", + "Java", + "C/C++", + "Git", + ], + ), + Skill( + name="Interests", + attributes=[ + "Linux", + "Open-source", + "Shell Scripting", + "Automation", + "Cloud", + "Front-end Web Development", + "Data Analytics", + ], + ), + ], + experiences=[ + Experience( + name="ReelData AI", + address="Halifax, Nova Scotia", + role="Junior Software Developer", + start="Sept 2023", + end="Dec 2023", + attributes=[ + "Collaborated with a dynamic Agile team on ReelAppetite, a key product, demonstrating strong teamwork and interpersonal skills", + "Successfully integrated into a large existing codebase, showcasing adaptability and quick learning", + "Implemented features using test-driven development and containerization, contributing to the software’s robustness", + "Experienced the deployment of code to production, highlighting practical application and impact of contributions", + ], + ), + Experience( + name="Sensor Technology LTD (COVE)", + address="Dartmouth, Nova Scotia", + role="Research Intern", + start="May 2023", + end="Aug 2023", + attributes=[ + "Configured Raspberry Pi SBCs with OpenPlotter Marine OS for the purpose of developing and testing the Acoustic Projector Control and Logging System", + "Developed Python script for generation and playback of audio files from given wavelength and duration", + "Implemented module to connect to private Signal K server and utilize its API to effectively retrieve sensor data", + "Created a script for logging data from sensors, consuming it via API calls, and storing it in an SQLite database", + ], + ), + ], + projects=[ + Project( + name="Cy | Pass - Secure Password Generator", + address="https://pypi.org/project/cybarpass", + role="Software Developer", + start="Apr 2022", + end="Apr 2023", + attributes=[ + "Modularized code by splitting up project into multiple scripts and using proper object-oriented techniques to ensure separation of concerns", + "Designed and implemented simple and elegant tkinter GUI and robust CLI for convenience and ease of access", + "Packaged and published project to Python Package Index (PyPI), making it easy and convenient for users to install", + "Created companion tool [CheckPass](https://checkpass.cybar.dev) to allow users to test the security of generated passphrase", + ], + ), + Project( + name="Cy | Search - Search Engine Frontend", + address="https://search.cybar.dev", + role="Full-stack Developer", + start="Jan 2022", + end="Apr 2022", + attributes=[ + "Designed a search engine frontend that uses NodeJS functions to request and fetch search results from a public API", + "Successfully displayed the fetched results in a clear and concise format", + "Secured the API key by encrypting it as a repository secret and using code obfuscation techniques", + "Implemented progressive web app functionality to allow users to install it as an app", + ], + ), + ], + education=Education( + school="Saint Mary's University", + location="Halifax, Nova Scotia", + program="Bachelor of Science", + major="Computing Science", + start="Sep 2020", + end="Dec 2024", + courses=[ + "Artificial Intelligence", + "Data Structures and Algorithms", + "Software Engineering", + "Systems Security", ], ), - ], - education=Education( - school="Saint Mary's University", - location="Halifax, Nova Scotia", - program="Bachelor of Science", - major="Computing Science", - start="Sep 2020", - end="Dec 2024", - courses=[ - "Artificial Intelligence", - "Data Structures and Algorithms", - "Software Engineering", - "Systems Security", - ], - ), -) - - -if __name__ == "__main__": - generate_resume(me, "./assets/") + ) diff --git a/src/resume/__init__.py b/src/resume/__init__.py index 28fdfa3..62eff45 100644 --- a/src/resume/__init__.py +++ b/src/resume/__init__.py @@ -2,13 +2,3 @@ # metadata __version__ = "1.0.0" - -# import everything needed for a resume -from .components.address import Address -from .components.author import Author -from .components.education import Education -from .components.experience import Experience -from .components.project import Project -from .components.resume import Resume -from .components.skill import Skill -from .utils import generate_resume, md_to_pdf diff --git a/src/resume/__main__.py b/src/resume/__main__.py deleted file mode 100644 index 9c66d31..0000000 --- a/src/resume/__main__.py +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import json - -from src.utils import generate_resume - - -def main(): - # TODO: read in Python resume file and output PDF and PNG - pass - - -if __name__ == __main__: - main() diff --git a/src/resume/builder/__init__.py b/src/resume/builder/__init__.py new file mode 100644 index 0000000..143f486 --- /dev/null +++ b/src/resume/builder/__init__.py @@ -0,0 +1 @@ +# __init__.py diff --git a/src/resume/builder/__main__.py b/src/resume/builder/__main__.py new file mode 100755 index 0000000..8098ed2 --- /dev/null +++ b/src/resume/builder/__main__.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 + +import argparse +import os +import sys + +from importlib.machinery import SourceFileLoader +from importlib.util import spec_from_loader, module_from_spec + +from ..components.resume import Resume +from ..utils import generate_resume + + +def main(args: argparse.Namespace): + full_path = os.path.abspath(args.resume) + filename = os.path.basename(full_path) + sys.path.append(os.path.dirname(full_path)) + + loader = SourceFileLoader(filename, full_path) + spec = spec_from_loader(filename, loader) + resume_info = module_from_spec(spec) + loader.exec_module(resume_info) + + resume_obj = Resume(resume_info.main()) + generate_resume(resume_obj, args.output) + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + prog="resume", + description="Generate a resume from a given python file", + allow_abbrev=False, + ) + parser.add_argument( + "resume", + metavar="RESUME", + type=str, + help="path to the Python file containing the resume data", + ) + parser.add_argument( + "-o", + "--output", + dest="output", + type=str, + help="path to the output directory", + default="./", + ) + return parser.parse_args() + + +if __name__ == "__main__": + main(parse_args()) diff --git a/src/resume/components/__init__.py b/src/resume/components/__init__.py index 143f486..0ec5834 100644 --- a/src/resume/components/__init__.py +++ b/src/resume/components/__init__.py @@ -1 +1,10 @@ # __init__.py + +# import everything needed for a resume +from .address import Address +from .author import Author +from .education import Education +from .experience import Experience +from .project import Project +from .resume import Resume +from .skill import Skill diff --git a/src/resume/utils.py b/src/resume/utils.py index 278d44a..d238b2a 100644 --- a/src/resume/utils.py +++ b/src/resume/utils.py @@ -58,9 +58,8 @@ def pdf_to_png( ) -def generate_resume(author, output_dir: str) -> Resume: +def generate_resume(resume, output_dir: str): # generate resume and output to markdown file - resume: Resume = Resume(author) filename = ( output_dir.rstrip("/") + "/"