absfuyu 4.2.0__py3-none-any.whl → 5.0.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.

Potentially problematic release.


This version of absfuyu might be problematic. Click here for more details.

Files changed (67) hide show
  1. absfuyu/__init__.py +4 -4
  2. absfuyu/__main__.py +13 -1
  3. absfuyu/cli/color.py +7 -0
  4. absfuyu/cli/do_group.py +0 -35
  5. absfuyu/cli/tool_group.py +5 -5
  6. absfuyu/config/__init__.py +17 -34
  7. absfuyu/core/__init__.py +49 -0
  8. absfuyu/core/baseclass.py +299 -0
  9. absfuyu/core/baseclass2.py +165 -0
  10. absfuyu/core/decorator.py +67 -0
  11. absfuyu/core/docstring.py +163 -0
  12. absfuyu/core/dummy_cli.py +67 -0
  13. absfuyu/core/dummy_func.py +47 -0
  14. absfuyu/dxt/__init__.py +42 -0
  15. absfuyu/dxt/dictext.py +201 -0
  16. absfuyu/dxt/dxt_support.py +79 -0
  17. absfuyu/dxt/intext.py +586 -0
  18. absfuyu/dxt/listext.py +508 -0
  19. absfuyu/dxt/strext.py +530 -0
  20. absfuyu/{extensions → extra}/__init__.py +2 -2
  21. absfuyu/extra/beautiful.py +251 -0
  22. absfuyu/{extensions → extra}/data_analysis.py +51 -82
  23. absfuyu/fun/__init__.py +110 -135
  24. absfuyu/fun/tarot.py +9 -17
  25. absfuyu/game/__init__.py +6 -0
  26. absfuyu/game/game_stat.py +6 -0
  27. absfuyu/game/sudoku.py +7 -1
  28. absfuyu/game/tictactoe.py +12 -5
  29. absfuyu/game/wordle.py +14 -8
  30. absfuyu/general/__init__.py +6 -79
  31. absfuyu/general/content.py +22 -36
  32. absfuyu/general/generator.py +17 -42
  33. absfuyu/general/human.py +108 -228
  34. absfuyu/general/shape.py +1334 -0
  35. absfuyu/logger.py +8 -13
  36. absfuyu/pkg_data/__init__.py +136 -99
  37. absfuyu/pkg_data/deprecated.py +133 -0
  38. absfuyu/sort.py +6 -130
  39. absfuyu/tools/__init__.py +2 -2
  40. absfuyu/tools/checksum.py +33 -22
  41. absfuyu/tools/converter.py +51 -48
  42. absfuyu/tools/keygen.py +25 -30
  43. absfuyu/tools/obfuscator.py +246 -112
  44. absfuyu/tools/passwordlib.py +99 -29
  45. absfuyu/tools/shutdownizer.py +68 -47
  46. absfuyu/tools/web.py +2 -9
  47. absfuyu/util/__init__.py +15 -15
  48. absfuyu/util/api.py +10 -15
  49. absfuyu/util/json_method.py +7 -24
  50. absfuyu/util/lunar.py +3 -9
  51. absfuyu/util/path.py +22 -27
  52. absfuyu/util/performance.py +43 -67
  53. absfuyu/util/shorten_number.py +65 -14
  54. absfuyu/util/zipped.py +9 -15
  55. {absfuyu-4.2.0.dist-info → absfuyu-5.0.0.dist-info}/METADATA +41 -14
  56. absfuyu-5.0.0.dist-info/RECORD +68 -0
  57. absfuyu/core.py +0 -57
  58. absfuyu/everything.py +0 -32
  59. absfuyu/extensions/beautiful.py +0 -188
  60. absfuyu/fun/WGS.py +0 -134
  61. absfuyu/general/data_extension.py +0 -1796
  62. absfuyu/tools/stats.py +0 -226
  63. absfuyu/util/pkl.py +0 -67
  64. absfuyu-4.2.0.dist-info/RECORD +0 -59
  65. {absfuyu-4.2.0.dist-info → absfuyu-5.0.0.dist-info}/WHEEL +0 -0
  66. {absfuyu-4.2.0.dist-info → absfuyu-5.0.0.dist-info}/entry_points.txt +0 -0
  67. {absfuyu-4.2.0.dist-info → absfuyu-5.0.0.dist-info}/licenses/LICENSE +0 -0
absfuyu/general/human.py CHANGED
@@ -3,58 +3,31 @@ Absfuyu: Human
3
3
  --------------
