absfuyu 5.2.0__py3-none-any.whl → 5.4.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 (73) hide show
  1. absfuyu/__init__.py +1 -1
  2. absfuyu/__main__.py +2 -2
  3. absfuyu/cli/__init__.py +2 -2
  4. absfuyu/cli/color.py +2 -2
  5. absfuyu/cli/config_group.py +2 -2
  6. absfuyu/cli/do_group.py +12 -2
  7. absfuyu/cli/game_group.py +2 -2
  8. absfuyu/cli/tool_group.py +2 -2
  9. absfuyu/config/__init__.py +2 -2
  10. absfuyu/core/__init__.py +2 -2
  11. absfuyu/core/baseclass.py +32 -2
  12. absfuyu/core/baseclass2.py +2 -2
  13. absfuyu/core/decorator.py +2 -2
  14. absfuyu/core/docstring.py +2 -2
  15. absfuyu/core/dummy_cli.py +2 -2
  16. absfuyu/core/dummy_func.py +2 -2
  17. absfuyu/dxt/__init__.py +2 -2
  18. absfuyu/dxt/dictext.py +15 -6
  19. absfuyu/dxt/dxt_support.py +2 -2
  20. absfuyu/dxt/intext.py +51 -33
  21. absfuyu/dxt/listext.py +138 -10
  22. absfuyu/dxt/strext.py +2 -2
  23. absfuyu/extra/__init__.py +2 -2
  24. absfuyu/extra/beautiful.py +2 -2
  25. absfuyu/extra/da/__init__.py +2 -2
  26. absfuyu/extra/da/dadf.py +57 -41
  27. absfuyu/extra/da/dadf_base.py +2 -2
  28. absfuyu/extra/da/df_func.py +2 -2
  29. absfuyu/extra/da/mplt.py +2 -2
  30. absfuyu/extra/data_analysis.py +2 -2
  31. absfuyu/fun/__init__.py +7 -2
  32. absfuyu/fun/rubik.py +442 -0
  33. absfuyu/fun/tarot.py +2 -2
  34. absfuyu/game/__init__.py +2 -2
  35. absfuyu/game/game_stat.py +2 -2
  36. absfuyu/game/sudoku.py +2 -2
  37. absfuyu/game/tictactoe.py +2 -2
  38. absfuyu/game/wordle.py +2 -2
  39. absfuyu/general/__init__.py +2 -2
  40. absfuyu/general/content.py +2 -2
  41. absfuyu/general/human.py +2 -2
  42. absfuyu/general/shape.py +2 -2
  43. absfuyu/logger.py +2 -2
  44. absfuyu/pkg_data/__init__.py +2 -2
  45. absfuyu/pkg_data/deprecated.py +2 -2
  46. absfuyu/sort.py +2 -2
  47. absfuyu/tools/__init__.py +4 -4
  48. absfuyu/tools/checksum.py +2 -2
  49. absfuyu/tools/converter.py +2 -2
  50. absfuyu/tools/generator.py +2 -2
  51. absfuyu/tools/inspector.py +41 -6
  52. absfuyu/tools/keygen.py +2 -2
  53. absfuyu/tools/obfuscator.py +2 -2
  54. absfuyu/tools/passwordlib.py +2 -2
  55. absfuyu/tools/shutdownizer.py +2 -2
  56. absfuyu/tools/web.py +2 -2
  57. absfuyu/typings.py +7 -2
  58. absfuyu/util/__init__.py +57 -3
  59. absfuyu/util/api.py +2 -2
  60. absfuyu/util/json_method.py +2 -2
  61. absfuyu/util/lunar.py +2 -2
  62. absfuyu/util/path.py +158 -4
  63. absfuyu/util/performance.py +2 -2
  64. absfuyu/util/shorten_number.py +2 -2
  65. absfuyu/util/text_table.py +220 -64
  66. absfuyu/util/zipped.py +2 -2
  67. absfuyu/version.py +2 -2
  68. {absfuyu-5.2.0.dist-info → absfuyu-5.4.0.dist-info}/METADATA +1 -1
  69. absfuyu-5.4.0.dist-info/RECORD +77 -0
  70. absfuyu-5.2.0.dist-info/RECORD +0 -76
  71. {absfuyu-5.2.0.dist-info → absfuyu-5.4.0.dist-info}/WHEEL +0 -0
  72. {absfuyu-5.2.0.dist-info → absfuyu-5.4.0.dist-info}/entry_points.txt +0 -0
  73. {absfuyu-5.2.0.dist-info → absfuyu-5.4.0.dist-info}/licenses/LICENSE +0 -0
