fake.py
Minimalistic, standalone alternative fake data generator with no dependencies.
fake.py is a standalone, portable library designed for generating various random data types for testing.
It offers a simplified, dependency-free alternative for creating random texts, (person) names, URLs, dates, file names, IPs, primitive Python data types (such as uuid, str, int, float, bool), GEO data such as city, country, geo-location, country code, latitude, longitude and locales, IBANs and ISBNs, as well as byte content for multiple file formats including PDF, DOCX, ODT, PNG, SVG, BMP, GIF, TIF, PPM, JPG, WAV, ZIP, TAR and EML.
The package also supports file creation on the filesystem and includes factories (dynamic fixtures) compatible with Django, TortoiseORM, Pydantic and SQLAlchemy (which means it works with SQLModel too).
Features
Generation of random texts, (person) names, emails, URLs, dates, IPs, and primitive Python data types.
Support for various file formats (PDF, DOCX, ODT, TXT, PNG, SVG, BMP, GIF, TIF, PPM, JPG, WAV, ZIP, TAR, EML) and file creation on the filesystem.
Basic factories for integration with Django, Pydantic, TortoiseORM and SQLAlchemy.
CLI for generating data from command line.
Prerequisites
Python 3.9+
Installation
pip
pip install fake.py
Download and copy
fake.py
is the sole, self-contained module of the package. It includes
tests too. If it’s more convenient to you, you could simply download the
fake.py
module and include it in your repository.
Since tests are included, it won’t have a negative impact on your test coverage (you might need to apply tweaks to your coverage configuration).
Documentation
Documentation is available on Read the Docs.
For various ready to use code examples see the Recipes.
For tips on how to use the factories see the Factories.
For customization tips see the Customization.
For generic information on how to create files see Creating files.
For tips on
PDF
creation see Creating PDF.For tips on
DOCX
creation see Creating DOCX.For tips on
ODT
creation see Creating ODT.For tips on images creation see Creating images.
For tips on archives creation see Creating archives.
For various implementation examples, see the Examples.
For CLI documentation, see the CLI.
For guidelines on contributing check the Contributor guidelines.
Usage
Generate data
Person names
from fake import FAKER
FAKER.first_name() # str
FAKER.first_names() # list[str]
FAKER.last_name() # str
FAKER.last_names() # list[str]
FAKER.name() # str
FAKER.names() # list[str]
FAKER.username() # str
FAKER.usernames() # list[str]
Random texts
from fake import FAKER
FAKER.password() # str
FAKER.paragraph() # str
FAKER.paragraphs() # list[str]
FAKER.sentence() # str
FAKER.sentences() # list[str]
FAKER.slug() # str
FAKER.slugs() # list[str]
FAKER.text() # str
FAKER.texts() # list[str]
FAKER.word() # str
FAKER.words() # list[str]
Internet
from fake import FAKER
FAKER.company_email() # str
FAKER.domain_name() # str
FAKER.email() # str
FAKER.free_email() # str
FAKER.free_email_domain() # str
FAKER.image_url() # str
FAKER.ipv4() # str
FAKER.tld() # str
FAKER.url() # str
Filenames
from fake import FAKER
FAKER.file_extension() # str
FAKER.file_name() # str
FAKER.mime_type() # str
Primitive data types
from fake import FAKER
FAKER.pybool() # bool
FAKER.pyfloat() # flot
FAKER.pyint() # int
FAKER.pystr() # str
FAKER.uuid() # uuid.UUID
Dates
from fake import FAKER
FAKER.date() # datetime.date
FAKER.date_time() # datetime.datetime
Geographic data
from fake import FAKER
FAKER.city() # str
FAKER.country() # str
FAKER.geo_location() # str
FAKER.country_code() # str
FAKER.locale() # str
FAKER.latitude() # float
FAKER.longitude() # float
FAKER.latitude_longitude() # tuple[float, float]
Books
from fake import FAKER
FAKER.isbn10() # str
FAKER.isbn13() # str
Banking
from fake import FAKER
FAKER.iban() # str
Generate files
As bytes
from fake import FAKER
FAKER.bmp() # bytes
FAKER.docx() # bytes
FAKER.eml() # bytes
FAKER.gif() # bytes
FAKER.jpg() # bytes
FAKER.odt() # bytes
FAKER.pdf() # bytes
FAKER.png() # bytes
FAKER.ppm() # bytes
FAKER.svg() # bytes
FAKER.tar() # bytes
FAKER.tif() # bytes
FAKER.wav() # bytes
FAKER.zip() # bytes
As files on the file system
from fake import FAKER
FAKER.bmp_file() # str
FAKER.docx_file() # str
FAKER.eml_file() # str
FAKER.gif_file() # str
FAKER.jpg_file() # str
FAKER.odt_file() # str
FAKER.pdf_file() # str
FAKER.png_file() # str
FAKER.ppm_file() # str
FAKER.svg_file() # str
FAKER.tar_file() # str
FAKER.tif_file() # str
FAKER.txt_file() # str
FAKER.wav_file() # str
FAKER.zip_file() # str
Factories/dynamic fixtures
This is how you could define factories for Django’s built-in Group
and User
models.
Filename: factories.py
from django.contrib.auth.models import Group, User
from fake import (
DjangoModelFactory,
FACTORY,
PostSave,
PreSave,
trait,
)
class GroupFactory(DjangoModelFactory):
"""Group factory."""
name = FACTORY.word()
class Meta:
model = Group
get_or_create = ("name",)
def set_password(user: User, password: str) -> None:
"""Helper function for setting password for the User."""
user.set_password(password)
def add_to_group(user: User, name: str) -> None:
"""Helper function for adding the User to a Group."""
group = GroupFactory(name=name)
user.groups.add(group)
class UserFactory(DjangoModelFactory):
"""User factory."""
username = FACTORY.username()
first_name = FACTORY.first_name()
last_name = FACTORY.last_name()
email = FACTORY.email()
date_joined = FACTORY.date_time()
last_login = FACTORY.date_time()
is_superuser = False
is_staff = False
is_active = FACTORY.pybool()
password = PreSave(set_password, password="test1234")
group = PostSave(add_to_group, name="Test group")
class Meta:
model = User
get_or_create = ("username",)
@trait
def is_admin_user(self, instance: User) -> None:
"""Trait."""
instance.is_superuser = True
instance.is_staff = True
instance.is_active = True
And this is how you could use it:
# Create just one user
user = UserFactory()
# Create 5 users
users = UserFactory.create_batch(5)
# Create a user using `is_admin_user` trait
user = UserFactory(is_admin_user=True)
# Create a user with custom password
user = UserFactory(
password=PreSave(set_password, password="another-password"),
)
# Add a user to another group
user = UserFactory(
group=PostSave(add_to_group, name="Another group"),
)
# Or even add user to multiple groups at once
user = UserFactory(
group_1=PostSave(add_to_group, name="Another group"),
group_2=PostSave(add_to_group, name="Yet another group"),
)
Customize
Make your own custom providers and utilize factories with them.
Filename: custom_fake.py
import random
import string
from fake import Faker, Factory, provider
class CustomFaker(Faker):
@provider
def postal_code(self) -> str:
number_part = "".join(random.choices(string.digits, k=4))
letter_part = "".join(random.choices(string.ascii_uppercase, k=2))
return f"{number_part} {letter_part}"
FAKER = CustomFaker()
FACTORY = Factory(FAKER)
Now you can use it as follows (make sure to import your custom instances
of FAKER
and FACTORY
):
from custom_fake import FAKER # Custom `FAKER` instance
FAKER.postal_code()
Or as follows:
from fake import ModelFactory
from custom_fake import FACTORY # Custom `FACTORY` instance
class AddressFactory(ModelFactory):
# ... other definitions
postal_code = FACTORY.postal_code()
# ... other definitions
class Meta:
model = Address
Tests
Run the tests with unittest:
python -m unittest fake.py
Or pytest:
pytest
Differences with alternatives
fake.py is Faker + factory_boy + faker-file in one package, radically simplified and reduced in features, but without any external dependencies (not even Pillow or dateutil).
fake.py is modeled after the famous Faker package. Its’ API is highly compatible, although drastically reduced. It’s not multilingual and does not support postal codes or that many RAW file formats. However, you could easily include it in your production setup without worrying about yet another dependency.
On the other hand, fake.py factories look quite similar to factory_boy factories, although again - drastically simplified and reduced in features.
The file generation part of fake.py is modelled after the faker-file. You don’t get a large variety of file types supported and you don’t have that much control over the content of the files generated, but you get dependency-free valid files and if that’s all you need, you don’t need to look further.
However, at any point, if you discover that you “need more”, go for Faker, factory_boy and faker-file combination.
Benchmarks
See fake-py-benchmarks for the details.
Writing documentation
Keep the following hierarchy.
=====
title
=====
header
======
sub-header
----------
sub-sub-header
~~~~~~~~~~~~~~
sub-sub-sub-header
^^^^^^^^^^^^^^^^^^
sub-sub-sub-sub-header
++++++++++++++++++++++
sub-sub-sub-sub-sub-header
**************************
License
MIT
Support
For security issues contact me at the e-mail given in the Author section.
For overall issues, go to GitHub.
Project documentation
Contents: