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,265 @@
|
|
|
1
|
+
"""ProfileProvider — generates coherent fake user profiles.
|
|
2
|
+
|
|
3
|
+
Each profile composes data from multiple providers (person, internet,
|
|
4
|
+
address, phone) to produce a consistent record where names, emails,
|
|
5
|
+
and usernames relate to each other.
|
|
6
|
+
|
|
7
|
+
Individual string fields are exposed in ``_field_map`` for Schema
|
|
8
|
+
compatibility. The compound ``profile()`` method returns a ``dict``
|
|
9
|
+
and is available only via direct API use.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from typing import TYPE_CHECKING, Literal, overload
|
|
13
|
+
|
|
14
|
+
from dataforge.backend import RandomEngine
|
|
15
|
+
from dataforge.providers.base import BaseProvider
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from dataforge.core import DataForge
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ProfileProvider(BaseProvider):
|
|
22
|
+
"""Generates coherent fake user profiles.
|
|
23
|
+
|
|
24
|
+
Unlike other providers, ``ProfileProvider`` needs a reference to
|
|
25
|
+
the parent :class:`DataForge` instance so it can delegate to
|
|
26
|
+
``person``, ``internet``, ``address``, and ``phone`` providers.
|
|
27
|
+
|
|
28
|
+
Parameters
|
|
29
|
+
----------
|
|
30
|
+
engine : RandomEngine
|
|
31
|
+
The shared random engine instance.
|
|
32
|
+
forge : DataForge
|
|
33
|
+
The parent DataForge instance for cross-provider access.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
__slots__ = ("_forge",)
|
|
37
|
+
|
|
38
|
+
_provider_name = "profile"
|
|
39
|
+
_locale_modules: tuple[str, ...] = ()
|
|
40
|
+
_needs_forge: bool = True
|
|
41
|
+
_field_map: dict[str, str] = {
|
|
42
|
+
"profile_first_name": "profile_first_name",
|
|
43
|
+
"profile_last_name": "profile_last_name",
|
|
44
|
+
"profile_email": "profile_email",
|
|
45
|
+
"profile_phone": "profile_phone",
|
|
46
|
+
"profile_city": "profile_city",
|
|
47
|
+
"profile_state": "profile_state",
|
|
48
|
+
"profile_zip_code": "profile_zip_code",
|
|
49
|
+
"profile_job_title": "profile_job_title",
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
def __init__(self, engine: RandomEngine, forge: "DataForge") -> None:
|
|
53
|
+
super().__init__(engine)
|
|
54
|
+
self._forge = forge
|
|
55
|
+
|
|
56
|
+
# ------------------------------------------------------------------
|
|
57
|
+
# Individual field methods (for _field_map / Schema compatibility)
|
|
58
|
+
# These delegate to sub-providers — values are independent per call.
|
|
59
|
+
# For coherent profiles, use profile() instead.
|
|
60
|
+
# ------------------------------------------------------------------
|
|
61
|
+
|
|
62
|
+
@overload
|
|
63
|
+
def profile_first_name(self) -> str: ...
|
|
64
|
+
@overload
|
|
65
|
+
def profile_first_name(self, count: Literal[1]) -> str: ...
|
|
66
|
+
@overload
|
|
67
|
+
def profile_first_name(self, count: int) -> str | list[str]: ...
|
|
68
|
+
def profile_first_name(self, count: int = 1) -> str | list[str]:
|
|
69
|
+
"""Generate a first name (delegates to PersonProvider).
|
|
70
|
+
|
|
71
|
+
Parameters
|
|
72
|
+
----------
|
|
73
|
+
count : int
|
|
74
|
+
Number of names to generate.
|
|
75
|
+
|
|
76
|
+
Returns
|
|
77
|
+
-------
|
|
78
|
+
str or list[str]
|
|
79
|
+
"""
|
|
80
|
+
return self._forge.person.first_name(count)
|
|
81
|
+
|
|
82
|
+
@overload
|
|
83
|
+
def profile_last_name(self) -> str: ...
|
|
84
|
+
@overload
|
|
85
|
+
def profile_last_name(self, count: Literal[1]) -> str: ...
|
|
86
|
+
@overload
|
|
87
|
+
def profile_last_name(self, count: int) -> str | list[str]: ...
|
|
88
|
+
def profile_last_name(self, count: int = 1) -> str | list[str]:
|
|
89
|
+
"""Generate a last name (delegates to PersonProvider).
|
|
90
|
+
|
|
91
|
+
Parameters
|
|
92
|
+
----------
|
|
93
|
+
count : int
|
|
94
|
+
Number of names to generate.
|
|
95
|
+
|
|
96
|
+
Returns
|
|
97
|
+
-------
|
|
98
|
+
str or list[str]
|
|
99
|
+
"""
|
|
100
|
+
return self._forge.person.last_name(count)
|
|
101
|
+
|
|
102
|
+
@overload
|
|
103
|
+
def profile_email(self) -> str: ...
|
|
104
|
+
@overload
|
|
105
|
+
def profile_email(self, count: Literal[1]) -> str: ...
|
|
106
|
+
@overload
|
|
107
|
+
def profile_email(self, count: int) -> str | list[str]: ...
|
|
108
|
+
def profile_email(self, count: int = 1) -> str | list[str]:
|
|
109
|
+
"""Generate an email address (delegates to InternetProvider).
|
|
110
|
+
|
|
111
|
+
Parameters
|
|
112
|
+
----------
|
|
113
|
+
count : int
|
|
114
|
+
Number of emails to generate.
|
|
115
|
+
|
|
116
|
+
Returns
|
|
117
|
+
-------
|
|
118
|
+
str or list[str]
|
|
119
|
+
"""
|
|
120
|
+
return self._forge.internet.email(count)
|
|
121
|
+
|
|
122
|
+
@overload
|
|
123
|
+
def profile_phone(self) -> str: ...
|
|
124
|
+
@overload
|
|
125
|
+
def profile_phone(self, count: Literal[1]) -> str: ...
|
|
126
|
+
@overload
|
|
127
|
+
def profile_phone(self, count: int) -> str | list[str]: ...
|
|
128
|
+
def profile_phone(self, count: int = 1) -> str | list[str]:
|
|
129
|
+
"""Generate a phone number (delegates to PhoneProvider).
|
|
130
|
+
|
|
131
|
+
Parameters
|
|
132
|
+
----------
|
|
133
|
+
count : int
|
|
134
|
+
Number of phone numbers to generate.
|
|
135
|
+
|
|
136
|
+
Returns
|
|
137
|
+
-------
|
|
138
|
+
str or list[str]
|
|
139
|
+
"""
|
|
140
|
+
return self._forge.phone.phone_number(count)
|
|
141
|
+
|
|
142
|
+
@overload
|
|
143
|
+
def profile_city(self) -> str: ...
|
|
144
|
+
@overload
|
|
145
|
+
def profile_city(self, count: Literal[1]) -> str: ...
|
|
146
|
+
@overload
|
|
147
|
+
def profile_city(self, count: int) -> str | list[str]: ...
|
|
148
|
+
def profile_city(self, count: int = 1) -> str | list[str]:
|
|
149
|
+
"""Generate a city name (delegates to AddressProvider).
|
|
150
|
+
|
|
151
|
+
Parameters
|
|
152
|
+
----------
|
|
153
|
+
count : int
|
|
154
|
+
Number of cities to generate.
|
|
155
|
+
|
|
156
|
+
Returns
|
|
157
|
+
-------
|
|
158
|
+
str or list[str]
|
|
159
|
+
"""
|
|
160
|
+
return self._forge.address.city(count)
|
|
161
|
+
|
|
162
|
+
@overload
|
|
163
|
+
def profile_state(self) -> str: ...
|
|
164
|
+
@overload
|
|
165
|
+
def profile_state(self, count: Literal[1]) -> str: ...
|
|
166
|
+
@overload
|
|
167
|
+
def profile_state(self, count: int) -> str | list[str]: ...
|
|
168
|
+
def profile_state(self, count: int = 1) -> str | list[str]:
|
|
169
|
+
"""Generate a state name (delegates to AddressProvider).
|
|
170
|
+
|
|
171
|
+
Parameters
|
|
172
|
+
----------
|
|
173
|
+
count : int
|
|
174
|
+
Number of states to generate.
|
|
175
|
+
|
|
176
|
+
Returns
|
|
177
|
+
-------
|
|
178
|
+
str or list[str]
|
|
179
|
+
"""
|
|
180
|
+
return self._forge.address.state(count)
|
|
181
|
+
|
|
182
|
+
@overload
|
|
183
|
+
def profile_zip_code(self) -> str: ...
|
|
184
|
+
@overload
|
|
185
|
+
def profile_zip_code(self, count: Literal[1]) -> str: ...
|
|
186
|
+
@overload
|
|
187
|
+
def profile_zip_code(self, count: int) -> str | list[str]: ...
|
|
188
|
+
def profile_zip_code(self, count: int = 1) -> str | list[str]:
|
|
189
|
+
"""Generate a zip code (delegates to AddressProvider).
|
|
190
|
+
|
|
191
|
+
Parameters
|
|
192
|
+
----------
|
|
193
|
+
count : int
|
|
194
|
+
Number of zip codes to generate.
|
|
195
|
+
|
|
196
|
+
Returns
|
|
197
|
+
-------
|
|
198
|
+
str or list[str]
|
|
199
|
+
"""
|
|
200
|
+
return self._forge.address.zip_code(count)
|
|
201
|
+
|
|
202
|
+
@overload
|
|
203
|
+
def profile_job_title(self) -> str: ...
|
|
204
|
+
@overload
|
|
205
|
+
def profile_job_title(self, count: Literal[1]) -> str: ...
|
|
206
|
+
@overload
|
|
207
|
+
def profile_job_title(self, count: int) -> str | list[str]: ...
|
|
208
|
+
def profile_job_title(self, count: int = 1) -> str | list[str]:
|
|
209
|
+
"""Generate a job title (delegates to CompanyProvider).
|
|
210
|
+
|
|
211
|
+
Parameters
|
|
212
|
+
----------
|
|
213
|
+
count : int
|
|
214
|
+
Number of job titles to generate.
|
|
215
|
+
|
|
216
|
+
Returns
|
|
217
|
+
-------
|
|
218
|
+
str or list[str]
|
|
219
|
+
"""
|
|
220
|
+
return self._forge.company.job_title(count)
|
|
221
|
+
|
|
222
|
+
# ------------------------------------------------------------------
|
|
223
|
+
# Compound profile method (direct API only, not in _field_map)
|
|
224
|
+
# ------------------------------------------------------------------
|
|
225
|
+
|
|
226
|
+
def profile(self, count: int = 1) -> dict[str, str] | list[dict[str, str]]:
|
|
227
|
+
"""Generate a coherent user profile.
|
|
228
|
+
|
|
229
|
+
Each profile is a ``dict`` with keys: ``first_name``,
|
|
230
|
+
``last_name``, ``email``, ``phone``, ``city``, ``state``,
|
|
231
|
+
``zip_code``, ``job_title``.
|
|
232
|
+
|
|
233
|
+
The ``email`` is derived from the same first/last name for
|
|
234
|
+
coherence within each profile.
|
|
235
|
+
|
|
236
|
+
Parameters
|
|
237
|
+
----------
|
|
238
|
+
count : int
|
|
239
|
+
Number of profiles to generate.
|
|
240
|
+
|
|
241
|
+
Returns
|
|
242
|
+
-------
|
|
243
|
+
dict[str, str] or list[dict[str, str]]
|
|
244
|
+
"""
|
|
245
|
+
|
|
246
|
+
def _one_profile() -> dict[str, str]:
|
|
247
|
+
first = self._forge.person.first_name()
|
|
248
|
+
last = self._forge.person.last_name()
|
|
249
|
+
# Build a coherent email from the person's name
|
|
250
|
+
domain = self._forge.internet.domain()
|
|
251
|
+
email = f"{first.lower()}.{last.lower()}@{domain}"
|
|
252
|
+
return {
|
|
253
|
+
"first_name": first,
|
|
254
|
+
"last_name": last,
|
|
255
|
+
"email": email,
|
|
256
|
+
"phone": self._forge.phone.phone_number(),
|
|
257
|
+
"city": self._forge.address.city(),
|
|
258
|
+
"state": self._forge.address.state(),
|
|
259
|
+
"zip_code": self._forge.address.zip_code(),
|
|
260
|
+
"job_title": self._forge.company.job_title(),
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if count == 1:
|
|
264
|
+
return _one_profile()
|
|
265
|
+
return [_one_profile() for _ in range(count)]
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
"""Science provider — elements, units, formulas, planets, etc."""
|
|
2
|
+
|
|
3
|
+
from typing import Literal, overload
|
|
4
|
+
|
|
5
|
+
from dataforge.providers.base import BaseProvider
|
|
6
|
+
|
|
7
|
+
_CHEMICAL_ELEMENTS: tuple[str, ...] = (
|
|
8
|
+
"Hydrogen",
|
|
9
|
+
"Helium",
|
|
10
|
+
"Lithium",
|
|
11
|
+
"Beryllium",
|
|
12
|
+
"Boron",
|
|
13
|
+
"Carbon",
|
|
14
|
+
"Nitrogen",
|
|
15
|
+
"Oxygen",
|
|
16
|
+
"Fluorine",
|
|
17
|
+
"Neon",
|
|
18
|
+
"Sodium",
|
|
19
|
+
"Magnesium",
|
|
20
|
+
"Aluminum",
|
|
21
|
+
"Silicon",
|
|
22
|
+
"Phosphorus",
|
|
23
|
+
"Sulfur",
|
|
24
|
+
"Chlorine",
|
|
25
|
+
"Argon",
|
|
26
|
+
"Potassium",
|
|
27
|
+
"Calcium",
|
|
28
|
+
"Scandium",
|
|
29
|
+
"Titanium",
|
|
30
|
+
"Vanadium",
|
|
31
|
+
"Chromium",
|
|
32
|
+
"Manganese",
|
|
33
|
+
"Iron",
|
|
34
|
+
"Cobalt",
|
|
35
|
+
"Nickel",
|
|
36
|
+
"Copper",
|
|
37
|
+
"Zinc",
|
|
38
|
+
"Gallium",
|
|
39
|
+
"Germanium",
|
|
40
|
+
"Arsenic",
|
|
41
|
+
"Selenium",
|
|
42
|
+
"Bromine",
|
|
43
|
+
"Krypton",
|
|
44
|
+
"Rubidium",
|
|
45
|
+
"Strontium",
|
|
46
|
+
"Yttrium",
|
|
47
|
+
"Zirconium",
|
|
48
|
+
"Niobium",
|
|
49
|
+
"Molybdenum",
|
|
50
|
+
"Technetium",
|
|
51
|
+
"Ruthenium",
|
|
52
|
+
"Rhodium",
|
|
53
|
+
"Palladium",
|
|
54
|
+
"Silver",
|
|
55
|
+
"Gold",
|
|
56
|
+
"Platinum",
|
|
57
|
+
"Iridium",
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
_ELEMENT_SYMBOLS: tuple[str, ...] = (
|
|
61
|
+
"H",
|
|
62
|
+
"He",
|
|
63
|
+
"Li",
|
|
64
|
+
"Be",
|
|
65
|
+
"B",
|
|
66
|
+
"C",
|
|
67
|
+
"N",
|
|
68
|
+
"O",
|
|
69
|
+
"F",
|
|
70
|
+
"Ne",
|
|
71
|
+
"Na",
|
|
72
|
+
"Mg",
|
|
73
|
+
"Al",
|
|
74
|
+
"Si",
|
|
75
|
+
"P",
|
|
76
|
+
"S",
|
|
77
|
+
"Cl",
|
|
78
|
+
"Ar",
|
|
79
|
+
"K",
|
|
80
|
+
"Ca",
|
|
81
|
+
"Sc",
|
|
82
|
+
"Ti",
|
|
83
|
+
"V",
|
|
84
|
+
"Cr",
|
|
85
|
+
"Mn",
|
|
86
|
+
"Fe",
|
|
87
|
+
"Co",
|
|
88
|
+
"Ni",
|
|
89
|
+
"Cu",
|
|
90
|
+
"Zn",
|
|
91
|
+
"Ga",
|
|
92
|
+
"Ge",
|
|
93
|
+
"As",
|
|
94
|
+
"Se",
|
|
95
|
+
"Br",
|
|
96
|
+
"Kr",
|
|
97
|
+
"Rb",
|
|
98
|
+
"Sr",
|
|
99
|
+
"Y",
|
|
100
|
+
"Zr",
|
|
101
|
+
"Nb",
|
|
102
|
+
"Mo",
|
|
103
|
+
"Tc",
|
|
104
|
+
"Ru",
|
|
105
|
+
"Rh",
|
|
106
|
+
"Pd",
|
|
107
|
+
"Ag",
|
|
108
|
+
"Au",
|
|
109
|
+
"Pt",
|
|
110
|
+
"Ir",
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
_SI_UNITS: tuple[str, ...] = (
|
|
114
|
+
"meter (m)",
|
|
115
|
+
"kilogram (kg)",
|
|
116
|
+
"second (s)",
|
|
117
|
+
"ampere (A)",
|
|
118
|
+
"kelvin (K)",
|
|
119
|
+
"mole (mol)",
|
|
120
|
+
"candela (cd)",
|
|
121
|
+
"hertz (Hz)",
|
|
122
|
+
"newton (N)",
|
|
123
|
+
"pascal (Pa)",
|
|
124
|
+
"joule (J)",
|
|
125
|
+
"watt (W)",
|
|
126
|
+
"coulomb (C)",
|
|
127
|
+
"volt (V)",
|
|
128
|
+
"farad (F)",
|
|
129
|
+
"ohm (Ω)",
|
|
130
|
+
"siemens (S)",
|
|
131
|
+
"weber (Wb)",
|
|
132
|
+
"tesla (T)",
|
|
133
|
+
"henry (H)",
|
|
134
|
+
"lumen (lm)",
|
|
135
|
+
"lux (lx)",
|
|
136
|
+
"becquerel (Bq)",
|
|
137
|
+
"gray (Gy)",
|
|
138
|
+
"sievert (Sv)",
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
_PLANETS: tuple[str, ...] = (
|
|
142
|
+
"Mercury",
|
|
143
|
+
"Venus",
|
|
144
|
+
"Earth",
|
|
145
|
+
"Mars",
|
|
146
|
+
"Jupiter",
|
|
147
|
+
"Saturn",
|
|
148
|
+
"Uranus",
|
|
149
|
+
"Neptune",
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
_GALAXIES: tuple[str, ...] = (
|
|
153
|
+
"Milky Way",
|
|
154
|
+
"Andromeda",
|
|
155
|
+
"Triangulum",
|
|
156
|
+
"Centaurus A",
|
|
157
|
+
"Messier 87",
|
|
158
|
+
"Sombrero Galaxy",
|
|
159
|
+
"Whirlpool Galaxy",
|
|
160
|
+
"Pinwheel Galaxy",
|
|
161
|
+
"Cartwheel Galaxy",
|
|
162
|
+
"Cigar Galaxy",
|
|
163
|
+
"Black Eye Galaxy",
|
|
164
|
+
"Sunflower Galaxy",
|
|
165
|
+
"Tadpole Galaxy",
|
|
166
|
+
"Hoag's Object",
|
|
167
|
+
"NGC 1300",
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
_CONSTELLATIONS: tuple[str, ...] = (
|
|
171
|
+
"Orion",
|
|
172
|
+
"Ursa Major",
|
|
173
|
+
"Ursa Minor",
|
|
174
|
+
"Cassiopeia",
|
|
175
|
+
"Scorpius",
|
|
176
|
+
"Leo",
|
|
177
|
+
"Gemini",
|
|
178
|
+
"Taurus",
|
|
179
|
+
"Sagittarius",
|
|
180
|
+
"Andromeda",
|
|
181
|
+
"Aquarius",
|
|
182
|
+
"Aries",
|
|
183
|
+
"Cancer",
|
|
184
|
+
"Capricornus",
|
|
185
|
+
"Libra",
|
|
186
|
+
"Pisces",
|
|
187
|
+
"Virgo",
|
|
188
|
+
"Cygnus",
|
|
189
|
+
"Lyra",
|
|
190
|
+
"Pegasus",
|
|
191
|
+
"Perseus",
|
|
192
|
+
"Draco",
|
|
193
|
+
"Centaurus",
|
|
194
|
+
"Canis Major",
|
|
195
|
+
"Canis Minor",
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
_SCIENTIFIC_DISCIPLINES: tuple[str, ...] = (
|
|
199
|
+
"Physics",
|
|
200
|
+
"Chemistry",
|
|
201
|
+
"Biology",
|
|
202
|
+
"Mathematics",
|
|
203
|
+
"Astronomy",
|
|
204
|
+
"Geology",
|
|
205
|
+
"Ecology",
|
|
206
|
+
"Genetics",
|
|
207
|
+
"Neuroscience",
|
|
208
|
+
"Biochemistry",
|
|
209
|
+
"Quantum Mechanics",
|
|
210
|
+
"Thermodynamics",
|
|
211
|
+
"Electrodynamics",
|
|
212
|
+
"Organic Chemistry",
|
|
213
|
+
"Inorganic Chemistry",
|
|
214
|
+
"Molecular Biology",
|
|
215
|
+
"Astrophysics",
|
|
216
|
+
"Cosmology",
|
|
217
|
+
"Paleontology",
|
|
218
|
+
"Oceanography",
|
|
219
|
+
"Meteorology",
|
|
220
|
+
"Seismology",
|
|
221
|
+
"Virology",
|
|
222
|
+
"Immunology",
|
|
223
|
+
"Epidemiology",
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
_METRIC_PREFIXES: tuple[str, ...] = (
|
|
227
|
+
"yotta (Y)",
|
|
228
|
+
"zetta (Z)",
|
|
229
|
+
"exa (E)",
|
|
230
|
+
"peta (P)",
|
|
231
|
+
"tera (T)",
|
|
232
|
+
"giga (G)",
|
|
233
|
+
"mega (M)",
|
|
234
|
+
"kilo (k)",
|
|
235
|
+
"hecto (h)",
|
|
236
|
+
"deca (da)",
|
|
237
|
+
"deci (d)",
|
|
238
|
+
"centi (c)",
|
|
239
|
+
"milli (m)",
|
|
240
|
+
"micro (μ)",
|
|
241
|
+
"nano (n)",
|
|
242
|
+
"pico (p)",
|
|
243
|
+
"femto (f)",
|
|
244
|
+
"atto (a)",
|
|
245
|
+
)
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
class ScienceProvider(BaseProvider):
|
|
249
|
+
"""Generates fake science data — elements, planets, units, etc."""
|
|
250
|
+
|
|
251
|
+
__slots__ = ()
|
|
252
|
+
|
|
253
|
+
_provider_name = "science"
|
|
254
|
+
_locale_modules: tuple[str, ...] = ()
|
|
255
|
+
_field_map: dict[str, str] = {
|
|
256
|
+
"chemical_element": "chemical_element",
|
|
257
|
+
"element": "chemical_element",
|
|
258
|
+
"element_symbol": "element_symbol",
|
|
259
|
+
"si_unit": "si_unit",
|
|
260
|
+
"unit": "si_unit",
|
|
261
|
+
"planet": "planet",
|
|
262
|
+
"galaxy": "galaxy",
|
|
263
|
+
"constellation": "constellation",
|
|
264
|
+
"scientific_discipline": "scientific_discipline",
|
|
265
|
+
"discipline": "scientific_discipline",
|
|
266
|
+
"metric_prefix": "metric_prefix",
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
# --- Public API ---
|
|
270
|
+
|
|
271
|
+
@overload
|
|
272
|
+
def chemical_element(self) -> str: ...
|
|
273
|
+
@overload
|
|
274
|
+
def chemical_element(self, count: Literal[1]) -> str: ...
|
|
275
|
+
@overload
|
|
276
|
+
def chemical_element(self, count: int) -> str | list[str]: ...
|
|
277
|
+
def chemical_element(self, count: int = 1) -> str | list[str]:
|
|
278
|
+
"""Generate a chemical element name (e.g., Hydrogen, Carbon)."""
|
|
279
|
+
if count == 1:
|
|
280
|
+
return self._engine.choice(_CHEMICAL_ELEMENTS)
|
|
281
|
+
return self._engine.choices(_CHEMICAL_ELEMENTS, count)
|
|
282
|
+
|
|
283
|
+
@overload
|
|
284
|
+
def element_symbol(self) -> str: ...
|
|
285
|
+
@overload
|
|
286
|
+
def element_symbol(self, count: Literal[1]) -> str: ...
|
|
287
|
+
@overload
|
|
288
|
+
def element_symbol(self, count: int) -> str | list[str]: ...
|
|
289
|
+
def element_symbol(self, count: int = 1) -> str | list[str]:
|
|
290
|
+
"""Generate a chemical element symbol (e.g., H, C, Fe)."""
|
|
291
|
+
if count == 1:
|
|
292
|
+
return self._engine.choice(_ELEMENT_SYMBOLS)
|
|
293
|
+
return self._engine.choices(_ELEMENT_SYMBOLS, count)
|
|
294
|
+
|
|
295
|
+
@overload
|
|
296
|
+
def si_unit(self) -> str: ...
|
|
297
|
+
@overload
|
|
298
|
+
def si_unit(self, count: Literal[1]) -> str: ...
|
|
299
|
+
@overload
|
|
300
|
+
def si_unit(self, count: int) -> str | list[str]: ...
|
|
301
|
+
def si_unit(self, count: int = 1) -> str | list[str]:
|
|
302
|
+
"""Generate an SI unit (e.g., meter (m), joule (J))."""
|
|
303
|
+
if count == 1:
|
|
304
|
+
return self._engine.choice(_SI_UNITS)
|
|
305
|
+
return self._engine.choices(_SI_UNITS, count)
|
|
306
|
+
|
|
307
|
+
@overload
|
|
308
|
+
def planet(self) -> str: ...
|
|
309
|
+
@overload
|
|
310
|
+
def planet(self, count: Literal[1]) -> str: ...
|
|
311
|
+
@overload
|
|
312
|
+
def planet(self, count: int) -> str | list[str]: ...
|
|
313
|
+
def planet(self, count: int = 1) -> str | list[str]:
|
|
314
|
+
"""Generate a planet name from our solar system."""
|
|
315
|
+
if count == 1:
|
|
316
|
+
return self._engine.choice(_PLANETS)
|
|
317
|
+
return self._engine.choices(_PLANETS, count)
|
|
318
|
+
|
|
319
|
+
@overload
|
|
320
|
+
def galaxy(self) -> str: ...
|
|
321
|
+
@overload
|
|
322
|
+
def galaxy(self, count: Literal[1]) -> str: ...
|
|
323
|
+
@overload
|
|
324
|
+
def galaxy(self, count: int) -> str | list[str]: ...
|
|
325
|
+
def galaxy(self, count: int = 1) -> str | list[str]:
|
|
326
|
+
"""Generate a galaxy name (e.g., Milky Way, Andromeda)."""
|
|
327
|
+
if count == 1:
|
|
328
|
+
return self._engine.choice(_GALAXIES)
|
|
329
|
+
return self._engine.choices(_GALAXIES, count)
|
|
330
|
+
|
|
331
|
+
@overload
|
|
332
|
+
def constellation(self) -> str: ...
|
|
333
|
+
@overload
|
|
334
|
+
def constellation(self, count: Literal[1]) -> str: ...
|
|
335
|
+
@overload
|
|
336
|
+
def constellation(self, count: int) -> str | list[str]: ...
|
|
337
|
+
def constellation(self, count: int = 1) -> str | list[str]:
|
|
338
|
+
"""Generate a constellation name (e.g., Orion, Leo)."""
|
|
339
|
+
if count == 1:
|
|
340
|
+
return self._engine.choice(_CONSTELLATIONS)
|
|
341
|
+
return self._engine.choices(_CONSTELLATIONS, count)
|
|
342
|
+
|
|
343
|
+
@overload
|
|
344
|
+
def scientific_discipline(self) -> str: ...
|
|
345
|
+
@overload
|
|
346
|
+
def scientific_discipline(self, count: Literal[1]) -> str: ...
|
|
347
|
+
@overload
|
|
348
|
+
def scientific_discipline(self, count: int) -> str | list[str]: ...
|
|
349
|
+
def scientific_discipline(self, count: int = 1) -> str | list[str]:
|
|
350
|
+
"""Generate a scientific discipline (e.g., Physics, Genetics)."""
|
|
351
|
+
if count == 1:
|
|
352
|
+
return self._engine.choice(_SCIENTIFIC_DISCIPLINES)
|
|
353
|
+
return self._engine.choices(_SCIENTIFIC_DISCIPLINES, count)
|
|
354
|
+
|
|
355
|
+
@overload
|
|
356
|
+
def metric_prefix(self) -> str: ...
|
|
357
|
+
@overload
|
|
358
|
+
def metric_prefix(self, count: Literal[1]) -> str: ...
|
|
359
|
+
@overload
|
|
360
|
+
def metric_prefix(self, count: int) -> str | list[str]: ...
|
|
361
|
+
def metric_prefix(self, count: int = 1) -> str | list[str]:
|
|
362
|
+
"""Generate a metric prefix (e.g., kilo (k), nano (n))."""
|
|
363
|
+
if count == 1:
|
|
364
|
+
return self._engine.choice(_METRIC_PREFIXES)
|
|
365
|
+
return self._engine.choices(_METRIC_PREFIXES, count)
|