4
4
  Human related stuff
5
5
 
6
- Version: 1.4.0
7
- Date updated: 15/08/2024 (dd/mm/yyyy)
6
+ Version: 5.0.0
7
+ Date updated: 25/02/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module level
11
- ###########################################################################
11
+ # ---------------------------------------------------------------------------
12
12
  __all__ = ["Human", "Person"]
13
13
 
14
14
 
15
15
  # Library
16
- ###########################################################################
17
- import re
18
- from datetime import datetime, time
19
- from typing import Optional, Union
20
- from urllib.parse import urlencode
21
-
22
- from dateutil.relativedelta import relativedelta
16
+ # ---------------------------------------------------------------------------
17
+ from datetime import date, datetime, time, timedelta
18
+ from enum import StrEnum
19
+ from typing import Self
23
20
 
21
+ from absfuyu.core import BaseClass
22
+ from absfuyu.dxt import IntExt
24
23
  from absfuyu.fun import zodiac_sign
25
- from absfuyu.general.data_extension import IntNumber
26
- from absfuyu.tools.web import soup_link
27
- from absfuyu.version import Version # type: ignore
28
-
29
-
30
- # Sub-Class
31
- ###########################################################################
32
- class _FloatBase:
33
- """To show some unit"""
34
-
35
- def __init__(self, value: float) -> None:
36
- self.value = value
37
-
38
- def __str__(self) -> str:
39
- return self.value.__str__()
40
-
41
- def to_float(self) -> float:
42
- return float(self.value)
43
-
44
24
 
45
- class _Height(_FloatBase):
46
- def __repr__(self) -> str:
47
- return f"{self.value:.2f} cm"
48
-
49
-
50
- class _Weight(_FloatBase):
51
- def __repr__(self) -> str:
52
- return f"{self.value:.2f} kg"
25
+ # from dateutil.relativedelta import relativedelta
53
26
 
54
27
 
55
28
  # Class
56
- ###########################################################################
57
- class BloodType:
29
+ # ---------------------------------------------------------------------------
30
+ class BloodType(StrEnum):
58
31
  A_PLUS = "A+"
59
32
  A_MINUS = "A-"
60
33
  AB_PLUS = "AB+"
@@ -67,33 +40,55 @@ class BloodType:
67
40
  AB = "AB"
68
41
  B = "B"
69
42
  O = "O"
70
- OTHER = None
71
- BLOOD_LIST = [A_MINUS, A_PLUS, B_MINUS, B_PLUS, AB_MINUS, AB_PLUS, O_MINUS, O_PLUS]
43
+ OTHER = "OTHER"
72
44
 
73
45
 
74
- class Human:
46
+ class Human(BaseClass):
75
47
  """
76
48
  Basic human data
77
49
  """
78
50
 
79
- __MEASUREMENT = "m|kg" # Metric system
80
- __VERSION = Version(1, 1, 1) # Internal version class check
81
-
82
51
  def __init__(
83
52
  self,
84
53
  first_name: str,
85
- last_name: Optional[str] = None,
86
- birthday: Union[str, datetime, None] = None,
87
- birth_time: Optional[str] = None,
88
- gender: Union[bool, None] = None,
54
+ last_name: str | None = None,
55
+ birthday: str | datetime | None = None,
56
+ birth_time: str | None = None,
57
+ gender: bool | None = None,
58
+ height: int | float | None = None,
59
+ weight: int | float | None = None,
60
+ blood_type: BloodType = BloodType.OTHER,
89
61
  ) -> None:
90
62
  """
91
- :param first_name: First name
92
- :param last_name: Last name
93
- :param birthday: Birthday in format: ``yyyy/mm/dd``
94
- :param birth_time: Birth time in format: ``hh:mm``
95
- :param gender: ``True``: Male; ``False``: Female (biologicaly)
63
+ Human instance
64
+
65
+ Parameters
66
+ ----------
67
+ first_name : str
68
+ First name
69
+
70
+ last_name : str | None, optional
71
+ Last name, by default ``None``
72
+
73
+ birthday : str | datetime | None, optional
74
+ Birthday in format: ``yyyy/mm/dd``, by default ``None`` (birthday = today)
75
+
76
+ birth_time : str | None, optional
77
+ Birth time in format: ``hh:mm``, by default ``None`` (birthtime = today)
78
+
79
+ gender : bool | None, optional
80
+ ``True``: Male; ``False``: Female (biologicaly), by default ``None``
81
+
82
+ height : int | float | None, optional
83
+ Height in centimeter (cm), by default ``None``
84
+
85
+ weight : int | float | None, optional
86
+ Weight in kilogram (kg), by default ``None``
87
+
88
+ blood_type : BloodType, optional
89
+ Blood type, by default ``BloodType.OTHER``
96
90
  """
