Skip to main content

DataForge

PyPI version Python versions CI License: MIT

The fastest fake data generator for Python. Zero dependencies. 18M items/second. Drop-in Faker replacement.

pip install dataforge-py
from dataforge import DataForge

forge = DataForge(seed=42)

forge.person.full_name()                  # "James Smith"
forge.internet.email()                    # "james.smith@gmail.com"
forge.person.first_name(count=1_000_000)  # 1M names in ~55ms

Why DataForge?

DataForge Faker
Throughput 18M items/s ~50K items/s
Dependencies Zero 3+
Batch generation count=N on every method Loop manually
Schema API Built-in, columnar Third-party
Bulk export CSV, JSONL, SQL, Parquet, Arrow, Polars None
CLI Built-in None
Pytest plugin Built-in fixtures Third-party
Type hints Full PEP 484 + @overload Partial
Migration effort from dataforge.compat import Faker

DataForge isn't a wrapper around Faker — it's a ground-up rewrite with vectorized batch paths, pre-resolved field lookups, lazy locale loading, and columnar-first schema generation. If you're generating more than a few hundred records, the difference is measurable in orders of magnitude.


Quick Start

Single values

from dataforge import DataForge

forge = DataForge(locale="en_US", seed=42)

forge.person.first_name()     # "James"
forge.internet.email()        # "james.smith@gmail.com"
forge.address.city()          # "Chicago"
forge.finance.price()         # "49.99"
forge.llm.model_name()        # "gpt-4o"

Batch generation

Every method accepts count=N and returns a list:

names  = forge.person.first_name(count=1000)
emails = forge.internet.email(count=1000)
cities = forge.address.city(count=1000)

Reproducible output

forge_a = DataForge(seed=42)
forge_b = DataForge(seed=42)
assert forge_a.person.first_name() == forge_b.person.first_name()

Migrating from Faker

Change one import. Keep your existing code:

# Before
# from faker import Faker

# After — same API, ~360x faster
from dataforge.compat import Faker

fake = Faker(locale="en_US", seed=42)
fake.name()     # "James Smith"
fake.email()    # "james.smith@gmail.com"
fake.address()  # "4821 Oak Ave, Chicago, IL 60614"

57 Faker methods are mapped. Unknown methods fall back to alias lookup, then direct field matching.


Schema API

Define reusable blueprints for structured data generation:

schema = forge.schema({
    "Name": "person.full_name",
    "Email": "internet.email",
    "City": "address.city",
    "Price": "finance.price",
})

rows = schema.generate(1000)        # list[dict]
csv_str = schema.to_csv(count=5000)
sql_str = schema.to_sql(count=5000, table="users")
df = schema.to_dataframe(count=5000)  # requires pandas

Row-dependent fields for correlated data:

schema = forge.schema({
    "City": "address.city",
    "Greeting": lambda row: f"Hello from {row['City']}!",
})

Bulk Export

# List of dicts
rows = forge.to_dict(fields=["first_name", "email"], count=100)

# CSV
forge.to_csv(fields={"Name": "person.full_name"}, count=5000, path="users.csv")

# JSONL
forge.to_jsonl(fields=["first_name", "email"], count=1000, path="users.jsonl")

# SQL INSERT statements
forge.to_sql(fields=["first_name", "email"], count=500, table="users", dialect="postgresql")

# Pandas / PyArrow / Polars / Parquet (requires optional deps)
df = forge.to_dataframe(fields=["first_name"], count=10_000)
table = forge.to_arrow(fields=["first_name"], count=1_000_000)
df = forge.to_polars(fields=["first_name"], count=1_000_000)
forge.to_parquet(fields=["first_name"], path="out.parquet", count=1_000_000)

Streaming Export

For datasets that don't fit in memory:

forge.stream_to_csv(fields=["first_name", "email"], path="users.csv", count=10_000_000)
forge.stream_to_jsonl(fields=["first_name", "email"], path="users.jsonl", count=10_000_000)

