# Fichier: python_cheats/cheatsheets/faker.txt
# Cheatsheet Faker Python - Guide Complet
# Génération de données factices pour tests, prototypes et démonstrations


[OK] INSTALLATION & IMPORT

# Installation
pip install faker
pip install faker==19.12.0           # Version spécifique

# Import basique
from faker import Faker

# Créer instance
fake = Faker()

# Instance avec locale spécifique
fake_fr = Faker('fr_FR')             # Français
fake_en = Faker('en_US')             # Anglais US
fake_es = Faker('es_ES')             # Espagnol
fake_de = Faker('de_DE')             # Allemand
fake_it = Faker('it_IT')             # Italien
fake_pt = Faker('pt_BR')             # Portugais Brésil
fake_ja = Faker('ja_JP')             # Japonais
fake_zh = Faker('zh_CN')             # Chinois
fake_ar = Faker('ar_SA')             # Arabe

# Multiples locales
fake_multi = Faker(['fr_FR', 'en_US', 'es_ES'])

# Seed pour reproductibilité
Faker.seed(4321)                     # Seed global
fake = Faker()
fake.seed_instance(1234)             # Seed instance spécifique


[OK] INFORMATIONS PERSONNELLES

from faker import Faker
fake = Faker('fr_FR')

# === NOMS ===

fake.name()                          # Nom complet
# "Jean Dupont"

fake.first_name()                    # Prénom
# "Marie"

fake.last_name()                     # Nom de famille
# "Martin"

fake.first_name_male()               # Prénom masculin
# "Pierre"

fake.first_name_female()             # Prénom féminin
# "Sophie"

fake.prefix()                        # Titre (M., Mme, Dr.)
# "M."

fake.suffix()                        # Suffixe (Jr., Sr., PhD)
# "Jr."

fake.name_male()                     # Nom complet masculin
# "Jacques Lefebvre"

fake.name_female()                   # Nom complet féminin
# "Claire Moreau"


# === DONNÉES DÉMOGRAPHIQUES ===

fake.ssn()                           # Numéro sécurité sociale
# "1 89 05 75 116 058 23"

fake.job()                           # Métier/profession
# "Ingénieur logiciel"

fake.company()                       # Nom entreprise
# "Dupont et Fils"

fake.company_suffix()                # Suffixe entreprise (SA, SARL)
# "SA"

fake.catch_phrase()                  # Slogan entreprise
# "Innovate seamless technologies"

fake.bs()                            # Business speak (jargon)
# "leverage synergistic solutions"


[OK] ADRESSES & GÉOGRAPHIE

# === ADRESSES ===

fake.address()                       # Adresse complète
# "45 rue de la Paix\n75002 Paris"

fake.street_address()                # Adresse rue
# "12 avenue des Champs-Élysées"

fake.street_name()                   # Nom de rue
# "rue Victor Hugo"

fake.building_number()               # Numéro bâtiment
# "42"

fake.city()                          # Ville
# "Lyon"

fake.postcode()                      # Code postal
# "69001"

fake.country()                       # Pays
# "France"

fake.country_code()                  # Code pays (ISO)
# "FR"

fake.current_country()               # Pays de la locale
# "France"

fake.current_country_code()          # Code pays de la locale
# "FR"


# === COORDONNÉES GÉOGRAPHIQUES ===

fake.latitude()                      # Latitude
# 48.8566

fake.longitude()                     # Longitude
# 2.3522

fake.local_latlng()                  # (lat, lng) locale
# ('48.8566', '2.3522', 'Paris', 'FR', 'Europe/Paris')

fake.location_on_land()              # Coordonnées sur terre
# ('48.8566', '2.3522', 'Paris', 'FR', 'Europe/Paris')

fake.coordinate()                    # Coordonnée unique
# "48.856614"


[OK] CONTACT & COMMUNICATION

# === EMAIL ===

fake.email()                         # Email générique
# "jean.dupont@example.com"

fake.free_email()                    # Email gratuit (gmail, yahoo)
# "marie.martin@gmail.com"

fake.company_email()                 # Email entreprise
# "pierre.durand@example.org"

fake.safe_email()                    # Email sécurisé (example.com)
# "sophie.bernard@example.com"

fake.ascii_email()                   # Email ASCII seulement
# "john.doe@example.com"

fake.ascii_safe_email()              # Email ASCII sécurisé
# "user123@example.org"


# === TÉLÉPHONE ===

fake.phone_number()                  # Numéro téléphone
# "+33 1 23 45 67 89"

fake.msisdn()                        # Numéro mobile international
# "33612345678"


# === INTERNET ===

fake.domain_name()                   # Nom domaine
# "example.com"

fake.domain_word()                   # Mot de domaine
# "example"

fake.tld()                           # Top-level domain (.com, .fr)
# "com"

fake.url()                           # URL complète
# "https://www.example.com/"

fake.uri()                           # URI
# "/search?q=test"

fake.uri_path()                      # Chemin URI
# "/category/item/123"

fake.uri_extension()                 # Extension fichier
# ".html"

fake.slug()                          # Slug URL
# "article-titre-exemple"

fake.hostname()                      # Nom d'hôte
# "web-server-01.example.com"

fake.ipv4()                          # Adresse IPv4
# "192.168.1.1"

fake.ipv4_private()                  # IPv4 privée
# "192.168.0.100"

fake.ipv4_public()                   # IPv4 publique
# "203.0.113.45"

fake.ipv6()                          # Adresse IPv6
# "2001:0db8:85a3:0000:0000:8a2e:0370:7334"

fake.mac_address()                   # Adresse MAC
# "00:1B:63:84:45:E6"

fake.user_name()                     # Nom utilisateur
# "jean_dupont"

fake.password()                      # Mot de passe aléatoire
# "xR7#mK9@pL2$"

fake.password(length=12, special_chars=True, digits=True, 
              upper_case=True, lower_case=True)
# Mot de passe personnalisé


[OK] DATES & TEMPS

from datetime import datetime, timedelta

# === DATES ===

fake.date()                          # Date (YYYY-MM-DD)
# "2023-05-15"

fake.date_object()                   # Objet date
# date(2023, 5, 15)

fake.date_of_birth()                 # Date naissance (adulte)
# date(1985, 3, 22)

fake.date_of_birth(minimum_age=18, maximum_age=65)
# Date naissance avec contraintes d'âge

fake.date_this_year()                # Date cette année
# date(2024, 8, 10)

fake.date_this_month()               # Date ce mois
# date(2024, 11, 5)

fake.date_this_decade()              # Date cette décennie
# date(2022, 3, 18)

fake.date_this_century()             # Date ce siècle
# date(2001, 7, 25)

fake.date_between(start_date='-30d', end_date='today')
# Date dans intervalle (30 derniers jours)

fake.date_between_dates(date_start=datetime(2020, 1, 1),
                        date_end=datetime(2024, 12, 31))
# Date entre deux dates spécifiques

fake.future_date()                   # Date future
# date(2025, 3, 10)

fake.past_date()                     # Date passée
# date(2023, 9, 5)


# === TEMPS ===

fake.time()                          # Heure (HH:MM:SS)
# "14:30:45"

fake.time_object()                   # Objet time
# time(14, 30, 45)

fake.am_pm()                         # AM/PM
# "PM"


# === DATETIME ===

fake.date_time()                     # DateTime
# datetime(2023, 5, 15, 14, 30, 45)

fake.date_time_this_year()           # DateTime cette année
# datetime(2024, 8, 10, 9, 15, 30)

fake.date_time_this_month()          # DateTime ce mois
# datetime(2024, 11, 5, 16, 20, 10)

fake.date_time_this_decade()         # DateTime cette décennie
# datetime(2022, 3, 18, 11, 45, 0)

fake.date_time_between(start_date='-30d', end_date='now')
# DateTime dans intervalle

fake.future_datetime()               # DateTime futur
# datetime(2025, 3, 10, 10, 30, 0)

fake.past_datetime()                 # DateTime passé
# datetime(2023, 9, 5, 15, 45, 20)


# === TIMESTAMPS ===

fake.unix_time()                     # Timestamp Unix
# 1699459200

fake.iso8601()                       # Format ISO 8601
# "2023-11-08T14:30:45"


# === TIMEZONES ===

fake.timezone()                      # Fuseau horaire
# "Europe/Paris"