91
+
97
92
  # Name
98
93
  self.first_name = first_name
99
94
  self.last_name = last_name
@@ -113,18 +108,16 @@ class Human:
113
108
  modified_birthday = datetime.strptime(birthday, "%Y/%m/%d")
114
109
  else:
115
110
  modified_birthday = birthday
116
- # birthday = list(map(int, birthday.split("/")))
117
- # modified_birthday = date(*birthday)
118
- # modified_birthday = date(birthday[0], birthday[1], birthday[2])
119
111
 
120
112
  if birth_time is None:
121
113
  modified_birthtime = now.time()
122
114
  else:
123
115
  birth_time = list(map(int, birth_time.split(":"))) # type: ignore
124
116
  modified_birthtime = time(*birth_time)
125
- # modified_birthtime = time(birth_time[0], birth_time[1])
126
117
 
127
- self.birthday = modified_birthday.date() # type: ignore
118
+ self.birthday = date(
119
+ modified_birthday.year, modified_birthday.month, modified_birthday.day
120
+ )
128
121
  self.birth_time = modified_birthtime
129
122
 
130
123
  self.birth = datetime(
@@ -136,23 +129,17 @@ class Human:
136
129
  )
137
130
 
138
131
  # Others
139
- self.gender: bool = gender # type: ignore # True: Male; False: Female
140
- self.height: float = None # type: ignore # centimeter
141
- self.weight: float = None # type: ignore # kilogram
142
- self.blood_type: Union[str, BloodType] = BloodType.OTHER # type: ignore
132
+ self.gender = gender
133
+ self.height = height
134
+ self.weight = weight
135
+ self.blood_type = blood_type
143
136
 
144
137
  def __str__(self) -> str:
145
138
  class_name = self.__class__.__name__
146
139
  return f"{class_name}({str(self.name)})"
147
140
 
148
- def __repr__(self) -> str:
149
- class_name = self.__class__.__name__
150
- name = str(self.name)
151
- gender = "M" if self.is_male else "F"
152
- return f"{class_name}({name} ({self.age}|{gender}))"
153
-
154
141
  @classmethod
155
- def JohnDoe(cls):
142
+ def JohnDoe(cls) -> Self:
156
143
  """
157
144
  Dummy Human for test
158
145
 
@@ -161,9 +148,7 @@ class Human:
161
148
  Human
162
149
  Dummy Human instance
163
150
  """
164
- temp = cls("John", "Doe", "1980/01/01", "00:00")
165
- temp.update({"gender": True, "height": 180, "weight": 80, "blood_type": "O+"})
166
- return temp
151
+ return cls("John", "Doe", "1980/01/01", "00:00", True, 180, 80, BloodType.O)
167
152
 
168
153
  @property
169
154
  def is_male(self) -> bool:
@@ -173,89 +158,64 @@ class Human:
173
158
  Returns
174
159
  -------
175
160
  bool
176
- | ``True``: Male
177
- | ``False``: Female
161
+ - ``True``: Male
162
+ - ``False``: Female
178
163
  """
164
+ if self.gender is None:
165
+ raise ValueError("Gender must be defined first")
179
166
  return self.gender
180
167
 
181
168
  @property
182
- def age(self):
169
+ def age(self) -> float:
183
170
  """
184
- Calculate age based on birthday
171
+ Calculate age based on birthday, precise to birth_time
185
172
 
186
173
  Returns
187
174
  -------
188
175
  float
189
176
  Age
