From cba1176c4baebd41c1c76c2b258f6d0c147c0321 Mon Sep 17 00:00:00 2001 From: Deepak Raj <54245038+codeperfectplus@users.noreply.github.com> Date: Sat, 1 Jun 2024 20:46:51 -0700 Subject: [PATCH 1/4] Update .readthedocs.yaml --- .readthedocs.yaml | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 4739e50..e9186fa 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -1,25 +1,24 @@ -# .readthedocs.yaml -# Read the Docs configuration file +# Read the Docs configuration file for Sphinx projects # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details # Required version: 2 -# Set the version of Python and other tools you might need +# Set the OS, Python version and other tools you might need build: - os: ubuntu-20.04 + os: ubuntu-22.04 tools: - python: "3.9" + python: "3.12" -# Build documentation in the docs/ directory with Sphinx +# Build documentation in the "docs/" directory with Sphinx sphinx: - configuration: docs/conf.py + configuration: docs/conf.py -# If using Sphinx, optionally build your docs in additional formats such as PDF +# Optionally build your docs in additional formats such as PDF and ePub formats: - - pdf + - pdf + - epub -# Optionally declare the Python requirements required to build your docs python: - install: - - requirements: docs/requirements.txt \ No newline at end of file + install: + - requirements: docs/requirements.txt From aa99e180a749a05239f4a5388c0cdd0c37f25c3f Mon Sep 17 00:00:00 2001 From: codeperfectplus Date: Thu, 2 Jan 2025 18:00:17 +0530 Subject: [PATCH 2/4] Bump version to 3.0.5 and update changelog with bug fixes --- CHANGELOG.md | 15 ++++++++++++++- docs/conf.py | 2 +- random_profile/__about__.py | 2 +- setup.py | 2 +- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db933e4..f81d1a5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,22 @@ All notable changes to this project will be documented in this file. The format ## Changelog -## [V3.0.2] - Minor Release - +## [V3.0.5] - Minor Release - 02-01-2025 + +- [x] Bug fixes + +## [V3.0.4] - Minor Release - 02-01-2025 + +- [x] Bug fixes + +## [V3.0.3] - Minor Release - 25-11-2024 + +- [x] Bug fixes + +## [V3.0.2] - Minor Release - 08-11-2023 - [x] Updating API Documentation +- [x] Bug fixes ## [V3.0.1] - Minor Release - 18-11-2022 diff --git a/docs/conf.py b/docs/conf.py index bdba5e8..1875dbf 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -5,7 +5,7 @@ __title__ = 'RandomProfileGenerator' __package_name__ = 'random_profile' -__version__ = '3.0.2' +__version__ = '3.0.5' __description__ = "Python Module To Generate Random Profile Data" __email__ = "deepak008@live.com" __author__ = 'Deepak Raj' diff --git a/random_profile/__about__.py b/random_profile/__about__.py index 7de9b03..67064c7 100644 --- a/random_profile/__about__.py +++ b/random_profile/__about__.py @@ -1,6 +1,6 @@ __title__ = 'RandomProfileGenerator' __package_name__ = 'random_profile' -__version__ = '3.0.2' +__version__ = '3.0.5' __description__ = "Python Module To Generate Random Profile Data" __email__ = "deepak008@live.com" __author__ = 'Deepak Raj' diff --git a/setup.py b/setup.py index b9bb5f2..eb41f55 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ __title__ = 'RandomProfileGenerator' __package_name__ = 'random_profile' -__version__ = '3.0.2' +__version__ = '3.0.5' __description__ = "Python Module To Generate Random Profile Data" __email__ = "deepak008@live.com" __author__ = 'Deepak Raj' From c73edd036510248e8bf379e28ae1c3c94637cf3e Mon Sep 17 00:00:00 2001 From: Deepak Raj <54245038+codeperfectplus@users.noreply.github.com> Date: Sat, 4 Jan 2025 10:34:09 +0530 Subject: [PATCH 3/4] =?UTF-8?q?Add=20UNSPECIFIED=20gender=20option=20and?= =?UTF-8?q?=20enhance=20random=20profile=20generation=20l=E2=80=A6=20(#62)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add UNSPECIFIED gender option and enhance random profile generation logic * Update pull request template to improve clarity and enforce issue tracking * Remove unnecessary header from pull request template * Fix formatting issues in RandomProfile class and update docstrings for clarity * Update pull request template to improve section headings for clarity * Refactor pull request template to enhance section headings for clarity --- .github/PULL_REQUEST_TEMPLATE.md | 21 +- random_profile/assets/job_titles.txt | 107 ++++++++++ random_profile/enums/gender.py | 1 + random_profile/main.py | 298 ++++++++++++++------------- random_profile/utils.py | 3 + 5 files changed, 281 insertions(+), 149 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 884d085..ed6ca49 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,13 +1,16 @@ **What have you Changed** + -what you changed in the codebase.write here +**Issue Number (must be provided)** + +**Checklist (Tick after making the pull request)** -### Issue no.(must) - # - -### 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. 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..809ec48 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) @@ -41,93 +43,108 @@ 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,121 +159,122 @@ 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) 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 fe254e3dfe8d077e0f610d11ed41b3bbe548a29a Mon Sep 17 00:00:00 2001 From: Deepak Raj <54245038+codeperfectplus@users.noreply.github.com> Date: Sat, 7 Jun 2025 18:44:19 +0530 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=94=96=20Release=20v3.0.6=20=E2=80=93?= =?UTF-8?q?=20Refactor,=20Version=20Bump=20&=20Changelog=20Update=20(#63)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Bump version to 3.0.6 and update changelog with minor release details * Refactor profile generation to use dataclass for improved structure and readability; update tests to reflect changes in return types * Update changelog for version 3.0.6 with recent changes and improvements --- CHANGELOG.md | 8 ++- docs/conf.py | 2 +- random_profile/__about__.py | 2 +- random_profile/main.py | 117 ++++++++++++++++++++++++++---------- setup.py | 2 +- tests/test_cases.py | 16 ++--- 6 files changed, 104 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f81d1a5..c1a7d8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Changelog +## [V3.0.6] - Minor Release - 07-06-2025 + +- [x] Bug fixes +- [x] Updated documentation +- [x] Refactored profile generation to use dataclass for improved structure and readability +- [x] Updated tests to reflect changes in return types +- [x] Bump version to 3.0.6 ## [V3.0.5] - Minor Release - 02-01-2025 diff --git a/docs/conf.py b/docs/conf.py index 1875dbf..e5ca515 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -5,7 +5,7 @@ __title__ = 'RandomProfileGenerator' __package_name__ = 'random_profile' -__version__ = '3.0.5' +__version__ = '3.0.6' __description__ = "Python Module To Generate Random Profile Data" __email__ = "deepak008@live.com" __author__ = 'Deepak Raj' diff --git a/random_profile/__about__.py b/random_profile/__about__.py index 67064c7..8637764 100644 --- a/random_profile/__about__.py +++ b/random_profile/__about__.py @@ -1,6 +1,6 @@ __title__ = 'RandomProfileGenerator' __package_name__ = 'random_profile' -__version__ = '3.0.5' +__version__ = '3.0.6' __description__ = "Python Module To Generate Random Profile Data" __email__ = "deepak008@live.com" __author__ = 'Deepak Raj' diff --git a/random_profile/main.py b/random_profile/main.py index 809ec48..59590c1 100644 --- a/random_profile/main.py +++ b/random_profile/main.py @@ -10,10 +10,13 @@ import uuid import random from typing import List, Tuple +from dataclasses import dataclass, asdict + # Ensure the current directory is in the path to import local modules # Adjust your path as needed sys.path.append('.') +from random_profile.enums import gender from random_profile.enums.gender import Gender from random_profile import utils from random_profile.__about__ import __version__ @@ -42,6 +45,30 @@ job_titles = utils.load_txt_file(job_titles_txt) job_levels = utils.load_txt_file(job_levels_txt) +@dataclass +class Profile: + id: str + gender: str + first_name: str + last_name: str + full_name: str + hair_color: str + blood_type: str + job_title: str + dob: str + age: int + phone_number: str + email: str + height: int + weight: int + ip_address: str + address: dict + full_address: str + job_experience: str + mother: str + father: str + payment_card: dict + coordinates: str class RandomProfile: """ @@ -95,6 +122,9 @@ def __getitem__(self, index): profiles = self.full_profiles() return profiles[index] + def _resolve_count(self, num): + return self.num if num is None else num + def ip_address(self, num: int = None) -> List[str]: """Generate one or more IPv4 addresses.""" count = self.num if num is None else num @@ -107,21 +137,21 @@ def job_title(self, num: int = None) -> List[str]: count = self.num if num is None else num if count == 1: return [random.choice(job_titles)] - return random.choices(job_titles, k=count) + return random.choices(job_titles, k=self._resolve_count(num)) def blood_type(self, num: int = None) -> List[str]: """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) + return random.choices(blood_types, k=self._resolve_count(num)) def hair_color(self, num: int = None) -> List[str]: """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) + return random.choices(hair_colors, k=self._resolve_count(num)) def dob_age(self, num: int = None) -> List[Tuple[str, int]]: """Generate DOB and age tuples.""" @@ -175,14 +205,14 @@ def first_names(self, num: int = None, gender: Gender = None) -> List[str]: if count == 1: return [random.choice(names_pool)] - return random.choices(names_pool, k=count) + return random.choices(names_pool, k=self._resolve_count(num)) 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) + return random.choices(lname, k=self._resolve_count(num)) def full_names(self, num: int = None, gender: Gender = None) -> List[str]: """Generate one or more full names (first + last).""" @@ -251,31 +281,56 @@ def full_profiles(self, num: int = None, gender: Gender = None) -> List[dict]: card = utils.generate_random_card() # 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) + # 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) + profile = Profile( + id=str(uuid.uuid4()), + gender=this_gender.value if this_gender.value is not None else "", + first_name=f_name, + last_name=l_name, + full_name=full_name, + hair_color=hair, + blood_type=blood, + 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(), + address=address_dict, + full_address=full_address, + job_experience=job_experience, + mother=mother, + father=father, + payment_card=card, + coordinates=coords_pretty + ) + profile_list.append(asdict(profile)) return profile_list diff --git a/setup.py b/setup.py index eb41f55..3ec58b8 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ __title__ = 'RandomProfileGenerator' __package_name__ = 'random_profile' -__version__ = '3.0.5' +__version__ = '3.0.6' __description__ = "Python Module To Generate Random Profile Data" __email__ = "deepak008@live.com" __author__ = 'Deepak Raj' diff --git a/tests/test_cases.py b/tests/test_cases.py index f46ff15..776468b 100644 --- a/tests/test_cases.py +++ b/tests/test_cases.py @@ -14,7 +14,7 @@ class RandomProfileTest(unittest.TestCase): # ----------------------------------------------------------------- # def test_fname_instance(self): - self.assertIsInstance(random_profile.first_names(), str) + self.assertIsInstance(random_profile.first_names(), List) def test_faname_with_num(self): self.assertEqual(len(RandomProfile(num=10).first_names()), 10) @@ -24,7 +24,7 @@ def test_fname_with_num_instance(self): # ----------------------------------------------------------------- # def test_lname_instance(self): - self.assertIsInstance(random_profile.last_names(), str) + self.assertIsInstance(random_profile.last_names(), List) def test_lname_with_num(self): self.assertEqual(len(RandomProfile(num=10).last_names()), 10) @@ -34,7 +34,7 @@ def test_lname_with_num_instance(self): # ----------------------------------------------------------------- # def test_full_names_instance(self): - self.assertIsInstance(random_profile.full_names(), str) + self.assertIsInstance(random_profile.full_names(), List) def test_full_names_with_num(self): self.assertEqual(len(RandomProfile(num=10).full_names()), 10) @@ -54,7 +54,7 @@ def test_full_profiles_with_num_instance(self): # ----------------------------------------------------------------- # def test_ipv4_instance(self): - self.assertIsInstance(random_profile.ip_address(), str) + self.assertIsInstance(random_profile.ip_address(), List) def test_ipv4_with_num(self): self.assertEqual(len(RandomProfile(num=10).ip_address()), 10) @@ -64,7 +64,7 @@ def test_ipv4_with_num_instance(self): # ----------------------------------------------------------------- # def test_job_title_instance(self): - self.assertIsInstance(random_profile.job_title(), str) + self.assertIsInstance(random_profile.job_title(), List) def test_job_title_with_num(self): self.assertEqual(len(RandomProfile(num=10).job_title()), 10) @@ -74,7 +74,7 @@ def test_job_title_with_num_instance(self): # ----------------------------------------------------------------- # def test_blood_type_instance(self): - self.assertIsInstance(random_profile.blood_type(), str) + self.assertIsInstance(random_profile.blood_type(), List) def test_blood_type_with_num(self): self.assertEqual(len(RandomProfile(num=10).blood_type()), 10) @@ -84,7 +84,7 @@ def test_blood_type_with_num_instance(self): # ----------------------------------------------------------------- # def test_hair_color_instance(self): - self.assertIsInstance(random_profile.hair_color(), str) + self.assertIsInstance(random_profile.hair_color(), List) def test_hair_color_with_num(self): self.assertEqual(len(RandomProfile(num=10).hair_color()), 10) @@ -94,7 +94,7 @@ def test_hair_color_with_num_instance(self): # ----------------------------------------------------------------- # def test_dob_age_instance(self): - self.assertIsInstance(random_profile.dob_age(), Tuple) + self.assertIsInstance(random_profile.dob_age(), List) def test_dob_age_with_num(self): self.assertEqual(len(RandomProfile(num=10).dob_age()), 10)