absfuyu 5.1.0__py3-none-any.whl → 5.3.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.
- absfuyu/__init__.py +1 -1
- absfuyu/__main__.py +3 -3
- absfuyu/cli/__init__.py +1 -1
- absfuyu/cli/color.py +3 -3
- absfuyu/cli/config_group.py +2 -2
- absfuyu/cli/do_group.py +12 -2
- absfuyu/cli/game_group.py +2 -2
- absfuyu/cli/tool_group.py +2 -3
- absfuyu/config/__init__.py +1 -1
- absfuyu/core/__init__.py +1 -1
- absfuyu/core/baseclass.py +32 -2
- absfuyu/core/baseclass2.py +1 -1
- absfuyu/core/decorator.py +4 -4
- absfuyu/core/docstring.py +43 -25
- absfuyu/core/dummy_cli.py +1 -1
- absfuyu/core/dummy_func.py +4 -4
- absfuyu/dxt/__init__.py +1 -1
- absfuyu/dxt/dictext.py +5 -2
- absfuyu/dxt/dxt_support.py +1 -1
- absfuyu/dxt/intext.py +5 -2
- absfuyu/dxt/listext.py +405 -127
- absfuyu/dxt/strext.py +75 -15
- absfuyu/extra/__init__.py +1 -1
- absfuyu/extra/beautiful.py +1 -1
- absfuyu/extra/da/__init__.py +1 -1
- absfuyu/extra/da/dadf.py +56 -4
- absfuyu/extra/da/dadf_base.py +1 -1
- absfuyu/extra/da/df_func.py +1 -1
- absfuyu/extra/da/mplt.py +1 -1
- absfuyu/extra/data_analysis.py +3 -3
- absfuyu/fun/__init__.py +1 -1
- absfuyu/fun/tarot.py +1 -1
- absfuyu/game/__init__.py +1 -1
- absfuyu/game/game_stat.py +1 -1
- absfuyu/game/sudoku.py +1 -1
- absfuyu/game/tictactoe.py +2 -3
- absfuyu/game/wordle.py +1 -1
- absfuyu/general/__init__.py +1 -1
- absfuyu/general/content.py +2 -2
- absfuyu/general/human.py +1 -1
- absfuyu/general/shape.py +1 -1
- absfuyu/logger.py +1 -1
- absfuyu/pkg_data/__init__.py +1 -1
- absfuyu/pkg_data/deprecated.py +1 -1
- absfuyu/sort.py +1 -1
- absfuyu/tools/__init__.py +16 -13
- absfuyu/tools/checksum.py +2 -2
- absfuyu/tools/converter.py +29 -8
- absfuyu/tools/generator.py +251 -110
- absfuyu/tools/inspector.py +84 -40
- absfuyu/tools/keygen.py +1 -1
- absfuyu/tools/obfuscator.py +2 -2
- absfuyu/tools/passwordlib.py +3 -4
- absfuyu/tools/shutdownizer.py +1 -1
- absfuyu/tools/web.py +1 -1
- absfuyu/typings.py +136 -0
- absfuyu/util/__init__.py +18 -4
- absfuyu/util/api.py +36 -16
- absfuyu/util/json_method.py +43 -14
- absfuyu/util/lunar.py +1 -1
- absfuyu/util/path.py +158 -4
- absfuyu/util/performance.py +120 -5
- absfuyu/util/shorten_number.py +1 -1
- absfuyu/util/text_table.py +235 -45
- absfuyu/util/zipped.py +4 -3
- absfuyu/version.py +2 -2
- {absfuyu-5.1.0.dist-info → absfuyu-5.3.0.dist-info}/METADATA +1 -1
- absfuyu-5.3.0.dist-info/RECORD +76 -0
- absfuyu/core/typings.py +0 -40
- absfuyu-5.1.0.dist-info/RECORD +0 -76
- {absfuyu-5.1.0.dist-info → absfuyu-5.3.0.dist-info}/WHEEL +0 -0
- {absfuyu-5.1.0.dist-info → absfuyu-5.3.0.dist-info}/entry_points.txt +0 -0
- {absfuyu-5.1.0.dist-info → absfuyu-5.3.0.dist-info}/licenses/LICENSE +0 -0
absfuyu/util/json_method.py
CHANGED
|
@@ -3,8 +3,8 @@ Absfuyu: Json Method
|
|
|
3
3
|
--------------------
|
|
4
4
|
``.json`` file handling
|
|
5
5
|
|
|
6
|
-
Version: 5.
|
|
7
|
-
Date updated:
|
|
6
|
+
Version: 5.2.0
|
|
7
|
+
Date updated: 12/03/2025 (dd/mm/yyyy)
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
# Module level
|
|
@@ -16,7 +16,6 @@ __all__ = ["JsonFile"]
|
|
|
16
16
|
# ---------------------------------------------------------------------------
|
|
17
17
|
import json
|
|
18
18
|
from pathlib import Path
|
|
19
|
-
from typing import Any
|
|
20
19
|
|
|
21
20
|
from absfuyu.core import BaseClass
|
|
22
21
|
|
|
@@ -26,6 +25,20 @@ from absfuyu.core import BaseClass
|
|
|
26
25
|
class JsonFile(BaseClass):
|
|
27
26
|
"""
|
|
28
27
|
``.json`` file handling
|
|
28
|
+
|
|
29
|
+
Parameters
|
|
30
|
+
----------
|
|
31
|
+
json_file_location : str | Path
|
|
32
|
+
.json file location
|
|
33
|
+
|
|
34
|
+
encoding : str | None, optional
|
|
35
|
+
Data encoding, by default ``"utf-8"``
|
|
36
|
+
|
|
37
|
+
indent : int | str | None, optional
|
|
38
|
+
Indentation when export to json file, by default ``4``
|
|
39
|
+
|
|
40
|
+
sort_keys : bool, optional
|
|
41
|
+
Sort the keys before export to json file, by default ``True``
|
|
29
42
|
"""
|
|
30
43
|
|
|
31
44
|
def __init__(
|
|
@@ -37,26 +50,40 @@ class JsonFile(BaseClass):
|
|
|
37
50
|
sort_keys: bool = True,
|
|
38
51
|
) -> None:
|
|
39
52
|
"""
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
53
|
+
``.json`` file handling
|
|
54
|
+
|
|
55
|
+
Parameters
|
|
56
|
+
----------
|
|
57
|
+
json_file_location : str | Path
|
|
58
|
+
.json file location
|
|
59
|
+
|
|
60
|
+
encoding : str | None, optional
|
|
61
|
+
Data encoding, by default ``"utf-8"``
|
|
62
|
+
|
|
63
|
+
indent : int | str | None, optional
|
|
64
|
+
Indentation when export to json file, by default ``4``
|
|
65
|
+
|
|
66
|
+
sort_keys : bool, optional
|
|
67
|
+
Sort the keys before export to json file, by default ``True``
|
|
44
68
|
"""
|
|
69
|
+
|
|
45
70
|
self.json_file_location = Path(json_file_location)
|
|
46
71
|
self.encoding = encoding
|
|
47
72
|
self.indent = indent
|
|
48
73
|
self.sort_keys = sort_keys
|
|
49
|
-
self.data: dict
|
|
74
|
+
self.data: dict = {}
|
|
50
75
|
|
|
51
76
|
def __str__(self) -> str:
|
|
52
77
|
return f"{self.__class__.__name__}({self.json_file_location.name})"
|
|
53
78
|
|
|
54
|
-
def load_json(self) -> dict
|
|
79
|
+
def load_json(self) -> dict:
|
|
55
80
|
"""
|
|
56
81
|
Load ``.json`` file
|
|
57
82
|
|
|
58
|
-
|
|
59
|
-
|
|
83
|
+
Returns
|
|
84
|
+
-------
|
|
85
|
+
dict
|
|
86
|
+
``.json`` data
|
|
60
87
|
"""
|
|
61
88
|
with open(self.json_file_location, "r", encoding=self.encoding) as file:
|
|
62
89
|
self.data = json.load(file)
|
|
@@ -68,11 +95,13 @@ class JsonFile(BaseClass):
|
|
|
68
95
|
with open(self.json_file_location, "w", encoding=self.encoding) as file:
|
|
69
96
|
file.writelines(json_data)
|
|
70
97
|
|
|
71
|
-
def update_data(self, data: dict
|
|
98
|
+
def update_data(self, data: dict) -> None:
|
|
72
99
|
"""
|
|
73
100
|
Update ``.json`` data without save
|
|
74
101
|
|
|
75
|
-
|
|
76
|
-
|
|
102
|
+
Parameters
|
|
103
|
+
----------
|
|
104
|
+
data : dict
|
|
105
|
+
``.json`` data
|
|
77
106
|
"""
|
|
78
107
|
self.data = data
|
absfuyu/util/lunar.py
CHANGED
absfuyu/util/path.py
CHANGED
|
@@ -3,8 +3,8 @@ Absfuyu: Path
|
|
|
3
3
|
-------------
|
|
4
4
|
Path related
|
|
5
5
|
|
|
6
|
-
Version: 5.
|
|
7
|
-
Date updated:
|
|
6
|
+
Version: 5.2.0
|
|
7
|
+
Date updated: 14/03/2025 (dd/mm/yyyy)
|
|
8
8
|
|
|
9
9
|
Feature:
|
|
10
10
|
--------
|
|
@@ -46,6 +46,128 @@ from absfuyu.core.decorator import add_subclass_methods_decorator
|
|
|
46
46
|
from absfuyu.core.docstring import deprecated, versionadded, versionchanged
|
|
47
47
|
from absfuyu.logger import logger
|
|
48
48
|
|
|
49
|
+
# Template
|
|
50
|
+
# ---------------------------------------------------------------------------
|
|
51
|
+
ORGANIZE_TEMPLATE: dict[str, list[str]] = {
|
|
52
|
+
"Code": [".ps1", ".py", ".rs", ".js", ".c", ".h", ".cpp", ".r", ".cmd", ".bat"],
|
|
53
|
+
"Comic": [".cbz", ".cbr", ".cb7", ".cbt", ".cba"],
|
|
54
|
+
"Compressed": [
|
|
55
|
+
".7z",
|
|
56
|
+
".zip",
|
|
57
|
+
".rar",
|
|
58
|
+
".apk",
|
|
59
|
+
".cab",
|
|
60
|
+
".tar",
|
|
61
|
+
".tgz",
|
|
62
|
+
".txz",
|
|
63
|
+
".bz2",
|
|
64
|
+
".gz",
|
|
65
|
+
".lz",
|
|
66
|
+
".lz4",
|
|
67
|
+
".lzma",
|
|
68
|
+
".xz",
|
|
69
|
+
".zipx",
|
|
70
|
+
".zst",
|
|
71
|
+
],
|
|
72
|
+
"Documents": [".docx", ".doc", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt"],
|
|
73
|
+
"Ebook": [
|
|
74
|
+
".epub",
|
|
75
|
+
".mobi",
|
|
76
|
+
".prc",
|
|
77
|
+
".lrf",
|
|
78
|
+
".lrx",
|
|
79
|
+
".pdb",
|
|
80
|
+
".azw",
|
|
81
|
+
".azw3",
|
|
82
|
+
".kf8",
|
|
83
|
+
".kfx",
|
|
84
|
+
".opf",
|
|
85
|
+
],
|
|
86
|
+
"Music": [".mp3", ".flac", ".wav", ".m4a", ".wma", ".aac", ".alac", ".aiff"],
|
|
87
|
+
"OS": [".iso", ".dmg", ".wim"],
|
|
88
|
+
"Pictures": [
|
|
89
|
+
".jpg",
|
|
90
|
+
".jpeg",
|
|
91
|
+
".png",
|
|
92
|
+
".apng",
|
|
93
|
+
".avif",
|
|
94
|
+
".bmp",
|
|
95
|
+
".gif",
|
|
96
|
+
".jfif",
|
|
97
|
+
".pjpeg",
|
|
98
|
+
".pjp",
|
|
99
|
+
".svg",
|
|
100
|
+
".ico",
|
|
101
|
+
".cur",
|
|
102
|
+
".tif",
|
|
103
|
+
".tiff",
|
|
104
|
+
".webp",
|
|
105
|
+
],
|
|
106
|
+
"Programs": [".exe", ".msi"],
|
|
107
|
+
"Video": [
|
|
108
|
+
".3g2",
|
|
109
|
+
".3gp",
|
|
110
|
+
".avi",
|
|
111
|
+
".flv",
|
|
112
|
+
".m2ts",
|
|
113
|
+
".m4v",
|
|
114
|
+
".mkv",
|
|
115
|
+
".mov",
|
|
116
|
+
".mp4",
|
|
117
|
+
".mpeg",
|
|
118
|
+
".mpv",
|
|
119
|
+
".mts",
|
|
120
|
+
".ts",
|
|
121
|
+
".vob",
|
|
122
|
+
".webm",
|
|
123
|
+
],
|
|
124
|
+
"Raw pictures": [
|
|
125
|
+
".3fr",
|
|
126
|
+
".ari",
|
|
127
|
+
".arw",
|
|
128
|
+
".bay",
|
|
129
|
+
".braw",
|
|
130
|
+
".crw",
|
|
131
|
+
".cr2",
|
|
132
|
+
".cr3",
|
|
133
|
+
".cap",
|
|
134
|
+
".data",
|
|
135
|
+
".dcs",
|
|
136
|
+
".dcr",
|
|
137
|
+
".dng",
|
|
138
|
+
".drf",
|
|
139
|
+
".eip",
|
|
140
|
+
".erf",
|
|
141
|
+
".fff",
|
|
142
|
+
".gpr",
|
|
143
|
+
".iiq",
|
|
144
|
+
".k25",
|
|
145
|
+
".kdc",
|
|
146
|
+
".mdc",
|
|
147
|
+
".mef",
|
|
148
|
+
".mos",
|
|
149
|
+
".mrw",
|
|
150
|
+
".nef",
|
|
151
|
+
".nrw",
|
|
152
|
+
".obm",
|
|
153
|
+
".orf",
|
|
154
|
+
".pef",
|
|
155
|
+
".ptx",
|
|
156
|
+
".pxn",
|
|
157
|
+
".r3d",
|
|
158
|
+
".raf",
|
|
159
|
+
".raw",
|
|
160
|
+
".rwl",
|
|
161
|
+
".rw2",
|
|
162
|
+
".rwz",
|
|
163
|
+
".sr2",
|
|
164
|
+
".srf",
|
|
165
|
+
".srw",
|
|
166
|
+
".tif",
|
|
167
|
+
".x3f",
|
|
168
|
+
],
|
|
169
|
+
}
|
|
170
|
+
|
|
49
171
|
|
|
50
172
|
# Support Class
|
|
51
173
|
# ---------------------------------------------------------------------------
|
|
@@ -444,10 +566,42 @@ class DirectoryArchiverMixin(DirectoryBase):
|
|
|
444
566
|
|
|
445
567
|
class DirectoryOrganizerMixin(DirectoryBase):
|
|
446
568
|
"""
|
|
447
|
-
Directory - File organizer
|
|
569
|
+
Directory - File organizer
|
|
570
|
+
|
|
571
|
+
- Organize
|
|
448
572
|
"""
|
|
449
573
|
|
|
450
|
-
|
|
574
|
+
@versionadded("5.3.0")
|
|
575
|
+
def organize(self, dirtemplate: dict[str, list[str]] | None = None) -> None:
|
|
576
|
+
"""
|
|
577
|
+
Organize a directory.
|
|
578
|
+
|
|
579
|
+
Parameters
|
|
580
|
+
----------
|
|
581
|
+
dirtemplate : dict[str, Collection[str]] | None, optional
|
|
582
|
+
| Template to move file to, by default ``None``.
|
|
583
|
+
| Example: {"Documents": [".txt", ".pdf", ...]}
|
|
584
|
+
"""
|
|
585
|
+
if dirtemplate is None:
|
|
586
|
+
template = ORGANIZE_TEMPLATE
|
|
587
|
+
else:
|
|
588
|
+
template = dirtemplate
|
|
589
|
+
|
|
590
|
+
other_dir = self.source_path.joinpath("Others")
|
|
591
|
+
other_dir.mkdir(parents=True, exist_ok=True)
|
|
592
|
+
|
|
593
|
+
for path in self.source_path.iterdir():
|
|
594
|
+
if path.is_dir():
|
|
595
|
+
continue
|
|
596
|
+
|
|
597
|
+
for dir_name, suffixes in template.items():
|
|
598
|
+
if path.suffix.lower() in suffixes:
|
|
599
|
+
move_path = self.source_path.joinpath(dir_name)
|
|
600
|
+
move_path.mkdir(parents=True, exist_ok=True)
|
|
601
|
+
path.rename(move_path.joinpath(path.name))
|
|
602
|
+
break
|
|
603
|
+
else:
|
|
604
|
+
path.rename(other_dir.joinpath(path.name))
|
|
451
605
|
|
|
452
606
|
|
|
453
607
|
class DirectoryTreeMixin(DirectoryBase):
|
absfuyu/util/performance.py
CHANGED
|
@@ -3,8 +3,8 @@ Absfuyu: Performance
|
|
|
3
3
|
--------------------
|
|
4
4
|
Performance Check
|
|
5
5
|
|
|
6
|
-
Version: 5.
|
|
7
|
-
Date updated:
|
|
6
|
+
Version: 5.2.0
|
|
7
|
+
Date updated: 15/03/2025 (dd/mm/yyyy)
|
|
8
8
|
|
|
9
9
|
Feature:
|
|
10
10
|
--------
|
|
@@ -20,6 +20,7 @@ Feature:
|
|
|
20
20
|
__all__ = [
|
|
21
21
|
# Wrapper
|
|
22
22
|
"function_debug",
|
|
23
|
+
"function_benchmark",
|
|
23
24
|
"measure_performance",
|
|
24
25
|
"retry",
|
|
25
26
|
# Class
|
|
@@ -32,12 +33,12 @@ __all__ = [
|
|
|
32
33
|
import time
|
|
33
34
|
import tracemalloc
|
|
34
35
|
from collections.abc import Callable
|
|
36
|
+
from dataclasses import dataclass
|
|
35
37
|
from functools import wraps
|
|
36
38
|
from inspect import getsource
|
|
37
|
-
from typing import Any, ParamSpec, TypeVar
|
|
39
|
+
from typing import Any, Literal, ParamSpec, TypeVar, overload
|
|
38
40
|
|
|
39
41
|
from absfuyu.core import deprecated, versionadded, versionchanged
|
|
40
|
-
from absfuyu.dxt import ListNoDunder
|
|
41
42
|
|
|
42
43
|
# Type
|
|
43
44
|
# ---------------------------------------------------------------------------
|
|
@@ -45,6 +46,30 @@ P = ParamSpec("P") # Parameter type
|
|
|
45
46
|
R = TypeVar("R") # Return type
|
|
46
47
|
|
|
47
48
|
|
|
49
|
+
# Support
|
|
50
|
+
# ---------------------------------------------------------------------------
|
|
51
|
+
@dataclass
|
|
52
|
+
class BenchmarkResult:
|
|
53
|
+
"""
|
|
54
|
+
Use ``format(BenchmarkResult(...), "seconds")`` to view result in seconds.
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
min_: float
|
|
58
|
+
max_: float
|
|
59
|
+
avg: float
|
|
60
|
+
|
|
61
|
+
def __format__(self, format_spec: str) -> str:
|
|
62
|
+
clsname = self.__class__.__name__
|
|
63
|
+
if format_spec.lower().strip().startswith("seconds"):
|
|
64
|
+
fields = [f"{x}={getattr(self, x):,.6f}s" for x in self._get_fields()]
|
|
65
|
+
return f"{clsname}({', '.join(fields)})"
|
|
66
|
+
return repr(self)
|
|
67
|
+
|
|
68
|
+
@classmethod
|
|
69
|
+
def _get_fields(cls) -> tuple[str, ...]:
|
|
70
|
+
return tuple(cls.__dataclass_fields__)
|
|
71
|
+
|
|
72
|
+
|
|
48
73
|
# Function
|
|
49
74
|
# ---------------------------------------------------------------------------
|
|
50
75
|
@versionchanged("3.2.0", reason="Updated functionality")
|
|
@@ -108,6 +133,96 @@ def measure_performance(f: Callable[P, R]) -> Callable[P, R]:
|
|
|
108
133
|
return wrapper
|
|
109
134
|
|
|
110
135
|
|
|
136
|
+
@overload
|
|
137
|
+
def function_benchmark(func: Callable[P, R], /) -> Callable[P, R]: ...
|
|
138
|
+
@overload
|
|
139
|
+
def function_benchmark(*, n: int = 1) -> Callable[[Callable[P, R]], Callable[P, R]]: ...
|
|
140
|
+
@overload
|
|
141
|
+
def function_benchmark(
|
|
142
|
+
*, n: int = 1, result_only: Literal[False] = False
|
|
143
|
+
) -> Callable[[Callable[P, R]], Callable[P, R]]: ...
|
|
144
|
+
@overload
|
|
145
|
+
def function_benchmark(
|
|
146
|
+
*, n: int = 1, result_only: Literal[True] = ...
|
|
147
|
+
) -> Callable[[Callable[P, R]], Callable[P, BenchmarkResult]]: ...
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
@versionadded("5.2.0")
|
|
151
|
+
def function_benchmark(
|
|
152
|
+
func: Callable[P, R] | None = None, /, *, n: int = 1, result_only: bool = False
|
|
153
|
+
):
|
|
154
|
+
"""
|
|
155
|
+
This run function for ``n`` times and calculate min, max, average runtime.
|
|
156
|
+
|
|
157
|
+
Parameters
|
|
158
|
+
----------
|
|
159
|
+
func : Callable[P, R] | None, optional
|
|
160
|
+
Callable with parameter **P and returns R, by default ``None``
|
|
161
|
+
|
|
162
|
+
n : int, optional
|
|
163
|
+
Run how many times, by default ``1``
|
|
164
|
+
|
|
165
|
+
result_only : bool, optional
|
|
166
|
+
Returns BenchmarkResult instead of ``func`` result, by default ``False``
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
Usage
|
|
170
|
+
-----
|
|
171
|
+
Use this as a decorator (``@function_benchmark``)
|
|
172
|
+
|
|
173
|
+
Example:
|
|
174
|
+
--------
|
|
175
|
+
>>> @function_benchmark
|
|
176
|
+
>>> def test():
|
|
177
|
+
... return 1 + 1
|
|
178
|
+
>>> test()
|
|
179
|
+
BenchmarkResult(min_=0.000000s, max_=0.000000s, avg=0.000000s)
|
|
180
|
+
2
|
|
181
|
+
|
|
182
|
+
>>> @function_benchmark(n=1)
|
|
183
|
+
>>> def test():
|
|
184
|
+
... return 1 + 1
|
|
185
|
+
>>> test()
|
|
186
|
+
BenchmarkResult(min_=0.000000s, max_=0.000000s, avg=0.000000s)
|
|
187
|
+
2
|
|
188
|
+
"""
|
|
189
|
+
|
|
190
|
+
times = max(n, 1)
|
|
191
|
+
|
|
192
|
+
def decorator(f: Callable[P, R]) -> Callable[P, R | BenchmarkResult]:
|
|
193
|
+
@wraps(f)
|
|
194
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> R | BenchmarkResult:
|
|
195
|
+
output = f(*args, **kwargs) # Run function and save result into a variable
|
|
196
|
+
|
|
197
|
+
def _run() -> float:
|
|
198
|
+
# Performance check
|
|
199
|
+
start_time = time.perf_counter() # Start time measure
|
|
200
|
+
f(*args, **kwargs)
|
|
201
|
+
finish_time = time.perf_counter() # Get finished time
|
|
202
|
+
return finish_time - start_time
|
|
203
|
+
|
|
204
|
+
# run = (_run() for _ in range(times))
|
|
205
|
+
run = [_run() for _ in range(times)]
|
|
206
|
+
try:
|
|
207
|
+
avg_runtime = sum(run) / len(run)
|
|
208
|
+
except ZeroDivisionError:
|
|
209
|
+
avg_runtime = min(run)
|
|
210
|
+
result = BenchmarkResult(min(run), max(run), avg_runtime)
|
|
211
|
+
|
|
212
|
+
if result_only:
|
|
213
|
+
return result
|
|
214
|
+
|
|
215
|
+
print(format(result, "seconds"))
|
|
216
|
+
|
|
217
|
+
return output
|
|
218
|
+
|
|
219
|
+
return wrapper
|
|
220
|
+
|
|
221
|
+
if func is None:
|
|
222
|
+
return decorator
|
|
223
|
+
return decorator(func)
|
|
224
|
+
|
|
225
|
+
|
|
111
226
|
@versionadded("3.2.0")
|
|
112
227
|
def function_debug(f: Callable[P, R]) -> Callable[P, R]:
|
|
113
228
|
"""
|
|
@@ -284,7 +399,7 @@ class Checker:
|
|
|
284
399
|
def dir_(self) -> list[str]:
|
|
285
400
|
"""``dir()`` of variable"""
|
|
286
401
|
# return self.item_to_check.__dir__()
|
|
287
|
-
return
|
|
402
|
+
return [x for x in dir(self.item_to_check) if not x.startswith("__")]
|
|
288
403
|
|
|
289
404
|
@property
|
|
290
405
|
def source(self) -> str | None:
|