absfuyu 5.0.0__py3-none-any.whl → 6.1.2__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 (103) hide show
  1. absfuyu/__init__.py +5 -3
  2. absfuyu/__main__.py +3 -3
  3. absfuyu/cli/__init__.py +13 -2
  4. absfuyu/cli/audio_group.py +98 -0
  5. absfuyu/cli/color.py +30 -14
  6. absfuyu/cli/config_group.py +9 -2
  7. absfuyu/cli/do_group.py +23 -6
  8. absfuyu/cli/game_group.py +27 -2
  9. absfuyu/cli/tool_group.py +81 -11
  10. absfuyu/config/__init__.py +3 -3
  11. absfuyu/core/__init__.py +12 -8
  12. absfuyu/core/baseclass.py +929 -96
  13. absfuyu/core/baseclass2.py +44 -3
  14. absfuyu/core/decorator.py +70 -4
  15. absfuyu/core/docstring.py +64 -41
  16. absfuyu/core/dummy_cli.py +3 -3
  17. absfuyu/core/dummy_func.py +19 -6
  18. absfuyu/dxt/__init__.py +2 -2
  19. absfuyu/dxt/base_type.py +93 -0
  20. absfuyu/dxt/dictext.py +204 -16
  21. absfuyu/dxt/dxt_support.py +2 -2
  22. absfuyu/dxt/intext.py +151 -34
  23. absfuyu/dxt/listext.py +969 -127
  24. absfuyu/dxt/strext.py +77 -17
  25. absfuyu/extra/__init__.py +2 -2
  26. absfuyu/extra/audio/__init__.py +8 -0
  27. absfuyu/extra/audio/_util.py +57 -0
  28. absfuyu/extra/audio/convert.py +192 -0
  29. absfuyu/extra/audio/lossless.py +281 -0
  30. absfuyu/extra/beautiful.py +3 -2
  31. absfuyu/extra/da/__init__.py +72 -0
  32. absfuyu/extra/da/dadf.py +1600 -0
  33. absfuyu/extra/da/dadf_base.py +186 -0
  34. absfuyu/extra/da/df_func.py +181 -0
  35. absfuyu/extra/da/mplt.py +219 -0
  36. absfuyu/extra/ggapi/__init__.py +8 -0
  37. absfuyu/extra/ggapi/gdrive.py +223 -0
  38. absfuyu/extra/ggapi/glicense.py +148 -0
  39. absfuyu/extra/ggapi/glicense_df.py +186 -0
  40. absfuyu/extra/ggapi/gsheet.py +88 -0
  41. absfuyu/extra/img/__init__.py +30 -0
  42. absfuyu/extra/img/converter.py +402 -0
  43. absfuyu/extra/img/dup_check.py +291 -0
  44. absfuyu/extra/pdf.py +87 -0
  45. absfuyu/extra/rclone.py +253 -0
  46. absfuyu/extra/xml.py +90 -0
  47. absfuyu/fun/__init__.py +7 -20
  48. absfuyu/fun/rubik.py +442 -0
  49. absfuyu/fun/tarot.py +2 -2
  50. absfuyu/game/__init__.py +2 -2
  51. absfuyu/game/game_stat.py +2 -2
  52. absfuyu/game/schulte.py +78 -0
  53. absfuyu/game/sudoku.py +2 -2
  54. absfuyu/game/tictactoe.py +2 -3
  55. absfuyu/game/wordle.py +6 -4
  56. absfuyu/general/__init__.py +4 -4
  57. absfuyu/general/content.py +4 -4
  58. absfuyu/general/human.py +2 -2
  59. absfuyu/general/resrel.py +213 -0
  60. absfuyu/general/shape.py +3 -8
  61. absfuyu/general/tax.py +344 -0
  62. absfuyu/logger.py +806 -59
  63. absfuyu/numbers/__init__.py +13 -0
  64. absfuyu/numbers/number_to_word.py +321 -0
  65. absfuyu/numbers/shorten_number.py +303 -0
  66. absfuyu/numbers/time_duration.py +217 -0
  67. absfuyu/pkg_data/__init__.py +2 -2
  68. absfuyu/pkg_data/deprecated.py +2 -2
  69. absfuyu/pkg_data/logo.py +1462 -0
  70. absfuyu/sort.py +4 -4
  71. absfuyu/tools/__init__.py +28 -2
  72. absfuyu/tools/checksum.py +144 -9
  73. absfuyu/tools/converter.py +120 -34
  74. absfuyu/tools/generator.py +461 -0
  75. absfuyu/tools/inspector.py +752 -0
  76. absfuyu/tools/keygen.py +2 -2
  77. absfuyu/tools/obfuscator.py +47 -9
  78. absfuyu/tools/passwordlib.py +89 -25
  79. absfuyu/tools/shutdownizer.py +3 -8
  80. absfuyu/tools/sw.py +718 -0
  81. absfuyu/tools/web.py +10 -13
  82. absfuyu/typings.py +138 -0
  83. absfuyu/util/__init__.py +114 -6
  84. absfuyu/util/api.py +41 -18
  85. absfuyu/util/cli.py +119 -0
  86. absfuyu/util/gui.py +91 -0
  87. absfuyu/util/json_method.py +43 -14
  88. absfuyu/util/lunar.py +2 -2
  89. absfuyu/util/package.py +124 -0
  90. absfuyu/util/path.py +702 -82
  91. absfuyu/util/performance.py +122 -7
  92. absfuyu/util/shorten_number.py +244 -21
  93. absfuyu/util/text_table.py +481 -0
  94. absfuyu/util/zipped.py +8 -7
  95. absfuyu/version.py +79 -59
  96. {absfuyu-5.0.0.dist-info → absfuyu-6.1.2.dist-info}/METADATA +52 -11
  97. absfuyu-6.1.2.dist-info/RECORD +105 -0
  98. {absfuyu-5.0.0.dist-info → absfuyu-6.1.2.dist-info}/WHEEL +1 -1
  99. absfuyu/extra/data_analysis.py +0 -1078
  100. absfuyu/general/generator.py +0 -303
  101. absfuyu-5.0.0.dist-info/RECORD +0 -68
  102. {absfuyu-5.0.0.dist-info → absfuyu-6.1.2.dist-info}/entry_points.txt +0 -0
  103. {absfuyu-5.0.0.dist-info → absfuyu-6.1.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,752 @@
1
+ """
2
+ Absfuyu: Inspector
3
+ ------------------
4
+ Inspector
5
+
6
+ Version: 6.1.1
7
+ Date updated: 30/12/2025 (dd/mm/yyyy)
8
+ """
9
+
10
+ # Module level
11
+ # ---------------------------------------------------------------------------
12
+ __all__ = ["Inspector", "inspect_all"]
13
+
14
+
15
+ # Library
16
+ # ---------------------------------------------------------------------------
17
+ import inspect as _inspect
18
+ import os
19
+ from collections.abc import Callable
20
+ from dataclasses import dataclass
21
+ from functools import partial
22
+ from textwrap import TextWrapper
23
+ from textwrap import shorten as text_shorten
24
+ from typing import Any, Literal, Protocol, get_overloads, overload
25
+
26
+ from absfuyu.core.baseclass import (
27
+ AutoREPRMixin,
28
+ BaseDataclass,
29
+ ClassMembers,
30
+ ClassMembersResult,
31
+ GetClassMembersMixin,
32
+ )
33
+ from absfuyu.dxt.listext import ListExt
34
+ from absfuyu.typings import P, R
35
+ from absfuyu.util.text_table import BoxStyle, OneColumnTableMaker
36
+
37
+
38
+ # TODO: rewrite with each class for docs, method, property, attr, param, title
39
+ # Dataclass
40
+ # ---------------------------------------------------------------------------
41
+ @dataclass
42
+ class BaseDCInspect(BaseDataclass):
43
+ def _make_repr(self) -> str | None:
44
+ fields = self._get_fields()
45
+ if 0 < len(fields) < 2:
46
+ return repr(getattr(self, fields[0]))
47
+ return None
48
+
49
+ def _long_list_terminal_size(
50
+ self, long_list: list[str], width: int = 80, /
51
+ ) -> list[str]:
52
+ ll = ListExt(long_list).wrap_to_column(width, margin=4, transpose=True)
53
+ return list(ll)
54
+
55
+
56
+ @dataclass
57
+ class _TitleSignature:
58
+ """
59
+ Inspector:
60
+ Object's title and signature
61
+ """
62
+
63
+ title: str
64
+ signature: list[str]
65
+
66
+ def make_output(self):
67
+ pass
68
+
69
+
70
+ @dataclass
71
+ class _Docstring(BaseDCInspect):
72
+ """
73
+ Inspector:
74
+ Object's docstring
75
+ """
76
+
77
+ docs: str
78
+
79
+ def __repr__(self) -> str:
80
+ r = self._make_repr()
81
+ if r is not None:
82
+ return r
83
+ return super().__repr__()
84
+
85
+ def _get_first_paragraph(self) -> str:
86
+ # Get docs and get first paragraph
87
+ doc_lines = []
88
+ for line in self.docs.splitlines():
89
+ if len(line) < 1:
90
+ break
91
+ doc_lines.append(line.strip())
92
+ return " ".join(doc_lines)
93
+
94
+ def make_output(self) -> list[str]:
95
+ if len(self._get_first_paragraph()) > 0:
96
+ return ["Docstring:", self._get_first_paragraph()]
97
+ return [""]
98
+
99
+
100
+ @dataclass
101
+ class _MRO(BaseDCInspect):
102
+ """
103
+ Inspector:
104
+ Object's MRO, bases
105
+ """
106
+
107
+ mro: tuple[type, ...]
108
+
109
+ def __repr__(self) -> str:
110
+ r = self._make_repr()
111
+ if r is not None:
112
+ return r
113
+ return super().__repr__()
114
+
115
+ def _make_output(self) -> list[str]:
116
+ out = [
117
+ f"- {i:02}. {x.__module__}.{x.__name__}"
118
+ for i, x in enumerate(self.mro[1:], start=1)
119
+ ]
120
+ # ListExt.wrap_to_column
121
+ return out
122
+
123
+ def make_output(self, *, width: int = 80) -> list[str]:
124
+ out = self._make_output()
125
+ if len(out) > 0:
126
+ out_ = self._long_list_terminal_size(out, width)
127
+ return ["", f"Bases (Len: {len(out)}):", *out_]
128
+ return [""]
129
+
130
+
131
+ @dataclass
132
+ class _Member(BaseDCInspect):
133
+ """
134
+ Inspector:
135
+ Object's member
136
+ """
137
+
138
+ member: ClassMembers
139
+
140
+ def __repr__(self) -> str:
141
+ r = self._make_repr()
142
+ if r is not None:
143
+ return r
144
+ return super().__repr__()
145
+
146
+ def make_output(
147
+ self,
148
+ *,
149
+ width: int = 80,
150
+ obj,
151
+ include_method: bool = True,
152
+ include_property: bool = True,
153
+ ) -> list[str]:
154
+ mems = self.member.pack().sort()
155
+ body: list[str] = []
156
+
157
+ if include_method:
158
+ ml = [text_shorten(f"- {x}", width - 4) for x in mems.methods]
159
+ if len(ml) > 0:
160
+ head = ["", f"Methods (Len: {len(ml)}):"]
161
+ head.extend(self._long_list_terminal_size(ml, width))
162
+ body.extend(head)
163
+
164
+ if include_property:
165
+ pl = [
166
+ text_shorten(f"- {x} = {getattr(obj, x, None)}", width - 4)
167
+ for x in mems.properties
168
+ ]
169
+ if len(pl) > 0:
170
+ head = ["", f"Properties (Len: {len(pl)}):"]
171
+ head.extend(self._long_list_terminal_size(pl, width))
172
+ body.extend(head)
173
+
174
+ if len(body) > 0:
175
+ return body
176
+ return [""]
177
+
178
+
179
+ class InspectComponents(Protocol):
180
+ """Supports make_output() -> list[str]"""
181
+
182
+ @overload
183
+ def make_output(self) -> list[str]: ...
184
+ @overload
185
+ def make_output(self, *, width: int = ...) -> list[str]: ...
186
+ def make_output(self, *args, **kwargs) -> list[str]: ...
187
+
188
+
189
+ # Class
190
+ # ---------------------------------------------------------------------------
191
+ class Inspector(AutoREPRMixin):
192
+ """
193
+ Inspect an object.
194
+ By default shows object's docstring and attribute (if any).
195
+
196
+ Parameters
197
+ ----------
198
+ obj : Any
199
+ Object to inspect
200
+
201
+ line_length: int | None
202
+ Number of cols in inspect output (Split line every line_length).
203
+ Set to ``None`` to use ``os.get_terminal_size()``, by default ``None``
204
+
205
+ include_docs : bool, optional
206
+ Include docstring, by default ``True``
207
+
208
+ include_mro : bool, optional
209
+ Include class bases (__mro__), by default ``False``
210
+
211
+ include_method : bool, optional
212
+ Include object's methods (if any), by default ``False``
213
+
214
+ include_property : bool, optional
215
+ Include object's properties (if any), by default ``False``
216
+
217
+ include_attribute : bool, optional
218
+ Include object's attributes (if any), by default ``True``
219
+
220
+ include_private : bool, optional
221
+ Include object's private attributes, by default ``False``
222
+
223
+ include_all : bool, optional
224
+ Include all infomation availble, by default ``False``
225
+
226
+ max_textwrap_lines : int, optional
227
+ Maximum lines for the output's header (class, signature, repr).
228
+ Must be >= 1, by default ``8``
229
+
230
+ style : BoxStyle, optional
231
+ Style for the table, by default ``"normal"``
232
+
233
+
234
+ Example:
235
+ --------
236
+ >>> print(Inspector(<object>, **kwargs))
237
+ """
238
+
239
+ @overload
240
+ def __init__(self, obj: Any) -> None: ...
241
+
242
+ @overload
243
+ def __init__(self, obj: Any, *, include_all: Literal[True] = ...) -> None: ...
244
+
245
+ @overload
246
+ def __init__(
247
+ self,
248
+ obj: Any,
249
+ *,
250
+ line_length: int | None = None,
251
+ include_docs: bool = True,
252
+ include_mro: bool = False,
253
+ include_method: bool = False,
254
+ include_property: bool = False,
255
+ include_attribute: bool = True,
256
+ include_private: bool = False,
257
+ max_textwrap_lines: int = 8,
258
+ style: BoxStyle = "normal",
259
+ ) -> None: ...
260
+
261
+ def __init__(
262
+ self,
263
+ obj: Any,
264
+ *,
265
+ # Line length
266
+ line_length: int | None = None,
267
+ line_length_offset: int = 0, # line_length += line_length_offset (when line_length=None)
268
+ max_textwrap_lines: int = 8,
269
+ # Include
270
+ include_docs: bool = True,
271
+ include_mro: bool = False,
272
+ include_method: bool = False,
273
+ include_property: bool = False,
274
+ include_attribute: bool = True,
275
+ include_dunder: bool = False,
276
+ include_private: bool = False,
277
+ include_all: bool = False,
278
+ # Style
279
+ style: BoxStyle = "normal",
280
+ ) -> None:
281
+ """
282
+ Inspect an object.
283
+ By default shows object's docstring and attribute (if any).
284
+
285
+ Parameters
286
+ ----------
287
+ obj : Any
288
+ Object to inspect
289
+
290
+ line_length: int | None
291
+ Number of cols in inspect output (Split line every line_length).
292
+ Set to ``None`` to use ``os.get_terminal_size()``, by default ``None``
293
+
294
+ include_docs : bool, optional
295
+ Include docstring, by default ``True``
296
+
297
+ include_mro : bool, optional
298
+ Include class bases (__mro__), by default ``False``
299
+
300
+ include_method : bool, optional
301
+ Include object's methods (if any), by default ``False``
302
+
303
+ include_property : bool, optional
304
+ Include object's properties (if any), by default ``False``
305
+
306
+ include_attribute : bool, optional
307
+ Include object's attributes (if any), by default ``True``
308
+
309
+ include_private : bool, optional
310
+ Include object's private attributes, by default ``False``
311
+
312
+ include_all : bool, optional
313
+ Include all infomation availble, by default ``False``
314
+
315
+ max_textwrap_lines : int, optional
316
+ Maximum lines for the output's header (class, signature, repr).
317
+ Must be >= 1, by default ``8``
318
+
319
+ style : BoxStyle | Literal["normal", "bold", "dashed", "double", "rounded", ...], optional
320
+ Style for the table, by default ``"normal"``
321
+
322
+
323
+ Example:
324
+ --------
325
+ >>> print(Inspector(<object>, **kwargs))
326
+ """
327
+ self.obj = obj
328
+ self.include_docs = include_docs
329
+ self.include_mro = include_mro
330
+ self.include_method = include_method
331
+ self.include_property = include_property
332
+ self.include_attribute = include_attribute
333
+ self.include_private = include_private
334
+ self.include_dunder = include_dunder
335
+ self._style = style
336
+
337
+ if include_all:
338
+ self.include_docs = True
339
+ self.include_mro = True
340
+ self.include_method = True
341
+ self.include_property = True
342
+ self.include_attribute = True
343
+ self.include_private = True
344
+
345
+ # Setup line length
346
+ if line_length is None:
347
+ try:
348
+ self._linelength = os.get_terminal_size().columns + line_length_offset
349
+ except OSError:
350
+ self._linelength = 88
351
+ elif isinstance(line_length, (int, float)):
352
+ self._linelength = max(int(line_length), 9)
353
+ else:
354
+ raise ValueError("Use different line_length")
355
+
356
+ # Textwrap
357
+ self._text_wrapper = TextWrapper(
358
+ width=self._linelength - 4,
359
+ initial_indent="",
360
+ subsequent_indent="",
361
+ tabsize=4,
362
+ break_long_words=True,
363
+ max_lines=max(max_textwrap_lines, 1),
364
+ )
365
+
366
+ # Output
367
+ self._inspect_output = self._make_output()
368
+
369
+ def __str__(self) -> str:
370
+ return self._inspect_output.make_table()
371
+
372
+ # 00. Support
373
+ # -----------------------------------------------------------
374
+ # @deprecated
375
+ def _long_list_terminal_size(self, long_list: list) -> list:
376
+ ll = ListExt(long_list).wrap_to_column(
377
+ self._linelength, margin=4, transpose=True
378
+ )
379
+ return list(ll)
380
+
381
+ # 01. Signature
382
+ # -----------------------------------------------------------
383
+ def _make_title(self) -> str:
384
+ title_str = (
385
+ str(self.obj)
386
+ if (
387
+ _inspect.isclass(self.obj)
388
+ or callable(self.obj)
389
+ or _inspect.ismodule(self.obj)
390
+ )
391
+ else str(type(self.obj))
392
+ )
393
+ return title_str
394
+
395
+ def _get_signature_prefix(self) -> str:
396
+ # signature prefix
397
+ if _inspect.isclass(self.obj):
398
+ return "class"
399
+ elif _inspect.iscoroutinefunction(self.obj):
400
+ return "async def"
401
+ elif _inspect.isfunction(self.obj):
402
+ return "def"
403
+ return ""
404
+
405
+ # @deprecated
406
+ def get_parameters(self) -> list[str] | None:
407
+ try:
408
+ sig = _inspect.signature(self.obj)
409
+ except (ValueError, AttributeError, TypeError):
410
+ return None
411
+ return [str(x) for x in sig.parameters.values()]
412
+
413
+ def _get_func_signature(self, func: Callable[P, R]) -> list[str]:
414
+ overloads = list(get_overloads(func))
415
+ if len(overloads) < 1:
416
+ return [
417
+ f"{self._get_signature_prefix()} {func.__name__}{_inspect.signature(func)}"
418
+ ]
419
+ return [
420
+ f"{self._get_signature_prefix()} {x.__name__}{_inspect.signature(x)}"
421
+ for x in overloads
422
+ ]
423
+
424
+ # @deprecated
425
+ def _make_signature(self) -> list[str]:
426
+ try:
427
+ # if isinstance(self.obj, Callable):
428
+ if _inspect.isfunction(self.obj):
429
+ funcs = [
430
+ self._text_wrapper.wrap(x)
431
+ for x in self._get_func_signature(self.obj)
432
+ ]
433
+ return ListExt(funcs).flatten()
434
+ return self._text_wrapper.wrap(
435
+ f"{self._get_signature_prefix()} {self.obj.__name__}{_inspect.signature(self.obj)}"
436
+ )
437
+ # not class, func | not type | is module
438
+ except (ValueError, AttributeError, TypeError):
439
+ return self._text_wrapper.wrap(repr(self.obj))
440
+
441
+ @property
442
+ def obj_signature(self) -> _TitleSignature:
443
+ """Object's title and signature"""
444
+ title: str = self._make_title()
445
+ sig: list[str] = []
446
+ try:
447
+ if _inspect.isfunction(self.obj):
448
+ sig.extend(self._get_func_signature(self.obj))
449
+ sig.append(
450
+ f"{self._get_signature_prefix()} {self.obj.__name__}{_inspect.signature(self.obj)}"
451
+ )
452
+ # not class, func | not type | is module
453
+ except (ValueError, AttributeError, TypeError):
454
+ sig.append(repr(self.obj))
455
+
456
+ return _TitleSignature(title=title, signature=sig)
457
+
458
+ # 02. Docstring
459
+ # -----------------------------------------------------------
460
+ @property
461
+ def obj_docs(self) -> _Docstring:
462
+ """Object's docstring"""
463
+ docs: str | None = _inspect.getdoc(self.obj)
464
+
465
+ if docs is None:
466
+ return _Docstring("")
467
+ return _Docstring(docs=docs)
468
+
469
+ # @deprecated
470
+ def _get_docs(self) -> str:
471
+ docs: str | None = _inspect.getdoc(self.obj)
472
+
473
+ if docs is None:
474
+ return ""
475
+
476
+ # Get docs and get first paragraph
477
+ # doc_lines: list[str] = [x.strip() for x in docs.splitlines()]
478
+ doc_lines = []
479
+ for line in docs.splitlines():
480
+ if len(line) < 1:
481
+ break
482
+ doc_lines.append(line.strip())
483
+
484
+ return text_shorten(" ".join(doc_lines), width=self._linelength - 4, tabsize=4)
485
+
486
+ # 03. MRO/Bases
487
+ # -----------------------------------------------------------
488
+ @property
489
+ def obj_mro(self) -> _MRO:
490
+ """Object's MRO, bases"""
491
+ if isinstance(self.obj, type):
492
+ return _MRO(mro=self.obj.__mro__[::-1])
493
+ return _MRO(mro=type(self.obj).__mro__[::-1])
494
+
495
+ @property
496
+ def obj_bases(self) -> _MRO:
497
+ """Object's MRO, bases"""
498
+ return self.obj_mro
499
+
500
+ # @deprecated
501
+ def _get_mro(self) -> tuple[type, ...]:
502
+ """Get MRO in reverse and subtract <class 'object'>"""
503
+ if isinstance(self.obj, type):
504
+ return self.obj.__mro__[::-1][1:]
505
+ return type(self.obj).__mro__[::-1][1:]
506
+
507
+ # @deprecated
508
+ def _make_mro_data(self) -> list[str]:
509
+ mro = [
510
+ f"- {i:02}. {x.__module__}.{x.__name__}"
511
+ for i, x in enumerate(self._get_mro(), start=1)
512
+ ]
513
+ mod_chunk = self._long_list_terminal_size(mro)
514
+
515
+ # return [text_shorten(x, self._linelength - 4) for x in mod_chunk]
516
+ return mod_chunk
517
+
518
+ # 04. Class's members
519
+ # -----------------------------------------------------------
520
+ def _get_obj_member(self) -> ClassMembersResult:
521
+ # if _inspect.isclass(self.obj) or inspect.ismodule(self.obj):
522
+ if _inspect.isclass(self.obj):
523
+ tmpcls = type(
524
+ "tmpcls",
525
+ (
526
+ self.obj,
527
+ GetClassMembersMixin,
528
+ ),
529
+ {},
530
+ )
531
+ else:
532
+ tmpcls = type(
533
+ "tmpcls",
534
+ (
535
+ type(self.obj),
536
+ GetClassMembersMixin,
537
+ ),
538
+ {},
539
+ )
540
+ med_prop = tmpcls._get_members( # type: ignore
541
+ dunder=False, private=self.include_private
542
+ )
543
+
544
+ try:
545
+ # If self.obj is a subclass of GetClassMembersMixin
546
+ _mro = getattr(
547
+ self.obj, "__mro__", getattr(type(self.obj), "__mro__", None)
548
+ )
549
+ if GetClassMembersMixin in _mro: # type: ignore
550
+ return med_prop # type: ignore
551
+ except AttributeError: # Not a class
552
+ pass
553
+ med_prop.__delitem__(GetClassMembersMixin.__name__)
554
+ return med_prop # type: ignore
555
+
556
+ @property
557
+ def obj_member(self) -> _Member:
558
+ """Object's members"""
559
+ try:
560
+ mem = self._get_obj_member()
561
+ return _Member(mem.flatten_value())
562
+ except (TypeError, AttributeError):
563
+ return _Member(ClassMembers())
564
+
565
+ # @deprecated
566
+ def _get_method_property(self) -> ClassMembersResult:
567
+ return self._get_obj_member()
568
+
569
+ # Attribute
570
+ @staticmethod
571
+ def _is_real_attribute(obj: Any) -> bool:
572
+ """
573
+ Not method, classmethod, staticmethod, property
574
+ """
575
+ if callable(obj):
576
+ return False
577
+ if isinstance(obj, staticmethod):
578
+ return False
579
+ if isinstance(obj, classmethod):
580
+ return False
581
+ if isinstance(obj, property):
582
+ return False
583
+ return True
584
+
585
+ def _get_attributes(self) -> list[tuple[str, Any]]:
586
+ # Get attributes
587
+ cls_dict = getattr(self.obj, "__dict__", None)
588
+ cls_slots = getattr(self.obj, "__slots__", None)
589
+ out = []
590
+
591
+ # Check if __dict__ exist and len(__dict__) > 0
592
+ if cls_dict is not None and len(cls_dict) > 0:
593
+ if self.include_private:
594
+ out = [
595
+ (k, v)
596
+ for k, v in self.obj.__dict__.items()
597
+ if self._is_real_attribute(v)
598
+ ]
599
+ else:
600
+ out = [
601
+ (k, v)
602
+ for k, v in self.obj.__dict__.items()
603
+ if not k.startswith("_") and self._is_real_attribute(v)
604
+ ]
605
+
606
+ # Check if __slots__ exist and len(__slots__) > 0
607
+ elif cls_slots is not None and len(cls_slots) > 0:
608
+ if self.include_private:
609
+ out = [
610
+ (x, getattr(self.obj, x))
611
+ for x in self.obj.__slots__ # type: ignore
612
+ if self._is_real_attribute(getattr(self.obj, x))
613
+ ]
614
+ else:
615
+ out = [
616
+ (x, getattr(self.obj, x))
617
+ for x in self.obj.__slots__ # type: ignore
618
+ if not x.startswith("_")
619
+ and self._is_real_attribute(getattr(self.obj, x))
620
+ ]
621
+
622
+ return out
623
+
624
+ def _handle_attributes_for_output(
625
+ self, attr_list: list[tuple[str, Any]]
626
+ ) -> list[str]:
627
+ return [
628
+ text_shorten(f"- {x[0]} = {x[1]}", self._linelength - 4) for x in attr_list
629
+ ]
630
+
631
+ # Output
632
+ # -----------------------------------------------------------
633
+ # @deprecated
634
+ def _make_output(self) -> OneColumnTableMaker:
635
+ table = OneColumnTableMaker(self._linelength, style=self._style) # type: ignore
636
+ body: list[str] = []
637
+
638
+ # Signature
639
+ title = self._make_title()
640
+ table.add_title(title)
641
+ sig = self._make_signature()
642
+ if table._title == "": # Title too long
643
+ _title = [title]
644
+ _title.extend(sig)
645
+ table.add_paragraph(_title)
646
+ else:
647
+ table.add_paragraph(sig)
648
+
649
+ # Docstring
650
+ docs = self._get_docs()
651
+ if len(docs) > 0 and self.include_docs:
652
+ body.extend(["Docstring:", docs])
653
+
654
+ # Class bases
655
+ clsbases = self._make_mro_data()
656
+ if len(clsbases) > 0 and self.include_mro:
657
+ body.extend(["", f"Bases (Len: {len(self._get_mro())}):"])
658
+ body.extend(clsbases)
659
+
660
+ # Method & Property
661
+ try:
662
+ method_n_properties = (
663
+ self._get_method_property().flatten_value().pack().sort()
664
+ )
665
+ if self.include_method:
666
+ ml = [
667
+ text_shorten(f"- {x}", self._linelength - 4)
668
+ for x in method_n_properties.methods
669
+ ]
670
+ if len(ml) > 0:
671
+ head = ["", f"Methods (Len: {len(ml)}):"]
672
+ head.extend(self._long_list_terminal_size(ml))
673
+ body.extend(head)
674
+ if self.include_property:
675
+ pl = [
676
+ text_shorten(
677
+ f"- {x} = {getattr(self.obj, x, None)}", self._linelength - 4
678
+ )
679
+ for x in method_n_properties.properties
680
+ ]
681
+ if len(pl) > 0:
682
+ head = ["", f"Properties (Len: {len(pl)}):"]
683
+ head.extend(pl)
684
+ body.extend(head)
685
+ except (TypeError, AttributeError):
686
+ pass
687
+
688
+ # Attribute
689
+ attrs = self._get_attributes()
690
+ if len(attrs) > 0 and self.include_attribute:
691
+ body.extend(["", f"Attributes (Len: {len(attrs)}):"])
692
+ body.extend(self._handle_attributes_for_output(attr_list=attrs))
693
+
694
+ # Add to table
695
+ table.add_paragraph(body)
696
+
697
+ return table
698
+
699
+ def _make_output_2(self) -> OneColumnTableMaker:
700
+ # Prep
701
+ # components: list[InspectComponents] = [
702
+ # self.obj_signature,
703
+ # self.obj_docs,
704
+ # self.obj_mro,
705
+ # self.obj_member,
706
+ # ]
707
+ table = OneColumnTableMaker(self._linelength, style=self._style) # type: ignore
708
+ body: list[str] = []
709
+
710
+ # Signature
711
+ title = self.obj_signature.title
712
+ table.add_title(title)
713
+ if table._title == "": # Title too long
714
+ _title = [title]
715
+ _title.extend(self.obj_signature.signature)
716
+ table.add_paragraph(_title)
717
+ else:
718
+ table.add_paragraph(self.obj_signature.signature)
719
+
720
+ # Docstring
721
+ if self.include_docs:
722
+ body.extend(self.obj_docs.make_output())
723
+
724
+ # Class bases
725
+ if self.include_mro:
726
+ body.extend(self.obj_mro.make_output(width=self._linelength))
727
+
728
+ # Method & Property
729
+ body.extend(
730
+ self.obj_member.make_output(
731
+ width=self._linelength,
732
+ obj=self.obj,
733
+ include_method=self.include_method,
734
+ include_property=self.include_property,
735
+ )
736
+ )
737
+
738
+ # Attribute
739
+ attrs = self._get_attributes()
740
+ if len(attrs) > 0 and self.include_attribute:
741
+ body.extend(["", f"Attributes (Len: {len(attrs)}):"])
742
+ body.extend(self._handle_attributes_for_output(attr_list=attrs))
743
+
744
+ # Add to table
745
+ table.add_paragraph(body)
746
+
747
+ return table
748
+
749
+
750
+ # Partial
751
+ # ---------------------------------------------------------------------------
752
+ inspect_all = partial(Inspector, line_length=None, include_all=True) # type: ignore