Skip to content

Commit

Permalink
Merge pull request #23 from Gaffney/faker-to-fake-factory
Browse files Browse the repository at this point in the history
faker -> fake-factory
  • Loading branch information
terite committed Apr 13, 2016
2 parents 8c28c31 + f33eea6 commit fca30d3
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 96 deletions.
40 changes: 16 additions & 24 deletions anonymizer/base.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import decimal
import random
import six

from six.moves import xrange

from collections import defaultdict
from datetime import datetime
from multiprocessing import Pool
from uuid import uuid4

import six
from anonymizer import replacers
from django.db import connection, transaction
from faker import Faker, data
from faker.utils import bothify, uk_postcode
from faker import Faker

from six.moves import xrange

randrange = random.SystemRandom().randrange

Expand Down Expand Up @@ -73,13 +71,9 @@ def get_allowed_value(self, source, field):

return retval

# Public interface
def uuid(self, field=None):
retval = str(uuid4())
max_length = getattr(field, 'max_length', None)
if max_length is not None:
retval = retval[:max_length]
return retval
# bypass chopping from max_length
return str(uuid4())

def varchar(self, field=None):
"""
Expand All @@ -98,7 +92,7 @@ def simple_pattern(self, pattern, field=None):
Use a simple pattern to make the field - # is replaced with a random number,
? with a random letter.
"""
return self.get_allowed_value(lambda: bothify(pattern), field)
return self.get_allowed_value(lambda: self.faker.bothify(pattern), field)

def bool(self, field=None):
"""
Expand Down Expand Up @@ -144,14 +138,11 @@ def source():
return decimal.Decimal(random.randrange(0, 100000))/(10**field.decimal_places)
return self.get_allowed_value(source, field)

def uk_postcode(self, field=None):
return self.get_allowed_value(uk_postcode, field)

def uk_county(self, field=None):
return self.get_allowed_value(lambda: random.choice(data.UK_COUNTIES), field)
def postcode(self, field=None):
return self.get_allowed_value(self.faker.postcode, field)

def uk_country(self, field=None):
return self.get_allowed_value(lambda: random.choice(data.UK_COUNTRIES), field)
def country(self, field=None):
return self.get_allowed_value(self.faker.country, field)

def lorem(self, field=None, val=None):
"""
Expand All @@ -164,7 +155,7 @@ def generate(length):
# Get lorem ipsum of a specific length.
collect = ""
while len(collect) < length:
collect += self.faker.lorem()
collect += ' %s' % self.faker.sentence()
collect = collect[:length]
return collect

Expand All @@ -177,7 +168,8 @@ def source():
parts[i] = generate(len(p))
return "\n".join(parts)
else:
source = self.faker.lorem
def source():
return ' '.join(self.faker.sentences())
return self.get_allowed_value(source, field)

def unique_lorem(self, field=None, val=None):
Expand All @@ -202,12 +194,12 @@ def choice(self, field=None):
return self.get_allowed_value(lambda: random.choice(choices), field)

# Other attributes provided by 'Faker':
# username
# user_name
# first_name
# last_name
# name
# email
# full_address
# address
# phonenumber
# street_address
# city
Expand Down
15 changes: 1 addition & 14 deletions anonymizer/introspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@
(r'(\b|_)email\d*', '"email"'),
(r'(\b|_)town\d*', '"city"'),
(r'(\b|_)city\d*', '"city"'),
(r'(\b|_)county\d*', '"uk_county"'),
(r'(\b|_)post_code\d*', '"uk_postcode"'),
(r'(\b|_)postcode\d*', '"uk_postcode"'),
(r'(\b|_)zip\d*', '"zip_code"'),
(r'(\b|_)zipcode\d*', '"zip_code"'),
(r'(\b|_)zip_code\d*', '"zip_code"'),
Expand Down Expand Up @@ -97,17 +94,7 @@ class %(modelname)sAnonymizer(Anonymizer):

def create_anonymizer(model):
attributes = []
fields = list(model._meta.fields)
# For the faker.name/username/email magic to work as expected and produce
# consistent sets of names/email addreses, they must be accessed in the
# same order. This will usually not be a problem, but if duplicate names
# are produced and the field is unique=True, the logic in DjangoFaker for
# getting new values from the 'source' means that the order will become out
# of sync. To avoid this, we put fields with 'unique=True' at the beginning
# of the list. Usually this will only be the username.
fields.sort(key=lambda f: not getattr(f, 'unique', False))