fake.pytimezone()                    # Objet timezone Python
# <DstTzInfo 'Europe/Paris' LMT+0:09:00 STD>


# === PÉRIODES ===

fake.century()                       # Siècle
# "XXI"

fake.year()                          # Année
# "2023"

fake.month()                         # Mois (numéro)
# "05"

fake.month_name()                    # Nom mois
# "Mai"

fake.day_of_week()                   # Jour semaine
# "Lundi"

fake.day_of_month()                  # Jour du mois
# "15"


[OK] TEXTE & CONTENU

# === TEXTE LOREM IPSUM ===

fake.word()                          # Un mot
# "dolor"

fake.words(nb=5)                     # Liste de mots
# ['lorem', 'ipsum', 'dolor', 'sit', 'amet']

fake.sentence()                      # Une phrase
# "Lorem ipsum dolor sit amet consectetur."

fake.sentence(nb_words=10)           # Phrase de 10 mots
# "Lorem ipsum dolor sit amet consectetur adipiscing elit sed do."

fake.sentences(nb=3)                 # Liste de phrases
# ['Lorem ipsum.', 'Dolor sit amet.', 'Consectetur adipiscing.']

fake.paragraph()                     # Un paragraphe
# "Lorem ipsum dolor sit amet..."

fake.paragraph(nb_sentences=5)       # Paragraphe de 5 phrases
# "Lorem ipsum... (5 phrases)"

fake.paragraphs(nb=3)                # Liste paragraphes
# ['Paragraph 1...', 'Paragraph 2...', 'Paragraph 3...']

fake.text()                          # Texte long (200 caractères)
# "Lorem ipsum dolor sit amet..."

fake.text(max_nb_chars=500)          # Texte de max 500 caractères
# "Lorem ipsum... (jusqu'à 500 caractères)"

fake.texts(nb_texts=3)               # Liste de textes
# ['Text 1...', 'Text 2...', 'Text 3...']


[OK] NUMÉROS & IDENTIFIANTS

# === NUMÉROS ===

fake.random_int(min=1, max=100)      # Entier aléatoire
# 42

fake.random_digit()                  # Chiffre 0-9
# 7

fake.random_digit_not_null()         # Chiffre 1-9
# 5

fake.random_number(digits=5)         # Nombre à n chiffres
# 54321

fake.random_letter()                 # Lettre aléatoire
# "m"

fake.random_lowercase_letter()       # Lettre minuscule
# "a"

fake.random_uppercase_letter()       # Lettre majuscule
# "K"


# === CODES & IDENTIFIANTS ===

fake.uuid4()                         # UUID version 4
# "550e8400-e29b-41d4-a716-446655440000"

fake.ean()                           # Code-barres EAN-13
# "1234567890123"

fake.ean8()                          # Code-barres EAN-8
# "12345678"

fake.ean13()                         # Code-barres EAN-13
# "1234567890123"

fake.isbn10()                        # ISBN-10
# "1234567890"

fake.isbn13()                        # ISBN-13
# "978-1234567890"


# === NOMBRES FORMATÉS ===

fake.numerify(text="ID-###")         # Remplace # par chiffres
# "ID-742"

fake.numerify(text="Order-#####")
# "Order-34892"

fake.lexify(text="Code-????")        # Remplace ? par lettres
# "Code-XKMP"

fake.bothify(text="Ref-??##")        # Combine lettres et chiffres
# "Ref-AB42"

fake.bothify(text="SN-????-####-??##")
# "SN-ABCD-1234-EF56"


[OK] BANQUE & FINANCE

# === CARTES BANCAIRES ===

fake.credit_card_number()            # Numéro carte
# "4532123456789012"

fake.credit_card_provider()          # Fournisseur carte
# "Visa"

fake.credit_card_security_code()     # CVV
# "123"

fake.credit_card_expire()            # Date expiration
# "05/26"

fake.credit_card_full()              # Infos complètes carte
# "Visa\n4532123456789012\n05/26\nCVC: 123"


# === DEVISES ===

fake.currency()                      # Devise (code ISO)
# "EUR"

fake.currency_name()                 # Nom devise
# "Euro"

fake.currency_symbol()               # Symbole devise
# "€"

fake.cryptocurrency()                # Cryptomonnaie (code)
# "BTC"

fake.cryptocurrency_name()           # Nom cryptomonnaie
# "Bitcoin"

fake.cryptocurrency_code()           # Code crypto
# "BTC"


# === BANQUE ===

fake.iban()                          # IBAN
# "FR76 3000 6000 0112 3456 7890 189"

fake.bban()                          # BBAN (Basic Bank Account Number)
# "BARC20658244971655"

fake.swift()                         # Code SWIFT/BIC
# "DEUTDEFF"

fake.swift8()                        # Code SWIFT 8 caractères
# "DEUTDEFF"

fake.swift11()                       # Code SWIFT 11 caractères
# "DEUTDEFFXXX"


[OK] FICHIERS & SYSTÈME

# === FICHIERS ===

fake.file_name()                     # Nom fichier
# "document.pdf"

fake.file_name(category='image')     # Fichier image
# "photo.jpg"

fake.file_name(extension='txt')      # Extension spécifique
# "file.txt"

fake.file_path()                     # Chemin fichier
# "/home/user/document.pdf"

fake.file_path(depth=3, category='image')
# "/home/user/photos/image.jpg"

fake.file_extension()                # Extension
# "pdf"

fake.file_extension(category='image')
# "jpg"

fake.mime_type()                     # Type MIME
# "application/pdf"

fake.mime_type(category='image')     # MIME image
# "image/jpeg"


# === SYSTÈME ===

fake.unix_device()                   # Device Unix
# "/dev/sda1"

fake.unix_partition()                # Partition Unix
# "/dev/sdb2"


[OK] COULEURS

fake.color_name()                    # Nom couleur
# "Red"

fake.safe_color_name()               # Couleur sécurisée
# "blue"

fake.hex_color()                     # Couleur hex
# "#a3c2f0"

fake.rgb_color()                     # RGB
# "255,128,64"

fake.rgb_css_color()                 # RGB CSS
# "rgb(255, 128, 64)"


[OK] USER AGENT & NAVIGATEURS

fake.user_agent()                    # User agent complet
# "Mozilla/5.0 (Windows NT 10.0; Win64; x64)..."

fake.chrome()                        # User agent Chrome
# "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/91.0.4472.124"

fake.firefox()                       # User agent Firefox
# "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Firefox/89.0"

fake.safari()                        # User agent Safari
# "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)... Safari/605.1.15"

fake.opera()                         # User agent Opera
# "Opera/9.80 (Windows NT 6.1; WOW64)..."

fake.internet_explorer()             # User agent IE
# "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"

fake.windows_platform_token()        # Token Windows
# "Windows NT 10.0"

fake.linux_platform_token()          # Token Linux
# "X11; Linux x86_64"

fake.mac_platform_token()            # Token Mac
# "Macintosh; Intel Mac OS X 10_15_7"


[OK] LOCALES SPÉCIFIQUES

# === Français (fr_FR) ===

fake_fr = Faker('fr_FR')

fake_fr.name()                       # "Jean Dupont"
fake_fr.address()                    # "45 rue Victor Hugo\n75001 Paris"
fake_fr.phone_number()               # "01 23 45 67 89"
fake_fr.company()                    # "Dupont et Fils"
fake_fr.job()                        # "Ingénieur informatique"


# === Anglais US (en_US) ===

fake_us = Faker('en_US')

fake_us.name()                       # "John Smith"
fake_us.address()                    # "123 Main St, New York, NY 10001"
fake_us.phone_number()               # "(555) 123-4567"
fake_us.ssn()                        # "123-45-6789"
fake_us.state()                      # "California"
fake_us.state_abbr()                 # "CA"
fake_us.zipcode()                    # "90210"


# === Espagnol (es_ES) ===

fake_es = Faker('es_ES')

fake_es.name()                       # "Juan García"
fake_es.address()                    # "Calle Mayor, 15\n28001 Madrid"
fake_es.phone_number()               # "+34 912 345 678"


# === Allemand (de_DE) ===

fake_de = Faker('de_DE')

fake_de.name()                       # "Hans Müller"
fake_de.address()                    # "Hauptstraße 42\n10115 Berlin"
fake_de.phone_number()               # "+49 30 12345678"


# === Italien (it_IT) ===

