absfuyu 5.0.0__py3-none-any.whl → 5.1.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 (72) 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 +30 -14
  5. absfuyu/cli/config_group.py +9 -2
  6. absfuyu/cli/do_group.py +13 -6
  7. absfuyu/cli/game_group.py +9 -2
  8. absfuyu/cli/tool_group.py +16 -9
  9. absfuyu/config/__init__.py +2 -2
  10. absfuyu/core/__init__.py +2 -2
  11. absfuyu/core/baseclass.py +449 -80
  12. absfuyu/core/baseclass2.py +2 -2
  13. absfuyu/core/decorator.py +69 -3
  14. absfuyu/core/docstring.py +25 -22
  15. absfuyu/core/dummy_cli.py +2 -2
  16. absfuyu/core/dummy_func.py +19 -6
  17. absfuyu/core/typings.py +40 -0
  18. absfuyu/dxt/__init__.py +2 -2
  19. absfuyu/dxt/dictext.py +2 -2
  20. absfuyu/dxt/dxt_support.py +2 -2
  21. absfuyu/dxt/intext.py +31 -3
  22. absfuyu/dxt/listext.py +28 -3
  23. absfuyu/dxt/strext.py +3 -3
  24. absfuyu/extra/__init__.py +2 -2
  25. absfuyu/extra/beautiful.py +3 -2
  26. absfuyu/extra/da/__init__.py +36 -0
  27. absfuyu/extra/da/dadf.py +1138 -0
  28. absfuyu/extra/da/dadf_base.py +186 -0
  29. absfuyu/extra/da/df_func.py +97 -0
  30. absfuyu/extra/da/mplt.py +219 -0
  31. absfuyu/extra/data_analysis.py +10 -1067
  32. absfuyu/fun/__init__.py +2 -2
  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 +4 -4
  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 +25 -2
  48. absfuyu/tools/checksum.py +27 -7
  49. absfuyu/tools/converter.py +93 -28
  50. absfuyu/{general → tools}/generator.py +2 -2
  51. absfuyu/tools/inspector.py +433 -0
  52. absfuyu/tools/keygen.py +2 -2
  53. absfuyu/tools/obfuscator.py +46 -8
  54. absfuyu/tools/passwordlib.py +88 -23
  55. absfuyu/tools/shutdownizer.py +2 -2
  56. absfuyu/tools/web.py +2 -2
  57. absfuyu/util/__init__.py +2 -2
  58. absfuyu/util/api.py +2 -2
  59. absfuyu/util/json_method.py +2 -2
  60. absfuyu/util/lunar.py +2 -2
  61. absfuyu/util/path.py +190 -82
  62. absfuyu/util/performance.py +4 -4
  63. absfuyu/util/shorten_number.py +40 -10
  64. absfuyu/util/text_table.py +272 -0
  65. absfuyu/util/zipped.py +6 -6
  66. absfuyu/version.py +59 -42
  67. {absfuyu-5.0.0.dist-info → absfuyu-5.1.0.dist-info}/METADATA +10 -3
  68. absfuyu-5.1.0.dist-info/RECORD +76 -0
  69. absfuyu-5.0.0.dist-info/RECORD +0 -68
  70. {absfuyu-5.0.0.dist-info → absfuyu-5.1.0.dist-info}/WHEEL +0 -0
  71. {absfuyu-5.0.0.dist-info → absfuyu-5.1.0.dist-info}/entry_points.txt +0 -0
  72. {absfuyu-5.0.0.dist-info → absfuyu-5.1.0.dist-info}/licenses/LICENSE +0 -0
absfuyu/core/decorator.py CHANGED
@@ -3,13 +3,17 @@ Absfuyu: Core
3
3
  -------------
4
4
  Decorator
5
5
 
6
- Version: 5.0.0
7
- Date updated: 22/02/2025 (dd/mm/yyyy)
6
+ Version: 5.1.0
7
+ Date updated: 10/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module Package
11
11
  # ---------------------------------------------------------------------------