CLI

Generate data from the terminal — no Python required:

dataforge --count 10 --format csv first_name last_name email
dataforge -n 100 -f jsonl -o users.jsonl first_name email city
dataforge --locale fr_FR --seed 42 -n 5 first_name city
dataforge --list-fields
Flag Short Description
--count N -n Number of rows (default: 10)
--format FMT -f text, csv, json, jsonl
--locale LOC -l Locale code (default: en_US)
--seed S -s Random seed
--output PATH -o Write to file
--no-header Omit header row
--list-fields List all available fields

Pytest Plugin

Auto-registers via pytest11 entry point. Three fixtures, zero config:

def test_name(forge):
    assert isinstance(forge.person.first_name(), str)

def test_email(fake):  # alias for forge
    assert "@" in fake.internet.email()

@pytest.mark.forge_seed(42)
def test_deterministic(forge):
    assert forge.person.first_name() == "James"
pytest --forge-seed 42  # session-wide seed

27 Providers, 198 Methods

Every method accepts count=N for batch generation.

person, address, internet, company, phone, finance, datetime — Core providers

person

Method Example
first_name() "James"
last_name() "Smith"
full_name() "James Smith"
male_first_name() "Robert"
female_first_name() "Jennifer"
prefix() "Mr."
suffix() "Jr."

address

Method Example
street_name() "Elm Street"
street_address() "742 Elm Street"
city() "Chicago"
state() "California"
zip_code() "90210"
full_address() "742 Elm St, Chicago, IL 90210"
country() "United States"
country_code() "US"
latitude() / longitude() "41.8781" / "-87.6298"

internet

Method Example
email() "james.smith@gmail.com"
safe_email() "james@example.com"
username() "jsmith42"
domain() "example.com"
url() "https://example.com"
ipv4() "192.168.1.1"
slug() "lorem-ipsum-dolor"

company

Method Example
company_name() "Acme Corp"
job_title() "Software Engineer"
catch_phrase() "Innovative solutions"

phone

Method Example
phone_number() "(555) 123-4567"
cell_phone() "555-987-6543"

finance

Method Example
credit_card_number() "4532015112830366"
iban() "DE89370400440532013000"
bic() "DEUTDEFFXXX"
price(min_val, max_val) "49.99"
currency_code() "USD"
bitcoin_address() "1A1zP1eP5QGefi2DMPTfTL..."

dt (datetime)

Method Example
date(start, end, fmt) "2024-03-15"
datetime(start, end, fmt) "2024-03-15 14:30:00"
date_of_birth(min_age, max_age) "1990-05-12"
timezone() "US/Eastern"
unix_timestamp(start, end) 1710504600
color, file, network, lorem, barcode, misc — Utility providers

color

Method Example
color_name() "red"
hex_color() "#ff5733"
rgb_color() "rgb(255, 87, 51)"

file

Method Example
file_name() "report.pdf"
file_extension() "pdf"
mime_type() "application/pdf"

network

Method Example
mac_address() "00:1B:44:11:3A:B7"
user_agent() "Mozilla/5.0 ..."
port() 8080

lorem

Method Example
word() "lorem"
sentence() "Lorem ipsum dolor sit amet."
paragraph() "Lorem ipsum dolor sit amet, ..."
text() Multi-paragraph string

barcode

Method Example
ean13() "5901234123457"
ean8() "96385074"
upc_a() "012345678905"

misc

Method Example
boolean() True
uuid4() "f47ac10b-58cc-..."
md5() / sha1() / sha256() Hex digest strings
password() "aB3$xK9p"
automotive, crypto, ecommerce, education, geo, government, medical, payment, profile, science, text — Domain providers

automotive

Method Example
vin() "1HGBH41JXMN109186"
license_plate() "ABC-1234"

crypto

Method Example
bitcoin_address() "1A1zP1eP5QGefi2..."
ethereum_address() "0x742d35Cc6634C0532925a3b8D..."