fake_it = Faker('it_IT')

fake_it.name()                       # "Mario Rossi"
fake_it.address()                    # "Via Roma, 10\n00100 Roma"


# === Japonais (ja_JP) ===

fake_ja = Faker('ja_JP')

fake_ja.name()                       # "田中 太郎"
fake_ja.address()                    # "東京都渋谷区..."


# === Portugais Brésil (pt_BR) ===

fake_br = Faker('pt_BR')

fake_br.name()                       # "João Silva"
fake_br.cpf()                        # CPF brésilien
fake_br.cnpj()                       # CNPJ (entreprise)


[OK] PROVIDERS PERSONNALISÉS

# === Créer Provider Custom ===

from faker import Faker
from faker.providers import BaseProvider

class GameProvider(BaseProvider):
    """Provider personnalisé pour jeux vidéo"""
    
    def game_title(self):
        """Génère titre de jeu"""
        games = [
            "The Legend of Adventure",
            "Space Warriors",
            "Dragon Quest Online",
            "Cyber Revolution",
            "Fantasy Kingdom"
        ]
        return self.random_element(games)
    
    def game_genre(self):
        """Génère genre de jeu"""
        genres = ["RPG", "FPS", "Strategy", "Adventure", "Simulation"]
        return self.random_element(genres)
    
    def player_level(self):
        """Génère niveau joueur"""
        return self.random_int(min=1, max=100)
    
    def achievement(self):
        """Génère achievement"""
        achievements = [
            "First Blood",
            "Master of the Universe",
            "Speed Demon",
            "Treasure Hunter",
            "Ultimate Warrior"
        ]
        return self.random_element(achievements)

# Ajouter provider
fake = Faker()
fake.add_provider(GameProvider)

# Utiliser provider custom
print(fake.game_title())             # "Dragon Quest Online"
print(fake.game_genre())             # "RPG"
print(fake.player_level())           # 42
print(fake.achievement())            # "Master of the Universe"


# === Provider E-commerce ===

class EcommerceProvider(BaseProvider):
    """Provider pour e-commerce"""
    
    def product_name(self):
        """Nom produit"""
        adjectives = ["Premium", "Deluxe", "Pro", "Ultra", "Smart"]
        items = ["Laptop", "Phone", "Tablet", "Watch", "Camera"]
        return f"{self.random_element(adjectives)} {self.random_element(items)}"
    
    def product_category(self):
        """Catégorie produit"""
        categories = ["Electronics", "Clothing", "Home", "Sports", "Books"]
        return self.random_element(categories)
    
    def product_price(self, min_price=10, max_price=1000):
        """Prix produit"""
        return round(self.random_int(min=min_price*100, max=max_price*100) / 100, 2)
    
    def product_sku(self):
        """SKU produit"""
        return f"SKU-{self.bothify(text='????-####')}"
    
    def review_rating(self):
        """Note avis (1-5)"""
        return self.random_int(min=1, max=5)
    
    def stock_quantity(self):
        """Quantité stock"""
        return self.random_int(min=0, max=500)

fake.add_provider(EcommerceProvider)

print(fake.product_name())           # "Premium Laptop"
print(fake.product_price())          # 599.99
print(fake.product_sku())            # "SKU-ABCD-1234"


[OK] GÉNÉRATION DE DATASETS

# === Dataset Simple ===

from faker import Faker
fake = Faker('fr_FR')

# Générer 100 utilisateurs
users = []
for _ in range(100):
    user = {
        'id': fake.uuid4(),
        'name': fake.name(),
        'email': fake.email(),
        'phone': fake.phone_number(),
        'address': fake.address(),
        'birthdate': fake.date_of_birth(minimum_age=18, maximum_age=80),
        'job': fake.job(),
        'company': fake.company(),
        'created_at': fake.date_time_this_year()
    }
    users.append(user)


# === Dataset avec Relations ===

# Générer entreprises
companies = []
for _ in range(10):
    company = {
        'id': fake.uuid4(),
        'name': fake.company(),
        'address': fake.address(),
        'phone': fake.phone_number(),
        'email': fake.company_email(),
        'website': fake.url()
    }
    companies.append(company)

# Générer employés liés aux entreprises
employees = []
for _ in range(100):
    employee = {
        'id': fake.uuid4(),
        'company_id': fake.random_element(companies)['id'],
        'name': fake.name(),
        'email': fake.email(),
        'job_title': fake.job(),
        'salary': fake.random_int(min=30000, max=150000),
        'hire_date': fake.date_between(start_date='-5y', end_date='today')
    }
    employees.append(employee)


# === Dataset E-commerce Complet ===

def generate_ecommerce_dataset(num_products=100, num_customers=50, num_orders=200):
    """Génère dataset e-commerce complet"""
    fake = Faker('fr_FR')
    fake.add_provider(EcommerceProvider)
    
    # Produits
    products = []
    for _ in range(num_products):
        product = {
            'id': fake.uuid4(),
            'name': fake.product_name(),
            'category': fake.product_category(),
            'price': fake.product_price(),
            'sku': fake.product_sku(),
            'stock': fake.stock_quantity(),
            'description': fake.text(max_nb_chars=200),
            'created_at': fake.date_time_between(start_date='-1y', end_date='now')
        }
        products.append(product)
    
    # Clients
    customers = []
    for _ in range(num_customers):
        customer = {
            'id': fake.uuid4(),
            'name': fake.name(),
            'email': fake.email(),
            'phone': fake.phone_number(),
            'address': fake.address(),
            'city': fake.city(),
            'postcode': fake.postcode(),
            'registered_at': fake.date_time_between(start_date='-2y', end_date='now')
        }
        customers.append(customer)
    
    # Commandes
    orders = []
    for _ in range(num_orders):
        order = {
            'id': fake.uuid4(),
            'customer_id': fake.random_element(customers)['id'],
            'order_date': fake.date_time_between(start_date='-6m', end_date='now'),
            'status': fake.random_element(['pending', 'shipped', 'delivered', 'cancelled']),
            'total': fake.random_int(min=20, max=500),
            'items': [
                {
                    'product_id': fake.random_element(products)['id'],
                    'quantity': fake.random_int(min=1, max=5),
                    'price': fake.product_price()
                }
                for _ in range(fake.random_int(min=1, max=5))
            ]
        }
        orders.append(order)
    
    return {
        'products': products,
        'customers': customers,
        'orders': orders
    }

# Utilisation
dataset = generate_ecommerce_dataset(100, 50, 200)


[OK] EXPORT DE DONNÉES

# === Export CSV ===

import csv
from faker import Faker

fake = Faker('fr_FR')

# Générer et exporter vers CSV
with open('users.csv', 'w', newline='', encoding='utf-8') as f:
    fieldnames = ['name', 'email', 'phone', 'address', 'birthdate']
    writer = csv.DictWriter(f, fieldnames=fieldnames)
    
    writer.writeheader()
    for _ in range(100):
        writer.writerow({
            'name': fake.name(),
            'email': fake.email(),
            'phone': fake.phone_number(),
            'address': fake.address().replace('\n', ', '),
            'birthdate': fake.date_of_birth()
        })


# === Export JSON ===

import json
from faker import Faker

fake = Faker('fr_FR')

# Générer données
data = []
for _ in range(100):
    user = {
        'id': fake.uuid4(),
        'name': fake.name(),
        'email': fake.email(),
        'created_at': fake.iso8601()
    }
    data.append(user)

# Export JSON
with open('users.json', 'w', encoding='utf-8') as f:
    json.dump(data, f, indent=2, ensure_ascii=False, default=str)


# === Export SQL ===

from faker import Faker

fake = Faker('fr_FR')

with open('insert_users.sql', 'w', encoding='utf-8') as f:
    for _ in range(100):
        name = fake.name().replace("'", "''")
        email = fake.email()
        phone = fake.phone_number()
        
        sql = f"""INSERT INTO users (name, email, phone) 
VALUES ('{name}', '{email}', '{phone}');\n"""
        f.write(sql)


# === Export DataFrame Pandas ===

import pandas as pd
from faker import Faker

fake = Faker('fr_FR')

# Générer DataFrame
data = {
    'name': [fake.name() for _ in range(100)],
    'email': [fake.email() for _ in range(100)],
    'phone': [fake.phone_number() for _ in range(100)],
    'city': [fake.city() for _ in range(100)],
    'birthdate': [fake.date_of_birth() for _ in range(100)]
}