12
- __all__ = ["dummy_decorator", "dummy_decorator_with_args"]
12
+ __all__ = [
13
+ "dummy_decorator",
14
+ "dummy_decorator_with_args",
15
+ "add_subclass_methods_decorator",
16
+ ]
13
17
 
14
18
 
15
19
  # Library
@@ -52,8 +56,10 @@ def dummy_decorator_with_args(*args, **kwargs):
52
56
 
53
57
  @overload
54
58
  def decorator(obj: T) -> T: ...
59
+
55
60
  @overload
56
61
  def decorator(obj: Callable[P, R]) -> Callable[P, R]: ...
62
+
57
63
  def decorator(obj: Callable[P, R] | T) -> Callable[P, R] | T:
58
64
  if isinstance(obj, type):
59
65
  return obj
@@ -65,3 +71,63 @@ def dummy_decorator_with_args(*args, **kwargs):
65
71
  return wrapper
66
72
 
67
73
  return decorator
74
+
75
+
76
+ def add_subclass_methods_decorator(cls: T) -> T:
77
+ """
78
+ Class decorator replace the ``__init_subclass__`` method.
79
+
80
+ This method populates a dictionary with subclass names as keys
81
+ and their available methods as values.
82
+
83
+ - Create 2 class attributes: ``_METHOD_INCLUDE`` (bool) and ``SUBCLASS_METHODS`` (dict[str, list[str]])
84
+ - Automatically add subclass methods to class variable: ``SUBCLASS_METHODS``
85
+ - Set class attribute ``_METHOD_INCLUDE`` to ``False`` to exclude from ``SUBCLASS_METHODS``
86
+
87
+ Example:
88
+ --------
89
+ >>> # Normal behavior
90
+ >>> @add_subclass_methods_decorator
91
+ >>> class TestParent: ...
92
+ >>> class TestChild(TestParent):
93
+ ... def method1(self): ...
94
+ >>> TestChild.SUBCLASS_METHODS
95
+ {'__main__.TestChild': ['method1']}
96
+
97
+ >>> # Hidden from ``SUBCLASS_METHODS``
98
+ >>> @add_subclass_methods_decorator
99
+ >>> class TestParent: ...
100
+ >>> class TestChildHidden(TestParent):
101
+ ... _METHOD_INCLUDE = False
102
+ ... def method1(self): ...
103
+ >>> TestChildHidden.SUBCLASS_METHODS
104
+ {}
105
+ """
106
+
107
+ # Check for class
108
+ if not isinstance(cls, type):
109
+ raise ValueError("Object is not a class")
110
+
111
+ class AutoSubclassMixin:
112
+ _METHOD_INCLUDE: bool = True # Include in SUBCLASS_METHODS
113
+ SUBCLASS_METHODS: dict[str, list[str]] = {}
114
+
115
+ def __init_subclass__(cls, *args, **kwargs) -> None:
116
+ """
117
+ This create a dictionary with:
118
+ - key (str) : Subclass
119
+ - value (list[str]): List of available methods
120
+ """
121
+ super().__init_subclass__(*args, **kwargs)
122
+
123
+ if cls._METHOD_INCLUDE and not any(
124
+ [x.endswith(cls.__name__) for x in cls.SUBCLASS_METHODS.keys()]
125
+ ):
126
+ methods_list: list[str] = [
127
+ k for k, v in cls.__dict__.items() if callable(v)
128
+ ]
129
+ if len(methods_list) > 0:
130
+ name = f"{cls.__module__}.{cls.__name__}"
131
+ cls.SUBCLASS_METHODS.update({name: sorted(methods_list)})
132
+
133
+ return type("AutoSubclass", (AutoSubclassMixin, cls), {}) # type: ignore[return-value]
absfuyu/core/docstring.py CHANGED
@@ -3,8 +3,8 @@ Absfuyu: Core
3
3
  -------------
