123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- # coding=utf-8
- from collections import Counter
- import re
- import string
- from faker.utils.distribution import choices_distribution, choices_distribution_unique
- _re_hash = re.compile(r'#')
- _re_perc = re.compile(r'%')
- _re_excl = re.compile(r'!')
- _re_at = re.compile(r'@')
- _re_qm = re.compile(r'\?')
- _re_cir = re.compile(r'\^')
- class BaseProvider(object):
- __provider__ = 'base'
- __lang__ = None
- def __init__(self, generator):
- self.generator = generator
- def random_int(self, min=0, max=9999):
- """
- Returns a random integer between two values.
- :param min: lower bound value (inclusive; default=0)
- :param max: upper bound value (inclusive; default=9999)
- :returns: random integer between min and max
- """
- return self.generator.random.randint(min, max)
- def random_digit(self):
- """
- Returns a random digit/number
- between 0 and 9.
- """
- return self.generator.random.randint(0, 9)
- def random_digit_not_null(self):
- """
- Returns a random non-zero digit/number
- between 1 and 9.
- """
- return self.generator.random.randint(1, 9)
- def random_digit_or_empty(self):
- """
- Returns a random digit/number
- between 0 and 9 or an empty string.
- """
- if self.generator.random.randint(0, 1):
- return self.generator.random.randint(0, 9)
- else:
- return ''
- def random_digit_not_null_or_empty(self):
- """
- Returns a random non-zero digit/number
- between 1 and 9 or and empty string.
- """
- if self.generator.random.randint(0, 1):
- return self.generator.random.randint(1, 9)
- else:
- return ''
- def random_number(self, digits=None, fix_len=False):
- """
- Returns a random number with 1 digit (default, when digits==None),
- a random number with 0 to given number of digits, or a random number
- with given number to given number of digits (when ``fix_len==True``).
- :param digits: maximum number of digits
- :param fix_len: should the number have fixed length?
- :returns: random number with 0 to given number of digits or
- fixed length number
- """
- if digits is None:
- digits = self.random_digit()
- if fix_len:
- return self.generator.random.randint(
- pow(10, digits - 1), pow(10, digits) - 1)
- else:
- return self.generator.random.randint(0, pow(10, digits) - 1)
- def random_letter(self):
- """Returns a random letter (between a-z and A-Z)."""
- return self.generator.random.choice(
- getattr(string, 'letters', string.ascii_letters))
- def random_letters(self, length=16):
- """Returns a random letter (between a-z and A-Z)."""
- return self.random_choices(
- getattr(string, 'letters', string.ascii_letters),
- length=length,
- )
- def random_lowercase_letter(self):
- """Returns a random lowercase letter (between a-z)."""
- return self.generator.random.choice(string.ascii_lowercase)
- def random_uppercase_letter(self):
- """Returns a random letter (between A-Z)."""
- return self.generator.random.choice(string.ascii_uppercase)
- def random_elements(self, elements=('a', 'b', 'c'), length=None, unique=False):
- fn = choices_distribution_unique if unique else choices_distribution
- if length is None:
- length = self.generator.random.randint(1, len(elements))
- if unique and length > len(elements):
- raise ValueError(
- "Sample length cannot be longer than the number of unique elements to pick from.")
- if isinstance(elements, dict):
- choices = elements.keys()
- probabilities = elements.values()
- else:
- if unique:
- # shortcut
- return self.generator.random.sample(elements, length)
- choices = elements
- probabilities = [1.0 for _ in range(len(choices))]
- return fn(
- list(choices),
- list(probabilities),
- self.generator.random,
- length=length,
- )
- def random_choices(self, elements=('a', 'b', 'c'), length=None):
- """
- Returns a list of random, non-unique elements from a passed object.
- If `elements` is a dictionary, the value will be used as
- a weighting element. For example::
- random_element({"{{variable_1}}": 0.5, "{{variable_2}}": 0.2, "{{variable_3}}": 0.2, "{{variable_4}}": 0.1})
- will have the following distribution:
- * `variable_1`: 50% probability
- * `variable_2`: 20% probability
- * `variable_3`: 20% probability
- * `variable_4`: 10% probability
- """
- return self.random_elements(elements, length, unique=False)
- def random_element(self, elements=('a', 'b', 'c')):
- """
- Returns a random element from a passed object.
- If `elements` is a dictionary, the value will be used as
- a weighting element. For example::
- random_element({"{{variable_1}}": 0.5, "{{variable_2}}": 0.2, "{{variable_3}}": 0.2, "{{variable_4}}": 0.1})
- will have the following distribution:
- * `variable_1`: 50% probability
- * `variable_2`: 20% probability
- * `variable_3`: 20% probability
- * `variable_4`: 10% probability
- """
- return self.random_elements(elements, length=1)[0]
- def random_sample(self, elements=('a', 'b', 'c'), length=None):
- """
- Returns a list of random unique elements for the specified length.
- Multiple occurrences of the same value increase its probability to be in the output.
- """
- return self.random_elements(elements, length, unique=True)
- def randomize_nb_elements(
- self,
- number=10,
- le=False,
- ge=False,
- min=None,
- max=None):
- """
- Returns a random value near number.
- :param number: value to which the result must be near
- :param le: result must be lower or equal to number
- :param ge: result must be greater or equal to number
- :returns: a random int near number
- """
- if le and ge:
- return number
- _min = 100 if ge else 60
- _max = 100 if le else 140
- nb = int(number * self.generator.random.randint(_min, _max) / 100)
- if min is not None and nb < min:
- nb = min
- if max is not None and nb > min:
- nb = max
- return nb
- def numerify(self, text='###'):
- """
- Replaces all placeholders in given text with randomized values,
- replacing: all hash sign ('#') occurrences with a random digit
- (from 0 to 9); all percentage sign ('%') occurrences with a
- random non-zero digit (from 1 to 9); all exclamation mark ('!')
- occurrences with a random digit (from 0 to 9) or an empty string;
- and all at symbol ('@') occurrences with a random non-zero digit
- (from 1 to 9) or an empty string.
- :param text: string to be parsed
- :returns: string with all numerical placeholders filled in
- """
- text = _re_hash.sub(
- lambda x: str(self.random_digit()),
- text)
- text = _re_perc.sub(
- lambda x: str(self.random_digit_not_null()),
- text)
- text = _re_excl.sub(
- lambda x: str(self.random_digit_or_empty()),
- text)
- text = _re_at.sub(
- lambda x: str(self.random_digit_not_null_or_empty()),
- text)
- return text
- def lexify(self, text='????', letters=string.ascii_letters):
- """
- Replaces all question mark ('?') occurrences with a random letter.
- :param text: string to be parsed
- :param letters: a set of letters to choose from.
- :returns: string with all letter placeholders filled in
- """
- return _re_qm.sub(lambda x: self.random_element(letters), text)
- def bothify(self, text='## ??', letters=string.ascii_letters):
- """
- Replaces all placeholders with random numbers and letters.
- :param text: string to be parsed
- :returns: string with all numerical and letter placeholders filled in
- """
- return self.lexify(self.numerify(text), letters=letters)
- def hexify(self, text='^^^^', upper=False):
- """
- Replaces all circumflex ('^') occurrences with a random
- hexadecimal character.
- :param text: string to be parsed
- :param upper: Format as uppercase hexadecimal
- :returns: string with all letter placeholders filled in
- """
- letters = string.hexdigits[:-6]
- if upper:
- letters = letters.upper()
- return _re_cir.sub(lambda x: self.random_element(letters), text)
|