Farsi Faker | فارسی فیکر
Generate realistic fake Persian/Farsi names for testing and development
تولید اسمهای فارسی فیک واقعگرایانه برای تست و توسعه
✨ Features
- Embedded name database — Persian first and family names shipped with the package
- Gender-specific generation — separate male and female first-name pools
- Dynamic extension —
extend_name_pools()to merge your own names at runtime - Profile fields — national ID (کد ملی with checksum), mobile, email, postal code, address
- CLI —
python -m farsi_fakerfor JSON/CSV fixtures - Fast cold start — pickle-backed name cache, shared across instances
- Reproducible — seed support for stable fixtures
- Zero required dependencies — production install needs only the standard library
- Concurrent instantiation — shared name cache is lock-guarded and immutable
- Typed — type hints plus a
py.typedmarker (PEP 561) - Tested — unit, packaging, concurrency, profile, and data-quality gates in CI
- Unicode — Persian/Farsi text output
- Optional pandas — DataFrame output for data-science workflows
- Cleaning helpers —
farsi_faker.cleaningfor OCR-split and ZWNJ repair
Data provenance: see DATA_PROVENANCE.md. Core common names (
محمد,فاطمه, …) ship in the embedded pool as of v1.5.0.
📦 Installation
From PyPI (Recommended)
pip install farsi-faker
With pandas support (for DataFrame output)
pip install farsi-faker[pandas]
From Source
git clone https://github.com/alisadeghiaghili/farsi-faker.git
cd farsi-faker
pip install -e ".[dev]"
Requirements
- Python 3.9+
- No external dependencies for production use
- Optional:
pandasfor DataFrame output (as_dataframe=True)
🚀 Quick Start
Basic Usage
from farsi_faker import FarsiFaker
faker = FarsiFaker()
# Generate a random person
person = faker.full_name()
print(person)
# {'name': 'علی صادقی عقیلی', 'first_name': 'علی', 'last_name': 'صادقی عقیلی', 'gender': 'male'}
# Generate male name
male = faker.full_name('male')
print(male['name']) # علی صادقی عقیلی
# Generate female name
female = faker.full_name('female')
print(female['name']) # سپیده جلیلی
Synthetic Profile Fields (v1.3.0+)
from farsi_faker import FarsiFaker, is_valid_national_id
faker = FarsiFaker(seed=42)
person = faker.profile('male')
# {
# 'name': '...', 'first_name': '...', 'last_name': '...', 'gender': 'male',
# 'national_id': '10-digit کد ملی',
# 'mobile': '0912...',
# 'email': 'first.last@gmail.com',
# 'postal_code': '10-digit',
# }
assert is_valid_national_id(person['national_id'])
assert person['mobile'].startswith('09')
CLI
python -m farsi_faker --count 5 --seed 42
python -m farsi_faker --count 100 --profile --format csv > people.csv
python -m farsi_faker --count 3 --gender female --format json
Generate Multiple Names
# 10 random names as a list (default)
people = faker.generate_names(10)
# 50 male names as a list
men = faker.generate_names(50, 'male')
# 30 female names as a pandas DataFrame
women_df = faker.generate_names(30, 'female', as_dataframe=True)
print(women_df.shape) # (30, 4)
print(list(women_df.columns)) # ['name', 'first_name', 'last_name', 'gender']
print(women_df.head(2))
# name first_name last_name gender
# 0 فاطمه احمدی فاطمه احمدی female
# 1 زینب رضایی زینب رضایی female
Generate Balanced Dataset
# 100 people with 60% male ratio — as a list
dataset = faker.generate_dataset(100, male_ratio=0.6)
print(len(dataset)) # 100
# Same, but as a pandas DataFrame
df = faker.generate_dataset(500, male_ratio=0.5, as_dataframe=True)
print(df.shape) # (500, 4)
print(df['gender'].value_counts())
# male 250
# female 250
# Name: gender, dtype: int64
Reproducible Results
faker1 = FarsiFaker(seed=42)
faker2 = FarsiFaker(seed=42)
assert faker1.full_name() == faker2.full_name() # True
Quick One-Off Generation
from farsi_faker import generate_fake_name
person = generate_fake_name('male')
print(person['name']) # علی صادقی عقیلی
📖 Documentation
Class: FarsiFaker
Main class for generating Persian names.
Constructor
FarsiFaker(seed: Optional[int] = None)
Parameters:
seed(int, optional): Random seed for reproducible results
Example:
faker = FarsiFaker() # random
faker = FarsiFaker(seed=42) # reproducible
male_first_name() -> str
Return a random male first name.
faker.male_first_name() # 'محمد'
female_first_name() -> str
Return a random female first name.
faker.female_first_name() # 'فاطمه'
first_name(gender=None) -> Tuple[str, str]
Return a first name with its normalised gender.
Parameters:
gender(str, optional): Any supported gender token (see Gender Input Options)
Returns: (name, gender) — gender is always 'male' or 'female'
name, g = faker.first_name('male')
# ('علی', 'male')
name, g = faker.first_name() # random gender
# ('مریم', 'female')
last_name() -> str
Return a random Persian family name.
faker.last_name() # 'احمدی'
full_name(gender=None) -> Dict[str, str]
Return a complete person record.
Returns: dict with keys name, first_name, last_name, gender
person = faker.full_name('female')
# {
# 'name': 'سپیده جلیلی',
# 'first_name': 'سپیده',
# 'last_name': 'جلیلی',
# 'gender': 'female'
# }
assert person['name'] == person['first_name'] + ' ' + person['last_name']
generate_names(count=10, gender=None, as_dataframe=False)
Generate multiple full-name records.
Parameters:
count(int, default10): Number of records to generategender(str, optional): Gender applied to all records; random mix whenNoneas_dataframe(bool, defaultFalse): Return apandas.DataFrameinstead of a list
Returns: List[Dict] or pandas.DataFrame with columns ['name', 'first_name', 'last_name', 'gender']
Raises: ValueError if count ≤ 0; ImportError if as_dataframe=True and pandas is not installed
# List (default)
people = faker.generate_names(5, 'male')
assert len(people) == 5
assert all(p['gender'] == 'male' for p in people)
# DataFrame
df = faker.generate_names(100, as_dataframe=True)
assert df.shape == (100, 4)
assert list(df.columns) == ['name', 'first_name', 'last_name', 'gender']
assert not df.isnull().any().any()
assert (df['name'] == df['first_name'] + ' ' + df['last_name']).all()
generate_dataset(count=100, male_ratio=0.5, as_dataframe=False)
Generate a balanced dataset with a configurable gender ratio.
Parameters:
count(int, default100): Total number of recordsmale_ratio(float, default0.5): Fraction of male records in[0.0, 1.0]as_dataframe(bool, defaultFalse): Return apandas.DataFrameinstead of a list
Returns: Shuffled List[Dict] or pandas.DataFrame
Raises: ValueError if count ≤ 0 or male_ratio outside [0.0, 1.0]; ImportError if pandas missing and as_dataframe=True
# List (default)
dataset = faker.generate_dataset(10, male_ratio=0.6)
assert len(dataset) == 10
assert sum(1 for p in dataset if p['gender'] == 'male') == 6
# DataFrame
df = faker.generate_dataset(100, male_ratio=0.5, as_dataframe=True)
assert df.shape == (100, 4)
assert df['gender'].value_counts().to_dict() == {'male': 50, 'female': 50}
# Edge cases
assert all(p['gender'] == 'female' for p in faker.generate_dataset(5, male_ratio=0.0))
assert all(p['gender'] == 'male' for p in faker.generate_dataset(5, male_ratio=1.0))
get_stats() -> Dict[str, int]
Return statistics about the embedded names database.
Returns: dict with keys male_names_count, female_names_count, last_names_count, total_names, possible_combinations
stats = faker.get_stats()
assert stats['possible_combinations'] == \
(stats['male_names_count'] + stats['female_names_count']) * stats['last_names_count']
print(f"Possible combinations: {stats['possible_combinations']:,}")
# Possible combinations: 21,000,000
Function: generate_fake_name(gender=None, seed=None) -> Dict[str, str]
Convenience wrapper for one-off generation. For bulk generation prefer a FarsiFaker instance directly.
from farsi_faker import generate_fake_name
p1 = generate_fake_name('female', seed=99)
p2 = generate_fake_name('female', seed=99)
assert p1 == p2 # reproducible
🎨 Examples
Example 1: Django test fixtures
from farsi_faker import FarsiFaker
from myapp.models import User
faker = FarsiFaker(seed=42)
for person in faker.generate_dataset(100, male_ratio=0.5):
User.objects.create(**person)
Example 2: Export to CSV
import csv
from farsi_faker import FarsiFaker
faker = FarsiFaker()
with open('people.csv', 'w', encoding='utf-8', newline='') as f:
writer = csv.DictWriter(f, fieldnames=['name', 'first_name', 'last_name', 'gender'])
writer.writeheader()
writer.writerows(faker.generate_dataset(1000, male_ratio=0.6))
Example 3: pandas DataFrame for data science
from farsi_faker import FarsiFaker
faker = FarsiFaker(seed=123)
df = faker.generate_dataset(500, male_ratio=0.55, as_dataframe=True)
print(df.shape) # (500, 4)
print(df['gender'].value_counts()) # male 275 / female 225
print(df.groupby('gender')['last_name'].nunique())
Example 4: pytest fixture
import pytest
from farsi_faker import FarsiFaker
@pytest.fixture
def fake_users():
return FarsiFaker(seed=42).generate_dataset(10, male_ratio=0.5)
def test_user_creation(fake_users):
assert len(fake_users) == 10
assert all('name' in u for u in fake_users)
Example 5: Flask mock API
from flask import Flask, jsonify
from farsi_faker import FarsiFaker
app = Flask(__name__)
faker = FarsiFaker()
@app.route('/api/users/random')
def random_user():
return jsonify(faker.full_name())
@app.route('/api/users/<int:count>')
def multiple_users(count):
return jsonify(faker.generate_names(min(count, 100)))
🎯 Gender Input Options
| Input | Resolves to |
|---|---|
'male', 'm' |
'male' |
'مرد', 'پسر', 'مذکر' |
'male' |
'female', 'f' |
'female' |
'زن', 'دختر', 'مونث' |
'female' |
None |
random |
📊 Database Statistics
from farsi_faker import FarsiFaker
stats = FarsiFaker().get_stats()
print(f"Male names: {stats['male_names_count']:,}")
print(f"Female names: {stats['female_names_count']:,}")
print(f"Last names: {stats['last_names_count']:,}")
print(f"Total names: {stats['total_names']:,}")
print(f"Possible combinations: {stats['possible_combinations']:,}")
🧪 Testing
pip install -e ".[dev]"
pytest tests/ -v
pytest tests/ --cov=farsi_faker --cov-report=html
🛠️ Development
git clone https://github.com/alisadeghiaghili/farsi-faker.git
cd farsi-faker
python -m venv venv && source venv/bin/activate
pip install -e ".[all]"
# quality checks
black farsi_faker/ && isort farsi_faker/ && mypy farsi_faker/
pytest tests/ -v
📁 Project Structure
farsi-faker/
├── farsi_faker/
│ ├── __init__.py
│ ├── faker.py ← core class
│ ├── _version.py
│ └── data/names.pkl
├── tests/test_faker.py
├── scripts/create_pickle.py
├── setup.py
├── pyproject.toml
├── CHANGELOG.md
└── README.md
🤝 Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Add tests for new functionality
- Run tests (
pytest tests/) - Commit (
git commit -m 'Add amazing feature') - Push and open a Pull Request
Code style: Black + isort. Type hints required. Docstrings required.
📄 License
MIT — see LICENSE.
📞 Contact
- Author: Ali Sadeghi Aghili
- GitHub: alisadeghiaghili/farsi-faker
- PyPI: pypi.org/project/farsi-faker
- Issues: github.com/alisadeghiaghili/farsi-faker/issues
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file farsi_faker-1.6.0.tar.gz.
File metadata
- Download URL: farsi_faker-1.6.0.tar.gz
- Upload date:
- Size: 138.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
330dcdf4422eb4a7ef4388ed80b76d249cb307c8b2498a5a687a86bcf632208f
|
|
| MD5 |
52ff9fafc53d03db62ca09221427562e
|
|
| BLAKE2b-256 |
5292833b56802495139352d419d9fe2de48216c437af55893901ed390d999a56
|
File details
Details for the file farsi_faker-1.6.0-py3-none-any.whl.
File metadata
- Download URL: farsi_faker-1.6.0-py3-none-any.whl
- Upload date:
- Size: 107.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
decb02796d03d08ee516d712358187ad314eef7709f7f1c5ffc47965288f55c5
|
|
| MD5 |
a798952f1b6f37e4ba370d1374c0f577
|
|
| BLAKE2b-256 |
ce3371390b162c8ec20b7d4eec35d302373167b80ebf262f614624455950fc47
|