4
4
  Sphinx docstring decorator
5
5
 
6
- Version: 5.0.0
7
- Date updated: 13/02/2025 (dd/mm/yyyy)
6
+ Version: 5.1.0
7
+ Date updated: 10/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module Package
@@ -28,9 +28,9 @@ from typing import ClassVar, ParamSpec, TypeVar, overload
28
28
 
29
29
  # Type
30
30
  # ---------------------------------------------------------------------------
31
- P = ParamSpec("P") # Parameter type
32
- R = TypeVar("R") # Return type - Can be anything
33
- T = TypeVar("T", bound=type) # Type type - Can be any subtype of `type`
31
+ _P = ParamSpec("_P") # Parameter type
32
+ _R = TypeVar("_R") # Return type - Can be anything
33
+ _T = TypeVar("_T", bound=type) # Type type - Can be any subtype of `type`
34
34
 
35
35
  _SPHINX_DOCS_TEMPLATE = Template("$line_break*$mode in version $version$reason*")
36
36
 
@@ -88,10 +88,13 @@ class SphinxDocstring:
88
88
  self.mode = mode
89
89
 
90
90
  @overload
91
- def __call__(self, obj: T) -> T: ... # Class overload
91
+ def __call__(self, obj: _T) -> _T: ... # Class overload
92
+
92
93
  @overload
93
- def __call__(self, obj: Callable[P, R]) -> Callable[P, R]: ... # Function overload
94
- def __call__(self, obj: T | Callable[P, R]) -> T | Callable[P, R]:
94
+ def __call__(
95
+ self, obj: Callable[_P, _R]
96
+ ) -> Callable[_P, _R]: ... # Function overload
97
+ def __call__(self, obj: _T | Callable[_P, _R]) -> _T | Callable[_P, _R]:
95
98
  # Class wrapper
96
99
  if isinstance(obj, type): # if inspect.isclass(obj):