df = pd.DataFrame(data)

# Export vers différents formats
df.to_csv('users.csv', index=False)
df.to_excel('users.xlsx', index=False)
df.to_json('users.json', orient='records', indent=2)
df.to_html('users.html', index=False)


[OK] SEED & REPRODUCTIBILITÉ

from faker import Faker

# === Seed Global ===

Faker.seed(0)
fake1 = Faker()
print(fake1.name())                  # Toujours "Karen Clark"

Faker.seed(0)
fake2 = Faker()
print(fake2.name())                  # Toujours "Karen Clark"


# === Seed Instance ===

fake = Faker()
fake.seed_instance(12345)
print(fake.name())                   # Résultat prévisible

fake.seed_instance(12345)            # Réinitialiser
print(fake.name())                   # Même résultat


# === Seed pour Tests Unitaires ===

import unittest
from faker import Faker

class TestWithFaker(unittest.TestCase):
    
    def setUp(self):
        """Initialise faker avec seed avant chaque test"""
        Faker.seed(0)
        self.fake = Faker()
    
    def test_name_generation(self):
        """Test génération nom"""
        name = self.fake.name()
        self.assertEqual(name, "Karen Clark")  # Prévisible avec seed
    
    def test_email_generation(self):
        """Test génération email"""
        Faker.seed(0)  # Réinitialiser
        fake = Faker()
        email = fake.email()
        self.assertIn('@', email)


# === Reproductibilité Multi-Locales ===

from faker import Faker

# Même seed, locales différentes
Faker.seed(42)
fake_fr = Faker('fr_FR')
fake_en = Faker('en_US')

print(fake_fr.name())                # Résultat prévisible FR
print(fake_en.name())                # Résultat prévisible EN


[OK] EXEMPLES PRATIQUES AVANCÉS

# === 1. Générateur de Profils Utilisateurs Complets ===

from faker import Faker
from datetime import datetime, timedelta
import random

def generate_user_profile(locale='fr_FR'):
    """Génère profil utilisateur réaliste complet"""
    fake = Faker(locale)
    
    # Informations de base
    gender = random.choice(['male', 'female'])
    first_name = fake.first_name_male() if gender == 'male' else fake.first_name_female()
    last_name = fake.last_name()
    
    # Date de naissance (18-70 ans)
    birthdate = fake.date_of_birth(minimum_age=18, maximum_age=70)
    age = (datetime.now().date() - birthdate).days // 365
    
    # Email basé sur le nom
    email_prefix = f"{first_name.lower()}.{last_name.lower()}"
    email = f"{email_prefix}@{fake.free_email_domain()}"
    
    # Profil complet
    profile = {
        'id': fake.uuid4(),
        'username': f"{first_name.lower()}{random.randint(100, 999)}",
        'first_name': first_name,
        'last_name': last_name,
        'full_name': f"{first_name} {last_name}",
        'gender': gender,
        'birthdate': birthdate.isoformat(),
        'age': age,
        'email': email.lower(),
        'phone': fake.phone_number(),
        'address': {
            'street': fake.street_address(),
            'city': fake.city(),
            'postcode': fake.postcode(),
            'country': fake.current_country()
        },
        'job': fake.job(),
        'company': fake.company(),
        'bio': fake.text(max_nb_chars=200),
        'website': fake.url(),
        'avatar': f"https://i.pravatar.cc/150?u={fake.uuid4()}",
        'registered_at': fake.date_time_between(start_date='-2y', end_date='now').isoformat(),
        'last_login': fake.date_time_between(start_date='-30d', end_date='now').isoformat(),
        'is_active': random.choice([True, True, True, False]),  # 75% actifs
        'email_verified': random.choice([True, True, True, False])
    }
    
    return profile

# Utilisation
user = generate_user_profile('fr_FR')
print(user)


# === 2. Générateur de Posts de Blog ===

def generate_blog_posts(num_posts=10, locale='fr_FR'):
    """Génère posts de blog"""
    fake = Faker(locale)
    posts = []
    
    for _ in range(num_posts):
        # Générer titre accrocheur
        title_words = fake.words(nb=random.randint(3, 8))
        title = ' '.join(word.capitalize() for word in title_words)
        
        # Slug URL
        slug = '-'.join(title_words)
        
        # Contenu
        num_paragraphs = random.randint(3, 8)
        content = '\n\n'.join([fake.paragraph(nb_sentences=random.randint(4, 8)) 
                               for _ in range(num_paragraphs)])
        
        post = {
            'id': fake.uuid4(),
            'title': title,
            'slug': slug,
            'author': fake.name(),
            'content': content,
            'excerpt': fake.text(max_nb_chars=150),
            'category': fake.random_element(['Technology', 'Business', 'Lifestyle', 'Travel', 'Food']),
            'tags': fake.words(nb=random.randint(2, 5)),
            'views': random.randint(100, 10000),
            'likes': random.randint(10, 1000),
            'published_at': fake.date_time_between(start_date='-1y', end_date='now').isoformat(),
            'updated_at': fake.date_time_between(start_date='-6m', end_date='now').isoformat(),
            'status': fake.random_element(['published', 'published', 'published', 'draft'])
        }
        
        posts.append(post)
    
    return posts

# Utilisation
blog_posts = generate_blog_posts(20)


# === 3. Générateur de Transactions Bancaires ===

def generate_transactions(num_transactions=100, account_id=None):
    """Génère transactions bancaires réalistes"""
    fake = Faker('fr_FR')
    
    if account_id is None:
        account_id = fake.iban()
    
    transactions = []
    balance = 5000.0  # Solde initial
    
    # Types de transactions avec probabilités
    transaction_types = [
        ('debit', 'Purchase', 0.4),
        ('debit', 'ATM Withdrawal', 0.15),
        ('debit', 'Bill Payment', 0.2),
        ('credit', 'Salary', 0.05),
        ('credit', 'Transfer In', 0.15),
        ('credit', 'Refund', 0.05)
    ]
    
    for i in range(num_transactions):
        # Sélectionner type avec pondération
        types, descriptions, weights = zip(*transaction_types)
        trans_type = random.choices(list(zip(types, descriptions)), weights=weights)[0]
        
        # Montant selon type
        if trans_type[1] == 'Salary':
            amount = round(random.uniform(2000, 5000), 2)
        elif trans_type[1] == 'ATM Withdrawal':
            amount = random.choice([20, 40, 50, 80, 100, 200])
        elif trans_type[1] == 'Bill Payment':
            amount = round(random.uniform(30, 300), 2)
        else:
            amount = round(random.uniform(5, 500), 2)
        
        # Calculer nouveau solde
        if trans_type[0] == 'debit':
            balance -= amount
        else:
            balance += amount
        
        transaction = {
            'id': fake.uuid4(),
            'account_id': account_id,
            'date': fake.date_time_between(start_date='-6m', end_date='now').isoformat(),
            'type': trans_type[0],
            'description': trans_type[1],
            'merchant': fake.company() if trans_type[0] == 'debit' else None,
            'amount': amount,
            'balance': round(balance, 2),
            'category': fake.random_element(['Food', 'Transport', 'Shopping', 'Bills', 'Entertainment', 'Other']),
            'status': 'completed',
            'reference': fake.bothify(text='TRX-########')
        }
        
        transactions.append(transaction)
    
    # Trier par date
    transactions.sort(key=lambda x: x['date'])
    
    return transactions

# Utilisation
transactions = generate_transactions(50)


# === 4. Générateur de Données Médicales (Fictives) ===

from faker.providers import BaseProvider