ecommerce

Method Example
product_name() "Wireless Bluetooth Headphones"
category() "Electronics"
sku() "ELC-2847-BLK"

education

Method Example
university() "MIT"
degree() "Bachelor of Science"
course_name() "Introduction to Computer Science"

geo

Method Example
continent() "North America"
timezone_name() "America/Chicago"

government

Method Example
ssn() "123-45-6789"
passport_number() "X1234567"

medical

Method Example
blood_type() "O+"
diagnosis() "Hypertension"
medication() "Lisinopril"

payment

Method Example
credit_card() {"type": "Visa", "number": "...", ...}
card_type() "Visa"

profile

Method Example
profile() Full profile dict
simple_profile() Simplified profile dict

science

Method Example
chemical_element() "Carbon"
scientist() "Marie Curie"

text

Method Example
sentence() Contextual sentence
paragraph() Contextual paragraph
ai_prompt, llm, ai_chat — AI/LLM providers

ai_prompt

Method Example
system_prompt() "You are a helpful assistant..."
user_prompt() "Explain quantum computing..."

llm

Method Example
model_name() "gpt-4o"
provider() "OpenAI"
token_count() 1024

ai_chat

Method Example
conversation() Multi-turn chat dict
message() Single chat message dict

28 Locales

forge = DataForge(locale="fr_FR")
forge.address.city()      # "Paris"
forge.person.full_name()  # "Jean Dupont"

forge = DataForge(locale="ja_JP")
forge.person.full_name()  # "田中太郎"
en_US en_GB en_AU en_CA
de_DE fr_FR es_ES it_IT
pt_BR nl_NL pl_PL ru_RU
ar_SA hi_IN ja_JP ko_KR
zh_CN uk_UA cs_CZ sk_SK
ro_RO hu_HU el_GR da_DK
fi_FI nb_NO sv_SE tr_TR

Multi-locale mixing:

forge = DataForge(locale=["en_US", "fr_FR", "de_DE"])
forge.person.full_name()  # randomly picks a locale per call

Unique Values

name1 = forge.unique.person.first_name()
name2 = forge.unique.person.first_name()
assert name1 != name2

names = forge.unique.person.first_name(count=100)
assert len(names) == len(set(names))

forge.unique.clear()  # reset tracking

Uses adaptive over-sampling — starts at 20% extra and scales with collision rate.


Advanced Features

Dynamic Fields (define()) — Custom data pools and generators
from dataforge import define

schema = forge.schema({
    "Status": define(["active", "inactive", "pending"]),
    "Priority": define(["low", "medium", "high"], weights=[0.5, 0.3, 0.2]),
    "Score": define(lambda: forge.misc.boolean()),
})
Transform Pipelines (pipe()) — Post-generation data transformation
from dataforge import pipe

schema = forge.schema({
    "Username": pipe("internet.username", str.upper),
    "Bio": pipe("lorem.sentence", lambda s: s[:50]),
})
Type-Driven Schema — Generate from dataclasses and TypedDicts
from dataclasses import dataclass

@dataclass
class User:
    first_name: str
    last_name: str
    email: str

schema = forge.schema_from_dataclass(User)
rows = schema.generate(1000)
Data Contract Validation — Semantic pattern and constraint checking
from dataforge.validation import validate

errors = validate(rows, {
    "email": {"pattern": r"^[^@]+@[^@]+\.[^@]+$"},
    "name": {"non_empty": True},
})
Hypothesis Strategy Bridge — Property-based testing integration
from dataforge.hypothesis import strategy

@given(strategy("person.full_name"))
def test_name_format(name):
    assert " " in name
HTTP Mock Data Server — Zero-dependency JSON API
dataforge --serve --port 8080
curl http://localhost:8080/api/users?count=10
XLSX Export — Excel spreadsheet generation
schema.to_excel(count=5000, path="users.xlsx")