190
-
191
- None
192
- When unable to get ``self.birthday``
193
177
  """
194
- if self.birthday is not None:
195
- now = datetime.now()
196
- # age = now - self.birthday
197
- try:
198
- rdelta = relativedelta(now, self.birthday)
199
- except Exception:
200
- date_str = self.birthday
201
- if date_str is None:
202
- self.birthday = datetime.now().date()
203
- else:
204
- for x in ["/", "-"]:
205
- date_str = date_str.replace(x, "/")
206
- date = datetime.strptime(date_str, "%Y/%m/%d")
207
- self.birthday = date
208
- rdelta = relativedelta(now, self.birthday)
209
- return round(rdelta.years + rdelta.months / 12, 2)
210
- else:
211
- return None
178
+ now = datetime.now()
179
+ # age = now - self.birthday
180
+ rdelta = now - self.birth
181
+ # rdelta = relativedelta(now, self.birthday)
182
+ # return round(rdelta.years + rdelta.months / 12, 2)
183
+ return round(rdelta / timedelta(days=365.2425), 2)
212
184
 
213
185
  @property
214
- def is_adult(self):
186
+ def is_adult(self) -> bool:
215
187
  """
216
188
  Check if ``self.age`` >= ``18``
217
189
 
218
- :rtype: bool
190
+ Returns
191
+ -------
192
+ bool
193
+ If is adult
219
194
  """
220
195
  return self.age >= 18
221
196
 
222
197
  @property
223
- def bmi(self):
198
+ def bmi(self) -> float:
224
199
  r"""
225
200
  Body Mass Index (kg/m^2)
226
201
 
227
202
  Formula: :math:`\frac{weight (kg)}{height (m)^2}`
228
203
 
229
204
  - BMI < 18.5: Skinny
230
- - 18.5 < BMI < 25: normal
205
+ - 18.5 < BMI < 25: Normal
231
206
  - BMI > 30: Obesse
232
207
 
233
208
  Returns
234
209
  -------
235
210
  float
236
211
  BMI value
237
-
238
- None
239
- When unable to get ``self.height`` and ``self.weight``
240
- """
241
- try:
242
- temp = self.height / 100
243
- bmi = self.weight / (temp * temp)
244
- return round(bmi, 2)
245
- except Exception:
246
- return None
247
-
248
- # @property
249
- def dir_(self) -> list:
250
212
  """
251
- List property
213
+ if self.height is None or self.weight is None:
214
+ raise ValueError("Height and Weight must be defined")
252
215
 
253
- Returns
254
- -------
255
- list[str]
256
- List of available properties
257
- """
258
- return [x for x in self.__dir__() if not x.startswith("_")]
216
+ height_in_meter = self.height / 100
217
+ bmi = self.weight / (height_in_meter**2)
218
+ return round(bmi, 2)
259
219
 
260
220
  def update(self, data: dict) -> None:
261
221
  """
@@ -271,7 +231,6 @@ class Human:
271
231
  None
272
232
  """
273
233
  self.__dict__.update(data)
274
- # return self
275
234
 
276
235
 
277
236
  class Person(Human):
@@ -279,31 +238,41 @@ class Person(Human):
279
238
  More detailed ``Human`` data
280
239
  """
281
240
 
282
- __VERSION = Version(1, 1, 1) # Internal version class check
283
-
284
241
  def __init__(
285
242
  self,
286
- first_name: str,
287
- last_name: Optional[str] = None,
288
- birthday: Union[str, datetime, None] = None,
289
- birth_time: Optional[str] = None,
290
- gender: Union[bool, None] = None,
243
+ first_name,
244
+ last_name=None,
245
+ birthday=None,
246
+ birth_time=None,
247
+ gender=None,
248
+ height=None,
249
+ weight=None,
250
+ blood_type=BloodType.OTHER,
291
251
  ) -> None:
292
- super().__init__(first_name, last_name, birthday, birth_time, gender)
252
+ super().__init__(
253
+ first_name,
254
+ last_name,
255
+ birthday,
256
+ birth_time,
257
+ gender,
258
+ height,
259
+ weight,
260
+ blood_type,
261
+ )
293
262
  self.address: str = None # type: ignore
294
263
  self.hometown: str = None # type: ignore
295
264
  self.email: str = None # type: ignore
296
265
  self.phone_number: str = None # type: ignore
297
- self.nationality = None # type: ignore
266
+ self.nationality: str = None # type: ignore
298
267
  self.likes: list = None # type: ignore
299
268
  self.hates: list = None # type: ignore
300
- self.education = None # type: ignore
269
+ self.education: str = None # type: ignore
301
270
  self.occupation: str = None # type: ignore
302
- self.personality = None # type: ignore
271
+ self.personality: str = None # type: ignore
303
272
  self.note: str = None # type: ignore
304
273
 
305
274
  @property