absfuyu/dxt/listext.py CHANGED
@@ -3,8 +3,8 @@ Absfuyu: Data Extension
3
3
  -----------------------
4
4
  list extension
5
5
 
6
- Version: 5.2.0
7
- Date updated: 15/03/2025 (dd/mm/yyyy)
6
+ Version: 5.4.0
7
+ Date updated: 21/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module Package
@@ -18,11 +18,12 @@ import operator
18
18
  import random
19
19
  from collections import Counter
20
20
  from collections.abc import Callable, Iterable
21
- from itertools import accumulate, chain, groupby
21
+ from itertools import accumulate, chain, groupby, zip_longest
22
22
  from typing import Any, Literal, Self, cast, overload
23
23
 
24
24
  from absfuyu.core.baseclass import ShowAllMethodsMixin
25
25
  from absfuyu.core.docstring import deprecated, versionadded, versionchanged
26
+ from absfuyu.typings import T as _T
26
27
  from absfuyu.util import set_min_max
27
28
 
28
29
 
@@ -71,6 +72,12 @@ class ListExt(ShowAllMethodsMixin, list):
71
72
  -------
72
73
  list
73
74
  Filtered list
75
+
76
+
77
+ Example:
78
+ --------
79
+ >>> ListExt(range(10)).head(2)
80
+ [0, 1]
74
81
  """
75
82
  number_of_items = int(
76
83
  set_min_max(number_of_items, min_value=0, max_value=len(self))
@@ -91,6 +98,12 @@ class ListExt(ShowAllMethodsMixin, list):
91
98
  -------
92
99
  list
93
100
  Filtered list
101
+
102
+
103
+ Example:
104
+ --------
105
+ >>> ListExt(range(10)).tail(2)
106
+ [8, 9]
94
107
  """