for f in fields:
for f in model._meta.fields:
replacer = get_replacer_for_field(f)
attributes.append(attribute_template % {'attname': f.attname,
'replacer': replacer})
Expand Down
29 changes: 11 additions & 18 deletions anonymizer/replacers.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,32 +71,25 @@ def decimal(anon, obj, field, val):
return anon.faker.decimal(field=field)


def uk_postcode(anon, obj, field, val):
def postcode(anon, obj, field, val):
"""
Generates a random UK postcode (not necessarily valid, but it will look like one).
Generates a random postcode (not necessarily valid, but it will look like one).
"""
return anon.faker.uk_postcode(field=field)
return anon.faker.postcode(field=field)


def uk_country(anon, obj, field, val):
def country(anon, obj, field, val):
"""
Returns a randomly selected country that is part of the UK
Returns a randomly selected country.
"""
return anon.faker.uk_country(field=field)


def uk_county(anon, obj, field, val):
"""
Returns a randomly selected county from the UK
"""
return anon.faker.uk_county(field=field)
return anon.faker.country(field=field)


def username(anon, obj, field, val):
"""
Generates a random username
"""
return anon.faker.username(field=field)
return anon.faker.user_name(field=field)


def first_name(anon, obj, field, val):
Expand Down Expand Up @@ -139,14 +132,14 @@ def full_address(anon, obj, field, val):
Generates a random full address, using newline characters between the lines.
Resembles a US address
"""
return anon.faker.full_address(field=field)
return anon.faker.address(field=field)


def phonenumber(anon, obj, field, val):
"""
Generates a random US-style phone number
"""
return anon.faker.phonenumber(field=field)
return anon.faker.phone_number(field=field)


def street_address(anon, obj, field, val):
Expand Down Expand Up @@ -174,7 +167,7 @@ def zip_code(anon, obj, field, val):
"""
Returns a randomly generated US zip code (not necessarily valid, but will look like one).
"""
return anon.faker.zip_code(field=field)
return anon.faker.zipcode(field=field)


def company(anon, obj, field, val):
Expand All @@ -188,7 +181,7 @@ def lorem(anon, obj, field, val):
"""
Generates a paragraph of lorem ipsum text
"""
return anon.faker.lorem(field=field)
return ' '.join(anon.faker.sentences(field=field))


def unique_lorem(anon, obj, field, val):
Expand Down
26 changes: 22 additions & 4 deletions anonymizer/tests/models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import uuid

from django.db import models


Expand All @@ -9,12 +11,11 @@ class EverythingModel(models.Model):
name = models.CharField(max_length=30)
email = models.EmailField()
username = models.CharField(max_length=20, unique=True)
address_city = models.CharField(max_length=50)
address_post_code = models.CharField(max_length=10)
address = models.TextField()
o1 = models.ForeignKey(Other)
something = models.TextField()
something_else = models.TextField()
lorem = models.TextField()
similar_lorem = models.TextField()
unique_lorem = models.TextField(unique=True)
some_varchar = models.CharField(max_length=5)
birthday = models.DateTimeField()
age = models.PositiveSmallIntegerField()
Expand All @@ -25,3 +26,20 @@ class EverythingModel(models.Model):
('F', 'Female')])
price = models.DecimalField(decimal_places=2, max_digits=10)
binary = models.BinaryField()
uuid = models.UUIDField(default=uuid.uuid4)
boolean = models.BooleanField()
small_integer = models.SmallIntegerField()
positive_small_integer = models.PositiveSmallIntegerField()
postcode = models.CharField(max_length=9)
country = models.CharField(max_length=45)
first_name = models.CharField(max_length=5)
last_name = models.CharField(max_length=5)
similar_email = models.EmailField()
phonenumber = models.CharField(max_length=10)
last_name = models.CharField(max_length=11)
street_address = models.CharField(max_length=15)
state = models.CharField(max_length=2)
zip_code = models.CharField(max_length=9)
company = models.CharField(max_length=30)
similar_datetime = models.DateTimeField()
similar_date = models.DateField()
Loading

0 comments on commit fca30d3

Please sign in to comment.