Requires openpyxl.

Statistical Distribution Fitting — Infer distributions from data
from dataforge.inference import fit_distribution

fit = fit_distribution(data)
# Normal, LogNormal, Exponential, Beta, Zipf
Time-Series Generation — Trends, seasonality, anomalies
from dataforge.timeseries import TimeSeriesGenerator

ts = TimeSeriesGenerator(forge)
data = ts.generate(points=1000, trend="linear", seasonality="daily", noise=0.1)
Schema Inference — Auto-detect types from CSV, DataFrames, records
schema = forge.infer_schema(records)
schema = forge.infer_schema_from_csv("data.csv")
Chaos Testing — Inject data quality issues
from dataforge.chaos import ChaosConfig

chaos = ChaosConfig(null_rate=0.05, type_mismatch_rate=0.02)
rows = forge.with_chaos(chaos).to_dict(fields=["first_name", "email"], count=1000)
Constraint Engine — Geographic, temporal, statistical constraints
from dataforge.constraints import Constraint

schema = forge.schema({
    "City": "address.city",
    "State": Constraint("address.state", depends_on="City"),
})
PII Anonymization — HMAC-SHA256 with format preservation
from dataforge.anonymizer import Anonymizer

anon = Anonymizer(key="secret")
anon.anonymize(rows, fields=["email", "ssn"])
Database Seeding — SQLAlchemy-powered bulk insertion
from dataforge.seeder import DatabaseSeeder

seeder = DatabaseSeeder(engine)
seeder.seed(User, count=10_000)
OpenAPI / JSON Schema Import — Generate from API specs
schema = forge.schema_from_openapi("openapi.json")
schema = forge.schema_from_json_schema("schema.json")
Streaming to Message Queues — HTTP, Kafka, RabbitMQ
forge.stream_to_http(fields=["first_name"], url="http://api.example.com", count=1000)
forge.stream_to_kafka(fields=["first_name"], topic="users", count=1000)
forge.stream_to_rabbitmq(fields=["first_name"], queue="users", count=1000)
Interactive TUI — Terminal UI for browsing and exporting
dataforge --tui

Requires textual.


Integrations

PyArrow

table = forge.to_arrow(fields=["first_name", "email"], count=1_000_000)
forge.to_parquet(fields=["first_name", "email"], path="users.parquet", count=1_000_000)

Polars

df = forge.to_polars(fields=["first_name", "email"], count=1_000_000)

Pydantic

from pydantic import BaseModel

class User(BaseModel):
    first_name: str
    email: str

schema = forge.schema_from_pydantic(User)
rows = schema.generate(1000)

SQLAlchemy

schema = forge.schema_from_sqlalchemy(User)
rows = schema.generate(1000)  # primary keys auto-skipped

Benchmarks

Measured on a standard developer machine:

Operation Throughput
misc.boolean() 8.5M items/s
person.first_name() 3.7M items/s
address.city() 3.4M items/s
person.first_name(count=1M) 15M items/s
dt.timezone(count=1M) 18M items/s
network.user_agent(count=1M) 18M items/s
Schema generate(100K) 343K rows/s
Schema to_csv(100K) 312K rows/s

Run locally:

uv run python benchmark.py
uv run python benchmark.py --compare  # against saved baseline
Performance architecture details
  • Columnar generation — Schema generates column-first, then transposes to rows
  • csv.writer over csv.DictWriter — ~36% faster CSV writes
  • Cumulative weight caching — weighted choices cache at module level
  • Bulk null injectionbinomialvariate() + random.sample() instead of per-element flips
  • Vectorized batch paths — internet, datetime, finance providers use dedicated batch code
  • deque for BFS traversal — O(1) popleft() in relational generation
  • Adaptive unique over-sampling — scales with observed collision rate
  • In-place list mutationnumerify()/bothify() avoid re-allocation

Examples

The examples/ directory contains 21 runnable scripts covering every feature:

File Topic
01_timeseries.py IoT sensor monitoring with regime changes
02_schema_inference.py Auto-detect schemas from records and CSV
03_chaos_testing.py Data quality issue injection
04_constraints.py Geographic, temporal, correlation constraints
05_anonymizer.py PII masking with referential integrity
06_database_seeding.py SQLAlchemy introspection and seeding
07_openapi_import.py Generate from JSON Schema / OpenAPI specs
08_streaming.py HTTP/Kafka/RabbitMQ streaming
09_tui.py Interactive TUI
10_real_world_scenarios.py E-commerce, healthcare, IoT, API testing
11_faker_compat.py Faker migration
12_multi_locale.py Multi-locale generation
13_dynamic_fields.py Custom data pools with define()
14_transform_pipelines.py Transform chains with pipe()
15_type_driven_schema.py Dataclass / TypedDict schemas
16_data_validation.py Data contract validation
17_hypothesis_bridge.py Hypothesis property-based testing
18_mock_server.py HTTP mock data server
19_xlsx_export.py Excel spreadsheet generation
20_distribution_fitting.py Statistical distribution inference
21_advanced_scenarios.py Multi-feature workflows

Installation

pip install dataforge-py        # zero dependencies
uv add dataforge-py             # with uv

Optional extras:

pip install dataforge-py[db]       # SQLAlchemy (database seeding)
pip install dataforge-py[kafka]    # confluent-kafka
pip install dataforge-py[rabbitmq] # pika
pip install dataforge-py[tui]      # textual (interactive TUI)
pip install dataforge-py[all]      # everything

Optional integrations (install separately):

pip install pyarrow polars pandas pydantic sqlalchemy openpyxl hypothesis

Requires Python >= 3.12.


Contributing

Contributions welcome. See an issue? Open one. Want to add a provider or locale? PRs appreciated.

git clone https://github.com/Sanady/dataforge-py.git
cd dataforge-py
uv sync
uv run pytest          # 1870 tests
uv run ruff check src/ tests/
uv run python benchmark.py

All commits use Conventional Commits. Performance is the primary selling point — all PRs must pass benchmark.py --compare without regressions.

If DataForge saves you time, a star helps others find it.


License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dataforge_py-0.6.0.tar.gz (183.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dataforge_py-0.6.0-py3-none-any.whl (265.2 kB view details)

Uploaded Python 3

File details

Details for the file dataforge_py-0.6.0.tar.gz.

File metadata

  • Download URL: dataforge_py-0.6.0.tar.gz
  • Upload date:
  • Size: 183.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for dataforge_py-0.6.0.tar.gz
Algorithm Hash digest
SHA256 f39d0872bd57f8e2bd8ecdabd7fb860f915a46ef86c26ca4ff4f2f5cfac562c0
MD5 6b1212a284c7af99a17aea407c8dbfdf
BLAKE2b-256 e369af9c6713d8f4115ab9ccf13e6eb124f128c8445eb76c2696bc747afd68e1

See more details on using hashes here.

Provenance

The following attestation bundles were made for dataforge_py-0.6.0.tar.gz:

Publisher: release-please.yml on Sanady/dataforge-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dataforge_py-0.6.0-py3-none-any.whl.

File metadata

  • Download URL: dataforge_py-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 265.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for dataforge_py-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 98cefca213395da9ab20258954485c015af872884c7f5f1e51dcce0af7b90a36
MD5 f1380d2ceee677c92a4a20895edf6660
BLAKE2b-256 afac5320711dbaa32d53ed7227731195df5ab8688879848fd10eb50c989ea745

See more details on using hashes here.

Provenance

The following attestation bundles were made for dataforge_py-0.6.0-py3-none-any.whl:

Publisher: release-please.yml on Sanady/dataforge-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.6.0 This release

2 files

0.5.0

2 files

0.4.0

2 files

0.3.0

2 files

0.2.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page