95
108
  number_of_items = int(
96
109
  set_min_max(number_of_items, min_value=0, max_value=len(self))
@@ -354,6 +367,40 @@ class ListExt(ShowAllMethodsMixin, list):
354
367
  start = max(start, 0)
355
368
  return self.__class__(enumerate(self, start=start))
356
369
 
370
+ @versionadded("5.3.0") # no test case yet
371
+ def transpose(self, fillvalue: _T | None = None, /) -> Self:
372
+ """
373
+ Transpose a list of iterable.
374
+
375
+ Parameters
376
+ ----------
377
+ fillvalue : Any, optional
378
+ A fill value, by default ``None``
379
+
380
+ Returns
381
+ -------
382
+ Self | list[list[T]]
383
+ Transposed list.
384
+
385
+
386
+ Example:
387
+ --------
388
+ >>> ListExt([1, 1, 1, 1]).transpose()
389
+ [(1, 1, 1, 1)]
390
+
391
+ >>> ListExt([[1, 1, 1, 1], [1, 1, 1, 1]]).transpose()
392
+ [(1, 1), (1, 1), (1, 1), (1, 1)]
393
+
394
+ >>> ListExt([[1, 1, 1, 1], [1, 1, 1, 1], [1]]).transpose()
395
+ [(1, 1, 1), (1, 1, None), (1, 1, None), (1, 1, None)]
396
+ """
397
+ try:
398
+ return self.__class__(zip_longest(*self, fillvalue=fillvalue)).apply(list)
399
+ except TypeError: # Dimension of 1
400
+ mod_dat = self.apply(lambda x: [x])
401
+ # return self.__class__(zip_longest(*mod_dat, fillvalue=fillvalue)).apply(list)
402
+ return mod_dat
403
+
357
404
  # Random
358
405
  def pick_one(self) -> Any:
359
406
  """
@@ -620,7 +667,7 @@ class ListExt(ShowAllMethodsMixin, list):
620
667
  return self.__class__(data[i1:i2] for i1, i2 in zip([0] + points[:-1], points))
621
668
 
622
669
  @versionadded("5.1.0")
623
- def split_chunk(self, chunk_size: int) -> Self:
670
+ def split_chunk(self, chunk_size: int, /) -> Self:
624
671
  """
625
672
  Split list into smaller chunks
626
673
 
@@ -643,8 +690,75 @@ class ListExt(ShowAllMethodsMixin, list):
643
690
  slice_points = list(range(0, len(self), max(chunk_size, 1)))[1:]
644
691
  return self.slice_points(slice_points)
645
692
 
693
+ @versionadded("5.3.0") # no test case yet
694
+ def to_column(self, ncols: int, fillvalue: _T | None = None) -> Self:
695
+ """
696
+ Smart convert 1 dimension list to 2 dimension list,
697
+ in which, number of columns = ``ncols``.
698
+
699
+ Parameters
700
+ ----------
701
+ ncols : int
702
+ Number of columns
703
+
704
+ fillvalue : T | None, optional
705
+ Fill value, by default ``None``
706
+
707
+ Returns
708
+ -------
709
+ Self
710
+ Coulumned list.
711
+
712
+
713
+ Example:
714
+ --------
715
+ >>> ins = ListExt(range(1,20))
716
+
717
+ >>> # Normal split chunk
718
+ >>> ins.split_chunk(10)
719
+ [
720
+ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
721
+ [11, 12, 13, 14, 15, 16, 17, 18, 19]
722
+ ]
723
+
724
+ >>> # Column split chunk
725
+ >>> ins.to_column(10)
726
+ [
727
+ [1, 3, 5, 7, 9, 11, 13, 15, 17, 19],
728
+ [2, 4, 6, 8, 10, 12, 14, 16, 18, None]
729
+ ]
730
+ """
731
+ num_of_col = max(ncols, 1)
732
+ len_cols = len(self.split_chunk(num_of_col))
733
+ return self.split_chunk(len_cols).transpose(fillvalue)
734
+
735
+ @overload
736
+ def wrap_to_column(self, width: int, /) -> Self: ...
737
+
738
+ @overload
739
+ def wrap_to_column(
740
+ self,
741
+ width: int,
742
+ /,
743
+ *,
744
+ margin: int = 4,
745
+ sep: str = "",
746
+ fill: str = " ",
747
+ transpose: bool = False,
748
+ ) -> Self: ...
749
+
750
+ @versionchanged("5.3.0", reason="New `sep`, `fill`, `transpose` parameters")
646
751
  @versionadded("5.2.0") # no test case yet
647
- def wrap_to_column(self, width: int, margin: int = 4) -> Self:
752
+ def wrap_to_column(
753
+ self,
754
+ width: int,
755
+ /,
756
+ *,
757
+ margin: int = 4,
758
+ sep: str = "",
759
+ fill: str = " ",
760
+ transpose: bool = False,
761
+ ) -> Self:
648
762
  """
649
763
  Arrange list[str] items into aligned text columns (for printing)
650
764
  with automatic column count calculation.
@@ -655,7 +769,16 @@ class ListExt(ShowAllMethodsMixin, list):
655
769
  Total available display width (must be >= ``margin``)
656
770
 
657
771
  margin : int, optional
658
- Reserved space for borders/padding, by default ``4``
772
+ Reserved space for borders/padding, should be an even number, by default ``4``
773
+
774
+ sep : str, optional
775
+ Separator between each element, by default ``""``
776
+
777
+ fill : str, optional
778
+ Fill character for spacing, must have the length of 1, by default ``" "``
779
+
780
+ transpose : bool, optional
781
+ Smart transpose the columns, by default ``False``
659
782
 
660
783
  Returns
661
784
  -------
@@ -673,8 +796,10 @@ class ListExt(ShowAllMethodsMixin, list):
673
796
  ['apple ', 'banana ', 'cherry ', 'date ']
674
797
  """
675
798
 
676
- max_item_length = self.max_item_len() + 1 # +1 for spacing
677
- available_width = max(width, 4) - max(margin, 2) # Set boundary
799
+ max_item_length = self.max_item_len() + max(len(sep), 1)
800
+ available_width = max(width, 4) - max(margin, 0) # Set boundary
801
+ if len(fill) != 1:
802
+ fill = " "
678
803
 
679
804
  # Calculate how many columns of text
680
805
  column_count = (
@@ -688,8 +813,11 @@ class ListExt(ShowAllMethodsMixin, list):
688
813
 
689
814
  def mod_item(item: list[str]) -> str:
690
815
  # Set width for str item and join them together
691
- return "".join(x.ljust(max_item_length, " ") for x in item)
816
+ return sep.join(x.ljust(max_item_length, fill) for x in item)
692
817
 
693
- mod_chunk = self.split_chunk(column_count).apply(mod_item)
818
+ if transpose:
819
+ mod_chunk = self.to_column(column_count, fillvalue="").apply(mod_item)
820
+ else:
821
+ mod_chunk = self.split_chunk(column_count).apply(mod_item)
694
822
 
695
823
  return mod_chunk
absfuyu/dxt/strext.py CHANGED
@@ -3,8 +3,8 @@ Absfuyu: Data Extension
3
3
  -----------------------
4
4
  str extension
5
5
 
6
- Version: 5.2.0
7
- Date updated: 13/03/2025 (dd/mm/yyyy)
6
+ Version: 5.4.0
7
+ Date updated: 21/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module Package
absfuyu/extra/__init__.py CHANGED
@@ -3,8 +3,8 @@ Absfuyu: Extra
3
3
  --------------
4
4
  Features that require additional libraries
5
5
 
6
- Version: 5.2.0
7
- Date updated: 10/03/2025 (dd/mm/yyyy)
6
+ Version: 5.4.0
7
+ Date updated: 21/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
 
@@ -3,8 +3,8 @@ Absfuyu: Beautiful
3
3
  ------------------
4
4
  A decorator that makes output more beautiful
5
5
 
6
- Version: 5.2.0
7
- Date updated: 10/03/2025 (dd/mm/yyyy)
6
+ Version: 5.4.0
7
+ Date updated: 21/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module level
@@ -3,8 +3,8 @@ Absfuyu: Data Analysis
3
3
  ----------------------
4
4
  Data Analyst
5
5
 
6
- Version: 5.2.0
7
- Date updated: 10/03/2025 (dd/mm/yyyy)
6
+ Version: 5.4.0
7
+ Date updated: 21/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module level
absfuyu/extra/da/dadf.py CHANGED
@@ -3,8 +3,8 @@ Absfuyu: Data Analysis
3
3
  ----------------------
4
4
  Data Analyst DataFrame
5
5
 
6
- Version: 5.2.0
7
- Date updated: 15/03/2025 (dd/mm/yyyy)
6
+ Version: 5.4.0
7
+ Date updated: 21/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module level
@@ -58,6 +58,7 @@ class DataAnalystDataFrameColumnMethodMixin(DFBase):
58
58
  - Drop columns
59
59
  - Drop rightmost column
60
60
  - Add blank column
61
+ - Split str column
61
62
  """
62
63
 
63
64
  def rearrange_rightmost_column(
@@ -200,6 +201,59 @@ class DataAnalystDataFrameColumnMethodMixin(DFBase):
200
201
  self[column_name] = [fill] * self.shape[0]
201
202
  return self
202
203
 
204
+ @versionadded("5.2.0") # No test cases
205
+ def split_str_column(
206
+ self,
207
+ col: str,
208
+ pattern: str = " ",
209
+ *,
210
+ n: int | None = None,
211
+ regex: bool = False,
212
+ ) -> Self:
213
+ """
214
+ Split column with dtype[str] into other columns.
215
+
216
+ Parameters
217
+ ----------
218
+ col : str
219
+ Column name
220
+
221
+ pattern : str, optional
222
+ Split pattern, by default ``" "``
223
+
224
+ n : int | None, optional
225
+ Split by how many times, by default ``None``
226
+
227
+ regex : bool, optional
228
+ Regex mode, by default ``False``
229
+
230
+ Returns
231
+ -------
232
+ Self
233
+ DataFrame
234
+
235
+
236
+ Example:
237
+ --------
238
+ >>> df = DADF(DADF.sample_df(5)[["text"]])
239
+ >>> df.split_str_column("text", "s"))
240
+ text text_0 text_1
241
+ 0 uwfzbsgj uwfzb gj
242
+ 1 lxlskayx lxl kayx
243
+ 2 fzgpzjtp fzgpzjtp None
244
+ 3 lxnytktz lxnytktz None
245
+ 4 onryaxtt onryaxtt None
246
+ """
247
+ if n is None:
248
+ pass
249
+ splited_data: pd.DataFrame = self[col].str.split(
250
+ pat=pattern, n=n, expand=True, regex=regex
251
+ )
252
+ num_of_splitted_cols = splited_data.shape[1]
253
+ new_col_names = [f"{col}_{x}" for x in range(num_of_splitted_cols)]
254
+ self[new_col_names] = splited_data
255
+ return self
256
+
203
257
 
204
258
  # Row method
205
259
  # ---------------------------------------------------------------------------
@@ -1136,42 +1190,4 @@ class DADF_WIP(DADF):
1136
1190
  W.I.P - No test cases written
1137
1191
  """
1138
1192
 
1139
- def split_str_column(
1140
- self,
1141
- col: str,
1142
- pattern: str = " ",
1143
- *,
1144
- n: int | None = None,
1145
- regex: bool = False,
1146
- ) -> Self:
1147
- """
1148
- Split column with dtype[str] into other columns.
1149
-
1150
- Parameters
1151
- ----------
1152
- col : str
1153
- Column name
1154
-
1155
- pattern : str, optional
1156
- Split pattern, by default ``" "``
1157
-
1158
- n : int | None, optional
1159
- Split by how many times, by default ``None``
1160
-
1161
- regex : bool, optional
1162
- Regex mode, by default ``False``
1163
-
1164
- Returns
1165
- -------
1166
- Self
1167
- DataFrame
1168
- """
1169
- if n is None:
1170
- pass
1171
- splited_data: pd.DataFrame = self[col].str.split(
1172
- pat=pattern, n=n, expand=True, regex=regex
1173
- )
1174
- num_of_splitted_cols = splited_data.shape[1]
1175
- new_col_names = [f"{col}_{x}" for x in range(num_of_splitted_cols)]
1176
- self[new_col_names] = splited_data
1177
- return self
1193
+ pass
@@ -3,8 +3,8 @@ Absfuyu: Data Analysis
3
3
  ----------------------
4
4
  Data Analyst DataFrame - Base/Core
5
5
 
6
- Version: 5.2.0
7
- Date updated: 10/03/2025 (dd/mm/yyyy)
6
+ Version: 5.4.0
7
+ Date updated: 21/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module level
@@ -3,8 +3,8 @@ Absfuyu: Data Analysis
3
3
  ----------------------
4
4
  DF Function
5
5
 
6
- Version: 5.2.0
7
- Date updated: 10/03/2025 (dd/mm/yyyy)
6
+ Version: 5.4.0
7
+ Date updated: 21/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module level
absfuyu/extra/da/mplt.py CHANGED
@@ -3,8 +3,8 @@ Absfuyu: Data Analysis
3
3
  ----------------------
4
4
  Matplotlib Helper
5
5
 
6
- Version: 5.2.0
7
- Date updated: 10/03/2025 (dd/mm/yyyy)
6
+ Version: 5.4.0
7
+ Date updated: 21/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module level
@@ -4,8 +4,8 @@ Absfuyu: Data Analysis [W.I.P]
4
4
  Extension for ``pd.DataFrame``
5
5
  (deprecated)
6
6
 
7
- Version: 5.2.0
8
- Date updated: 15/03/2025 (dd/mm/yyyy)
7
+ Version: 5.4.0
8
+ Date updated: 21/03/2025 (dd/mm/yyyy)
9
9
  """
10
10
 
11
11
  # Library
absfuyu/fun/__init__.py CHANGED
@@ -3,10 +3,15 @@ Absfuyu: Fun
3
3
  ------------
4
4
  Some fun or weird stuff
5
5
 
6
- Version: 5.2.0
7
- Date updated: 10/03/2025 (dd/mm/yyyy)
6
+ Version: 5.4.0
7
+ Date updated: 21/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
+ # Module level
11
+ # ---------------------------------------------------------------------------
12
+ __all__ = ["zodiac_sign", "happy_new_year", "human_year_to_dog_year"]
13
+
14
+
10
15
  # Library
11
16
  # ---------------------------------------------------------------------------
12
17
  from datetime import date