dataforge-py 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dataforge/__init__.py +20 -0
- dataforge/backend.py +147 -0
- dataforge/cli.py +166 -0
- dataforge/core.py +1169 -0
- dataforge/locales/__init__.py +1 -0
- dataforge/locales/ar_SA/__init__.py +1 -0
- dataforge/locales/ar_SA/address.py +128 -0
- dataforge/locales/ar_SA/company.py +183 -0
- dataforge/locales/ar_SA/internet.py +25 -0
- dataforge/locales/ar_SA/person.py +217 -0
- dataforge/locales/ar_SA/phone.py +15 -0
- dataforge/locales/de_DE/__init__.py +1 -0
- dataforge/locales/de_DE/address.py +148 -0
- dataforge/locales/de_DE/company.py +125 -0
- dataforge/locales/de_DE/internet.py +32 -0
- dataforge/locales/de_DE/person.py +212 -0
- dataforge/locales/de_DE/phone.py +17 -0
- dataforge/locales/en_AU/__init__.py +1 -0
- dataforge/locales/en_AU/address.py +231 -0
- dataforge/locales/en_AU/company.py +193 -0
- dataforge/locales/en_AU/internet.py +34 -0
- dataforge/locales/en_AU/person.py +370 -0
- dataforge/locales/en_AU/phone.py +16 -0
- dataforge/locales/en_CA/__init__.py +1 -0
- dataforge/locales/en_CA/address.py +276 -0
- dataforge/locales/en_CA/company.py +193 -0
- dataforge/locales/en_CA/internet.py +34 -0
- dataforge/locales/en_CA/person.py +377 -0
- dataforge/locales/en_CA/phone.py +15 -0
- dataforge/locales/en_GB/__init__.py +1 -0
- dataforge/locales/en_GB/address.py +312 -0
- dataforge/locales/en_GB/company.py +196 -0
- dataforge/locales/en_GB/internet.py +34 -0
- dataforge/locales/en_GB/person.py +372 -0
- dataforge/locales/en_GB/phone.py +15 -0
- dataforge/locales/en_US/__init__.py +1 -0
- dataforge/locales/en_US/address.py +268 -0
- dataforge/locales/en_US/company.py +191 -0
- dataforge/locales/en_US/internet.py +34 -0
- dataforge/locales/en_US/person.py +370 -0
- dataforge/locales/en_US/phone.py +15 -0
- dataforge/locales/es_ES/__init__.py +1 -0
- dataforge/locales/es_ES/address.py +151 -0
- dataforge/locales/es_ES/company.py +125 -0
- dataforge/locales/es_ES/internet.py +30 -0
- dataforge/locales/es_ES/person.py +207 -0
- dataforge/locales/es_ES/phone.py +15 -0
- dataforge/locales/fr_FR/__init__.py +1 -0
- dataforge/locales/fr_FR/address.py +145 -0
- dataforge/locales/fr_FR/company.py +125 -0
- dataforge/locales/fr_FR/internet.py +30 -0
- dataforge/locales/fr_FR/person.py +212 -0
- dataforge/locales/fr_FR/phone.py +15 -0
- dataforge/locales/hi_IN/__init__.py +1 -0
- dataforge/locales/hi_IN/address.py +177 -0
- dataforge/locales/hi_IN/company.py +191 -0
- dataforge/locales/hi_IN/internet.py +26 -0
- dataforge/locales/hi_IN/person.py +218 -0
- dataforge/locales/hi_IN/phone.py +21 -0
- dataforge/locales/it_IT/__init__.py +1 -0
- dataforge/locales/it_IT/address.py +218 -0
- dataforge/locales/it_IT/company.py +151 -0
- dataforge/locales/it_IT/internet.py +31 -0
- dataforge/locales/it_IT/person.py +187 -0
- dataforge/locales/it_IT/phone.py +15 -0
- dataforge/locales/ja_JP/__init__.py +1 -0
- dataforge/locales/ja_JP/address.py +174 -0
- dataforge/locales/ja_JP/company.py +121 -0
- dataforge/locales/ja_JP/internet.py +30 -0
- dataforge/locales/ja_JP/person.py +207 -0
- dataforge/locales/ja_JP/phone.py +18 -0
- dataforge/locales/ko_KR/__init__.py +1 -0
- dataforge/locales/ko_KR/address.py +121 -0
- dataforge/locales/ko_KR/company.py +151 -0
- dataforge/locales/ko_KR/internet.py +30 -0
- dataforge/locales/ko_KR/person.py +157 -0
- dataforge/locales/ko_KR/phone.py +26 -0
- dataforge/locales/nl_NL/__init__.py +1 -0
- dataforge/locales/nl_NL/address.py +152 -0
- dataforge/locales/nl_NL/company.py +182 -0
- dataforge/locales/nl_NL/internet.py +41 -0
- dataforge/locales/nl_NL/person.py +218 -0
- dataforge/locales/nl_NL/phone.py +19 -0
- dataforge/locales/pl_PL/__init__.py +1 -0
- dataforge/locales/pl_PL/address.py +140 -0
- dataforge/locales/pl_PL/company.py +183 -0
- dataforge/locales/pl_PL/internet.py +36 -0
- dataforge/locales/pl_PL/person.py +217 -0
- dataforge/locales/pl_PL/phone.py +15 -0
- dataforge/locales/pt_BR/__init__.py +1 -0
- dataforge/locales/pt_BR/address.py +127 -0
- dataforge/locales/pt_BR/company.py +151 -0
- dataforge/locales/pt_BR/internet.py +31 -0
- dataforge/locales/pt_BR/person.py +187 -0
- dataforge/locales/pt_BR/phone.py +15 -0
- dataforge/locales/ru_RU/__init__.py +1 -0
- dataforge/locales/ru_RU/address.py +156 -0
- dataforge/locales/ru_RU/company.py +168 -0
- dataforge/locales/ru_RU/internet.py +26 -0
- dataforge/locales/ru_RU/person.py +218 -0
- dataforge/locales/ru_RU/phone.py +16 -0
- dataforge/locales/zh_CN/__init__.py +1 -0
- dataforge/locales/zh_CN/address.py +141 -0
- dataforge/locales/zh_CN/company.py +151 -0
- dataforge/locales/zh_CN/internet.py +30 -0
- dataforge/locales/zh_CN/person.py +157 -0
- dataforge/locales/zh_CN/phone.py +25 -0
- dataforge/providers/__init__.py +1 -0
- dataforge/providers/address.py +460 -0
- dataforge/providers/ai_chat.py +170 -0
- dataforge/providers/ai_prompt.py +447 -0
- dataforge/providers/automotive.py +416 -0
- dataforge/providers/barcode.py +149 -0
- dataforge/providers/base.py +34 -0
- dataforge/providers/color.py +247 -0
- dataforge/providers/company.py +144 -0
- dataforge/providers/crypto.py +105 -0
- dataforge/providers/datetime.py +397 -0
- dataforge/providers/ecommerce.py +316 -0
- dataforge/providers/education.py +234 -0
- dataforge/providers/file.py +271 -0
- dataforge/providers/finance.py +545 -0
- dataforge/providers/geo.py +332 -0
- dataforge/providers/government.py +114 -0
- dataforge/providers/internet.py +351 -0
- dataforge/providers/llm.py +726 -0
- dataforge/providers/lorem.py +241 -0
- dataforge/providers/medical.py +364 -0
- dataforge/providers/misc.py +196 -0
- dataforge/providers/network.py +283 -0
- dataforge/providers/payment.py +300 -0
- dataforge/providers/person.py +195 -0
- dataforge/providers/phone.py +87 -0
- dataforge/providers/profile.py +265 -0
- dataforge/providers/science.py +365 -0
- dataforge/providers/text.py +365 -0
- dataforge/py.typed +0 -0
- dataforge/pytest_plugin.py +80 -0
- dataforge/registry.py +164 -0
- dataforge/schema.py +772 -0
- dataforge/unique.py +171 -0
- dataforge_py-0.2.0.dist-info/METADATA +964 -0
- dataforge_py-0.2.0.dist-info/RECORD +145 -0
- dataforge_py-0.2.0.dist-info/WHEEL +4 -0
- dataforge_py-0.2.0.dist-info/entry_points.txt +35 -0
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
"""Payment provider — credit card types, payment methods, processors, etc."""
|
|
2
|
+
|
|
3
|
+
from typing import Literal, overload
|
|
4
|
+
|
|
5
|
+
from dataforge.providers.base import BaseProvider
|
|
6
|
+
|
|
7
|
+
_CARD_TYPES: tuple[str, ...] = (
|
|
8
|
+
"Visa",
|
|
9
|
+
"Mastercard",
|
|
10
|
+
"American Express",
|
|
11
|
+
"Discover",
|
|
12
|
+
"Diners Club",
|
|
13
|
+
"JCB",
|
|
14
|
+
"UnionPay",
|
|
15
|
+
"Maestro",
|
|
16
|
+
"Mir",
|
|
17
|
+
"Elo",
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
_PAYMENT_METHODS: tuple[str, ...] = (
|
|
21
|
+
"Credit Card",
|
|
22
|
+
"Debit Card",
|
|
23
|
+
"PayPal",
|
|
24
|
+
"Apple Pay",
|
|
25
|
+
"Google Pay",
|
|
26
|
+
"Samsung Pay",
|
|
27
|
+
"Bank Transfer",
|
|
28
|
+
"Wire Transfer",
|
|
29
|
+
"Cash",
|
|
30
|
+
"Check",
|
|
31
|
+
"Cryptocurrency",
|
|
32
|
+
"Venmo",
|
|
33
|
+
"Zelle",
|
|
34
|
+
"Alipay",
|
|
35
|
+
"WeChat Pay",
|
|
36
|
+
"Klarna",
|
|
37
|
+
"Afterpay",
|
|
38
|
+
"Cash App",
|
|
39
|
+
"Money Order",
|
|
40
|
+
"ACH Transfer",
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
_PROCESSORS: tuple[str, ...] = (
|
|
44
|
+
"Stripe",
|
|
45
|
+
"Square",
|
|
46
|
+
"Adyen",
|
|
47
|
+
"Braintree",
|
|
48
|
+
"Worldpay",
|
|
49
|
+
"Checkout.com",
|
|
50
|
+
"PayPal Commerce",
|
|
51
|
+
"Authorize.Net",
|
|
52
|
+
"2Checkout",
|
|
53
|
+
"BlueSnap",
|
|
54
|
+
"Payoneer",
|
|
55
|
+
"Razorpay",
|
|
56
|
+
"Mollie",
|
|
57
|
+
"dLocal",
|
|
58
|
+
"Nuvei",
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
_TRANSACTION_STATUSES: tuple[str, ...] = (
|
|
62
|
+
"pending",
|
|
63
|
+
"processing",
|
|
64
|
+
"completed",
|
|
65
|
+
"failed",
|
|
66
|
+
"refunded",
|
|
67
|
+
"partially_refunded",
|
|
68
|
+
"voided",
|
|
69
|
+
"disputed",
|
|
70
|
+
"chargeback",
|
|
71
|
+
"authorized",
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
_CURRENCIES: tuple[str, ...] = (
|
|
75
|
+
"USD",
|
|
76
|
+
"EUR",
|
|
77
|
+
"GBP",
|
|
78
|
+
"JPY",
|
|
79
|
+
"CHF",
|
|
80
|
+
"CAD",
|
|
81
|
+
"AUD",
|
|
82
|
+
"CNY",
|
|
83
|
+
"HKD",
|
|
84
|
+
"NZD",
|
|
85
|
+
"SEK",
|
|
86
|
+
"NOK",
|
|
87
|
+
"DKK",
|
|
88
|
+
"SGD",
|
|
89
|
+
"KRW",
|
|
90
|
+
"INR",
|
|
91
|
+
"BRL",
|
|
92
|
+
"MXN",
|
|
93
|
+
"ZAR",
|
|
94
|
+
"PLN",
|
|
95
|
+
"TRY",
|
|
96
|
+
"RUB",
|
|
97
|
+
"THB",
|
|
98
|
+
"TWD",
|
|
99
|
+
"AED",
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
_CURRENCY_SYMBOLS: tuple[str, ...] = (
|
|
103
|
+
"$",
|
|
104
|
+
"€",
|
|
105
|
+
"£",
|
|
106
|
+
"¥",
|
|
107
|
+
"Fr",
|
|
108
|
+
"C$",
|
|
109
|
+
"A$",
|
|
110
|
+
"¥",
|
|
111
|
+
"HK$",
|
|
112
|
+
"NZ$",
|
|
113
|
+
"kr",
|
|
114
|
+
"kr",
|
|
115
|
+
"kr",
|
|
116
|
+
"S$",
|
|
117
|
+
"₩",
|
|
118
|
+
"₹",
|
|
119
|
+
"R$",
|
|
120
|
+
"MX$",
|
|
121
|
+
"R",
|
|
122
|
+
"zł",
|
|
123
|
+
"₺",
|
|
124
|
+
"₽",
|
|
125
|
+
"฿",
|
|
126
|
+
"NT$",
|
|
127
|
+
"د.إ",
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class PaymentProvider(BaseProvider):
|
|
132
|
+
"""Generates fake payment and transaction data."""
|
|
133
|
+
|
|
134
|
+
__slots__ = ()
|
|
135
|
+
|
|
136
|
+
_provider_name = "payment"
|
|
137
|
+
_locale_modules: tuple[str, ...] = ()
|
|
138
|
+
_field_map: dict[str, str] = {
|
|
139
|
+
"card_type": "card_type",
|
|
140
|
+
"payment_method": "payment_method",
|
|
141
|
+
"payment_processor": "payment_processor",
|
|
142
|
+
"processor": "payment_processor",
|
|
143
|
+
"transaction_status": "transaction_status",
|
|
144
|
+
"transaction_id": "transaction_id",
|
|
145
|
+
"txn_id": "transaction_id",
|
|
146
|
+
"currency_code": "currency_code",
|
|
147
|
+
"currency_symbol": "currency_symbol",
|
|
148
|
+
"payment_amount": "payment_amount",
|
|
149
|
+
"cvv": "cvv",
|
|
150
|
+
"expiry_date": "expiry_date",
|
|
151
|
+
"card_expiry": "expiry_date",
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
# --- Scalar helpers ---
|
|
155
|
+
|
|
156
|
+
def _one_transaction_id(self) -> str:
|
|
157
|
+
return f"TXN-{self._engine.random_digits_str(12)}"
|
|
158
|
+
|
|
159
|
+
def _one_payment_amount(self) -> str:
|
|
160
|
+
dollars = self._engine.random_int(1, 9999)
|
|
161
|
+
cents = self._engine.random_int(0, 99)
|
|
162
|
+
return f"{dollars}.{cents:02d}"
|
|
163
|
+
|
|
164
|
+
def _one_cvv(self) -> str:
|
|
165
|
+
return self._engine.random_digits_str(
|
|
166
|
+
4 if self._engine.random_int(0, 1) == 0 else 3
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
def _one_expiry_date(self) -> str:
|
|
170
|
+
month = self._engine.random_int(1, 12)
|
|
171
|
+
year = self._engine.random_int(25, 32)
|
|
172
|
+
return f"{month:02d}/{year:02d}"
|
|
173
|
+
|
|
174
|
+
# --- Public API ---
|
|
175
|
+
|
|
176
|
+
@overload
|
|
177
|
+
def card_type(self) -> str: ...
|
|
178
|
+
@overload
|
|
179
|
+
def card_type(self, count: Literal[1]) -> str: ...
|
|
180
|
+
@overload
|
|
181
|
+
def card_type(self, count: int) -> str | list[str]: ...
|
|
182
|
+
def card_type(self, count: int = 1) -> str | list[str]:
|
|
183
|
+
"""Generate a credit/debit card type (e.g., Visa, Mastercard)."""
|
|
184
|
+
if count == 1:
|
|
185
|
+
return self._engine.choice(_CARD_TYPES)
|
|
186
|
+
return self._engine.choices(_CARD_TYPES, count)
|
|
187
|
+
|
|
188
|
+
@overload
|
|
189
|
+
def payment_method(self) -> str: ...
|
|
190
|
+
@overload
|
|
191
|
+
def payment_method(self, count: Literal[1]) -> str: ...
|
|
192
|
+
@overload
|
|
193
|
+
def payment_method(self, count: int) -> str | list[str]: ...
|
|
194
|
+
def payment_method(self, count: int = 1) -> str | list[str]:
|
|
195
|
+
"""Generate a payment method (e.g., Credit Card, PayPal)."""
|
|
196
|
+
if count == 1:
|
|
197
|
+
return self._engine.choice(_PAYMENT_METHODS)
|
|
198
|
+
return self._engine.choices(_PAYMENT_METHODS, count)
|
|
199
|
+
|
|
200
|
+
@overload
|
|
201
|
+
def payment_processor(self) -> str: ...
|
|
202
|
+
@overload
|
|
203
|
+
def payment_processor(self, count: Literal[1]) -> str: ...
|
|
204
|
+
@overload
|
|
205
|
+
def payment_processor(self, count: int) -> str | list[str]: ...
|
|
206
|
+
def payment_processor(self, count: int = 1) -> str | list[str]:
|
|
207
|
+
"""Generate a payment processor name (e.g., Stripe, Square)."""
|
|
208
|
+
if count == 1:
|
|
209
|
+
return self._engine.choice(_PROCESSORS)
|
|
210
|
+
return self._engine.choices(_PROCESSORS, count)
|
|
211
|
+
|
|
212
|
+
@overload
|
|
213
|
+
def transaction_status(self) -> str: ...
|
|
214
|
+
@overload
|
|
215
|
+
def transaction_status(self, count: Literal[1]) -> str: ...
|
|
216
|
+
@overload
|
|
217
|
+
def transaction_status(self, count: int) -> str | list[str]: ...
|
|
218
|
+
def transaction_status(self, count: int = 1) -> str | list[str]:
|
|
219
|
+
"""Generate a transaction status (e.g., pending, completed)."""
|
|
220
|
+
if count == 1:
|
|
221
|
+
return self._engine.choice(_TRANSACTION_STATUSES)
|
|
222
|
+
return self._engine.choices(_TRANSACTION_STATUSES, count)
|
|
223
|
+
|
|
224
|
+
@overload
|
|
225
|
+
def transaction_id(self) -> str: ...
|
|
226
|
+
@overload
|
|
227
|
+
def transaction_id(self, count: Literal[1]) -> str: ...
|
|
228
|
+
@overload
|
|
229
|
+
def transaction_id(self, count: int) -> str | list[str]: ...
|
|
230
|
+
def transaction_id(self, count: int = 1) -> str | list[str]:
|
|
231
|
+
"""Generate a transaction ID (TXN-############)."""
|
|
232
|
+
if count == 1:
|
|
233
|
+
return self._one_transaction_id()
|
|
234
|
+
# Inlined batch with local-bound random_digits_str
|
|
235
|
+
_rds = self._engine.random_digits_str
|
|
236
|
+
return [f"TXN-{_rds(12)}" for _ in range(count)]
|
|
237
|
+
|
|
238
|
+
@overload
|
|
239
|
+
def currency_code(self) -> str: ...
|
|
240
|
+
@overload
|
|
241
|
+
def currency_code(self, count: Literal[1]) -> str: ...
|
|
242
|
+
@overload
|
|
243
|
+
def currency_code(self, count: int) -> str | list[str]: ...
|
|
244
|
+
def currency_code(self, count: int = 1) -> str | list[str]:
|
|
245
|
+
"""Generate an ISO 4217 currency code (e.g., USD, EUR)."""
|
|
246
|
+
if count == 1:
|
|
247
|
+
return self._engine.choice(_CURRENCIES)
|
|
248
|
+
return self._engine.choices(_CURRENCIES, count)
|
|
249
|
+
|
|
250
|
+
@overload
|
|
251
|
+
def currency_symbol(self) -> str: ...
|
|
252
|
+
@overload
|
|
253
|
+
def currency_symbol(self, count: Literal[1]) -> str: ...
|
|
254
|
+
@overload
|
|
255
|
+
def currency_symbol(self, count: int) -> str | list[str]: ...
|
|
256
|
+
def currency_symbol(self, count: int = 1) -> str | list[str]:
|
|
257
|
+
"""Generate a currency symbol (e.g., $, EUR, GBP)."""
|
|
258
|
+
if count == 1:
|
|
259
|
+
return self._engine.choice(_CURRENCY_SYMBOLS)
|
|
260
|
+
return self._engine.choices(_CURRENCY_SYMBOLS, count)
|
|
261
|
+
|
|
262
|
+
@overload
|
|
263
|
+
def payment_amount(self) -> str: ...
|
|
264
|
+
@overload
|
|
265
|
+
def payment_amount(self, count: Literal[1]) -> str: ...
|
|
266
|
+
@overload
|
|
267
|
+
def payment_amount(self, count: int) -> str | list[str]: ...
|
|
268
|
+
def payment_amount(self, count: int = 1) -> str | list[str]:
|
|
269
|
+
"""Generate a payment amount (e.g., 49.99)."""
|
|
270
|
+
if count == 1:
|
|
271
|
+
return self._one_payment_amount()
|
|
272
|
+
_ri = self._engine.random_int
|
|
273
|
+
return [f"{_ri(1, 9999)}.{_ri(0, 99):02d}" for _ in range(count)]
|
|
274
|
+
|
|
275
|
+
@overload
|
|
276
|
+
def cvv(self) -> str: ...
|
|
277
|
+
@overload
|
|
278
|
+
def cvv(self, count: Literal[1]) -> str: ...
|
|
279
|
+
@overload
|
|
280
|
+
def cvv(self, count: int) -> str | list[str]: ...
|
|
281
|
+
def cvv(self, count: int = 1) -> str | list[str]:
|
|
282
|
+
"""Generate a CVV code (3 or 4 digits)."""
|
|
283
|
+
if count == 1:
|
|
284
|
+
return self._one_cvv()
|
|
285
|
+
_rds = self._engine.random_digits_str
|
|
286
|
+
_ri = self._engine.random_int
|
|
287
|
+
return [_rds(4 if _ri(0, 1) == 0 else 3) for _ in range(count)]
|
|
288
|
+
|
|
289
|
+
@overload
|
|
290
|
+
def expiry_date(self) -> str: ...
|
|
291
|
+
@overload
|
|
292
|
+
def expiry_date(self, count: Literal[1]) -> str: ...
|
|
293
|
+
@overload
|
|
294
|
+
def expiry_date(self, count: int) -> str | list[str]: ...
|
|
295
|
+
def expiry_date(self, count: int = 1) -> str | list[str]:
|
|
296
|
+
"""Generate a card expiry date (MM/YY)."""
|
|
297
|
+
if count == 1:
|
|
298
|
+
return self._one_expiry_date()
|
|
299
|
+
_ri = self._engine.random_int
|
|
300
|
+
return [f"{_ri(1, 12):02d}/{_ri(25, 32):02d}" for _ in range(count)]
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"""Person provider — generates fake personal names."""
|
|
2
|
+
|
|
3
|
+
from types import ModuleType
|
|
4
|
+
from typing import Literal, overload
|
|
5
|
+
|
|
6
|
+
from dataforge.backend import RandomEngine
|
|
7
|
+
from dataforge.providers.base import BaseProvider
|
|
8
|
+
|
|
9
|
+
# Module-level constants for zero per-call overhead
|
|
10
|
+
_PREFIXES: tuple[str, ...] = ("Mr.", "Mrs.", "Ms.", "Dr.")
|
|
11
|
+
_SUFFIXES: tuple[str, ...] = ("Jr.", "Sr.", "III", "IV", "V")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class PersonProvider(BaseProvider):
|
|
15
|
+
"""Generates fake first names, last names, and full names.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
engine : RandomEngine
|
|
20
|
+
The shared random engine instance.
|
|
21
|
+
locale_data : ModuleType
|
|
22
|
+
The imported locale module (e.g. ``dataforge.locales.en_US.person``).
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
__slots__ = (
|
|
26
|
+
"_first_names",
|
|
27
|
+
"_last_names",
|
|
28
|
+
"_male_first_names",
|
|
29
|
+
"_female_first_names",
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
_provider_name = "person"
|
|
33
|
+
_locale_modules = ("person",)
|
|
34
|
+
_field_map = {
|
|
35
|
+
"first_name": "first_name",
|
|
36
|
+
"last_name": "last_name",
|
|
37
|
+
"full_name": "full_name",
|
|
38
|
+
"name": "full_name",
|
|
39
|
+
"prefix": "prefix",
|
|
40
|
+
"suffix": "suffix",
|
|
41
|
+
"male_first_name": "male_first_name",
|
|
42
|
+
"female_first_name": "female_first_name",
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
def __init__(self, engine: RandomEngine, locale_data: ModuleType) -> None:
|
|
46
|
+
super().__init__(engine)
|
|
47
|
+
self._first_names: tuple[str, ...] = locale_data.first_names
|
|
48
|
+
self._last_names: tuple[str, ...] = locale_data.last_names
|
|
49
|
+
# Gendered names — optional in locale data; fall back to full list
|
|
50
|
+
self._male_first_names: tuple[str, ...] = getattr(
|
|
51
|
+
locale_data, "male_first_names", locale_data.first_names
|
|
52
|
+
)
|
|
53
|
+
self._female_first_names: tuple[str, ...] = getattr(
|
|
54
|
+
locale_data, "female_first_names", locale_data.first_names
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
# ------------------------------------------------------------------
|
|
58
|
+
# Public API
|
|
59
|
+
# ------------------------------------------------------------------
|
|
60
|
+
|
|
61
|
+
@overload
|
|
62
|
+
def first_name(self) -> str: ...
|
|
63
|
+
@overload
|
|
64
|
+
def first_name(self, count: Literal[1]) -> str: ...
|
|
65
|
+
@overload
|
|
66
|
+
def first_name(self, count: int) -> str | list[str]: ...
|
|
67
|
+
def first_name(self, count: int = 1) -> str | list[str]:
|
|
68
|
+
"""Generate a random first name.
|
|
69
|
+
|
|
70
|
+
Parameters
|
|
71
|
+
----------
|
|
72
|
+
count : int
|
|
73
|
+
Number of names to generate. ``1`` returns a single ``str``;
|
|
74
|
+
any value > 1 returns a ``list[str]``.
|
|
75
|
+
"""
|
|
76
|
+
if count == 1:
|
|
77
|
+
return self._engine.choice(self._first_names)
|
|
78
|
+
return self._engine.choices(self._first_names, count)
|
|
79
|
+
|
|
80
|
+
@overload
|
|
81
|
+
def last_name(self) -> str: ...
|
|
82
|
+
@overload
|
|
83
|
+
def last_name(self, count: Literal[1]) -> str: ...
|
|
84
|
+
@overload
|
|
85
|
+
def last_name(self, count: int) -> str | list[str]: ...
|
|
86
|
+
def last_name(self, count: int = 1) -> str | list[str]:
|
|
87
|
+
"""Generate a random last name.
|
|
88
|
+
|
|
89
|
+
Parameters
|
|
90
|
+
----------
|
|
91
|
+
count : int
|
|
92
|
+
Number of names to generate. ``1`` returns a single ``str``;
|
|
93
|
+
any value > 1 returns a ``list[str]``.
|
|
94
|
+
"""
|
|
95
|
+
if count == 1:
|
|
96
|
+
return self._engine.choice(self._last_names)
|
|
97
|
+
return self._engine.choices(self._last_names, count)
|
|
98
|
+
|
|
99
|
+
@overload
|
|
100
|
+
def full_name(self) -> str: ...
|
|
101
|
+
@overload
|
|
102
|
+
def full_name(self, count: Literal[1]) -> str: ...
|
|
103
|
+
@overload
|
|
104
|
+
def full_name(self, count: int) -> str | list[str]: ...
|
|
105
|
+
def full_name(self, count: int = 1) -> str | list[str]:
|
|
106
|
+
"""Generate a random full name (first + last).
|
|
107
|
+
|
|
108
|
+
Parameters
|
|
109
|
+
----------
|
|
110
|
+
count : int
|
|
111
|
+
Number of names to generate. ``1`` returns a single ``str``;
|
|
112
|
+
any value > 1 returns a ``list[str]``.
|
|
113
|
+
"""
|
|
114
|
+
if count == 1:
|
|
115
|
+
first = self._engine.choice(self._first_names)
|
|
116
|
+
last = self._engine.choice(self._last_names)
|
|
117
|
+
return f"{first} {last}"
|
|
118
|
+
|
|
119
|
+
firsts = self._engine.choices(self._first_names, count)
|
|
120
|
+
lasts = self._engine.choices(self._last_names, count)
|
|
121
|
+
return [f"{f} {ln}" for f, ln in zip(firsts, lasts)]
|
|
122
|
+
|
|
123
|
+
@overload
|
|
124
|
+
def prefix(self) -> str: ...
|
|
125
|
+
@overload
|
|
126
|
+
def prefix(self, count: Literal[1]) -> str: ...
|
|
127
|
+
@overload
|
|
128
|
+
def prefix(self, count: int) -> str | list[str]: ...
|
|
129
|
+
def prefix(self, count: int = 1) -> str | list[str]:
|
|
130
|
+
"""Generate a name prefix (Mr., Mrs., Ms., Dr.).
|
|
131
|
+
|
|
132
|
+
Parameters
|
|
133
|
+
----------
|
|
134
|
+
count : int
|
|
135
|
+
Number of prefixes to generate.
|
|
136
|
+
"""
|
|
137
|
+
prefixes = _PREFIXES
|
|
138
|
+
if count == 1:
|
|
139
|
+
return self._engine.choice(prefixes)
|
|
140
|
+
return self._engine.choices(prefixes, count)
|
|
141
|
+
|
|
142
|
+
@overload
|
|
143
|
+
def suffix(self) -> str: ...
|
|
144
|
+
@overload
|
|
145
|
+
def suffix(self, count: Literal[1]) -> str: ...
|
|
146
|
+
@overload
|
|
147
|
+
def suffix(self, count: int) -> str | list[str]: ...
|
|
148
|
+
def suffix(self, count: int = 1) -> str | list[str]:
|
|
149
|
+
"""Generate a name suffix (Jr., Sr., III, IV, V).
|
|
150
|
+
|
|
151
|
+
Parameters
|
|
152
|
+
----------
|
|
153
|
+
count : int
|
|
154
|
+
Number of suffixes to generate.
|
|
155
|
+
"""
|
|
156
|
+
suffixes = _SUFFIXES
|
|
157
|
+
if count == 1:
|
|
158
|
+
return self._engine.choice(suffixes)
|
|
159
|
+
return self._engine.choices(suffixes, count)
|
|
160
|
+
|
|
161
|
+
@overload
|
|
162
|
+
def male_first_name(self) -> str: ...
|
|
163
|
+
@overload
|
|
164
|
+
def male_first_name(self, count: Literal[1]) -> str: ...
|
|
165
|
+
@overload
|
|
166
|
+
def male_first_name(self, count: int) -> str | list[str]: ...
|
|
167
|
+
def male_first_name(self, count: int = 1) -> str | list[str]:
|
|
168
|
+
"""Generate a random male first name.
|
|
169
|
+
|
|
170
|
+
Parameters
|
|
171
|
+
----------
|
|
172
|
+
count : int
|
|
173
|
+
Number of names to generate.
|
|
174
|
+
"""
|
|
175
|
+
if count == 1:
|
|
176
|
+
return self._engine.choice(self._male_first_names)
|
|
177
|
+
return self._engine.choices(self._male_first_names, count)
|
|
178
|
+
|
|
179
|
+
@overload
|
|
180
|
+
def female_first_name(self) -> str: ...
|
|
181
|
+
@overload
|
|
182
|
+
def female_first_name(self, count: Literal[1]) -> str: ...
|
|
183
|
+
@overload
|
|
184
|
+
def female_first_name(self, count: int) -> str | list[str]: ...
|
|
185
|
+
def female_first_name(self, count: int = 1) -> str | list[str]:
|
|
186
|
+
"""Generate a random female first name.
|
|
187
|
+
|
|
188
|
+
Parameters
|
|
189
|
+
----------
|
|
190
|
+
count : int
|
|
191
|
+
Number of names to generate.
|
|
192
|
+
"""
|
|
193
|
+
if count == 1:
|
|
194
|
+
return self._engine.choice(self._female_first_names)
|
|
195
|
+
return self._engine.choices(self._female_first_names, count)
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""Phone provider — generates fake phone and cell numbers."""
|
|
2
|
+
|
|
3
|
+
from types import ModuleType
|
|
4
|
+
from typing import Literal, overload
|
|
5
|
+
|
|
6
|
+
from dataforge.backend import RandomEngine
|
|
7
|
+
from dataforge.providers.base import BaseProvider
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class PhoneProvider(BaseProvider):
|
|
11
|
+
"""Generates fake phone and cell phone numbers.
|
|
12
|
+
|
|
13
|
+
Parameters
|
|
14
|
+
----------
|
|
15
|
+
engine : RandomEngine
|
|
16
|
+
The shared random engine instance.
|
|
17
|
+
locale_data : ModuleType
|
|
18
|
+
The imported locale module (e.g. ``dataforge.locales.en_US.phone``).
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
__slots__ = ("_phone_formats", "_cell_formats")
|
|
22
|
+
|
|
23
|
+
_provider_name = "phone"
|
|
24
|
+
_locale_modules = ("phone",)
|
|
25
|
+
_field_map = {
|
|
26
|
+
"phone_number": "phone_number",
|
|
27
|
+
"phone": "phone_number",
|
|
28
|
+
"cell_phone": "cell_phone",
|
|
29
|
+
"cell": "cell_phone",
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
def __init__(self, engine: RandomEngine, locale_data: ModuleType) -> None:
|
|
33
|
+
super().__init__(engine)
|
|
34
|
+
self._phone_formats: tuple[str, ...] = locale_data.phone_formats
|
|
35
|
+
self._cell_formats: tuple[str, ...] = locale_data.cell_formats
|
|
36
|
+
|
|
37
|
+
# ------------------------------------------------------------------
|
|
38
|
+
# Scalar helpers
|
|
39
|
+
# ------------------------------------------------------------------
|
|
40
|
+
|
|
41
|
+
def _one_phone(self) -> str:
|
|
42
|
+
fmt = self._engine.choice(self._phone_formats)
|
|
43
|
+
return self._engine.numerify(fmt)
|
|
44
|
+
|
|
45
|
+
def _one_cell(self) -> str:
|
|
46
|
+
fmt = self._engine.choice(self._cell_formats)
|
|
47
|
+
return self._engine.numerify(fmt)
|
|
48
|
+
|
|
49
|
+
# ------------------------------------------------------------------
|
|
50
|
+
# Public API
|
|
51
|
+
# ------------------------------------------------------------------
|
|
52
|
+
|
|
53
|
+
@overload
|
|
54
|
+
def phone_number(self) -> str: ...
|
|
55
|
+
@overload
|
|
56
|
+
def phone_number(self, count: Literal[1]) -> str: ...
|
|
57
|
+
@overload
|
|
58
|
+
def phone_number(self, count: int) -> str | list[str]: ...
|
|
59
|
+
def phone_number(self, count: int = 1) -> str | list[str]:
|
|
60
|
+
"""Generate a random phone number.
|
|
61
|
+
|
|
62
|
+
Parameters
|
|
63
|
+
----------
|
|
64
|
+
count : int
|
|
65
|
+
Number of phone numbers to generate.
|
|
66
|
+
"""
|
|
67
|
+
if count == 1:
|
|
68
|
+
return self._one_phone()
|
|
69
|
+
return [self._one_phone() for _ in range(count)]
|
|
70
|
+
|
|
71
|
+
@overload
|
|
72
|
+
def cell_phone(self) -> str: ...
|
|
73
|
+
@overload
|
|
74
|
+
def cell_phone(self, count: Literal[1]) -> str: ...
|
|
75
|
+
@overload
|
|
76
|
+
def cell_phone(self, count: int) -> str | list[str]: ...
|
|
77
|
+
def cell_phone(self, count: int = 1) -> str | list[str]:
|
|
78
|
+
"""Generate a random cell phone number.
|
|
79
|
+
|
|
80
|
+
Parameters
|
|
81
|
+
----------
|
|
82
|
+
count : int
|
|
83
|
+
Number of cell phone numbers to generate.
|
|
84
|
+
"""
|
|
85
|
+
if count == 1:
|
|
86
|
+
return self._one_cell()
|
|
87
|
+
return [self._one_cell() for _ in range(count)]
|