class MedicalProvider(BaseProvider):
    """Provider médical (données fictives uniquement!)"""
    
    def blood_type(self):
        """Groupe sanguin"""
        types = ['A+', 'A-', 'B+', 'B-', 'AB+', 'AB-', 'O+', 'O-']
        weights = [35, 6, 8, 2, 4, 1, 35, 9]
        return random.choices(types, weights=weights)[0]
    
    def diagnosis(self):
        """Diagnostic (exemples génériques)"""
        diagnoses = [
            'Common Cold', 'Flu', 'Migraine', 'Allergies',
            'Hypertension', 'Diabetes Type 2', 'Asthma',
            'Back Pain', 'Anxiety', 'Depression'
        ]
        return self.random_element(diagnoses)
    
    def medication(self):
        """Médicament (noms génériques)"""
        meds = [
            'Aspirin', 'Ibuprofen', 'Paracetamol',
            'Amoxicillin', 'Metformin', 'Lisinopril',
            'Omeprazole', 'Simvastatin'
        ]
        return self.random_element(meds)
    
    def vital_signs(self):
        """Signes vitaux"""
        return {
            'temperature': round(random.uniform(36.1, 37.5), 1),
            'blood_pressure': f"{random.randint(110, 140)}/{random.randint(70, 90)}",
            'heart_rate': random.randint(60, 100),
            'respiratory_rate': random.randint(12, 20),
            'oxygen_saturation': random.randint(95, 100)
        }

def generate_patient_records(num_records=50):
    """Génère dossiers patients (FICTIFS)"""
    fake = Faker('fr_FR')
    fake.add_provider(MedicalProvider)
    
    records = []
    
    for _ in range(num_records):
        record = {
            'patient_id': fake.uuid4(),
            'name': fake.name(),
            'birthdate': fake.date_of_birth(minimum_age=1, maximum_age=90),
            'gender': random.choice(['M', 'F']),
            'blood_type': fake.blood_type(),
            'email': fake.email(),
            'phone': fake.phone_number(),
            'address': fake.address(),
            'emergency_contact': {
                'name': fake.name(),
                'relation': random.choice(['Spouse', 'Parent', 'Sibling', 'Friend']),
                'phone': fake.phone_number()
            },
            'diagnosis': fake.diagnosis(),
            'medications': [fake.medication() for _ in range(random.randint(0, 3))],
            'allergies': random.choice([[], ['Penicillin'], ['Peanuts'], ['Latex']]),
            'vital_signs': fake.vital_signs(),
            'last_visit': fake.date_between(start_date='-1y', end_date='today'),
            'next_appointment': fake.date_between(start_date='today', end_date='+3m')
        }
        
        records.append(record)
    
    return records

# Utilisation
medical_records = generate_patient_records(30)


# === 5. Générateur de Données IoT/Sensors ===

def generate_iot_sensor_data(sensor_id=None, duration_hours=24, interval_minutes=5):
    """Génère données capteurs IoT"""
    fake = Faker()
    
    if sensor_id is None:
        sensor_id = fake.bothify(text='SENSOR-???-####')
    
    num_readings = (duration_hours * 60) // interval_minutes
    start_time = fake.date_time_between(start_date='-7d', end_date='now')
    
    readings = []
    
    # Valeurs de base avec variation
    base_temp = random.uniform(20, 25)
    base_humidity = random.uniform(40, 60)
    
    for i in range(num_readings):
        timestamp = start_time + timedelta(minutes=i * interval_minutes)
        
        # Variation naturelle
        temp_variation = random.gauss(0, 0.5)
        humidity_variation = random.gauss(0, 2)
        
        reading = {
            'sensor_id': sensor_id,
            'timestamp': timestamp.isoformat(),
            'temperature': round(base_temp + temp_variation, 2),
            'humidity': round(base_humidity + humidity_variation, 2),
            'pressure': round(random.uniform(1000, 1030), 2),
            'light_level': random.randint(0, 1000),
            'battery_level': max(0, 100 - (i * 0.1)),  # Décroissance batterie
            'signal_strength': random.randint(-90, -30),
            'status': 'ok' if random.random() > 0.02 else 'warning'
        }
        
        readings.append(reading)
    
    return readings

# Utilisation
sensor_data = generate_iot_sensor_data(duration_hours=48)


# === 6. Générateur de Données Réseaux Sociaux ===

def generate_social_media_posts(num_posts=100):
    """Génère posts réseaux sociaux"""
    fake = Faker('fr_FR')
    
    posts = []
    
    for _ in range(num_posts):
        # Type de post
        post_type = random.choice(['text', 'image', 'video', 'link'])
        
        # Contenu selon type
        if post_type == 'text':
            content = fake.text(max_nb_chars=280)  # Style Twitter
        elif post_type == 'image':
            content = fake.sentence()
            image_url = f"https://picsum.photos/800/600?random={random.randint(1, 1000)}"
        elif post_type == 'video':
            content = fake.sentence()
            video_url = f"https://example.com/video/{fake.uuid4()}"
        else:  # link
            content = fake.sentence()
            link_url = fake.url()
        
        # Engagement aléatoire (distribution réaliste)
        views = random.randint(100, 100000)
        engagement_rate = random.uniform(0.01, 0.1)
        likes = int(views * engagement_rate)
        comments = int(likes * random.uniform(0.05, 0.2))
        shares = int(likes * random.uniform(0.01, 0.1))
        
        post = {
            'id': fake.uuid4(),
            'author': fake.name(),
            'author_username': fake.user_name(),
            'type': post_type,
            'content': content,
            'hashtags': [f"#{fake.word()}" for _ in range(random.randint(0, 5))],
            'mentions': [f"@{fake.user_name()}" for _ in range(random.randint(0, 3))],
            'likes': likes,
            'comments': comments,
            'shares': shares,
            'views': views,
            'created_at': fake.date_time_between(start_date='-30d', end_date='now').isoformat(),
            'is_verified': random.choice([True, False, False, False])  # 25% vérifiés
        }
        
        if post_type == 'image':
            post['media_url'] = image_url
        elif post_type == 'video':
            post['media_url'] = video_url
        elif post_type == 'link':
            post['link_url'] = link_url
        
        posts.append(post)
    
    return posts

# Utilisation
social_posts = generate_social_media_posts(50)


# === 7. Générateur de Logs Serveur ===

def generate_server_logs(num_logs=1000):
    """Génère logs serveur réalistes"""
    fake = Faker()
    
    logs = []
    
    # Endpoints communs
    endpoints = [
        ('/api/users', ['GET', 'POST']),
        ('/api/products', ['GET']),
        ('/api/orders', ['GET', 'POST', 'PUT']),
        ('/api/auth/login', ['POST']),
        ('/api/auth/logout', ['POST']),
        ('/', ['GET']),
        ('/about', ['GET']),
        ('/contact', ['GET', 'POST'])
    ]
    
    # Status codes avec probabilités
    status_codes = [
        (200, 0.7),   # OK
        (201, 0.1),   # Created
        (400, 0.05),  # Bad Request
        (401, 0.05),  # Unauthorized
        (404, 0.05),  # Not Found
        (500, 0.05)   # Server Error
    ]
    
    for _ in range(num_logs):
        endpoint, methods = random.choice(endpoints)
        method = random.choice(methods)
        status = random.choices([s[0] for s in status_codes], 
                              weights=[s[1] for s in status_codes])[0]
        
        # Temps de réponse réaliste
        if status >= 500:
            response_time = random.uniform(2000, 10000)  # Erreurs plus lentes
        elif status >= 400:
            response_time = random.uniform(100, 500)
        else:
            response_time = random.uniform(10, 300)
        
        log = {
            'timestamp': fake.date_time_between(start_date='-1d', end_date='now').isoformat(),
            'ip': fake.ipv4(),
            'method': method,
            'endpoint': endpoint,
            'status': status,
            'response_time_ms': round(response_time, 2),
            'user_agent': fake.user_agent(),
            'bytes_sent': random.randint(100, 50000)
        }
        
        logs.append(log)
    
    # Trier par timestamp
    logs.sort(key=lambda x: x['timestamp'])
    
    return logs

# Utilisation
server_logs = generate_server_logs(500)


# === 8. Générateur de Données Événements ===