306
- def zodiac_sign(self):
275
+ def zodiac_sign(self) -> str:
307
276
  """
308
277
  Zodiac sign of ``Person``
309
278
 
@@ -311,17 +280,11 @@ class Person(Human):
311
280
  -------
312
281
  str
313
282
  Zodiac sign
314
-
315
- None
316
- When unable to get ``self.birthday``
317
283
  """
318
- try:
319
- return zodiac_sign(self.birthday.day, self.birthday.month)
320
- except Exception:
321
- return None
284
+ return zodiac_sign(self.birthday.day, self.birthday.month)
322
285
 
323
286
  @property
324
- def zodiac_sign_13(self):
287
+ def zodiac_sign_13(self) -> str:
325
288
  """
326
289
  Zodiac sign of ``Person`` (13 zodiac signs version)
327
290
 
@@ -329,14 +292,8 @@ class Person(Human):
329
292
  -------
330
293
  str
331
294
  Zodiac sign
332
-
333
- None
334
- When unable to get ``self.birthday``
335
295
  """
336
- try:
337
- return zodiac_sign(self.birthday.day, self.birthday.month, zodiac13=True)
338
- except Exception:
339
- return None
296
+ return zodiac_sign(self.birthday.day, self.birthday.month, zodiac13=True)
340
297
 
341
298
  @property
342
299
  def numerology(self) -> int:
@@ -349,81 +306,4 @@ class Person(Human):
349
306
  Numerology number
350
307
  """
351
308
  temp = f"{self.birthday.year}{self.birthday.month}{self.birthday.day}"
352
- return IntNumber(temp).add_to_one_digit(master_number=True)
353
-
354
-
355
- class Human2:
356
- """W.I.P for cli"""
357
-
358
- def __init__(self, birthday_string: str, is_male: bool = True) -> None:
359
- """
360
- :param birthday_string: Format ``<yyyymmddhhmm>`` or ``<yyyymmdd>``
361
- """
362
- if len(birthday_string) == 12:
363
- day = datetime(
364
- year=int(birthday_string[:4]),
365
- month=int(birthday_string[4:6]),
366
- day=int(birthday_string[6:8]),
367
- hour=int(birthday_string[8:10]),
368
- minute=int(birthday_string[10:]),
369
- )
370
- else:
371
- day = datetime(
372
- year=int(birthday_string[:4]),
373
- month=int(birthday_string[4:6]),
374
- day=int(birthday_string[6:]),
375
- )
376
- self._date_str = birthday_string[:8]
377
- self.day = day
378
- self.is_male = is_male
379
-
380
- def __str__(self) -> str:
381
- class_name = self.__class__.__name__
382
- return f"{class_name}({str(self.day)})"
383
-
384
- def __repr__(self) -> str:
385
- class_name = self.__class__.__name__
386
- return f"{class_name}({str(self.day)})"
387
-
388
- def numerology(self) -> int:
389
- # numerology
390
- return IntNumber(self._date_str).add_to_one_digit(master_number=True)
391
-
392
- def _make_fengshui_check_query(self) -> str:
393
- """
394
- Generate query to check Feng-shui
395
- """
396
- params = {
397
- "ngay": self.day.day.__str__().rjust(2, "0"),
398
- "thang": self.day.month.__str__().rjust(2, "0"),
399
- "nam": self.day.year,
400
- "gio": self.day.hour.__str__().rjust(2, "0"),
401
- "phut": self.day.minute.__str__().rjust(2, "0"),
402
- "gioitinh": "nam" if self.is_male else "nu",
403
- }
404
- output = urlencode(params)
405
- return output
406
-
407
- def fs(self, number_string: str) -> float:
408
- # fengshui
409
- base = "https://thanglongdaoquan.vn/boi-so-tai-khoan/?taikhoan="
410
- link = f"{base}{number_string}&{self._make_fengshui_check_query()}"
411
- soup = soup_link(link)
412
- val = soup.find_all(class_="total_point")[0].get_text()
413
- pattern = r"([0-9.]{1,3})/10"
414
- res = re.findall(pattern, val)[0]
415
- return float(res)
416
-
417
- def info(self) -> dict:
418
- out = {
419
- "numerology": self.numerology(),
420
- "zodiac": zodiac_sign(self.day.day, self.day.month),
421
- }
422
- return out
423
-
424
-
425
- # Run
426
- ###########################################################################
427
- if __name__ == "__main__":
428
- # print(Person.JohnDoe().__dict__)
429
- pass
309
+ return IntExt(temp).add_to_one_digit(master_number=True)