From 5fa271e9102f2a2e135e21e200a82e0d571a36dd Mon Sep 17 00:00:00 2001 From: codeperfectplus Date: Sat, 4 Jan 2025 07:56:46 +0530 Subject: [PATCH 1/6] Add UNSPECIFIED gender option and enhance random profile generation logic --- random_profile/assets/job_titles.txt | 107 ++++++++++ random_profile/enums/gender.py | 1 + random_profile/main.py | 305 ++++++++++++++------------- random_profile/utils.py | 3 + 4 files changed, 272 insertions(+), 144 deletions(-) diff --git a/random_profile/assets/job_titles.txt b/random_profile/assets/job_titles.txt index 3c5207b..080be1d 100644 --- a/random_profile/assets/job_titles.txt +++ b/random_profile/assets/job_titles.txt @@ -104,3 +104,110 @@ Software Ninjaneer Director of Bean Counting Digital Overlord Director of Storytelling +Dynamic Functionality Analyst +Dynamic Quality Agent +Direct Interactions Architect +Product Intranet Specialist +Regional Directives Director +International Division Assistant +Human Division Director +Chief Quality Producer +Senior Applications Consultant +Chief Security Engineer +International Assurance Architect +National Security Administrator +Senior Data Specialist +Human Quality Strategist +Future Implementation Strategist +Global Paradigm Consultant +Customer Branding Developer +Direct Web Specialist +Product Program Supervisor +Human Creative Associate +Chief Operations Facilitator +Senior Program Engineer +Chief Division Technician +Central Factors Strategist +Senior Implementation Technician +Investor Creative Planner +District Web Associate +Internal Program Manager +Direct Web Liaison +Direct Creative Manager +Investor Tactics Liaison +Chief Solutions Assistant +Internal Division Supervisor +Dynamic Usability Developer +Direct Assurance Architect +Dynamic Metrics Engineer +Forward Markets Director +Dynamic Brand Manager +District Interactions Technician +Human Brand Director +District Integration Developer +International Communications Strategist +Chief Metrics Analyst +District Optimization Planner +Chief Identity Assistant +Chief Applications Assistant +Human Identity Director +Internal Marketing Liaison +Regional Data Consultant +Direct Branding Director +Central Division Executive +International Division Representative +District Mobility Representative +Regional Functionality Agent +Dynamic Markets Planner +Chief Configuration Director +District Mobility Director +Principal Program Engineer +District Accountability Administrator +Legacy Quality Technician +Global Directives Planner +Corporate Integration Liaison +Senior Markets Architect +Chief Mobility Designer +Investor Optimization Technician +Senior Security Representative +Internal Mobility Architect +Regional Tactics Liaison +Forward Applications Officer +Internal Web Planner +Legacy Interactions Analyst +District Marketing Planner +Central Branding Planner +District Group Administrator +Central Intranet Engineer +Customer Security Technician +Internal Mobility Architect +International Paradigm Agent +Dynamic Assurance Technician +Dynamic Brand Manager +Future Metrics Manager +Lead Creative Orchestrator +Central Web Orchestrator +National Solutions Agent +District Group Representative +Principal Accountability Officer +Future Configuration Agent +Dynamic Directives Supervisor +Senior Program Administrator +Principal Usability Technician +Dynamic Assurance Assistant +Lead Accounts Coordinator +Central Response Executive +Senior Creative Consultant +Senior Applications Manager +Human Creative Coordinator +Future Applications Assistant +Chief Tactics Architect +Senior Applications Strategist +Product Functionality Director +National Quality Engineer +National Optimization Liaison +Investor Interactions Assistant +Human Accounts Specialist +Regional Solutions Producer +Lead Tactics Administrator +Senior Program Manager \ No newline at end of file diff --git a/random_profile/enums/gender.py b/random_profile/enums/gender.py index 74ba8c9..8ad816f 100644 --- a/random_profile/enums/gender.py +++ b/random_profile/enums/gender.py @@ -5,3 +5,4 @@ class Gender(Enum): """ Gender Enum Class """ MALE = "Male" FEMALE = "Female" + UNSPECIFIED = None diff --git a/random_profile/main.py b/random_profile/main.py index 8c1a7a7..c330cc2 100644 --- a/random_profile/main.py +++ b/random_profile/main.py @@ -11,12 +11,14 @@ import random from typing import List, Tuple +# Adjust your path as needed sys.path.append('.') from random_profile.enums.gender import Gender from random_profile import utils from random_profile.__about__ import __version__ +# Asset file paths lname_txt = os.path.join(utils.ASSETS_DIR, "lnames.txt") fname_male_txt = os.path.join(utils.ASSETS_DIR, "fnames_male.txt") fname_female_txt = os.path.join(utils.ASSETS_DIR, "fnames_female.txt") @@ -28,7 +30,7 @@ job_titles_txt = os.path.join(utils.ASSETS_DIR, "job_titles.txt") job_levels_txt = os.path.join(utils.ASSETS_DIR, "job_levels.txt") -# loading data from txt files +# Load text data lname = utils.load_txt_file(lname_txt) fname_male = utils.load_txt_file(fname_male_txt) fname_female = utils.load_txt_file(fname_female_txt) @@ -40,94 +42,108 @@ job_titles = utils.load_txt_file(job_titles_txt) job_levels = utils.load_txt_file(job_levels_txt) - -class RandomProfile(object): - """ Random Profile Generator +class RandomProfile: + """ + Random Profile Generator Args: - num (int, optional): Total No. of Name You Want To Print. Defaults to 1. - gender(str, optional): default is None. if you want to generate define gender then pass + num (int, optional): Number of profiles to generate. Defaults to 1. + gender (Gender, optional): Specify a gender. Defaults to None for random. Methods: - full_profiles: Generate Full Profile - first_names: Generate First Name - last_names: Generate Last Name - full_names: Generate Full Name - email: Generate Email - phone_number: Generate Phone Number - dob_age: Generate Date of Birth and Age - height_weight: Generate Height and Weight - address: Generate Address - ip_address: Generate IP Address - hair_color: Generate Hair Color - blood_type: Generate Blood Type - job_title: Generate Job Title + full_profiles: Generate a list of full profiles. + first_names: Generate first names. + last_names: Generate last names. + full_names: Generate full names (first + last). + email: Generate email addresses. + phone_number: Generate phone numbers. + dob_age: Generate date of birth and age. + height_weight: Generate height and weight. + address: Generate address data. + ip_address: Generate IP addresses. + hair_color: Generate hair color(s). + blood_type: Generate blood type(s). + job_title: Generate job title(s). """ - def __init__(self, num: int = 1, gender: Gender = None): + + def __init__(self, num: int = 1, gender: Gender = Gender.UNSPECIFIED): + if num < 1: + raise ValueError("Number of profiles must be greater than 0.") self.num = num self.gender = gender def __str__(self) -> str: - return f'Random Profile Generator version {__version__}' + return f"Random Profile Generator version {__version__}" def __repr__(self) -> str: - return f'RandomProfile(num={self.num})' + return f"RandomProfile(num={self.num}, gender={self.gender})" def __call__(self, num: int = None) -> List[dict]: - return self.full_profile(num) + return self.full_profiles(num) # Call to generate full profiles def __iter__(self): - yield self.full_profile() + yield self.full_profiles() def __next__(self): - yield self.full_profile() + yield self.full_profiles() def __len__(self): return self.num def __getitem__(self, index): - return self.full_profile()[index] + profiles = self.full_profiles() + return profiles[index] def ip_address(self, num: int = None) -> List[str]: - num = self.num if num is None else num - if num == 1 or num is None: - return utils.ipv4_gen() - return [utils.ipv4_gen() for _ in range(num)] + """Generate one or more IPv4 addresses.""" + count = self.num if num is None else num + if count == 1: + return [utils.ipv4_gen()] + return [utils.ipv4_gen() for _ in range(count)] def job_title(self, num: int = None) -> List[str]: - num = self.num if num is None else num - if num == 1 or num is None: - return random.choice(job_titles) - return random.choices(job_titles, k=num) + """Generate one or more job titles.""" + count = self.num if num is None else num + if count == 1: + return [random.choice(job_titles)] + return random.choices(job_titles, k=count) def blood_type(self, num: int = None) -> List[str]: - num = self.num if num is None else num - if num == 1 or num is None: - return random.choice(blood_types) - return random.choices(blood_types, k=num) + """Generate one or more blood types.""" + count = self.num if num is None else num + if count == 1: + return [random.choice(blood_types)] + return random.choices(blood_types, k=count) def hair_color(self, num: int = None) -> List[str]: - num = self.num if num is None else num - if num == 1 or num is None: - return random.choice(hair_colors) - return random.choices(hair_colors, k=num) + """Generate one or more hair colors.""" + count = self.num if num is None else num + if count == 1: + return [random.choice(hair_colors)] + return random.choices(hair_colors, k=count) def dob_age(self, num: int = None) -> List[Tuple[str, int]]: - num = self.num if num is None else num - if num == 1 or num is None: - return utils.generate_dob_age() - return [utils.generate_dob_age() for _ in range(num)] + """Generate DOB and age tuples.""" + count = self.num if num is None else num + if count == 1: + return [utils.generate_dob_age()] + return [utils.generate_dob_age() for _ in range(count)] def height_weight(self, num: int = None) -> List[Tuple[int, int]]: - num = self.num if num is None else num - if num == 1 or num is None: - return utils.generate_random_height_weight() - return [utils.generate_random_height_weight() for _ in range(num)] - - def generate_address(self, num: int = None) -> List[str]: - num = self.num if num is None else num + """Generate height and weight tuples.""" + count = self.num if num is None else num + if count == 1: + return [utils.generate_random_height_weight()] + return [utils.generate_random_height_weight() for _ in range(count)] + + def generate_address(self, num: int = None) -> List[dict]: + """ + Generate one or more addresses. + Returns a list of dictionaries with address components. + """ + count = self.num if num is None else num address_list = [] - for _ in range(num): + for _ in range(count): street_num = random.randint(100, 999) street = random.choice(street_names) city = random.choice(cities_name) @@ -142,122 +158,123 @@ def generate_address(self, num: int = None) -> List[str]: 'zip_code': zip_code } address_list.append(address) - return address_list - def first_names(self, num: int = None, gender: Gender = None) -> list: - num = self.num if num is None else num - gender = self.gender if gender is None else gender + def first_names(self, num: int = None, gender: Gender = None) -> List[str]: + """Generate one or more first names based on gender.""" + count = self.num if num is None else num + gen = self.gender if gender is None else gender - # DRY CODE - if gender is None: - names = fname_female + fname_male - elif gender.value == Gender.MALE.value: - names = fname_male + if gen is None: + names_pool = fname_female + fname_male + elif gen.value == Gender.MALE.value: + names_pool = fname_male else: - names = fname_female - - if num == 1 or num is None: - return random.choice(names) - - return random.choices(names, k=num) - - def last_names(self, num: int = None) -> list: - num = self.num if num is None else num - if num == 1 or num is None: - return random.choice(lname) - - return random.choices(lname, k=num) - - def full_names(self, num: int = None, gender: Gender = None) -> list: - num = self.num if num is None else num - gender = self.gender if gender is None else gender - - if gender is None: - names = fname_female + fname_male - elif gender.value == Gender.MALE.value: - names = fname_male + names_pool = fname_female + + if count == 1: + return [random.choice(names_pool)] + return random.choices(names_pool, k=count) + + def last_names(self, num: int = None) -> List[str]: + """Generate one or more last names.""" + count = self.num if num is None else num + if count == 1: + return [random.choice(lname)] + return random.choices(lname, k=count) + + def full_names(self, num: int = None, gender: Gender = None) -> List[str]: + """Generate one or more full names (first + last).""" + count = self.num if num is None else num + gen = self.gender if gender is None else gender + + if gen is None: + first_pool = fname_female + fname_male + elif gen.value == Gender.MALE.value: + first_pool = fname_male else: - names = fname_female - - if num == 1 or num is None: - return random.choice(names) + ' ' + random.choice(lname) - - return [random.choice(names) + ' ' + random.choice(lname) for _ in range(num)] - - def full_profiles(self, num: int = None, gender: Gender = None) -> list: - num = self.num if num is None else num - + first_pool = fname_female + + names = [] + for _ in range(count): + f_name = random.choice(first_pool) + l_name = random.choice(lname) + names.append(f"{f_name} {l_name}") + return names + + def full_profiles(self, num: int = None, gender: Gender = None) -> List[dict]: + """ + Generate one or more full profiles. + Each profile is a dictionary containing various personal details. + """ + count = self.num if num is None else num profile_list = [] - for _ in range(num): - # random gender for every profile in list + for _ in range(count): this_gender = utils.generate_random_gender() if gender is None else gender - first = random.choice(fname_male if this_gender.value == Gender.MALE.value else fname_female) - last = random.choice(lname) - full_name = first + ' ' + last - - hair_color = random.choice(hair_colors) - blood_type = random.choice(blood_types) - - phone_number = f'+1-{random.randint(300, 500)}-{random.randint(800, 999)}-{random.randint(1000,9999)}' - + + # Generate names + f_name = random.choice(fname_male if this_gender.value == Gender.MALE.value else fname_female) + l_name = random.choice(lname) + full_name = f"{f_name} {l_name}" + + # Generate personal data + hair = random.choice(hair_colors) + blood = random.choice(blood_types) + phone_number = f"+1-{random.randint(300, 500)}-{random.randint(800, 999)}-{random.randint(1000,9999)}" dob, age = utils.generate_dob_age() height, weight = utils.generate_random_height_weight() job_experience = utils.generate_random_job_level(age, job_levels) + city, coords = utils.generate_random_city_coords(cities_name) + coords_pretty = utils.coords_string(coords) + # Generate address street_num = random.randint(100, 999) street = random.choice(street_names) - city, coords = utils.generate_random_city_coords(cities_name) - coords_pretty = utils.coords_string(coords) state = random.choice(states_names) zip_code = random.randint(10000, 99999) - - address = { + address_dict = { 'street_num': street_num, 'street': street, 'city': city, 'state': state, 'zip_code': zip_code } + full_address = f"{street_num} {street}, {city}, {state} {zip_code}" - full_address = f'{street_num} {street}, {city}, {state} {zip_code}' - - mother = self.first_names(1, Gender.FEMALE)[0] + ' ' + last - father = self.first_names(1, Gender.MALE)[0] + ' ' + last + # Generate parents + mother = f"{random.choice(fname_female)} {l_name}" + father = f"{random.choice(fname_male)} {l_name}" + # Generate payment card info card = utils.generate_random_card() - profile = {} - profile['id'] = str(uuid.uuid4()) - profile['gender'] = this_gender.value - - profile['first_name'] = first - profile['last_name'] = last - profile['hair_color'] = hair_color - profile['blood_type'] = blood_type - profile['full_name'] = full_name - - profile['job_title'] = self.job_title(num=1) - profile['dob'] = dob - profile['age'] = age - profile['phone_number'] = phone_number - profile['email'] = profile['first_name'].lower() + profile['last_name'].lower() + '@example.com' - - profile['blood_type'] = self.blood_type(num=1) - profile['height'] = height - profile['weight'] = weight - profile['hair_color'] = self.hair_color(num=1) - profile['ip_address'] = self.ip_address(num=1) - - profile['address'] = address - profile['full_address'] = full_address - profile['job_experience'] = job_experience - profile['mother'] = mother - profile['father'] = father - profile['payment_card'] = card - profile['coordinates'] = coords_pretty + # Compose the profile dict + profile = { + 'id': str(uuid.uuid4()), + 'gender': this_gender.value, + 'first_name': f_name, + 'last_name': l_name, + 'full_name': full_name, + 'hair_color': [hair], # matching the list return type from hair_color() + 'blood_type': [blood], # matching the list return type from blood_type() + 'job_title': [random.choice(job_titles)], + 'dob': dob, + 'age': age, + 'phone_number': phone_number, + 'email': f"{f_name.lower()}{l_name.lower()}@example.com", + 'height': height, + 'weight': weight, + 'ip_address': [utils.ipv4_gen()], # typically returns a list + 'address': address_dict, + 'full_address': full_address, + 'job_experience': job_experience, + 'mother': mother, + 'father': father, + 'payment_card': card, + 'coordinates': coords_pretty + } profile_list.append(profile) - return profile_list + return profile_list \ No newline at end of file diff --git a/random_profile/utils.py b/random_profile/utils.py index c284307..a418b62 100644 --- a/random_profile/utils.py +++ b/random_profile/utils.py @@ -55,6 +55,7 @@ def ipv4_gen() -> str: def generate_dob_age() -> tuple: month = random.randint(1, 12) + day = 1 # default value for day if month == 2: # if month is feb day = random.randint(1, 28) elif month in [4, 6, 9, 11]: # if month has 30 days @@ -86,6 +87,8 @@ def generate_random_height_weight() -> tuple: weight = random.randint(80, 100) elif height <= 200: weight = random.randint(90, 110) + else: + weight = random.randint(100, 120) return height, weight From 55546e6c5f3bc41d0cb5f9be3712c3ad8adba5b7 Mon Sep 17 00:00:00 2001 From: codeperfectplus Date: Sat, 4 Jan 2025 07:58:57 +0530 Subject: [PATCH 2/6] Update pull request template to improve clarity and enforce issue tracking --- .github/PULL_REQUEST_TEMPLATE.md | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 884d085..f10c8c7 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,13 +1,19 @@ -**What have you Changed** +## Pull Request Template -what you changed in the codebase.write here +### What have you changed in the codebase? + +### Issue Number (must be provided) + +- # -### Issue no.(must) - # +### Checklist (Tick after making the pull request) -### Self Check(Tick After Making pull Request) - -- [x] One Change in one Pull Request -- [x] I am following clean code and Documentation and my code is well linted with flake8. - -Join Us on Discord:- https://discord.gg/JfbK3bS +- [x] Only one change or fix in this Pull Request. +- [x] Code is linted with flake8 and follows clean code principles. +- [x] Documentation or comments are updated as necessary. From 9e22ac9b453921e9d0382decf43cee258793fa95 Mon Sep 17 00:00:00 2001 From: codeperfectplus Date: Sat, 4 Jan 2025 07:59:27 +0530 Subject: [PATCH 3/6] Remove unnecessary header from pull request template --- .github/PULL_REQUEST_TEMPLATE.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index f10c8c7..4f0cb34 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,5 +1,3 @@ -## Pull Request Template - ### What have you changed in the codebase? -### Issue Number (must be provided) +## Issue Number (must be provided) -- # -### Checklist (Tick after making the pull request) +## Checklist (Tick after making the pull request) - [x] Only one change or fix in this Pull Request. - [x] Code is linted with flake8 and follows clean code principles. From acbeeeee806d9f963f8b7330790c69195da12cf8 Mon Sep 17 00:00:00 2001 From: codeperfectplus Date: Sat, 4 Jan 2025 10:27:37 +0530 Subject: [PATCH 6/6] Refactor pull request template to enhance section headings for clarity --- .github/PULL_REQUEST_TEMPLATE.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index eac12bd..ed6ca49 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,15 +1,15 @@ -## What have you changed in the codebase? +**What have you Changed** -## Issue Number (must be provided) +**Issue Number (must be provided)** -## Checklist (Tick after making the pull request) +**Checklist (Tick after making the pull request)** - [x] Only one change or fix in this Pull Request. - [x] Code is linted with flake8 and follows clean code principles.