def generate_events(num_events=50):
    """Génère événements (conférences, concerts, etc.)"""
    fake = Faker('fr_FR')
    
    events = []
    
    event_types = ['Conference', 'Concert', 'Workshop', 'Meetup', 'Webinar', 'Festival']
    
    for _ in range(num_events):
        event_type = random.choice(event_types)
        
        # Date événement (futur)
        event_date = fake.date_time_between(start_date='now', end_date='+6m')
        
        # Capacité selon type
        if event_type in ['Conference', 'Concert', 'Festival']:
            capacity = random.randint(500, 5000)
        elif event_type == 'Webinar':
            capacity = random.randint(100, 1000)
        else:
            capacity = random.randint(20, 200)
        
        # Places vendues
        tickets_sold = random.randint(0, capacity)
        
        event = {
            'id': fake.uuid4(),
            'title': f"{fake.catch_phrase()} {event_type}",
            'type': event_type,
            'description': fake.text(max_nb_chars=300),
            'organizer': fake.company(),
            'date': event_date.isoformat(),
            'duration_hours': random.choice([1, 2, 3, 4, 8]),
            'location': {
                'venue': fake.company() + " Center",
                'address': fake.address(),
                'city': fake.city(),
                'country': fake.current_country()
            },
            'capacity': capacity,
            'tickets_sold': tickets_sold,
            'tickets_available': capacity - tickets_sold,
            'price': round(random.uniform(0, 200), 2) if event_type != 'Webinar' else 0,
            'categories': random.sample(['Tech', 'Business', 'Art', 'Music', 'Science', 'Education'], 
                                       k=random.randint(1, 3)),
            'is_online': event_type == 'Webinar',
            'registration_url': fake.url(),
            'created_at': fake.date_time_between(start_date='-3m', end_date='now').isoformat()
        }
        
        events.append(event)
    
    return events

# Utilisation
events = generate_events(30)


[OK] INTÉGRATION AVEC FRAMEWORKS

# === Django Models ===

# models.py
from django.db import models

