winipedia-utils 0.4.46__py3-none-any.whl → 0.6.12__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.
@@ -18,40 +18,52 @@ class HealthCheckWorkflow(Workflow):
18
18
  @classmethod
19
19
  def get_workflow_triggers(cls) -> dict[str, Any]:
20
20
  """Get the workflow triggers."""
21
- return {
22
- "pull_request": {
23
- "types": ["opened", "synchronize", "reopened"],
24
- },
25
- "schedule": [
26
- {
27
- # run every day at 6 am
28
- "cron": "0 6 * * *",
29
- },
30
- ],
31
- "workflow_dispatch": {},
32
- }
33
-
34
- @classmethod
35
- def get_permissions(cls) -> dict[str, Any]:
36
- """Get the workflow permissions."""
37
- return {}
21
+ triggers = super().get_workflow_triggers()
22
+ triggers.update(cls.on_pull_request())
23
+ triggers.update(cls.on_schedule(cron="0 6 * * *"))
24
+ return triggers
38
25
 
39
26
  @classmethod
40
27
  def get_jobs(cls) -> dict[str, Any]:
41
28
  """Get the workflow jobs."""
42
- return {
43
- **cls.get_standard_job(
44
- steps=[
45
- *(
46
- cls.get_poetry_setup_steps(
47
- install_dependencies=True,
48
- token=True,
49
- )
50
- ),
51
- cls.get_protect_repository_step(),
52
- cls.get_pre_commit_step(),
53
- cls.get_commit_step(),
54
- cls.get_extract_version_step(),
55
- ],
29
+ jobs: dict[str, Any] = {}
30
+ jobs.update(cls.job_health_check_matrix())
31
+ jobs.update(cls.job_health_check())
32
+ return jobs
33
+
34
+ @classmethod
35
+ def job_health_check_matrix(cls) -> dict[str, Any]:
36
+ """Get the health check matrix job."""
37
+ return cls.get_job(
38
+ job_func=cls.job_health_check_matrix,
39
+ strategy=cls.strategy_matrix_os_and_python_version(),
40
+ runs_on=cls.insert_matrix_os(),
41
+ steps=cls.steps_health_check_matrix(),
42
+ )
43
+
44
+ @classmethod
45
+ def job_health_check(cls) -> dict[str, Any]:
46
+ """Get the health check job."""
47
+ return cls.get_job(
48
+ job_func=cls.job_health_check,
49
+ needs=[cls.make_id_from_func(cls.job_health_check_matrix)],
50
+ steps=cls.steps_aggregate_matrix_results(),
51
+ )
52
+
53
+ @classmethod
54
+ def steps_health_check_matrix(cls) -> list[dict[str, Any]]:
55
+ """Get the health check matrix steps."""
56
+ return [
57
+ *cls.steps_core_matrix_setup(
58
+ python_version=cls.insert_matrix_python_version()
56
59
  ),
57
- }
60
+ cls.step_protect_repository(),
61
+ cls.step_run_pre_commit_hooks(),
62
+ ]
63
+
64
+ @classmethod
65
+ def steps_aggregate_matrix_results(cls) -> list[dict[str, Any]]:
66
+ """Get the aggregate matrix results step."""
67
+ return [
68
+ cls.step_aggregate_matrix_results(),
69
+ ]
@@ -19,31 +19,33 @@ class PublishWorkflow(Workflow):
19
19
  @classmethod
20
20
  def get_workflow_triggers(cls) -> dict[str, Any]:
21
21
  """Get the workflow triggers."""
22
- return {
23
- "workflow_run": {
24
- "workflows": [ReleaseWorkflow.get_workflow_name()],
25
- "types": ["completed"],
26
- },
27
- }
28
-
29
- @classmethod
30
- def get_permissions(cls) -> dict[str, Any]:
31
- """Get the workflow permissions."""
32
- return {
33
- "contents": "read",
34
- }
22
+ triggers = super().get_workflow_triggers()
23
+ triggers.update(
24
+ cls.on_workflow_run(workflows=[ReleaseWorkflow.get_workflow_name()])
25
+ )
26
+ return triggers
35
27
 
36
28
  @classmethod
37
29
  def get_jobs(cls) -> dict[str, Any]:
38
30
  """Get the workflow jobs."""
39
- return cls.get_standard_job(
40
- steps=[
41
- *(
42
- cls.get_poetry_setup_steps(
43
- configure_pipy_token=True,
44
- )
45
- ),
46
- cls.get_publish_to_pypi_step(),
47
- ],
48
- if_condition="${{ github.event.workflow_run.conclusion == 'success' }}",
31
+ jobs: dict[str, Any] = {}
32
+ jobs.update(cls.job_publish())
33
+ return jobs
34
+
35
+ @classmethod
36
+ def job_publish(cls) -> dict[str, Any]:
37
+ """Get the publish job."""
38
+ return cls.get_job(
39
+ job_func=cls.job_publish,
40
+ steps=cls.steps_publish(),
41
+ if_condition=cls.if_workflow_run_is_success(),
49
42
  )
43
+
44
+ @classmethod
45
+ def steps_publish(cls) -> list[dict[str, Any]]:
46
+ """Get the publish steps."""
47
+ return [
48
+ *cls.steps_core_setup(),
49
+ cls.step_add_pypi_token_to_poetry(),
50
+ cls.step_publish_to_pypi(),
51
+ ]
@@ -19,16 +19,10 @@ class ReleaseWorkflow(HealthCheckWorkflow):
19
19
  @classmethod
20
20
  def get_workflow_triggers(cls) -> dict[str, Any]:
21
21
  """Get the workflow triggers."""
22
- return {
23
- "push": {"branches": ["main"]},
24
- "workflow_dispatch": {},
25
- "schedule": [
26
- {
27
- # run every Tuesday at 6 am
28
- "cron": "0 6 * * 2",
29
- },
30
- ],
31
- }
22
+ triggers = super().get_workflow_triggers()
23
+ triggers.update(cls.on_push())
24
+ triggers.update(cls.on_schedule(cron="0 6 * * 2"))
25
+ return triggers
32
26
 
33
27
  @classmethod
34
28
  def get_permissions(cls) -> dict[str, Any]:
@@ -40,6 +34,57 @@ class ReleaseWorkflow(HealthCheckWorkflow):
40
34
  @classmethod
41
35
  def get_jobs(cls) -> dict[str, Any]:
42
36
  """Get the workflow jobs."""
43
- steps = super().get_jobs()
44
- steps[cls.get_filename()]["steps"].extend(cls.get_release_steps())
45
- return steps
37
+ jobs = super().get_jobs()
38
+ last_job_name = list(jobs.keys())[-1]
39
+ jobs.update(cls.job_build(needs=[last_job_name]))
40
+ jobs.update(cls.job_release())
41
+ return jobs
42
+
43
+ @classmethod
44
+ def job_build(cls, needs: list[str] | None = None) -> dict[str, Any]:
45
+ """Get the build job."""
46
+ return cls.get_job(
47
+ job_func=cls.job_build,
48
+ needs=needs,
49
+ strategy=cls.strategy_matrix_os(),
50
+ runs_on=cls.insert_matrix_os(),
51
+ steps=cls.steps_build(),
52
+ )
53
+
54
+ @classmethod
55
+ def job_release(cls) -> dict[str, Any]:
56
+ """Get the release job."""
57
+ return cls.get_job(
58
+ job_func=cls.job_release,
59
+ needs=[cls.make_id_from_func(cls.job_build)],
60
+ steps=cls.steps_release(),
61
+ )
62
+
63
+ @classmethod
64
+ def steps_build(cls) -> list[dict[str, Any]]:
65
+ """Get the build steps."""
66
+ if not cls.BUILD_SCRIPT_PATH.exists():
67
+ return [cls.step_no_build_script()]
68
+ return [
69
+ *cls.steps_core_matrix_setup(),
70
+ cls.step_build_artifacts(),
71
+ cls.step_upload_artifacts(),
72
+ ]
73
+
74
+ @classmethod
75
+ def steps_release(cls) -> list[dict[str, Any]]:
76
+ """Get the release steps."""
77
+ return [
78
+ *cls.steps_core_setup(repo_token=True),
79
+ cls.step_install_python_dependencies(),
80
+ cls.step_setup_keyring(),
81
+ cls.step_setup_git(),
82
+ cls.step_run_pre_commit_hooks(),
83
+ cls.step_commit_added_changes(),
84
+ cls.step_push_commits(),
85
+ cls.step_create_and_push_tag(),
86
+ cls.step_extract_version(),
87
+ cls.step_download_artifacts(),
88
+ cls.step_build_changelog(),
89
+ cls.step_create_release(),
90
+ ]
@@ -5,9 +5,9 @@ from typing import Any
5
5
 
6
6
  import winipedia_utils
7
7
  from winipedia_utils.logging.logger import get_logger
8
- from winipedia_utils.modules.package import make_name_from_package
9
8
  from winipedia_utils.os.os import run_subprocess
10
9
  from winipedia_utils.text.config import YamlConfigFile
10
+ from winipedia_utils.text.string import make_name_from_obj
11
11
 
12
12
  logger = get_logger(__name__)
13
13
 
@@ -29,7 +29,7 @@ class PreCommitConfigConfigFile(YamlConfigFile):
29
29
  @classmethod
30
30
  def get_configs(cls) -> dict[str, Any]:
31
31
  """Get the config."""
32
- hook_name = make_name_from_package(winipedia_utils, capitalize=False)
32
+ hook_name = make_name_from_obj(winipedia_utils, capitalize=False)
33
33
  return {
34
34
  "repos": [
35
35
  {
@@ -38,7 +38,7 @@ class PreCommitConfigConfigFile(YamlConfigFile):
38
38
  {
39
39
  "id": hook_name,
40
40
  "name": hook_name,
41
- "entry": cls.get_python_setup_script(),
41
+ "entry": cls.get_poetry_run_setup_script(),
42
42
  "language": "system",
43
43
  "always_run": True,
44
44
  "pass_filenames": False,
@@ -7,84 +7,22 @@ strings are the arguments to the command. These funcs will be called by
7
7
  run_hooks.py, which will pass the returned list to subprocess.run().
8
8
  """
9
9
 
10
- from pathlib import Path
11
-
12
10
  from winipedia_utils.projects.poetry.poetry import (
13
11
  POETRY_ARG,
14
- get_run_python_module_args,
12
+ get_poetry_run_module_args,
15
13
  )
16
14
 
17
15
 
18
- def patch_version() -> list[str | Path]:
19
- """Patch the version in pyproject.toml.
20
-
21
- This function returns the input for subprocess.run() to patch the version
22
- in pyproject.toml.
23
- """
24
- return [POETRY_ARG, "version", "patch"]
25
-
26
-
27
- def add_version_patch_to_git() -> list[str | Path]:
28
- """Add the version patch to git.
29
-
30
- This function returns the input for subprocess.run() to add the version
31
- patch to git, so that the hook does not fail bc the file was changed.
32
- """
33
- return ["git", "add", "pyproject.toml"]
34
-
35
-
36
- def update_package_manager() -> list[str | Path]:
37
- """Update the package manager.
38
-
39
- This function returns the input for subprocess.run() to update the package
40
- manager.
41
- """
42
- return [POETRY_ARG, "self", "update"]
43
-
44
-
45
- def install_dependencies_with_dev() -> list[str | Path]:
46
- """Install all dependencies.
47
-
48
- This function returns the input for subprocess.run() to install all dependencies.
49
- """
50
- return [POETRY_ARG, "install", "--with", "dev"]
51
-
52
-
53
- def update_dependencies_with_dev() -> list[str | Path]:
54
- """Update all dependencies.
55
-
56
- This function returns the input for subprocess.run() to update all dependencies.
57
- """
58
- return [POETRY_ARG, "update", "--with", "dev"]
59
-
60
-
61
- def add_updates_to_git() -> list[str | Path]:
16
+ def add_updates_to_git() -> list[str]:
62
17
  """Add the updated dependencies to git.
63
18
 
64
19
  This function returns the input for subprocess.run() to add the updated
65
20
  dependencies to git, so that the hook does not fail bc the file was changed.
66
21
  """
67
- return ["git", "add", "pyproject.toml"]
68
-
69
-
70
- def lock_dependencies() -> list[str | Path]:
71
- """Lock the dependencies.
72
-
73
- This function returns the input for subprocess.run() to lock the dependencies.
74
- """
75
- return [POETRY_ARG, "lock"]
76
-
77
-
78
- def add_lock_file_to_git() -> list[str | Path]:
79
- """Add the lock file to git.
80
-
81
- This function returns the input for subprocess.run() to add the lock file
82
- to git, so that the hook does not fail bc the file was changed.
83
- """
84
- return ["git", "add", "poetry.lock"]
22
+ return ["git", "add", "pyproject.toml", "poetry.lock"]
85
23
 
86
24
 
87
- def check_package_manager_configs() -> list[str | Path]:
25
+ def check_package_manager_configs() -> list[str]:
88
26
  """Check that poetry.lock and pyproject.toml is up to date.
89
27
 
90
28
  This function returns the input for subprocess.run() to check that poetry.lock
@@ -93,7 +31,7 @@ def check_package_manager_configs() -> list[str | Path]:
93
31
  return [POETRY_ARG, "check", "--strict"]
94
32
 
95
33
 
96
- def create_missing_tests() -> list[str | Path]:
34
+ def create_missing_tests() -> list[str]:
97
35
  """Create all tests for the project.
98
36
 
99
37
  This function returns the input for subprocess.run() to create all tests.
@@ -102,10 +40,10 @@ def create_missing_tests() -> list[str | Path]:
102
40
  create_tests,
103
41
  )
104
42
 
105
- return [*get_run_python_module_args(create_tests)]
43
+ return get_poetry_run_module_args(create_tests)
106
44
 
107
45
 
108
- def lint_code() -> list[str | Path]:
46
+ def lint_code() -> list[str]:
109
47
  """Check the code.
110
48
 
111
49
  This function returns the input for subprocess.run() to lint the code.
@@ -114,7 +52,7 @@ def lint_code() -> list[str | Path]:
114
52
  return ["ruff", "check", "--fix"]
115
53
 
116
54
 
117
- def format_code() -> list[str | Path]:
55
+ def format_code() -> list[str]:
118
56
  """Format the code.
119
57
 
120
58
  This function calls ruff format to format the code.
@@ -122,7 +60,7 @@ def format_code() -> list[str | Path]:
122
60
  return ["ruff", "format"]
123
61
 
124
62
 
125
- def check_static_types() -> list[str | Path]:
63
+ def check_static_types() -> list[str]:
126
64
  """Check the types.
127
65
 
128
66
  This function returns the input for subprocess.run() to check the static types.
@@ -130,7 +68,7 @@ def check_static_types() -> list[str | Path]:
130
68
  return ["mypy", "--exclude-gitignore"]
131
69
 
132
70
 
133
- def check_security() -> list[str | Path]:
71
+ def check_security() -> list[str]:
134
72
  """Check the security of the code.
135
73
 
136
74
  This function returns the input for subprocess.run() to check the security of
@@ -139,7 +77,7 @@ def check_security() -> list[str | Path]:
139
77
  return ["bandit", "-c", "pyproject.toml", "-r", "."]
140
78
 
141
79
 
142
- def run_tests() -> list[str | Path]:
80
+ def run_tests() -> list[str]:
143
81
  """Run the tests.
144
82
 
145
83
  This function returns the input for subprocess.run() to run all tests.
@@ -19,7 +19,6 @@ def run_hooks() -> None:
19
19
  """Import all funcs defined in hooks.py and runs them."""
20
20
  hook_funcs = get_all_functions_from_module(hooks)
21
21
 
22
- exit_code = 0
23
22
  for hook_func in hook_funcs:
24
23
  subprocess_args = hook_func()
25
24
  result = run_subprocess(
@@ -28,19 +27,30 @@ def run_hooks() -> None:
28
27
  passed = result.returncode == 0
29
28
 
30
29
  log_method = logger.info
31
- passed_str = (f"{GREEN}PASSED" if passed else f"{RED}FAILED") + RESET
30
+ status_str = (f"{GREEN}PASSED" if passed else f"{RED}FAILED") + RESET
32
31
  if not passed:
33
32
  log_method = logger.error
34
- passed_str += f"\n{result.stdout}"
35
- exit_code = 1
33
+ status_str += f"""
34
+ ---------------------------------------------------------------------------------------------
35
+ Stdout:
36
+
37
+ {result.stdout}
38
+
39
+ ---------------------------------------------------------------------------------------------
40
+ Stderr:
41
+
42
+ {result.stderr}
43
+
44
+ ---------------------------------------------------------------------------------------------
45
+ """
46
+
36
47
  # make the dashes always the same lentgth by adjusting to len of hook name
37
48
  num_dashes = 50 - len(hook_func.__name__)
38
49
  log_method(
39
50
  "Hook %s -%s> %s",
40
51
  hook_func.__name__,
41
52
  "-" * num_dashes,
42
- passed_str,
53
+ status_str,
43
54
  )
44
-
45
- if exit_code != 0:
46
- sys.exit(exit_code)
55
+ if not passed:
56
+ sys.exit(1)
@@ -13,10 +13,14 @@ from types import ModuleType
13
13
  from typing import Any
14
14
 
15
15
  from winipedia_utils.modules.function import is_func
16
+ from winipedia_utils.modules.inspection import get_def_line, get_obj_members
16
17
 
17
18
 
18
19
  def get_all_methods_from_cls(
19
- class_: type, *, exclude_parent_methods: bool = False
20
+ class_: type,
21
+ *,
22
+ exclude_parent_methods: bool = False,
23
+ include_annotate: bool = False,
20
24
  ) -> list[Callable[..., Any]]:
21
25
  """Get all methods from a class.
22
26
 
@@ -27,17 +31,21 @@ def get_all_methods_from_cls(
27
31
  class_: The class to extract methods from
28
32
  exclude_parent_methods: If True, only include methods defined in this class,
29
33
  excluding those inherited from parent classes
34
+ include_annotate: If False, exclude __annotate__ method
35
+ introduced in Python 3.14, defaults to False
36
+
30
37
  Returns:
31
38
  A list of callable methods from the class
32
39
 
33
40
  """
34
41
  from winipedia_utils.modules.module import ( # noqa: PLC0415 # avoid circular import
35
- get_def_line,
36
42
  get_module_of_obj,
37
43
  )
38
44
 
39
45
  methods = [
40
- (method, name) for name, method in inspect.getmembers(class_) if is_func(method)
46
+ (method, name)
47
+ for name, method in get_obj_members(class_, include_annotate=include_annotate)
48
+ if is_func(method)
41
49
  ]
42
50
 
43
51
  if exclude_parent_methods:
@@ -67,7 +75,6 @@ def get_all_cls_from_module(module: ModuleType | str) -> list[type]:
67
75
 
68
76
  """
69
77
  from winipedia_utils.modules.module import ( # noqa: PLC0415 # avoid circular import
70
- get_def_line,
71
78
  get_module_of_obj,
72
79
  )
73
80
 
@@ -12,6 +12,8 @@ from importlib import import_module
12
12
  from types import ModuleType
13
13
  from typing import Any
14
14
 
15
+ from winipedia_utils.modules.inspection import get_def_line, get_obj_members
16
+
15
17
 
16
18
  def is_func_or_method(obj: Any) -> bool:
17
19
  """Return True if *obj* is a function or method.
@@ -57,7 +59,9 @@ def is_func(obj: Any) -> bool:
57
59
  return is_func_or_method(unwrapped)
58
60
 
59
61
 
60
- def get_all_functions_from_module(module: ModuleType | str) -> list[Callable[..., Any]]:
62
+ def get_all_functions_from_module(
63
+ module: ModuleType | str, *, include_annotate: bool = False
64
+ ) -> list[Callable[..., Any]]:
61
65
  """Get all functions defined in a module.
62
66
 
63
67
  Retrieves all function objects that are defined directly in the specified module,
@@ -66,13 +70,14 @@ def get_all_functions_from_module(module: ModuleType | str) -> list[Callable[...
66
70
 
67
71
  Args:
68
72
  module: The module to extract functions from
73
+ include_annotate: If False, exclude __annotate__ method
74
+ introduced in Python 3.14, defaults to False
69
75
 
70
76
  Returns:
71
77
  A list of callable functions defined in the module
72
78
 
73
79
  """
74
80
  from winipedia_utils.modules.module import ( # noqa: PLC0415 # avoid circular import
75
- get_def_line,
76
81
  get_module_of_obj,
77
82
  )
78
83
 
@@ -80,7 +85,8 @@ def get_all_functions_from_module(module: ModuleType | str) -> list[Callable[...
80
85
  module = import_module(module)
81
86
  funcs = [
82
87
  func
83
- for _name, func in inspect.getmembers(module, is_func)
88
+ for _name, func in get_obj_members(module, include_annotate=include_annotate)
89
+ if is_func(func)
84
90
  if get_module_of_obj(func).__name__ == module.__name__
85
91
  ]
86
92
  # sort by definition order
@@ -0,0 +1,56 @@
1
+ """Inspection utilities for introspecting Python objects.
2
+
3
+ This module provides utility functions for inspecting Python objects,
4
+ including checking if an object is a function or method, and unwrapping
5
+ methods to their underlying functions.
6
+ """
7
+
8
+ import inspect
9
+ import sys
10
+ from collections.abc import Callable
11
+ from typing import Any, cast
12
+
13
+
14
+ def get_obj_members(
15
+ obj: Any, *, include_annotate: bool = False
16
+ ) -> list[tuple[str, Any]]:
17
+ """Get all members of an object."""
18
+ members = [(member, value) for member, value in inspect.getmembers(obj)]
19
+ if not include_annotate:
20
+ members = [
21
+ (member, value)
22
+ for member, value in members
23
+ if member not in ("__annotate__", "__annotate_func__")
24
+ ]
25
+ return members
26
+
27
+
28
+ def inside_frozen_bundle() -> bool:
29
+ """Return True if the code is running inside a frozen bundle."""
30
+ return getattr(sys, "frozen", False)
31
+
32
+
33
+ def get_def_line(obj: Any) -> int:
34
+ """Return the line number where a method-like object is defined."""
35
+ if isinstance(obj, property):
36
+ obj = obj.fget
37
+ unwrapped = inspect.unwrap(obj)
38
+ if hasattr(unwrapped, "__code__"):
39
+ return int(unwrapped.__code__.co_firstlineno)
40
+ # getsourcelines does not work if in a pyinstaller bundle or something
41
+ if inside_frozen_bundle():
42
+ return 0
43
+ return inspect.getsourcelines(unwrapped)[1]
44
+
45
+
46
+ def get_unwrapped_obj(obj: Any) -> Any:
47
+ """Return the unwrapped version of a method-like object."""
48
+ if isinstance(obj, property):
49
+ obj = obj.fget # get the getter function of the property
50
+ return inspect.unwrap(obj)
51
+
52
+
53
+ def get_qualname_of_obj(obj: Callable[..., Any] | type) -> str:
54
+ """Return the name of a method-like object."""
55
+ unwrapped = get_unwrapped_obj(obj)
56
+ return cast("str", unwrapped.__qualname__)
@@ -17,7 +17,7 @@ from collections.abc import Callable, Sequence
17
17
  from importlib import import_module
18
18
  from pathlib import Path
19
19
  from types import ModuleType
20
- from typing import Any, cast
20
+ from typing import Any
21
21
 
22
22
  from winipedia_utils.logging.logger import get_logger
23
23
  from winipedia_utils.modules.class_ import (
@@ -25,6 +25,7 @@ from winipedia_utils.modules.class_ import (
25
25
  get_all_methods_from_cls,
26
26
  )
27
27
  from winipedia_utils.modules.function import get_all_functions_from_module
28
+ from winipedia_utils.modules.inspection import get_qualname_of_obj, get_unwrapped_obj
28
29
  from winipedia_utils.modules.package import (
29
30
  get_modules_and_packages_from_package,
30
31
  make_dir_with_init_file,
@@ -329,24 +330,6 @@ def get_default_module_content() -> str:
329
330
  return '''"""module."""'''
330
331
 
331
332
 
332
- def inside_frozen_bundle() -> bool:
333
- """Return True if the code is running inside a frozen bundle."""
334
- return getattr(sys, "frozen", False)
335
-
336
-
337
- def get_def_line(obj: Any) -> int:
338
- """Return the line number where a method-like object is defined."""
339
- if isinstance(obj, property):
340
- obj = obj.fget
341
- unwrapped = inspect.unwrap(obj)
342
- if hasattr(unwrapped, "__code__"):
343
- return int(unwrapped.__code__.co_firstlineno)
344
- # getsourcelines does not work if in a pyinstaller bundle or something
345
- if inside_frozen_bundle():
346
- return 0
347
- return inspect.getsourcelines(unwrapped)[1]
348
-
349
-
350
333
  def get_module_of_obj(obj: Any, default: ModuleType | None = None) -> ModuleType:
351
334
  """Return the module name where a method-like object is defined.
352
335
 
@@ -368,19 +351,6 @@ def get_module_of_obj(obj: Any, default: ModuleType | None = None) -> ModuleType
368
351
  return module
369
352
 
370
353
 
371
- def get_qualname_of_obj(obj: Callable[..., Any] | type) -> str:
372
- """Return the name of a method-like object."""
373
- unwrapped = get_unwrapped_obj(obj)
374
- return cast("str", unwrapped.__qualname__)
375
-
376
-
377
- def get_unwrapped_obj(obj: Any) -> Any:
378
- """Return the unwrapped version of a method-like object."""
379
- if isinstance(obj, property):
380
- obj = obj.fget # get the getter function of the property
381
- return inspect.unwrap(obj)
382
-
383
-
384
354
  def get_executing_module() -> ModuleType:
385
355
  """Get the module where execution has started.
386
356