Source code for mimesis.providers.person

# -*- coding: utf-8 -*-

"""Provides personal data."""

import hashlib
import re
from string import ascii_letters, digits, punctuation
from typing import Any, Final, List, Optional, Sequence, Tuple, Union

from mimesis.data import (
    BLOOD_GROUPS,
    CALLING_CODES,
    EMAIL_DOMAINS,
    GENDER_SYMBOLS,
    USERNAMES,
)
from mimesis.enums import Gender, TitleType
from mimesis.exceptions import NonEnumerableError
from mimesis.providers.base import BaseDataProvider
from mimesis.random import get_random_item

__all__ = ["Person"]


[docs]class Person(BaseDataProvider): """Class for generating personal data."""
[docs] def __init__(self, *args: Any, **kwargs: Any) -> None: """Initialize attributes. :param locale: Current locale. :param seed: Seed. """ super().__init__(*args, **kwargs) self._datafile = "person.json" self._load_datafile(self._datafile) self._store = { "age": 0, }
[docs] class Meta: """Class for metadata.""" name: Final[str] = "person"
[docs] def age(self, minimum: int = 16, maximum: int = 66) -> int: """Get a random integer value. :param maximum: Maximum value of age. :param minimum: Minimum value of age. :return: Random integer. :Example: 23. """ age = self.random.randint(minimum, maximum) self._store["age"] = age return age
[docs] def work_experience(self, working_start_age: int = 22) -> int: """Get a work experience. :param working_start_age: Age then person start to work. :return: Depend on previous generated age. """ age = self._store["age"] if age == 0: age = self.age() return max(age - working_start_age, 0)
[docs] def name(self, gender: Optional[Gender] = None) -> str: """Generate a random name. :param gender: Gender's enum object. :return: Name. :Example: John. """ key = self.validate_enum(gender, Gender) names: List[str] = self.extract(["names", key]) return self.random.choice(names)
[docs] def first_name(self, gender: Optional[Gender] = None) -> str: """Generate a random first name. ..note: An alias for self.name(). :param gender: Gender's enum object. :return: First name. """ return self.name(gender)
[docs] def surname(self, gender: Optional[Gender] = None) -> str: """Generate a random surname. :param gender: Gender's enum object. :return: Surname. :Example: Smith. """ surnames: Sequence[str] = self.extract(["surnames"]) # Surnames separated by gender. if isinstance(surnames, dict): key = self.validate_enum(gender, Gender) surnames = surnames[key] return self.random.choice(surnames)
[docs] def last_name(self, gender: Optional[Gender] = None) -> str: """Generate a random last name. ..note: An alias for self.surname(). :param gender: Gender's enum object. :return: Last name. """ return self.surname(gender)
[docs] def title( self, gender: Optional[Gender] = None, title_type: Optional[TitleType] = None ) -> str: """Generate a random title for name. You can generate random prefix or suffix for name using this method. :param gender: The gender. :param title_type: TitleType enum object. :return: The title. :raises NonEnumerableError: if gender or title_type in incorrect format. :Example: PhD. """ gender_key = self.validate_enum(gender, Gender) title_key = self.validate_enum(title_type, TitleType) titles: List[str] = self.extract(["title", gender_key, title_key]) return self.random.choice(titles)
[docs] def full_name(self, gender: Optional[Gender] = None, reverse: bool = False) -> str: """Generate a random full name. :param reverse: Return reversed full name. :param gender: Gender's enum object. :return: Full name. :Example: Johann Wolfgang. """ if gender is None: gender = get_random_item(Gender, rnd=self.random) if gender and isinstance(gender, Gender): gender = gender else: raise NonEnumerableError(Gender) fmt = "{1} {0}" if reverse else "{0} {1}" return fmt.format( self.name(gender), self.surname(gender), )
[docs] def username( self, mask: Optional[str] = None, drange: Tuple[int, int] = (1800, 2100) ) -> str: """Generate username by template. You can create many different usernames using masks. - **C** stands for capitalized username. - **U** stands for uppercase username. - **l** stands for lowercase username. - **d** stands for digits in username. You can also use symbols to separate the different parts of the username: **.** **_** **-** :param mask: Mask. :param drange: Digits range. :raises ValueError: If template is not supported. :return: Username as string. Example: >>> username(mask='C_C_d') Cotte_Article_1923 >>> username(mask='U.l.d') ELKINS.wolverine.2013 >>> username(mask='l_l_d', drange=(1900, 2021)) plasmic_blockader_1907 """ if len(drange) != 2: raise ValueError("The drange parameter must contain only two integers.") if mask is None: mask = "l_d" required_tags = "CUl" tags = re.findall(r"[CUld.\-_]", mask) if not any(tag in tags for tag in required_tags): raise ValueError( "Username mask must contain at least one of these: (C, U, l)." ) final_username = "" for tag in tags: username = self.random.choice(USERNAMES) if tag == "C": final_username += username.capitalize() if tag == "U": final_username += username.upper() elif tag == "l": final_username += username.lower() elif tag == "d": final_username += str(self.random.randint(*drange)) elif tag in "-_.": final_username += tag return final_username
[docs] def password(self, length: int = 8, hashed: bool = False) -> str: """Generate a password or hash of password. :param length: Length of password. :param hashed: MD5 hash. :return: Password or hash of password. :Example: k6dv2odff9#4h """ text = ascii_letters + digits + punctuation password = "".join([self.random.choice(text) for _ in range(length)]) if hashed: md5 = hashlib.md5() md5.update(password.encode()) return md5.hexdigest() return password
[docs] def email( self, domains: Optional[Sequence[str]] = None, unique: bool = False, ) -> str: """Generate a random email. :param domains: List of custom domains for emails. :param unique: Makes email addresses unique. :return: Email address. :raises ValueError: if «unique» is True and the provider was seeded. :Example: foretime10@live.com """ if unique and self.seed is not None: raise ValueError( "You cannot use «unique» parameter with the seeded provider" ) if not domains: domains = EMAIL_DOMAINS domain = self.random.choice(domains) if not domain.startswith("@"): domain = "@" + domain if unique: name = self.random.randstr(unique) else: name = self.username(mask="ld") return "{name}{domain}".format( name=name, domain=domain, )
[docs] def gender(self, iso5218: bool = False, symbol: bool = False) -> Union[str, int]: """Get a random gender. Get a random title of gender, code for the representation of human sexes is an international standard that defines a representation of human sexes through a language-neutral single-digit code or symbol of gender. :param iso5218: Codes for the representation of human sexes is an international standard (0 - not known, 1 - male, 2 - female, 9 - not applicable). :param symbol: Symbol of gender. :return: Title of gender. :Example: Male """ if iso5218: return self.random.choice([0, 1, 2, 9]) if symbol: return self.random.choice(GENDER_SYMBOLS) genders: List[str] = self.extract(["gender"]) return self.random.choice(genders)
[docs] def sex(self, *args: Any, **kwargs: Any) -> Union[str, int]: """An alias for method self.gender(). See docstrings of method self.gender() for details. :param args: Positional arguments. :param kwargs: Keyword arguments. :return: Sex """ return self.gender(*args, **kwargs)
[docs] def height(self, minimum: float = 1.5, maximum: float = 2.0) -> str: """Generate a random height in meters. :param minimum: Minimum value. :param float maximum: Maximum value. :return: Height. :Example: 1.85. """ h = self.random.uniform(minimum, maximum) return "{:0.2f}".format(h)
[docs] def weight(self, minimum: int = 38, maximum: int = 90) -> int: """Generate a random weight in Kg. :param minimum: min value :param maximum: max value :return: Weight. :Example: 48. """ return self.random.randint(minimum, maximum)
[docs] def blood_type(self) -> str: """Get a random blood type. :return: Blood type (blood group). :Example: A+ """ return self.random.choice(BLOOD_GROUPS)
[docs] def occupation(self) -> str: """Get a random job. :return: The name of job. :Example: Programmer. """ jobs: List[str] = self.extract(["occupation"]) return self.random.choice(jobs)
[docs] def political_views(self) -> str: """Get a random political views. :return: Political views. :Example: Liberal. """ views: List[str] = self.extract(["political_views"]) return self.random.choice(views)
[docs] def worldview(self) -> str: """Get a random worldview. :return: Worldview. :Example: Pantheism. """ views: List[str] = self.extract(["worldview"]) return self.random.choice(views)
[docs] def views_on(self) -> str: """Get a random views on. :return: Views on. :Example: Negative. """ views: List[str] = self.extract(["views_on"]) return self.random.choice(views)
[docs] def nationality(self, gender: Optional[Gender] = None) -> str: """Get a random nationality. :param gender: Gender. :return: Nationality. :Example: Russian """ nationalities: List[str] = self.extract(["nationality"]) # Separated by gender if isinstance(nationalities, dict): key = self.validate_enum(gender, Gender) nationalities = nationalities[key] return self.random.choice(nationalities)
[docs] def university(self) -> str: """Get a random university. :return: University name. :Example: MIT. """ universities: List[str] = self.extract(["university"]) return self.random.choice(universities)
[docs] def academic_degree(self) -> str: """Get a random academic degree. :return: Degree. :Example: Bachelor. """ degrees: List[str] = self.extract(["academic_degree"]) return self.random.choice(degrees)
[docs] def language(self) -> str: """Get a random language. :return: Random language. :Example: Irish. """ languages: List[str] = self.extract(["language"]) return self.random.choice(languages)
[docs] def telephone(self, mask: str = "", placeholder: str = "#") -> str: """Generate a random phone number. :param mask: Mask for formatting number. :param placeholder: A placeholder for a mask (default is #). :return: Phone number. :Example: +7-(963)-409-11-22. """ if not mask: code = self.random.choice(CALLING_CODES) default = "{}-(###)-###-####".format(code) masks = self.extract(["telephone_fmt"], default=[default]) mask = self.random.choice(masks) return self.random.custom_code(mask=mask, digit=placeholder)
[docs] def identifier(self, mask: str = "##-##/##") -> str: """Generate a random identifier by mask. With this method you can generate any identifiers that you need. Simply select the mask that you need. :param mask: The mask. Here ``@`` is a placeholder for characters and ``#`` is placeholder for digits. :return: An identifier. :Example: 07-97/04 """ return self.random.custom_code(mask=mask)