class User(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField(unique=True)
    phone = models.CharField(max_length=20)
    address = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

# management/commands/generate_fake_users.py
from django.core.management.base import BaseCommand
from faker import Faker
from myapp.models import User

class Command(BaseCommand):
    help = 'Generate fake users'
    
    def add_arguments(self, parser):
        parser.add_argument('count', type=int, help='Number of users to create')
    
    def handle(self, *args, **options):
        fake = Faker('fr_FR')
        count = options['count']
        
        for _ in range(count):
            User.objects.create(
                name=fake.name(),
                email=fake.email(),
                phone=fake.phone_number(),
                address=fake.address()
            )
        
        self.stdout.write(self.style.SUCCESS(f'{count} users created'))

# Utilisation
# python manage.py generate_fake_users 100


# === Flask API ===

from flask import Flask, jsonify
from faker import Faker

app = Flask(__name__)
fake = Faker('fr_FR')

@app.route('/api/users')
def get_users():
    """Génère utilisateurs factices pour demo"""
    users = []
    for _ in range(10):
        user = {
            'id': fake.uuid4(),
            'name': fake.name(),
            'email': fake.email(),
            'phone': fake.phone_number()
        }
        users.append(user)
    
    return jsonify(users)

@app.route('/api/user')
def get_user():
    """Génère un utilisateur factice"""
    user = {
        'id': fake.uuid4(),
        'name': fake.name(),
        'email': fake.email(),
        'avatar': f"https://i.pravatar.cc/150?u={fake.uuid4()}"
    }
    return jsonify(user)


# === FastAPI ===

from fastapi import FastAPI, Query
from faker import Faker
from pydantic import BaseModel
from typing import List

app = FastAPI()
fake = Faker('fr_FR')

class User(BaseModel):
    id: str
    name: str
    email: str
    phone: str

@app.get("/api/users", response_model=List[User])
async def get_users(count: int = Query(10, ge=1, le=100)):
    """Génère liste utilisateurs factices"""
    users = []
    for _ in range(count):
        user = User(
            id=fake.uuid4(),
            name=fake.name(),
            email=fake.email(),
            phone=fake.phone_number()
        )
        users.append(user)
    
    return users


# === SQLAlchemy ===

from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from faker import Faker

Base = declarative_base()

class User(Base):
    __tablename__ = 'users'
    
    id = Column(Integer, primary_key=True)
    name = Column(String(100))
    email = Column(String(100), unique=True)
    phone = Column(String(20))

# Créer base de données
engine = create_engine('sqlite:///test.db')
Base.metadata.create_all(engine)

# Session
Session = sessionmaker(bind=engine)
session = Session()

# Générer données
fake = Faker('fr_FR')

for _ in range(100):
    user = User(
        name=fake.name(),
        email=fake.email(),
        phone=fake.phone_number()
    )
    session.add(user)

session.commit()


[OK] TESTS UNITAIRES AVEC FAKER

import unittest
from faker import Faker

class TestUserModel(unittest.TestCase):
    
    def setUp(self):
        """Initialise Faker avant chaque test"""
        Faker.seed(0)
        self.fake = Faker('fr_FR')
    
    def test_user_creation(self):
        """Test création utilisateur avec données factices"""
        user_data = {
            'name': self.fake.name(),
            'email': self.fake.email(),
            'phone': self.fake.phone_number()
        }
        
        # Tester validation
        self.assertIsNotNone(user_data['name'])
        self.assertIn('@', user_data['email'])
    
    def test_email_uniqueness(self):
        """Test unicité email"""
        emails = [self.fake.email() for _ in range(100)]
        # Vérifier pas de doublons (très peu probable)
        self.assertEqual(len(emails), len(set(emails)))


# === Pytest Fixtures ===

import pytest
from faker import Faker

@pytest.fixture
def fake():
    """Fixture Faker pour tests"""
    Faker.seed(0)
    return Faker('fr_FR')

@pytest.fixture
def fake_user(fake):
    """Fixture utilisateur factice"""
    return {
        'id': fake.uuid4(),
        'name': fake.name(),
        'email': fake.email(),
        'phone': fake.phone_number()
    }

def test_user_data(fake_user):
    """Test avec fixture"""
    assert '@' in fake_user['email']
    assert len(fake_user['id']) == 36


# === Factory Boy Integration ===

import factory
from faker import Faker

fake = Faker('fr_FR')

class UserFactory(factory.Factory):
    class Meta:
        model = dict
    
    id = factory.LazyFunction(lambda: fake.uuid4())
    name = factory.LazyFunction(lambda: fake.name())
    email = factory.LazyFunction(lambda: fake.email())
    phone = factory.LazyFunction(lambda: fake.phone_number())

# Utilisation
user = UserFactory()
users = UserFactory.create_batch(10)


[OK] PERFORMANCE & OPTIMISATION

from faker import Faker
import time

# === Benchmark ===

fake = Faker('fr_FR')

# Mesurer performance
start = time.time()
for _ in range(10000):
    fake.name()
end = time.time()
print(f"10000 noms: {end - start:.2f}s")


# === Optimisation: Réutiliser Instance ===

# [X] LENT: Créer nouvelle instance à chaque fois
def generate_user_slow():
    fake = Faker('fr_FR')  # Lent!
    return fake.name()

# [OK] RAPIDE: Réutiliser instance
fake = Faker('fr_FR')

def generate_user_fast():
    return fake.name()


# === Optimisation: Batch Generation ===

# [X] LENT: Appels individuels
users = []
for _ in range(1000):
    users.append({
        'name': fake.name(),
        'email': fake.email()
    })

# [OK] RAPIDE: List comprehension
users = [
    {'name': fake.name(), 'email': fake.email()}
    for _ in range(1000)
]


# === Optimisation: Cache pour Données Répétitives ===

# Cache catégories (générées une fois)
CATEGORIES = [fake.word() for _ in range(20)]

# Réutiliser
products = []
for _ in range(1000):
    product = {
        'name': fake.word(),
        'category': random.choice(CATEGORIES)  # Réutilise cache
    }
    products.append(product)


[OK] BONNES PRATIQUES

# === 1. Toujours Utiliser Seed pour Tests ===

# [OK] BON: Tests reproductibles
def test_something():
    Faker.seed(42)
    fake = Faker()
    result = fake.name()
    assert result == "Christine Watson"  # Toujours le même


# === 2. Choisir Locale Appropriée ===

# [OK] BON: Locale selon contexte
fake_fr = Faker('fr_FR')  # Pour app française
fake_us = Faker('en_US')  # Pour app américaine


# === 3. Valider Données Générées ===

# [OK] BON: Valider format
email = fake.email()
assert '@' in email
assert '.' in email.split('@')[1]


# === 4. Ne PAS Utiliser en Production ===

# [X] MAUVAIS: Faker en production
if not user.email:
    user.email = fake.email()  # NON!

# [OK] BON: Seulement en dev/test
if settings.DEBUG:
    fake_data = generate_test_data()


# === 5. Éviter Doublons pour Champs Uniques ===

# [X] MAUVAIS: Peut créer doublons
emails = [fake.email() for _ in range(1000)]

# [OK] BON: Vérifier unicité
emails = set()
while len(emails) < 1000:
    emails.add(fake.email())

# [OK] MEILLEUR: Utiliser unique generator
from faker import Faker
fake = Faker()
unique_fake = fake.unique

emails = [unique_fake.email() for _ in range(1000)]

# Réinitialiser cache unique
fake.unique.clear()


# === 6. Combiner avec Données Réelles ===

# [OK] BON: Mélanger faker et données réelles
real_categories = ['Electronics', 'Clothing', 'Home', 'Sports']
products = []

for _ in range(100):
    product = {
        'name': fake.word(),
        'category': random.choice(real_categories),  # Données réelles
        'price': fake.random_int(10, 1000)
    }
    products.append(product)


# === 7. Documenter Seed dans Tests ===

def test_user_profile():
    """Test génération profil utilisateur
    
    Seed: 42 (pour reproductibilité)
    """
    Faker.seed(42)
    fake = Faker('fr_FR')
    profile = generate_profile(fake)
    assert profile['email'].endswith('@example.com')


[OK] MÉTHODES UTILES SUPPLÉMENTAIRES

# === Données Automobiles ===

fake.license_plate()                 # Plaque immatriculation
# "ABC-123"

# === Codes ===

fake.ean()                           # Code-barres EAN
fake.ean8()                          # EAN-8
fake.ean13()                         # EAN-13


# === Profils ===

fake.profile()                       # Profil complet
# {
#     'job': 'Scientist',
#     'company': 'Smith Inc',
#     'ssn': '123-45-6789',
#     'residence': '123 Main St',
#     'current_location': (45.5, -73.6),
#     'blood_group': 'O+',
#     'website': ['https://example.com'],
#     'username': 'john_doe',
#     'name': 'John Doe',
#     'sex': 'M',
#     'address': '123 Main St, City, State',
#     'mail': 'john@example.com',
#     'birthdate': date(1990, 1, 1)
# }

fake.simple_profile()                # Profil simplifié
# {
#     'username': 'john_doe',
#     'name': 'John Doe',
#     'sex': 'M',
#     'address': '123 Main St',
#     'mail': 'john@example.com',
#     'birthdate': date(1990, 1, 1)
# }


[OK] COMMANDES CLI

# Faker peut être utilisé en ligne de commande

# Générer une valeur
faker name
# "John Smith"

faker address
# "123 Main Street, New York, NY 10001"

faker email
# "john.smith@example.com"

# Spécifier locale
faker -l fr_FR name
# "Jean Dupont"

# Générer plusieurs valeurs
faker -r 5 name
# Génère 5 noms

# Seed
faker -s 12345 name
# Résultat reproductible

# Format JSON
faker -o json name email phone
# {"name": "John Doe", "email": "...", "phone": "..."}

# Sauver dans fichier
faker -r 100 name > names.txt


[OK] ASTUCES & TRICKS

# === 1. Générer Email depuis Nom ===

name = fake.name()
first_name, last_name = name.split()[:2]
email = f"{first_name.lower()}.{last_name.lower()}@example.com"


# === 2. Générer Username depuis Nom ===

name = fake.name()
username = name.lower().replace(' ', '_') + str(fake.random_int(100, 999))


# === 3. Dates Cohérentes ===

# Date naissance puis dates cohérentes
birthdate = fake.date_of_birth(minimum_age=25, maximum_age=50)

# Date inscription après naissance
registration_date = fake.date_between(
    start_date=birthdate + timedelta(days=365*18),
    end_date='today'
)

# Dernière connexion après inscription
last_login = fake.date_between(
    start_date=registration_date,
    end_date='today'
)


# === 4. Relations Entre Entités ===

# Générer entreprises
companies = [
    {'id': fake.uuid4(), 'name': fake.company()}
    for _ in range(10)
]

# Générer employés liés
employees = []
for _ in range(50):
    company = random.choice(companies)
    employee = {
        'id': fake.uuid4(),
        'company_id': company['id'],
        'company_name': company['name'],
        'name': fake.name(),
        'email': fake.company_email()
    }
    employees.append(employee)


# === 5. Pondération Réaliste ===

# Distribution réaliste des âges
ages = []
for _ in range(1000):
    # Plus de jeunes adultes
    if random.random() < 0.4:
        age = random.randint(18, 30)
    elif random.random() < 0.7:
        age = random.randint(31, 50)
    else:
        age = random.randint(51, 80)
    ages.append(age)


# === 6. Données Temporelles Réalistes ===

# Activité plus forte en journée
def realistic_timestamp():
    """Génère timestamp avec activité réaliste"""
    date = fake.date_time_between(start_date='-30d', end_date='now')
    
    # Ajuster heure (plus d'activité 9h-18h)
    hour_weights = [1]*9 + [5]*9 + [2]*6  # 24 heures
    hour = random.choices(range(24), weights=hour_weights)[0]
    
    return date.replace(hour=hour)


# === 7. Validation Personnalisée ===

def generate_valid_phone():
    """Génère téléphone avec format spécifique"""
    while True:
        phone = fake.phone_number()
        # Valider format
        if phone.startswith('+33') and len(phone) >= 12:
            return phone


# === 8. Mixage de Providers ===

# Combiner plusieurs providers
fake.add_provider(GameProvider)
fake.add_provider(EcommerceProvider)

game_product = {
    'name': fake.game_title(),
    'genre': fake.game_genre(),
    'price': fake.product_price(),
    'sku': fake.product_sku()
}


[OK] DEBUGGING & TROUBLESHOOTING

# === Voir Providers Disponibles ===

from faker import Faker
fake = Faker()

# Lister tous les providers
print(dir(fake))

# Voir méthodes d'un provider spécifique
from faker.providers import internet
print(dir(internet.Provider))


# === Vérifier Locale Disponible ===

from faker import Faker
from faker.config import AVAILABLE_LOCALES

print(AVAILABLE_LOCALES)
# ['ar_AA', 'ar_EG', 'ar_JO', 'ar_PS', 'ar_SA', ...]


# === Debug Génération ===

# Activer mode verbose
import logging
logging.basicConfig(level=logging.DEBUG)

fake = Faker('fr_FR')
fake.name()  # Affiche infos debug


# === Problème: Locale Non Trouvée ===

# [X] Erreur
try:
    fake = Faker('xx_XX')  # Locale invalide
except AttributeError as e:
    print(f"Locale invalide: {e}")

# [OK] Solution: Vérifier locale existe
if 'xx_XX' in AVAILABLE_LOCALES:
    fake = Faker('xx_XX')
else:
    fake = Faker()  # Fallback en_US


# === Problème: Méthode Non Trouvée ===

# Vérifier méthode existe
if hasattr(fake, 'custom_method'):
    result = fake.custom_method()
else:
    print("Méthode non disponible")


# === Problème: Unicité Épuisée ===

from faker import Faker
from faker.exceptions import UniquenessException

fake = Faker()

try:
    # Essayer générer plus de valeurs uniques que possible
    emails = [fake.unique.email() for _ in range(1000000)]
except UniquenessException:
    print("Impossible de générer plus de valeurs uniques")
    fake.unique.clear()  # Réinitialiser


[OK] ALTERNATIVES & COMPARAISONS

# === Mimesis ===
# Alternative à Faker, plus rapide

from mimesis import Person
person = Person('fr')

print(person.full_name())            # "Jean Dupont"
print(person.email())                # "jean@example.com"


# === Factory Boy ===
# Pour tests et fixtures Django/SQLAlchemy

import factory
from faker import Faker

fake = Faker()

class UserFactory(factory.Factory):
    class Meta:
        model = User
    
    name = factory.LazyFunction(lambda: fake.name())
    email = factory.LazyFunction(lambda: fake.email())


# === Hypothesis ===
# Property-based testing

from hypothesis import given
from hypothesis import strategies as st

@given(st.emails())
def test_email_validation(email):
    assert '@' in email


# === random vs Faker ===

import random
from faker import Faker

# random: nombres, choix simples
random.randint(1, 100)
random.choice(['a', 'b', 'c'])

# Faker: données complexes réalistes
fake = Faker()
fake.name()                          # Nom réaliste
fake.address()                       # Adresse complète


[OK] EXEMPLES DE SCRIPTS COMPLETS

# === Script 1: Générer Fichier SQL d'Import ===

from faker import Faker

def generate_sql_insert(table_name, num_records=1000, locale='fr_FR'):
    """Génère fichier SQL avec INSERT statements"""
    fake = Faker(locale)
    
    with open(f'{table_name}_insert.sql', 'w', encoding='utf-8') as f:
        for i in range(num_records):
            name = fake.name().replace("'", "''")
            email = fake.email()
            phone = fake.phone_number().replace("'", "''")
            created = fake.date_time_this_year().strftime('%Y-%m-%d %H:%M:%S')
            
            sql = f"""INSERT INTO {table_name} (name, email, phone, created_at)
VALUES ('{name}', '{email}', '{phone}', '{created}');
"""
            f.write(sql)
    
    print(f"[OK] Fichier {table_name}_insert.sql créé avec {num_records} enregistrements")

# Utilisation
generate_sql_insert('users', 10000)


# === Script 2: Mock API REST ===

from flask import Flask, jsonify, request
from faker import Faker
import random

app = Flask(__name__)
fake = Faker('fr_FR')

# Base de données en mémoire
users_db = []
products_db = []

def init_data():
    """Initialise données factices"""
    global users_db, products_db
    
    # Générer utilisateurs
    for _ in range(100):
        users_db.append({
            'id': len(users_db) + 1,
            'name': fake.name(),
            'email': fake.email(),
            'phone': fake.phone_number(),
            'created_at': fake.iso8601()
        })
    
    # Générer produits
    for _ in range(50):
        products_db.append({
            'id': len(products_db) + 1,
            'name': fake.word().capitalize() + " " + fake.word(),
            'price': round(random.uniform(10, 500), 2),
            'stock': random.randint(0, 100),
            'category': random.choice(['Electronics', 'Clothing', 'Home'])
        })

@app.route('/api/users', methods=['GET'])
def get_users():
    page = int(request.args.get('page', 1))
    per_page = int(request.args.get('per_page', 10))
    
    start = (page - 1) * per_page
    end = start + per_page
    
    return jsonify({
        'data': users_db[start:end],
        'page': page,
        'per_page': per_page,
        'total': len(users_db)
    })

@app.route('/api/users/<int:user_id>', methods=['GET'])
def get_user(user_id):
    user = next((u for u in users_db if u['id'] == user_id), None)
    if user:
        return jsonify(user)
    return jsonify({'error': 'User not found'}), 404

@app.route('/api/products', methods=['GET'])
def get_products():
    return jsonify(products_db)

if __name__ == '__main__':
    init_data()
    app.run(debug=True)


# === Script 3: Générateur de Dataset ML ===

import pandas as pd
from faker import Faker
import random

def generate_ml_dataset(num_samples=10000):
    """Génère dataset pour machine learning"""
    fake = Faker('fr_FR')
    
    data = {
        'age': [random.randint(18, 80) for _ in range(num_samples)],
        'gender': [random.choice(['M', 'F']) for _ in range(num_samples)],
        'income': [random.randint(20000, 200000) for _ in range(num_samples)],
        'city': [fake.city() for _ in range(num_samples)],
        'education': [random.choice(['High School', 'Bachelor', 'Master', 'PhD']) 
                     for _ in range(num_samples)],
        'experience_years': [random.randint(0, 40) for _ in range(num_samples)],
        'job_category': [random.choice(['Tech', 'Finance', 'Health', 'Education', 'Other']) 
                        for _ in range(num_samples)]
    }
    
    # Target variable (exemple: satisfaction)
    data['satisfaction'] = [
        random.choice(['Low', 'Medium', 'High']) 
        for _ in range(num_samples)
    ]
    
    df = pd.DataFrame(data)
    
    # Ajouter corrélations réalistes
    # Satisfaction plus élevée avec revenu élevé
    for idx in df.index:
        if df.loc[idx, 'income'] > 100000 and random.random() > 0.3:
            df.loc[idx, 'satisfaction'] = 'High'
    
    return df

# Utilisation
df = generate_ml_dataset(5000)
df.to_csv('ml_dataset.csv', index=False)


# === Script 4: Seed Management pour Tests ===

import json
from faker import Faker

class SeedManager:
    """Gestionnaire de seeds pour tests reproductibles"""
    
    def __init__(self, seed_file='test_seeds.json'):
        self.seed_file = seed_file
        self.seeds = self.load_seeds()
    
    def load_seeds(self):
        """Charge seeds depuis fichier"""
        try:
            with open(self.seed_file, 'r') as f:
                return json.load(f)
        except FileNotFoundError:
            return {}
    
    def save_seeds(self):
        """Sauvegarde seeds dans fichier"""
        with open(self.seed_file, 'w') as f:
            json.dump(self.seeds, f, indent=2)
    
    def get_seed(self, test_name):
        """Récupère ou crée seed pour test"""
        if test_name not in self.seeds:
            self.seeds[test_name] = random.randint(1, 1000000)
            self.save_seeds()
        return self.seeds[test_name]
    
    def get_faker(self, test_name, locale='fr_FR'):
        """Retourne instance Faker avec seed pour test"""
        seed = self.get_seed(test_name)
        Faker.seed(seed)
        return Faker(locale)

# Utilisation
seed_mgr = SeedManager()

def test_user_creation():
    fake = seed_mgr.get_faker('test_user_creation')
    user = fake.name()  # Toujours le même pour ce test
    assert user is not None


[OK] RESSOURCES & DOCUMENTATION

# Documentation officielle:
# https://faker.readthedocs.io/

# GitHub:
# https://github.com/joke2k/faker

# Liste complète des providers:
# https://faker.readthedocs.io/en/master/providers.html

# Locales disponibles:
# https://faker.readthedocs.io/en/master/locales.html

# Community providers:
# https://github.com/joke2k/faker/blob/master/docs/community.rst


[OK] RÉSUMÉ DES COMMANDES ESSENTIELLES

from faker import Faker

# Initialisation
fake = Faker('fr_FR')                # Avec locale
Faker.seed(42)                       # Pour reproductibilité

# Personnes
fake.name()                          # Nom complet
fake.email()                         # Email
fake.phone_number()                  # Téléphone

# Adresses
fake.address()                       # Adresse complète
fake.city()                          # Ville
fake.country()                       # Pays

# Dates
fake.date()                          # Date
fake.date_time()                     # DateTime
fake.date_of_birth()                 # Date naissance

# Texte
fake.text()                          # Texte long
fake.sentence()                      # Phrase
fake.word()                          # Mot

# Internet
fake.url()                           # URL
fake.ipv4()                          # Adresse IP
fake.user_agent()                    # User agent

# Identifiants
fake.uuid4()                         # UUID
fake.ean13()                         # Code-barres

# Finance
fake.credit_card_number()            # Numéro carte
fake.iban()                          # IBAN

# Unique values
fake.unique.email()                  # Email unique
fake.unique.clear()                  # Reset cache

# Profil complet
fake.profile()                       # Profil utilisateur complet

# Custom provider
fake.add_provider(MyProvider)        # Ajouter provider custom


[OK] CHECKLISTE UTILISATION

[OK] Installer faker: `pip install faker`
[OK] Choisir locale appropriée selon contexte
[OK] Utiliser seed pour tests unitaires reproductibles
[OK] Valider format des données générées
[OK] Utiliser unique() pour champs avec contraintes d'unicité
[OK] Réinitialiser unique.clear() entre tests
[OK] Ne JAMAIS utiliser en production
[OK] Créer providers custom pour besoins spécifiques
[OK] Combiner avec données réelles quand nécessaire
[OK] Générer relations cohérentes entre entités
[OK] Utiliser distributions réalistes pour données numériques
[OK] Documenter seeds utilisés dans tests
[OK] Exporter vers formats appropriés (CSV, JSON, SQL)
[OK] Tester performance pour gros volumes de données


[OK] PIÈGES À ÉVITER

[X] Ne pas utiliser Faker en production
[X] Ne pas oublier seed dans tests
[X] Ne pas supposer unicité sans unique()
[X] Ne pas générer données incohérentes (dates, relations)
[X] Ne pas créer nouvelle instance Faker dans boucles
[X] Ne pas ignorer locale pour données internationales
[X] Ne pas mélanger seeds entre tests
[X] Ne pas générer volumes massifs sans optimisation
[X] Ne pas oublier de valider données sensibles
[X] Ne pas utiliser pour données réelles/confidentielles