97
100
  obj.__doc__ = (obj.__doc__ or "") + self._generate_version_note(
@@ -101,7 +104,7 @@ class SphinxDocstring:
101
104
 
102
105
  # Function wrapper
103
106
  @wraps(obj)
104
- def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
107
+ def wrapper(*args: _P.args, **kwargs: _P.kwargs) -> _R:
105
108
  return obj(*args, **kwargs)
106
109
 
107
110
  # Add docstring
@@ -127,19 +130,19 @@ class SphinxDocstring:
127
130
  if docs is None:
128
131
  return res
129
132
 
130
- # # Index of the last whitespaces
131
- # # https://stackoverflow.com/a/13649118
132
- # res = next((i for i, c in enumerate(docs) if not c.isspace()), 0)
133
- # return res if res % 2 == 0 else res - 1
134
-
135
- # Alternative solution
136
- for char in docs:
137
- if char == " ":
138
- res += 1
139
- if char == "\t":
140
- res += 4
141
- if not char.isspace():
142
- break
133
+ try:
134
+ # Replace tabs with space and split line
135
+ lines = docs.expandtabs(4).splitlines()
136
+ except UnicodeError:
137
+ return res
138
+ else:
139
+ # Get indentation of each line and unique it
140
+ indent_set = {len(line) - len(line.lstrip()) for line in lines[1:]}
141
+ # Drop 0
142
+ res_list = sorted([x for x in indent_set if x > 0])
143
+
144
+ if res_list:
145
+ return res_list[0]
143
146
  return res
144
147
 
145
148
  def _generate_version_note(self, num_of_white_spaces: int) -> str:
absfuyu/core/dummy_cli.py CHANGED
@@ -3,8 +3,8 @@ Absfuyu: Core
3
3
  -------------
4
4
  Dummy cli
5
5
 
6
- Version: 5.0.0
7
- Date updated: 25/02/2025 (dd/mm/yyyy)
6
+ Version: 5.1.0
7
+ Date updated: 10/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module Package
@@ -3,8 +3,8 @@ Absfuyu: Core
3
3
  -------------
4
4
  Dummy functions when other libraries are unvailable
5
5
 
6
- Version: 5.0.0
7
- Date updated: 14/02/2025 (dd/mm/yyyy)
6
+ Version: 5.1.0
7
+ Date updated: 10/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module Package
@@ -12,6 +12,7 @@ Date updated: 14/02/2025 (dd/mm/yyyy)
12
12
  __all__ = [
13
13
  "tqdm",
14
14
  "unidecode",
15
+ "dummy_function",
15
16
  ]
16
17
 
17
18
 
@@ -23,8 +24,9 @@ from importlib import import_module
23
24
  # ---------------------------------------------------------------------------
24
25
  # tqdm wrapper
25
26
  try:
26
- tqdm = import_module("tqdm").tqdm
27
- except ModuleNotFoundError:
27
+ _tqdm = import_module("tqdm")
28
+ tqdm = getattr(_tqdm, "tqdm") # noqa
29
+ except (ModuleNotFoundError, AttributeError):
28
30
 
29
31
  def tqdm(iterable, *args, **kwargs):
30
32
  """
@@ -36,8 +38,9 @@ except ModuleNotFoundError:
36
38
 
37
39
  # unidecode wrapper
38
40
  try:
39
- unidecode = import_module("unidecode").unidecode
40
- except ModuleNotFoundError:
41
+ _unidecode = import_module("unidecode")
42
+ unidecode = getattr(_unidecode, "unidecode") # noqa
43
+ except (ModuleNotFoundError, AttributeError):
41
44
 
42
45
  def unidecode(*args, **kwargs):
43
46
  """
@@ -45,3 +48,13 @@ except ModuleNotFoundError:
45
48
  install package ``unidecode`` to fully use this feature
46
49
  """
47
50
  return args[0]
51
+
52
+
53
+ # dummy
54
+ def dummy_function(*args, **kwargs):
55
+ """This is a dummy function"""
56
+ if args:
57
+ return args[0]
58
+ if kwargs:
59
+ return kwargs[list(kwargs)[0]]
60
+ return None
@@ -0,0 +1,40 @@
1
+ """
2
+ Absfuyu: Core
3
+ -------------
4
+ Pre-defined typing
5
+
6
+ Version: 5.1.0
7
+ Date updated: 10/03/2025 (dd/mm/yyyy)
8
+ """
9
+
10
+ # Module Package
11
+ # ---------------------------------------------------------------------------
12
+ __all__ = ["_T", "_P", "_R", "_CALLABLE", "_CT", "_N", "_Number", "override"]
13
+
14
+
15
+ # Library
16
+ # ---------------------------------------------------------------------------
17
+ from collections.abc import Callable
18
+ from typing import ParamSpec, TypeVar
19
+
20
+ try:
21
+ from typing import override # type: ignore
22
+ except ImportError:
23
+ from absfuyu.core.decorator import dummy_decorator as override
24
+
25
+
26
+ # Type
27
+ # ---------------------------------------------------------------------------
28
+ _T = TypeVar("_T") # Type
29
+
30
+ # Callable
31
+ _P = ParamSpec("_P") # Parameter type
32
+ _R = TypeVar("_R") # Return type - Can be anything
33
+ _CALLABLE = Callable[_P, _R]
34
+
35
+ # Class type - Can be any subtype of `type`
36
+ _CT = TypeVar("_CT", bound=type)
37
+
38
+ # Number type
39
+ _N = TypeVar("_N", int, float)
40
+ _Number = int | float
absfuyu/dxt/__init__.py CHANGED
@@ -3,8 +3,8 @@ Absfuyu: Data Extension
3
3
  -----------------------
4
4
  Extension for data type such as ``list``, ``str``, ``dict``, ...
5
5
 
6
- Version: 5.0.0
7
- Date updated: 11/01/2025 (dd/mm/yyyy)
6
+ Version: 5.1.0
7
+ Date updated: 10/03/2025 (dd/mm/yyyy)
8
8
 
9
9
  Features:
10
10
  ---------
absfuyu/dxt/dictext.py CHANGED
@@ -3,8 +3,8 @@ Absfuyu: Data Extension
3
3
  -----------------------
4
4
  dict extension
5
5
 
6
- Version: 5.0.0
7
- Date updated: 14/02/2025 (dd/mm/yyyy)
6
+ Version: 5.1.0
7
+ Date updated: 10/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module Package
@@ -3,8 +3,8 @@ Absfuyu: Data Extension
3
3
  -----------------------
4
4
  Support classes
5
5
 
6
- Version: 5.0.0
7
- Date updated: 11/02/2025 (dd/mm/yyyy)
6
+ Version: 5.1.0
7
+ Date updated: 10/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module Package
absfuyu/dxt/intext.py CHANGED
@@ -3,8 +3,8 @@ Absfuyu: Data Extension
3
3
  -----------------------
4
4
  int extension
5
5
 
6
- Version: 5.0.0
7
- Date updated: 11/02/2025 (dd/mm/yyyy)
6
+ Version: 5.1.0
7
+ Date updated: 10/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module Package
@@ -18,7 +18,7 @@ import math
18
18
  from collections import Counter
19
19
  from typing import Any, Self
20
20
 
21
- from absfuyu.core import ShowAllMethodsMixin, versionchanged
21
+ from absfuyu.core import ShowAllMethodsMixin, versionadded, versionchanged
22
22
  from absfuyu.dxt.dxt_support import DictBoolTrue
23
23
 
24
24
 
@@ -584,3 +584,31 @@ class IntExt(ShowAllMethodsMixin, int):
584
584
 
585
585
  output["characteristic"] = characteristic
586
586
  return output # type: ignore
587
+
588
+ @versionadded("5.1.0")
589
+ def split(self, parts: int) -> list[int]:
590
+ """
591
+ Evenly split the number into ``parts`` parts
592
+
593
+ Parameters
594
+ ----------
595
+ parts : int
596
+ Split by how many parts
597
+
598
+ Returns
599
+ -------
600
+ list[int]
601
+ List of evenly splitted numbers
602
+
603
+
604
+ Example:
605
+ --------
606
+ >>> IntExt(10).split(4)
607
+ [2, 2, 3, 3]
608
+ """
609
+ p = max(1, parts)
610
+ if p == 1:
611
+ return [int(self)]
612
+
613
+ quotient, remainder = divmod(self, p)
614
+ return [quotient + (i >= (p - remainder)) for i in range(p)]
absfuyu/dxt/listext.py CHANGED
@@ -3,8 +3,8 @@ Absfuyu: Data Extension
3
3
  -----------------------
4
4
  list extension
5
5
 
6
- Version: 5.0.0
7
- Date updated: 11/02/2025 (dd/mm/yyyy)
6
+ Version: 5.1.0
7
+ Date updated: 10/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module Package
@@ -22,6 +22,7 @@ from itertools import accumulate, chain, groupby
22
22
  from typing import Any, Self
23
23
 
24
24
  from absfuyu.core import ShowAllMethodsMixin, deprecated
25
+ from absfuyu.core.docstring import versionadded
25
26
  from absfuyu.util import set_min, set_min_max
26
27
 
27
28
 
@@ -323,7 +324,7 @@ class ListExt(ShowAllMethodsMixin, list):
323
324
  # logger.debug(out)
324
325
  return out
325
326
 
326
- def apply(self, func: Callable) -> Self:
327
+ def apply(self, func: Callable[[Any], Any]) -> Self:
327
328
  """
328
329
  Apply function to each entry
329
330
 
@@ -490,6 +491,30 @@ class ListExt(ShowAllMethodsMixin, list):
490
491
  start = int(set_min(start, min_value=0))
491
492
  return self.__class__(enumerate(self, start=start))
492
493
 
494
+ @versionadded("5.1.0") # no test case yet
495
+ def split_chunk(self, chunk_size: int) -> list[list]:
496
+ """
497
+ Split list into smaller chunks
498
+
499
+ Parameters
500
+ ----------
501
+ chunk_size : int
502
+ Chunk size, minimum: ``1``
503
+
504
+ Returns
505
+ -------
506
+ list[list]
507
+ List of chunk
508
+
509
+
510
+ Example:
511
+ --------
512
+ >>> ListExt([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]).split_chunk(5)
513
+ [[1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1]]
514
+ """
515
+ slice_points = list(range(0, len(self), max(chunk_size, 1)))[1:]
516
+ return self.slice_points(slice_points)
517
+
493
518
  @staticmethod
494
519
  @deprecated("5.0.0")
495
520
  def _group_by_unique(iterable: list) -> list[list]:
absfuyu/dxt/strext.py CHANGED
@@ -3,8 +3,8 @@ Absfuyu: Data Extension
3
3
  -----------------------
4
4
  str extension
5
5
 
6
- Version: 5.0.0
7
- Date updated: 11/02/2025 (dd/mm/yyyy)
6
+ Version: 5.1.0
7
+ Date updated: 10/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module Package
@@ -18,8 +18,8 @@ import random
18
18
  from typing import NotRequired, Self, TypedDict
19
19
 
20
20
  from absfuyu.core import ShowAllMethodsMixin, deprecated, versionadded, versionchanged
21
- from absfuyu.general.generator import Charset, Generator
22
21
  from absfuyu.logger import logger
22
+ from absfuyu.tools.generator import Charset, Generator
23
23
  from absfuyu.util import set_min_max
24
24
 
25
25
 
absfuyu/extra/__init__.py CHANGED
@@ -3,8 +3,8 @@ Absfuyu: Extra
3
3
  --------------
4
4
  Features that require additional libraries
5
5
 
6
- Version: 1.0.1
7
- Date updated: 24/11/2023 (dd/mm/yyyy)
6
+ Version: 5.1.0
7
+ Date updated: 10/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.0.0
7
- Date updated: 18/02/2025 (dd/mm/yyyy)
6
+ Version: 5.1.0
7
+ Date updated: 10/03/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module level
@@ -77,6 +77,7 @@ class PerformanceOutput(NamedTuple):
77
77
  return out
78
78
 
79
79
 
80
+ # TODO: header and footer layout to 1,2,3 instead of true false
80
81
  class BeautifulOutput:
81
82
  """A decorator that makes output more beautiful"""
82
83
 
@@ -0,0 +1,36 @@
1
+ """
2
+ Absfuyu: Data Analysis
3
+ ----------------------
4
+ Data Analyst
5
+
6
+ Version: 5.1.0
7
+ Date updated: 10/03/2025 (dd/mm/yyyy)
8
+ """
9
+
10
+ # Module level
11
+ # ---------------------------------------------------------------------------
12
+ __all__ = ["MatplotlibFormatString", "DADF"]
13
+
14
+
15
+ # Library
16
+ # ---------------------------------------------------------------------------
17
+ DA_MODE = False
18
+
19
+ try:
20
+ import numpy as np
21
+ import pandas as pd
22
+ except ImportError:
23
+ from subprocess import run
24
+
25
+ from absfuyu.config import ABSFUYU_CONFIG
26
+
27
+ if ABSFUYU_CONFIG._get_setting("auto-install-extra").value:
28
+ cmd = "python -m pip install -U absfuyu[full]".split()
29
+ run(cmd)
30
+ else:
31
+ raise SystemExit("This feature is in absfuyu[full] package") # noqa: B904
32
+ else:
33
+ DA_MODE = True
34
+
35
+ from absfuyu.extra.da.dadf import DADF
36
+ from absfuyu.extra.da.mplt import MatplotlibFormatString