cengal.introspection.inspect.versions.v_0.inspect
1#!/usr/bin/env python 2# coding=utf-8 3 4# Copyright © 2012-2024 ButenkoMS. All rights reserved. Contacts: <gtalk@butenkoms.space> 5# 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17 18# __all__ = ['frame', 'get_exception', 'get_exception_tripple', 'exception_to_printable_text', 'is_async', 'is_callable', 'func_param_names', 'frame_param_names', 'intro_func_param_names', 'CodeParamsWithValues', 'intro_func_params_with_values', 'intro_func_all_params_with_values', 'intro_func_all_params_with_values_as_ordered_dict', 'code_params_with_values_to_signature_items_gen', 'code_params_with_values_to_signature'] 19 20from typing import Any, Callable, Awaitable, Dict, Generator, List, Optional, Tuple, NamedTuple, OrderedDict as OrderedDictType, Type, Union, Set, Sequence, cast 21from types import ModuleType, CodeType, FrameType 22import traceback 23import inspect 24from inspect import getattr_static as inspect__getattr_static 25import sys 26from cengal.code_flow_control.python_bytecode_manipulator import CodeParamNames, code_param_names, has_code, get_code, code_name 27from cengal.text_processing.brackets_processing import Bracket, BracketPair, replace_text_with_brackets, find_text_in_brackets 28from collections import OrderedDict 29from importlib import import_module 30 31 32""" 33Module Docstring 34Docstrings: http://www.python.org/dev/peps/pep-0257/ 35""" 36 37__author__ = "ButenkoMS <gtalk@butenkoms.space>" 38__copyright__ = "Copyright © 2012-2024 ButenkoMS. All rights reserved. Contacts: <gtalk@butenkoms.space>" 39__credits__ = ["ButenkoMS <gtalk@butenkoms.space>", ] 40__license__ = "Apache License, Version 2.0" 41__version__ = "4.4.1" 42__maintainer__ = "ButenkoMS <gtalk@butenkoms.space>" 43__email__ = "gtalk@butenkoms.space" 44# __status__ = "Prototype" 45__status__ = "Development" 46# __status__ = "Production" 47 48 49class WrongDepth(Exception): 50 pass 51 52 53class CanNotRetrieveFrame(Exception): 54 pass 55 56 57def frame(depth: Optional[int] = 1) -> FrameType: 58 """ 59 :param depth: 0 - frame of this function, 1 - frame of the caller function, etc. 60 :return: 61 """ 62 depth = depth or 0 63 if depth < 0: 64 raise WrongDepth(depth) 65 66 result = inspect.currentframe() 67 if result is None: 68 raise CanNotRetrieveFrame() 69 70 for i in range(depth): 71 result = result.f_back 72 73 return result 74 75 76def get_exception() -> Exception: 77 ex_type, ex_value, ex_traceback = sys.exc_info() 78 return ex_value.with_traceback(ex_traceback) 79 80 81def get_exception_tripple() -> Tuple[Type, Exception, Any]: 82 return sys.exc_info() 83 84 85def exception_to_printable_text(exception: Exception) -> str: 86 # return ''.join(traceback.format_exception(type(exception), exception, exception.__traceback__)) 87 return ''.join(traceback.TracebackException.from_exception(exception).format()) 88 89 90def is_async(entity) -> bool: 91 return inspect.iscoroutine(entity) or inspect.isgenerator(entity) or inspect.iscoroutinefunction(entity) or inspect.isgeneratorfunction(entity) or inspect.isasyncgen(entity) or inspect.isasyncgenfunction(entity) or inspect.isawaitable(entity) 92 93 94def is_callable(entity) -> bool: 95 return callable(entity) 96 97 98def func_param_names(func) -> CodeParamNames: 99 return code_param_names(get_code(func)) 100 101 102def entity_arguments_description(entity: Callable) -> Tuple[Set[str], Sequence[str], Sequence[str], Sequence[str]]: 103 init_code = get_code(entity) 104 cpn: CodeParamNames = code_param_names(init_code) 105 positional = cpn.positional 106 positional_only = cpn.positional_only 107 keyword_only = cpn.keyword_only 108 all: Set[str] = set(positional) | set(positional_only) | set(keyword_only) 109 return all, positional, positional_only, keyword_only 110 111 112def func_code_name(func): 113 code = get_code(func) 114 return code_name(code) 115 116 117def func_name(func): 118 try: 119 return func.__name__ 120 except AttributeError: 121 return str() 122 123 124def func_qualname(func): 125 try: 126 return func.__qualname__ 127 except AttributeError: 128 return str() 129 130 131def entity_name(entity): 132 if isinstance(entity, FrameType): 133 entity = entity.f_code 134 135 if isinstance(entity, CodeType): 136 return code_name(entity) 137 else: 138 return func_name(entity) 139 140 141def entity_qualname(entity): 142 if isinstance(entity, FrameType): 143 entity = entity.f_code 144 145 if isinstance(entity, CodeType): 146 if sys.version_info >= (3, 11): 147 return code_qualname(entity) 148 else: 149 # raise RuntimeError('CodeType.__qualname__ is available only since Python 3.11') 150 entity_instance = find_entity(entity) 151 return f'{entity_owner_name(entity_instance)}.{entity_name(entity_instance)}' 152 else: 153 return func_qualname(entity) 154 155 156def entity_class(func) -> Optional[Type]: 157 if inspect.ismethod(func): 158 for func_class in inspect.getmro(func.__self__.__class__): 159 if func_class.__dict__.get(func.__name__) is func: 160 return func_class 161 162 func_of_the_bound_method = func.__func__ 163 for func_class in inspect.getmro(func.__self__.__class__): 164 if func_class.__dict__.get(func.__name__) is func_of_the_bound_method: 165 return func_class 166 167 func = func_of_the_bound_method 168 169 if inspect.isfunction(func): 170 try: 171 func_class = getattr_ex(inspect.getmodule(func), func.__qualname__.split('.<locals>', 1)[0].rsplit('.', 1)[0]) 172 except AttributeError: 173 return None 174 175 if isinstance(func_class, type): 176 return func_class 177 178 return getattr_ex(func, '__objclass__', None) 179 180 181def entity_owner(func) -> Optional[Union[Type, ModuleType]]: 182 func_module = None 183 if inspect.ismethod(func): 184 for func_class in inspect.getmro(func.__self__.__class__): 185 if func_class.__dict__.get(func.__name__) is func: 186 return func_class 187 188 func_of_the_bound_method = func.__func__ 189 for func_class in inspect.getmro(func.__self__.__class__): 190 if func_class.__dict__.get(func.__name__) is func_of_the_bound_method: 191 return func_class 192 193 func = func_of_the_bound_method 194 195 if inspect.isfunction(func): 196 func_module = inspect.getmodule(func) 197 try: 198 func_class = getattr_ex(func_module, func.__qualname__.split('.<locals>', 1)[0].rsplit('.', 1)[0]) 199 except AttributeError: 200 return func_module 201 202 if isinstance(func_class, type): 203 return func_class 204 else: 205 return func_module 206 207 try: 208 return getattr_ex(func, '__objclass__') 209 except AttributeError: 210 if func_module is None: 211 func_module = inspect.getmodule(func) 212 213 return func_module 214 215 216module_repr_importable_str_bracket_pair: BracketPair = BracketPair([Bracket("<module '")], [Bracket("' from '")]) 217module_repr_full_file_path_bracket_pair: BracketPair = BracketPair([Bracket("' from '")], [Bracket("'>")]) 218 219 220def get_module_importable_str_and_path(module) -> Tuple[str, str]: 221 if not inspect.ismodule(module): 222 raise TypeError(f'Only modules are supported. {type(module)} was provided instead') 223 224 module_repr: str = repr(module) 225 importable_str = module_repr[find_text_in_brackets(module_repr, module_repr_importable_str_bracket_pair)] 226 full_file_path = module_repr[find_text_in_brackets(module_repr, module_repr_full_file_path_bracket_pair)] 227 return importable_str, full_file_path 228 229 230def entity_owning_module_info_and_owning_path(entity) -> Tuple[ModuleType, str, str, List[Union[Type, ModuleType]]]: 231 owning_path: List = list() 232 module = None 233 owner_is_module: bool = False 234 while not owner_is_module: 235 module = entity_owner(entity) 236 owning_path.append(module) 237 entity = module 238 owner_is_module = inspect.ismodule(module) 239 240 module_importable_str, module_file_full_path = get_module_importable_str_and_path(module) 241 return module, module_importable_str, module_file_full_path, owning_path 242 243 244def entity_owning_module_importable_str(entity) -> str: 245 _, module_importable_str, _, _ = entity_owning_module_info_and_owning_path(entity) 246 return module_importable_str 247 248 249def entity_module_importable_str_and_owning_names_path(entity) -> Tuple[str, List[str]]: 250 _, module_importable_str, _, owning_path = entity_owning_module_info_and_owning_path(entity) 251 owning_path = owning_path[:-1] 252 owning_names_path = [entity_name(owner) for owner in owning_path] 253 return module_importable_str, owning_names_path 254 255 256def entity_by_name_module_importable_str_and_owning_names_path(entity_name: str, module_importable_str: str, owning_names_path: List[str]) -> Any: 257 owner = import_module(module_importable_str) 258 for owner_name in reversed(owning_names_path): 259 owner = getattr(owner, owner_name) 260 261 return getattr(owner, entity_name) 262 263 264module_repr_limited_bracket_pair: BracketPair = BracketPair([Bracket(" from '")], [Bracket("'>")]) 265 266 267def normalized_owner_repr(owner: Optional[Union[Type, ModuleType]]) -> str: 268 if owner is None: 269 return str() 270 271 owner_repr: str = repr(owner) 272 result, _ = replace_text_with_brackets(owner_repr, module_repr_limited_bracket_pair, ">", 1) 273 return result 274 275 276def normalized_code_owner_repr(code: CodeType, owner: Optional[Union[Type, ModuleType]]) -> str: 277 if owner is None: 278 return str() 279 280 owner_repr: str = repr(owner) 281 result, _ = replace_text_with_brackets(owner_repr, module_repr_limited_bracket_pair, f" line {code.co_firstlineno}>", 1) 282 return result 283 284 285def entity_owner_repr(entity): 286 if isinstance(entity, FrameType): 287 entity = entity.f_code 288 289 if isinstance(entity, CodeType): 290 return normalized_code_owner_repr(entity, entity_owner(entity)) 291 else: 292 return normalized_owner_repr(entity_owner(entity)) 293 294 295def owner_name(owner: Optional[Union[Type, ModuleType]]) -> str: 296 if owner is None: 297 return str() 298 299 return owner.__name__ 300 301 302def entity_owner_name(entity): 303 return owner_name(entity_owner(entity)) 304 305 306def frame_param_names(frame_instance: FrameType) -> CodeParamNames: 307 return code_param_names(frame_instance.f_code) 308 309 310def intro_func_param_names(depth: Optional[int] = 1) -> CodeParamNames: 311 return frame_param_names(frame(depth + 1)) 312 313 314CodeParamsWithValues = CodeParamNames 315ParamWithValue = Tuple[str, Any] 316 317 318def fill_code_params_with_values(code_params: CodeParamNames, args, kwargs) -> Tuple[CodeParamsWithValues, Tuple, Dict]: 319 positional, positional_only, keyword_only = code_params 320 positional_len = len(positional) 321 positional_only_len = len(positional_only) 322 keyword_only_len = len(keyword_only) 323 positional_only_delimiter_place: Optional[int] = None 324 if positional_only_len: 325 positional_only_delimiter_place = positional_only_len 326 327 positional_values = tuple(((arg, args[index]) for index, arg in enumerate(positional))) 328 if positional_only_len: 329 positional_only_values = tuple(((arg, args[index]) for index, arg in enumerate(positional_only))) 330 else: 331 positional_only_values = tuple() 332 333 if keyword_only_len: 334 keyword_only_values = tuple(((arg, kwargs[arg]) for arg in keyword_only)) 335 else: 336 keyword_only_values = tuple() 337 338 result_args: Tuple = args[positional_len:] 339 result_kwargs: Dict = {key: value for key, value in kwargs.items() if key not in keyword_only} 340 341 return CodeParamsWithValues(positional_values, positional_only_values, keyword_only_values), result_args, result_kwargs 342 343 344def func_params_with_values(func: Union[Callable, Awaitable], args, kwargs) -> Tuple[CodeParamsWithValues, Tuple, Dict]: 345 return fill_code_params_with_values(func_param_names(func), args, kwargs) 346 347 348def intro_frame_params_with_values(frame_instance) -> CodeParamsWithValues: 349 positional, positional_only, keyword_only = frame_param_names(frame_instance) 350 fr_locals = frame_instance.f_locals 351 return CodeParamsWithValues(tuple(((arg, fr_locals[arg]) for arg in positional)), \ 352 tuple(((arg, fr_locals[arg]) for arg in positional_only)), \ 353 tuple(((arg, fr_locals[arg]) for arg in keyword_only))) 354 355 356def intro_func_params_with_values(depth: Optional[int] = 1) -> CodeParamsWithValues: 357 return intro_frame_params_with_values(frame(depth + 1)) 358 359 360def intro_frame_all_params_with_values(frame_instance) -> Tuple[ParamWithValue]: 361 positional, _, keyword_only = frame_param_names(frame_instance) 362 all_params = positional + keyword_only 363 fr_locals = frame_instance.f_locals 364 return tuple(((arg, fr_locals[arg]) for arg in all_params)) 365 366 367def intro_func_all_params_with_values(depth: Optional[int] = 1) -> Tuple[ParamWithValue]: 368 return intro_frame_all_params_with_values(frame(depth + 1)) 369 370 371def intro_frame_all_params_with_values_as_ordered_dict(frame_instance) -> OrderedDictType[str, Any]: 372 return OrderedDict(intro_frame_all_params_with_values(frame_instance)) 373 374 375def intro_func_all_params_with_values_as_ordered_dict(depth: Optional[int] = 1) -> OrderedDictType[str, Any]: 376 return intro_frame_all_params_with_values_as_ordered_dict(frame(depth + 1)) 377 378 379def code_params_with_values_to_signature_items_gen(code_params_with_values: CodeParamsWithValues, verbose: bool = False) -> Generator[str, None, None]: 380 positional, positional_only, keyword_only = code_params_with_values 381 positional_len = len(positional) 382 positional_only_len = len(positional_only) 383 keyword_only_len = len(keyword_only) 384 positional_only_delimiter_place: Optional[int] = None 385 if positional_only_len: 386 positional_only_delimiter_place = positional_only_len 387 388 for index, arg in enumerate(positional): 389 arg_name, arg_value = arg 390 if (positional_only_delimiter_place is not None) and (index == positional_only_delimiter_place): 391 yield '/' 392 393 if verbose: 394 yield f'{arg_name}={arg_value}' 395 else: 396 yield str(arg_value) 397 398 if keyword_only_len: 399 yield '*' 400 for arg in keyword_only: 401 arg_name, arg_value = arg 402 yield f'{arg_name}={arg_value}' 403 404 405def code_params_to_signature_items_gen(code_params: CodeParamNames) -> Generator[str, None, None]: 406 positional, positional_only, keyword_only = code_params 407 positional_len = len(positional) 408 positional_only_len = len(positional_only) 409 keyword_only_len = len(keyword_only) 410 positional_only_delimiter_place: Optional[int] = None 411 if positional_only_len: 412 positional_only_delimiter_place = positional_only_len 413 414 for index, arg in enumerate(positional): 415 if (positional_only_delimiter_place is not None) and (index == positional_only_delimiter_place): 416 yield '/' 417 418 # yield arg[0] 419 yield arg 420 421 if keyword_only_len: 422 yield '*' 423 for arg in keyword_only: 424 # yield arg[0] 425 yield arg 426 427 428def code_params_with_values_to_signature(params_with_values: CodeParamsWithValues, verbose: bool = False, formatted: bool = False) -> str: 429 if formatted: 430 delimiter = ',\n\t' 431 else: 432 delimiter = ', ' 433 434 return delimiter.join(code_params_with_values_to_signature_items_gen(params_with_values, verbose)) 435 436 437def code_params_to_signature(param_names: CodeParamNames, formatted: bool = False) -> str: 438 if formatted: 439 delimiter = ',\n\t' 440 else: 441 delimiter = ', ' 442 443 return delimiter.join(code_params_to_signature_items_gen(param_names)) 444 445 446def entity_repr_limited(entity, formatted: bool = False): 447 if isinstance(entity, FrameType): 448 entity = entity.f_code 449 450 if isinstance(entity, CodeType): 451 code = entity 452 else: 453 code = get_code(entity) 454 455 func_name = code_name(code) 456 param_names = code_param_names(code) 457 function_params_str = code_params_to_signature(param_names, formatted) 458 return f'{func_name}({function_params_str})' 459 460 461def entity_repr_limited_try_qualname(entity, formatted: bool = False): 462 if has_code(entity): 463 if isinstance(entity, FrameType): 464 entity = entity.f_code 465 466 if isinstance(entity, CodeType): 467 code = entity 468 func_name = code_name(code) 469 else: 470 code = get_code(entity) 471 func_name = func_qualname(entity) 472 473 param_names = code_param_names(code) 474 function_params_str = code_params_to_signature(param_names, formatted) 475 return f'{func_name}({function_params_str})' 476 else: 477 entity_type_name = type(entity).__name__ 478 entity_properties_with_values = entity_properties_values(entity) 479 if formatted: 480 delimiter = ',\n\t' 481 else: 482 delimiter = ', ' 483 484 entity_properties_str = delimiter.join([f'{key}={value}' for key, value in entity_properties_with_values.items()]) 485 return f'{entity_type_name}({entity_properties_str})' 486 487 488def entity_repr_owner_based(entity, formatted: bool = False): 489 if isinstance(entity, FrameType): 490 entity = entity.f_code 491 492 owner = entity_owner(entity) 493 if isinstance(entity, CodeType): 494 owner_repr = normalized_code_owner_repr(entity, owner) 495 else: 496 owner_repr = normalized_owner_repr(owner) 497 498 if isinstance(owner, ModuleType): 499 _entity_repr_limited = entity_repr_limited_try_qualname 500 else: 501 _entity_repr_limited = entity_repr_limited 502 503 if owner_repr: 504 return f'{owner_repr}.{_entity_repr_limited(entity, formatted)}' 505 else: 506 return _entity_repr_limited(entity, formatted) 507 508 509def entity_repr(entity, formatted: bool = False): 510 if isinstance(entity, FrameType): 511 entity = entity.f_code 512 513 module = inspect.getmodule(entity) 514 if isinstance(entity, CodeType): 515 owner_repr = normalized_code_owner_repr(entity, module) 516 else: 517 owner_repr = normalized_owner_repr(module) 518 519 if owner_repr: 520 return f'{owner_repr}.{entity_repr_limited_try_qualname(entity, formatted)}' 521 else: 522 return entity_repr_limited_try_qualname(entity, formatted) 523 524 525def entity_properties(entity) -> Set[str]: 526 """ 527 Example: 528 from cengal.parallel_execution.coroutines.coro_standard_services.wait_coro import WaitCoroRequest 529 from cengal.introspection.inspect import entity_properties 530 531 print(entity_properties(WaitCoroRequest)) 532 >> {'__weakref__', 'put_list', 'fastest', 'atomic', 'list', 'single', 'put_fastest', '_save', 'put_single', 'put_atomic'} 533 534 535 print(entity_properties(WaitCoroRequest())) 536 >> {'result_required', 'args', 'tree', 'kill_on_timeout', 'timeout', 'request_type', 'kwargs', 'provide_to_request_handler'} 537 538 539 def my_func(a, b, *, c, d): 540 return a + b + c + d 541 542 my_func.my_property = 2 543 544 print(entity_properties(my_func)) 545 >> {'my_property'} 546 547 548 Args: 549 entity (_type_): _description_ 550 551 Returns: 552 Set[str]: _description_ 553 """ 554 entity_type_items = set(dir(type(entity))) 555 entity_items = set(dir(entity)) 556 return entity_items - entity_type_items 557 558 559def entity_properties_values(entity) -> Dict[str, Any]: 560 result = dict() 561 for property_name in sorted(entity_properties(entity)): 562 result[property_name] = getattr(entity, property_name) 563 564 return result 565 566 567def class_properties(entity: Type) -> Set[str]: 568 """ 569 Example: 570 571 Args: 572 entity (_type_): _description_ 573 574 Returns: 575 Set[str]: _description_ 576 """ 577 entity_type_items = set(dir(type(entity))) 578 entity_items = set(dir(entity)) 579 mro = inspect.getmro(entity) 580 base_members: Set = set() 581 for base in mro: 582 if base is entity: 583 continue 584 585 base_members |= set(dir(base)) 586 587 return (entity_items - entity_type_items) - base_members 588 589 590def class_properties_values(entity) -> Dict[str, Any]: 591 result = dict() 592 for property_name in sorted(class_properties(entity)): 593 result[property_name] = getattr(entity, property_name) 594 595 return result 596 597 598def class_properties_withot_object(entity: Type) -> Set[str]: 599 """ 600 Example: 601 602 Args: 603 entity (_type_): _description_ 604 605 Returns: 606 Set[str]: _description_ 607 """ 608 object_type_items = set(dir(object)) 609 entity_items = set(dir(entity)) 610 return entity_items - object_type_items 611 612 613def class_properties_withot_object_values(entity) -> Dict[str, Any]: 614 result = dict() 615 for property_name in sorted(class_properties_withot_object(entity)): 616 result[property_name] = getattr(entity, property_name) 617 618 return result 619 620 621def class_properties_including_overrided(entity: Type) -> Set[str]: 622 """ 623 Example: 624 625 Args: 626 entity (_type_): _description_ 627 628 Returns: 629 Set[str]: _description_ 630 """ 631 entity_type_items = set(dir(type(entity))) 632 entity_items = set(entity.__dict__.keys()) 633 return entity_items - entity_type_items 634 635 636def class_properties_values_including_overrided(entity) -> Dict[str, Any]: 637 result = dict() 638 for property_name in sorted(class_properties_including_overrided(entity)): 639 result[property_name] = getattr(entity, property_name) 640 641 return result 642 643 644def intro_frame_repr_limited(frame_instance, verbose: bool = False): 645 func_name = code_name(frame_instance.f_code) 646 params_with_values = intro_frame_params_with_values(frame_instance) 647 function_params_str = code_params_with_values_to_signature(params_with_values, verbose) 648 return f'{func_name}({function_params_str})' 649 650 651def intro_frame_repr(frame_instance, verbose: bool = False): 652 code = frame_instance.f_code 653 func_name = code_name(code) 654 module = inspect.getmodule(code) 655 owner_repr = normalized_code_owner_repr(code, module) 656 params_with_values = intro_frame_params_with_values(frame_instance) 657 function_params_str = code_params_with_values_to_signature(params_with_values, verbose) 658 return f'{owner_repr}.{func_name}({function_params_str})' 659 660 661def intro_func_repr_limited(verbose: bool = False, depth: Optional[int] = 1): 662 return intro_frame_repr_limited(frame(depth + 1), verbose) 663 664 665def print_intro_func_repr_limited(verbose: bool = False, depth: Optional[int] = 1): 666 print(intro_func_repr_limited(verbose, depth + 1)) 667 668 669pifrl = print_intro_func_repr_limited 670 671 672def intro_func_repr(verbose: bool = False, depth: Optional[int] = 1): 673 return intro_frame_repr(frame(depth + 1), verbose) 674 675 676def print_intro_func_repr(verbose: bool = False, depth: Optional[int] = 1): 677 print(intro_func_repr(verbose, depth + 1)) 678 679 680pifr = print_intro_func_repr 681 682 683def get_str_of_data_info(data): 684 """Returns string with data info: type and value 685 686 Args: 687 data (_type_): _description_ 688 689 Returns: 690 _type_: _description_ 691 """ 692 return f'type: {type(data)}; value: {data}' 693 694 695gsodi = get_str_of_data_info 696 697 698def get_multistr_of_data_info(data, shift_num: Optional[int] = None, shift_char: str = '\t'): 699 """Returns multiline string with data info: type and value 700 701 Args: 702 data (_type_): _description_ 703 704 Returns: 705 _type_: _description_ 706 """ 707 shift_num = shift_num or 0 708 shift_str = shift_char * shift_num 709 from pprint import pformat 710 data_str = pformat(data) 711 data_str_lines = data_str.split('\n') 712 data_str = '\n'.join([f'{shift_str}{line}' for line in data_str_lines]) 713 return f'type: {type(data)}; value: \n{data_str}' 714 715 716gmsodi = get_multistr_of_data_info 717 718 719def get_multistr_of_data_value(data, shift_num: Optional[int] = None, shift_char: str = '\t'): 720 """Returns multiline string with data value 721 722 Args: 723 data (_type_): _description_ 724 725 Returns: 726 _type_: _description_ 727 """ 728 shift_num = shift_num or 0 729 shift_str = shift_char * shift_num 730 from pprint import pformat 731 data_str = pformat(data) 732 data_str_lines = data_str.split('\n') 733 data_str = '\n'.join([f'{shift_str}{line}' for line in data_str_lines]) 734 return data_str 735 736 737gmsodv = get_multistr_of_data_value 738 739 740def print_data_info(data): 741 """Print data info: type and value 742 743 Args: 744 data (_type_): _description_ 745 """ 746 print(get_str_of_data_info(data)) 747 748 749pdi = print_data_info 750 751 752def get_str_of_data_info_named(name, data): 753 return f'<<{name}>> type: {type(data)}; value: {data}' 754 755 756gsodin = get_str_of_data_info_named 757 758 759def print_data_info_named(name, data): 760 print(get_str_of_data_info_named(name, data)) 761 762 763pdin = print_data_info_named 764 765 766def get_str_of_data_info_by_name(name, depth: Optional[int] = 1): 767 fr = frame(depth + 1) 768 data = fr.f_locals[name] 769 return get_str_of_data_info_named(name, data) 770 771 772gsodibn = get_str_of_data_info_by_name 773 774 775def print_data_info_by_name(name, depth: Optional[int] = 1): 776 print(get_str_of_data_info_by_name(name, depth + 1)) 777 778 779pdibn = print_data_info_by_name 780 781 782def is_descriptor(entity): 783 return hasattr(entity, '__get__') or hasattr(entity, '__set__') or hasattr(entity, '__delete__') 784 785 786def is_setable_data_descriptor(entity): 787 return hasattr(entity, '__get__') and hasattr(entity, '__set__') 788 789 790def is_filled_descriptor(owning_object, entity) -> bool: 791 """ 792 class _foo: 793 __slots__ = ['foo', 'bar'] 794 795 def __init__(self): 796 self.bar = 2 797 798 'foo' - not filled 799 'bar' - filled 800 801 Args: 802 owning_object (_type_): _description_ 803 entity (_type_): _description_ 804 805 Returns: 806 _type_: _description_ 807 """ 808 try: 809 entity.__get__(owning_object) 810 except AttributeError: 811 return False 812 813 return True 814 815 816def filled_slots_names(owning_object) -> Optional[List[str]]: 817 try: 818 slots_names = owning_object.__slots__ 819 except AttributeError: 820 return None 821 822 result = list() 823 for slot_name in slots_names: 824 slot = inspect.getattr_static(owning_object, slot_name) 825 if is_filled_descriptor(owning_object, slot): 826 result.append(slot_name) 827 828 return result 829 830 831def filled_slots(owning_object) -> Optional[List[Any]]: 832 try: 833 slots_names = owning_object.__slots__ 834 except AttributeError: 835 return None 836 837 result = list() 838 for slot_name in slots_names: 839 slot = inspect.getattr_static(owning_object, slot_name) 840 if is_filled_descriptor(owning_object, slot): 841 result.append(slot) 842 843 return result 844 845 846def filled_slots_with_names(owning_object) -> Optional[List[Tuple[str, Any]]]: 847 try: 848 slots_names = owning_object.__slots__ 849 except AttributeError: 850 return None 851 852 result = list() 853 for slot_name in slots_names: 854 slot = inspect.getattr_static(owning_object, slot_name) 855 if is_filled_descriptor(owning_object, slot): 856 result.append((slot_name, slot)) 857 858 return result 859 860 861def filled_slots_with_names_gen(owning_object) -> Generator[Tuple[str, Any], Any, Any]: 862 try: 863 slots_names = owning_object.__slots__ 864 for slot_name in slots_names: 865 slot = inspect__getattr_static(owning_object, slot_name) 866 try: 867 slot.__get__(owning_object) 868 yield (slot_name, slot) 869 except AttributeError: 870 pass 871 except AttributeError: 872 pass 873 874 875def filled_slot_names_with_values_gen(owning_object) -> Generator[Tuple[str, Any], Any, Any]: 876 try: 877 slots_names = owning_object.__slots__ 878 for slot_name in slots_names: 879 try: 880 yield (slot_name, getattr(owning_object, slot_name)) 881 except AttributeError: 882 pass 883 except AttributeError: 884 pass 885 886 887def current_entity_name(depth: Optional[int] = 1): 888 fr = frame(depth + 1) 889 return entity_name(fr) 890 # entity_name = code_name(fr.f_code) 891 # # print(dir(fr.f_code)) 892 # # print(fr.f_code.__class__) 893 # # print(dir(fr)) 894 # # print(fr.__class__) 895 # return entity_name 896 897 898cen = current_entity_name 899 900 901def print_current_entity_name(depth: Optional[int] = 1): 902 print(current_entity_name(depth + 1)) 903 904 905print_cen = print_current_entity_name 906pcen = print_current_entity_name 907 908 909def current_entity_owner_name(depth: Optional[int] = 1): 910 fr = frame(depth + 1) 911 return owner_name(entity_owner(fr.f_code)) 912 913 914# def current_entity_full_name(depth: Optional[int] = 1): 915# fr = frame(depth + 1) 916# entity_name = code_name(fr.f_code) 917# return entity_name 918 919 920# cefn = current_entity_full_name 921 922 923def getattr_ex(entity, attr_name: str) -> Any: 924 try: 925 return getattr(entity, attr_name) 926 except AttributeError: # See code of the `inspect.getmembers()` 927 if attr_name in entity.__dict__: 928 return entity.__dict__[attr_name] 929 else: 930 raise AttributeError(f'Attribute "{attr_name}" was not found in the entity "{entity}"') 931 932 933def entity_is_function(entity) -> bool: 934 owner: Optional[Union[Type, ModuleType]] = entity_owner(entity) 935 if owner is None: 936 return False 937 938 if inspect.ismodule(owner): 939 entity_name_str: str = entity_name(entity) 940 if hasattr(owner, entity_name_str): 941 possible_entity = getattr_ex(owner, entity_name_str) 942 possible_entity_code = get_code(possible_entity) 943 entity_code = get_code(entity) 944 if possible_entity_code is entity_code: 945 return True 946 else: 947 return False 948 else: 949 return False 950 else: 951 return False 952 953 954def get_function_by_entity(entity) -> Optional[Callable]: 955 owner: Optional[Union[Type, ModuleType]] = entity_owner(entity) 956 if owner is None: 957 return None 958 959 if inspect.ismodule(owner): 960 entity_name_str: str = entity_name(entity) 961 if hasattr(owner, entity_name_str): 962 possible_entity = getattr_ex(owner, entity_name_str) 963 possible_entity_code = get_code(possible_entity) 964 entity_code = get_code(entity) 965 if possible_entity_code is entity_code: 966 return possible_entity 967 else: 968 return None 969 else: 970 return None 971 else: 972 return None 973 974 975def entity_is_method(entity) -> bool: 976 owner: Optional[Union[Type, ModuleType]] = entity_owner(entity) 977 if owner is None: 978 return False 979 980 if inspect.isclass(owner): 981 entity_name_str: str = entity_name(entity) 982 if hasattr(owner, entity_name_str): 983 possible_entity = getattr_ex(owner, entity_name_str) 984 possible_entity_code = get_code(possible_entity) 985 entity_code = get_code(entity) 986 if possible_entity_code is entity_code: 987 return True 988 else: 989 return False 990 else: 991 return False 992 else: 993 return False 994 995 996def get_method_by_entity(entity) -> Optional[Callable]: 997 owner: Optional[Union[Type, ModuleType]] = entity_owner(entity) 998 if owner is None: 999 return None 1000 1001 if inspect.isclass(owner): 1002 entity_name_str: str = entity_name(entity) 1003 if hasattr(owner, entity_name_str): 1004 possible_entity = getattr_ex(owner, entity_name_str) 1005 possible_entity_code = get_code(possible_entity) 1006 entity_code = get_code(entity) 1007 if possible_entity_code is entity_code: 1008 return possible_entity 1009 else: 1010 return None 1011 else: 1012 return None 1013 else: 1014 return None 1015 1016 1017def entity_is_unbound_method(entity): 1018 owner: Optional[Union[Type, ModuleType]] = entity_owner(entity) 1019 if owner is None: 1020 return False 1021 1022 if inspect.ismodule(owner): 1023 entity_name_str: str = entity_name(entity) 1024 if hasattr(owner, entity_name_str): 1025 possible_entity = getattr_ex(owner, entity_name_str) 1026 possible_entity_code = get_code(possible_entity) 1027 entity_code = get_code(entity) 1028 if possible_entity_code is entity_code: 1029 return False 1030 else: 1031 return True 1032 else: 1033 return True 1034 else: 1035 return False 1036 1037 1038def get_unbound_method_by_entity(entity) -> Optional[Callable]: 1039 raise NotImplementedError() 1040 1041 1042class AnAppropriateOwnerParameterWasNotFoundError(Exception): 1043 pass 1044 1045 1046class PossibleOwnerParameterDoesNotMatchError(AnAppropriateOwnerParameterWasNotFoundError): 1047 pass 1048 1049 1050class EntityHasNoPositionalParametersError(AnAppropriateOwnerParameterWasNotFoundError): 1051 pass 1052 1053 1054def get_owner_parameter(entity, owner_parameter_name: str, return_even_if_not_match: bool = False): 1055 if entity_is_function(entity): 1056 raise TypeError(f'Function has no {owner_parameter_name} parameter') 1057 1058 if entity_is_method(entity): 1059 return entity.__self__ 1060 elif entity_is_unbound_method(entity): 1061 if isinstance(entity, FrameType): 1062 entity_name_str: str = entity_name(entity) 1063 params_with_values: CodeParamsWithValues = intro_frame_params_with_values(entity) 1064 positional, positional_only, keyword_only = params_with_values 1065 if positional: 1066 possible_positional_self = positional[0][1] 1067 elif positional_only: 1068 possible_positional_self = positional_only[0][1] 1069 else: 1070 raise EntityHasNoPositionalParametersError 1071 1072 if hasattr(possible_positional_self, entity_name_str): 1073 possible_entity = getattr_ex(possible_positional_self, entity_name_str) 1074 possible_entity_code = get_code(possible_entity) 1075 entity_code = get_code(entity) 1076 if possible_entity_code is entity_code: 1077 return possible_positional_self 1078 else: 1079 if return_even_if_not_match: 1080 return possible_positional_self 1081 else: 1082 raise PossibleOwnerParameterDoesNotMatchError 1083 1084 raise AnAppropriateOwnerParameterWasNotFoundError(f'Can not find an appropriate {owner_parameter_name} parameter in {entity}') 1085 else: 1086 raise TypeError(f'{entity} of type {type(entity)} is not supported') 1087 1088 1089def get_self_parameter(entity): 1090 return get_owner_parameter(entity, 'self') 1091 1092 1093def get_cls_parameter(entity): 1094 return get_owner_parameter(entity, 'cls') 1095 1096 1097def get_any_owner_parameter(entity, owner_parameter_name: str, any_positional: bool = True, any_keyword: bool = True): 1098 if entity_is_function(entity): 1099 raise TypeError(f'Function has no {owner_parameter_name} parameter') 1100 1101 if entity_is_method(entity): 1102 return entity.__self__ 1103 elif entity_is_unbound_method(entity): 1104 if isinstance(entity, FrameType): 1105 entity_name_str: str = entity_name(entity) 1106 params_with_values: CodeParamsWithValues = intro_frame_params_with_values(entity) 1107 positional, positional_only, keyword_only = params_with_values 1108 1109 if any_positional: 1110 all_positional = positional + positional_only 1111 for param in all_positional: 1112 possible_positional_self_name, possible_positional_self = param 1113 if hasattr(possible_positional_self, entity_name_str): 1114 possible_entity = getattr_ex(possible_positional_self, entity_name_str) 1115 possible_entity_code = get_code(possible_entity) 1116 entity_code = get_code(entity) 1117 if possible_entity_code is entity_code: 1118 return possible_positional_self 1119 else: 1120 if positional: 1121 possible_positional_self = positional[0][1] 1122 elif positional_only: 1123 possible_positional_self = positional_only[0][1] 1124 1125 if hasattr(possible_positional_self, entity_name_str): 1126 possible_entity = getattr_ex(possible_positional_self, entity_name_str) 1127 possible_entity_code = get_code(possible_entity) 1128 entity_code = get_code(entity) 1129 if possible_entity_code is entity_code: 1130 return possible_positional_self 1131 1132 if any_keyword: 1133 for possible_keyword_self_name, possible_keyword_self in keyword_only: 1134 if hasattr(possible_keyword_self, entity_name_str): 1135 possible_entity = getattr_ex(possible_keyword_self, entity_name_str) 1136 possible_entity_code = get_code(possible_entity) 1137 entity_code = get_code(entity) 1138 if possible_entity_code is entity_code: 1139 return possible_keyword_self 1140 else: 1141 keyword_only_dict: Dict[str, Any] = dict(keyword_only) 1142 if owner_parameter_name in keyword_only_dict: 1143 possible_keyword_self = keyword_only_dict[owner_parameter_name] 1144 if hasattr(possible_keyword_self, entity_name_str): 1145 possible_entity = getattr_ex(possible_keyword_self, entity_name_str) 1146 possible_entity_code = get_code(possible_entity) 1147 entity_code = get_code(entity) 1148 if possible_entity_code is entity_code: 1149 return possible_keyword_self 1150 1151 raise AnAppropriateOwnerParameterWasNotFoundError(f'Can not find {owner_parameter_name} parameter in {entity}') 1152 1153 1154def get_any_self_parameter(entity, any_positional: bool = True, any_keyword: bool = True): 1155 return get_owner_parameter(entity, 'self', any_positional, any_keyword) 1156 1157 1158def get_any_cls_parameter(entity, any_positional: bool = True, any_keyword: bool = True): 1159 return get_owner_parameter(entity, 'cls' , any_positional, any_keyword) 1160 1161 1162def find_method_in_module_by_code(module, code_to_find: CodeType) -> Optional[CodeType]: 1163 for entity_name_str in dir(module): 1164 entity = getattr_ex(module, entity_name_str) 1165 if inspect.isclass(entity): 1166 possible_method = find_method_in_class_by_code(entity, code_to_find) 1167 if possible_method is not None: 1168 return possible_method 1169 1170 return None 1171 1172 1173def find_method_in_class_by_code(class_to_search_in, code_to_find: CodeType) -> Optional[CodeType]: 1174 subclassess = list() 1175 for entity_name_str in class_properties_including_overrided(class_to_search_in): 1176 entity = getattr_ex(class_to_search_in, entity_name_str) 1177 if inspect.isclass(entity): 1178 subclassess.append(entity) 1179 elif inspect.isfunction(entity) or inspect.ismethod(entity): 1180 if get_code(entity) is code_to_find: 1181 return entity 1182 1183 for subclass in subclassess: 1184 possible_method = find_method_in_class_by_code(subclass, code_to_find) 1185 if possible_method is not None: 1186 return possible_method 1187 1188 return None 1189 1190 1191class EntityWasNotFoundError(Exception): 1192 pass 1193 1194 1195def find_entity(entity: Union[Callable, FrameType, CodeType]) -> Callable: 1196 if not (inspect.isfunction(entity) or inspect.ismethod(entity) or isinstance(entity, FrameType) or isinstance(entity, CodeType)): 1197 raise TypeError(f'Only functions, methods, frames and codes are supported. {type(entity)} was provided instead') 1198 1199 result = get_function_by_entity(entity) 1200 if result is not None: 1201 return result 1202 1203 result = get_method_by_entity(entity) 1204 if result is not None: 1205 return result 1206 1207 entity_name_str: str = entity_name(entity) 1208 entity_instance: Callable = None 1209 if isinstance(entity, FrameType): 1210 owner = None 1211 need_to_try_clr: bool = False 1212 try: 1213 owner = get_self_parameter(entity) 1214 except AnAppropriateOwnerParameterWasNotFoundError: 1215 need_to_try_clr = True 1216 1217 if need_to_try_clr: 1218 try: 1219 owner = get_cls_parameter(entity) 1220 except AnAppropriateOwnerParameterWasNotFoundError: 1221 pass 1222 1223 entity_code = entity.f_code 1224 if owner is not None: 1225 entity_instance = getattr_ex(owner, entity_name_str) 1226 if get_code(entity_instance) is entity_code: 1227 return entity_instance 1228 1229 entity = entity_code 1230 1231 if isinstance(entity, CodeType): 1232 entity_owner_instance = entity_owner(entity) 1233 entity_instance = find_method_in_module_by_code(entity_owner_instance, entity) 1234 if entity_instance is not None: 1235 return entity_instance 1236 1237 raise EntityWasNotFoundError 1238 1239 1240def find_current_entity(depth: Optional[int] = 1) -> Callable: 1241 return find_entity(frame(depth + 1))
Common base class for all non-exit exceptions.
Inherited Members
- builtins.Exception
- Exception
- builtins.BaseException
- with_traceback
- args
Common base class for all non-exit exceptions.
Inherited Members
- builtins.Exception
- Exception
- builtins.BaseException
- with_traceback
- args
58def frame(depth: Optional[int] = 1) -> FrameType: 59 """ 60 :param depth: 0 - frame of this function, 1 - frame of the caller function, etc. 61 :return: 62 """ 63 depth = depth or 0 64 if depth < 0: 65 raise WrongDepth(depth) 66 67 result = inspect.currentframe() 68 if result is None: 69 raise CanNotRetrieveFrame() 70 71 for i in range(depth): 72 result = result.f_back 73 74 return result
:param depth: 0 - frame of this function, 1 - frame of the caller function, etc. :return:
103def entity_arguments_description(entity: Callable) -> Tuple[Set[str], Sequence[str], Sequence[str], Sequence[str]]: 104 init_code = get_code(entity) 105 cpn: CodeParamNames = code_param_names(init_code) 106 positional = cpn.positional 107 positional_only = cpn.positional_only 108 keyword_only = cpn.keyword_only 109 all: Set[str] = set(positional) | set(positional_only) | set(keyword_only) 110 return all, positional, positional_only, keyword_only
142def entity_qualname(entity): 143 if isinstance(entity, FrameType): 144 entity = entity.f_code 145 146 if isinstance(entity, CodeType): 147 if sys.version_info >= (3, 11): 148 return code_qualname(entity) 149 else: 150 # raise RuntimeError('CodeType.__qualname__ is available only since Python 3.11') 151 entity_instance = find_entity(entity) 152 return f'{entity_owner_name(entity_instance)}.{entity_name(entity_instance)}' 153 else: 154 return func_qualname(entity)
157def entity_class(func) -> Optional[Type]: 158 if inspect.ismethod(func): 159 for func_class in inspect.getmro(func.__self__.__class__): 160 if func_class.__dict__.get(func.__name__) is func: 161 return func_class 162 163 func_of_the_bound_method = func.__func__ 164 for func_class in inspect.getmro(func.__self__.__class__): 165 if func_class.__dict__.get(func.__name__) is func_of_the_bound_method: 166 return func_class 167 168 func = func_of_the_bound_method 169 170 if inspect.isfunction(func): 171 try: 172 func_class = getattr_ex(inspect.getmodule(func), func.__qualname__.split('.<locals>', 1)[0].rsplit('.', 1)[0]) 173 except AttributeError: 174 return None 175 176 if isinstance(func_class, type): 177 return func_class 178 179 return getattr_ex(func, '__objclass__', None)
182def entity_owner(func) -> Optional[Union[Type, ModuleType]]: 183 func_module = None 184 if inspect.ismethod(func): 185 for func_class in inspect.getmro(func.__self__.__class__): 186 if func_class.__dict__.get(func.__name__) is func: 187 return func_class 188 189 func_of_the_bound_method = func.__func__ 190 for func_class in inspect.getmro(func.__self__.__class__): 191 if func_class.__dict__.get(func.__name__) is func_of_the_bound_method: 192 return func_class 193 194 func = func_of_the_bound_method 195 196 if inspect.isfunction(func): 197 func_module = inspect.getmodule(func) 198 try: 199 func_class = getattr_ex(func_module, func.__qualname__.split('.<locals>', 1)[0].rsplit('.', 1)[0]) 200 except AttributeError: 201 return func_module 202 203 if isinstance(func_class, type): 204 return func_class 205 else: 206 return func_module 207 208 try: 209 return getattr_ex(func, '__objclass__') 210 except AttributeError: 211 if func_module is None: 212 func_module = inspect.getmodule(func) 213 214 return func_module
221def get_module_importable_str_and_path(module) -> Tuple[str, str]: 222 if not inspect.ismodule(module): 223 raise TypeError(f'Only modules are supported. {type(module)} was provided instead') 224 225 module_repr: str = repr(module) 226 importable_str = module_repr[find_text_in_brackets(module_repr, module_repr_importable_str_bracket_pair)] 227 full_file_path = module_repr[find_text_in_brackets(module_repr, module_repr_full_file_path_bracket_pair)] 228 return importable_str, full_file_path
231def entity_owning_module_info_and_owning_path(entity) -> Tuple[ModuleType, str, str, List[Union[Type, ModuleType]]]: 232 owning_path: List = list() 233 module = None 234 owner_is_module: bool = False 235 while not owner_is_module: 236 module = entity_owner(entity) 237 owning_path.append(module) 238 entity = module 239 owner_is_module = inspect.ismodule(module) 240 241 module_importable_str, module_file_full_path = get_module_importable_str_and_path(module) 242 return module, module_importable_str, module_file_full_path, owning_path
250def entity_module_importable_str_and_owning_names_path(entity) -> Tuple[str, List[str]]: 251 _, module_importable_str, _, owning_path = entity_owning_module_info_and_owning_path(entity) 252 owning_path = owning_path[:-1] 253 owning_names_path = [entity_name(owner) for owner in owning_path] 254 return module_importable_str, owning_names_path
257def entity_by_name_module_importable_str_and_owning_names_path(entity_name: str, module_importable_str: str, owning_names_path: List[str]) -> Any: 258 owner = import_module(module_importable_str) 259 for owner_name in reversed(owning_names_path): 260 owner = getattr(owner, owner_name) 261 262 return getattr(owner, entity_name)
277def normalized_code_owner_repr(code: CodeType, owner: Optional[Union[Type, ModuleType]]) -> str: 278 if owner is None: 279 return str() 280 281 owner_repr: str = repr(owner) 282 result, _ = replace_text_with_brackets(owner_repr, module_repr_limited_bracket_pair, f" line {code.co_firstlineno}>", 1) 283 return result
319def fill_code_params_with_values(code_params: CodeParamNames, args, kwargs) -> Tuple[CodeParamsWithValues, Tuple, Dict]: 320 positional, positional_only, keyword_only = code_params 321 positional_len = len(positional) 322 positional_only_len = len(positional_only) 323 keyword_only_len = len(keyword_only) 324 positional_only_delimiter_place: Optional[int] = None 325 if positional_only_len: 326 positional_only_delimiter_place = positional_only_len 327 328 positional_values = tuple(((arg, args[index]) for index, arg in enumerate(positional))) 329 if positional_only_len: 330 positional_only_values = tuple(((arg, args[index]) for index, arg in enumerate(positional_only))) 331 else: 332 positional_only_values = tuple() 333 334 if keyword_only_len: 335 keyword_only_values = tuple(((arg, kwargs[arg]) for arg in keyword_only)) 336 else: 337 keyword_only_values = tuple() 338 339 result_args: Tuple = args[positional_len:] 340 result_kwargs: Dict = {key: value for key, value in kwargs.items() if key not in keyword_only} 341 342 return CodeParamsWithValues(positional_values, positional_only_values, keyword_only_values), result_args, result_kwargs
349def intro_frame_params_with_values(frame_instance) -> CodeParamsWithValues: 350 positional, positional_only, keyword_only = frame_param_names(frame_instance) 351 fr_locals = frame_instance.f_locals 352 return CodeParamsWithValues(tuple(((arg, fr_locals[arg]) for arg in positional)), \ 353 tuple(((arg, fr_locals[arg]) for arg in positional_only)), \ 354 tuple(((arg, fr_locals[arg]) for arg in keyword_only)))
380def code_params_with_values_to_signature_items_gen(code_params_with_values: CodeParamsWithValues, verbose: bool = False) -> Generator[str, None, None]: 381 positional, positional_only, keyword_only = code_params_with_values 382 positional_len = len(positional) 383 positional_only_len = len(positional_only) 384 keyword_only_len = len(keyword_only) 385 positional_only_delimiter_place: Optional[int] = None 386 if positional_only_len: 387 positional_only_delimiter_place = positional_only_len 388 389 for index, arg in enumerate(positional): 390 arg_name, arg_value = arg 391 if (positional_only_delimiter_place is not None) and (index == positional_only_delimiter_place): 392 yield '/' 393 394 if verbose: 395 yield f'{arg_name}={arg_value}' 396 else: 397 yield str(arg_value) 398 399 if keyword_only_len: 400 yield '*' 401 for arg in keyword_only: 402 arg_name, arg_value = arg 403 yield f'{arg_name}={arg_value}'
406def code_params_to_signature_items_gen(code_params: CodeParamNames) -> Generator[str, None, None]: 407 positional, positional_only, keyword_only = code_params 408 positional_len = len(positional) 409 positional_only_len = len(positional_only) 410 keyword_only_len = len(keyword_only) 411 positional_only_delimiter_place: Optional[int] = None 412 if positional_only_len: 413 positional_only_delimiter_place = positional_only_len 414 415 for index, arg in enumerate(positional): 416 if (positional_only_delimiter_place is not None) and (index == positional_only_delimiter_place): 417 yield '/' 418 419 # yield arg[0] 420 yield arg 421 422 if keyword_only_len: 423 yield '*' 424 for arg in keyword_only: 425 # yield arg[0] 426 yield arg
429def code_params_with_values_to_signature(params_with_values: CodeParamsWithValues, verbose: bool = False, formatted: bool = False) -> str: 430 if formatted: 431 delimiter = ',\n\t' 432 else: 433 delimiter = ', ' 434 435 return delimiter.join(code_params_with_values_to_signature_items_gen(params_with_values, verbose))
447def entity_repr_limited(entity, formatted: bool = False): 448 if isinstance(entity, FrameType): 449 entity = entity.f_code 450 451 if isinstance(entity, CodeType): 452 code = entity 453 else: 454 code = get_code(entity) 455 456 func_name = code_name(code) 457 param_names = code_param_names(code) 458 function_params_str = code_params_to_signature(param_names, formatted) 459 return f'{func_name}({function_params_str})'
462def entity_repr_limited_try_qualname(entity, formatted: bool = False): 463 if has_code(entity): 464 if isinstance(entity, FrameType): 465 entity = entity.f_code 466 467 if isinstance(entity, CodeType): 468 code = entity 469 func_name = code_name(code) 470 else: 471 code = get_code(entity) 472 func_name = func_qualname(entity) 473 474 param_names = code_param_names(code) 475 function_params_str = code_params_to_signature(param_names, formatted) 476 return f'{func_name}({function_params_str})' 477 else: 478 entity_type_name = type(entity).__name__ 479 entity_properties_with_values = entity_properties_values(entity) 480 if formatted: 481 delimiter = ',\n\t' 482 else: 483 delimiter = ', ' 484 485 entity_properties_str = delimiter.join([f'{key}={value}' for key, value in entity_properties_with_values.items()]) 486 return f'{entity_type_name}({entity_properties_str})'
489def entity_repr_owner_based(entity, formatted: bool = False): 490 if isinstance(entity, FrameType): 491 entity = entity.f_code 492 493 owner = entity_owner(entity) 494 if isinstance(entity, CodeType): 495 owner_repr = normalized_code_owner_repr(entity, owner) 496 else: 497 owner_repr = normalized_owner_repr(owner) 498 499 if isinstance(owner, ModuleType): 500 _entity_repr_limited = entity_repr_limited_try_qualname 501 else: 502 _entity_repr_limited = entity_repr_limited 503 504 if owner_repr: 505 return f'{owner_repr}.{_entity_repr_limited(entity, formatted)}' 506 else: 507 return _entity_repr_limited(entity, formatted)
510def entity_repr(entity, formatted: bool = False): 511 if isinstance(entity, FrameType): 512 entity = entity.f_code 513 514 module = inspect.getmodule(entity) 515 if isinstance(entity, CodeType): 516 owner_repr = normalized_code_owner_repr(entity, module) 517 else: 518 owner_repr = normalized_owner_repr(module) 519 520 if owner_repr: 521 return f'{owner_repr}.{entity_repr_limited_try_qualname(entity, formatted)}' 522 else: 523 return entity_repr_limited_try_qualname(entity, formatted)
526def entity_properties(entity) -> Set[str]: 527 """ 528 Example: 529 from cengal.parallel_execution.coroutines.coro_standard_services.wait_coro import WaitCoroRequest 530 from cengal.introspection.inspect import entity_properties 531 532 print(entity_properties(WaitCoroRequest)) 533 >> {'__weakref__', 'put_list', 'fastest', 'atomic', 'list', 'single', 'put_fastest', '_save', 'put_single', 'put_atomic'} 534 535 536 print(entity_properties(WaitCoroRequest())) 537 >> {'result_required', 'args', 'tree', 'kill_on_timeout', 'timeout', 'request_type', 'kwargs', 'provide_to_request_handler'} 538 539 540 def my_func(a, b, *, c, d): 541 return a + b + c + d 542 543 my_func.my_property = 2 544 545 print(entity_properties(my_func)) 546 >> {'my_property'} 547 548 549 Args: 550 entity (_type_): _description_ 551 552 Returns: 553 Set[str]: _description_ 554 """ 555 entity_type_items = set(dir(type(entity))) 556 entity_items = set(dir(entity)) 557 return entity_items - entity_type_items
Example: from cengal.parallel_execution.coroutines.coro_standard_services.wait_coro import WaitCoroRequest from cengal.introspection.inspect import entity_properties
print(entity_properties(WaitCoroRequest))
>> {'__weakref__', 'put_list', 'fastest', 'atomic', 'list', 'single', 'put_fastest', '_save', 'put_single', 'put_atomic'}
print(entity_properties(WaitCoroRequest()))
>> {'result_required', 'args', 'tree', 'kill_on_timeout', 'timeout', 'request_type', 'kwargs', 'provide_to_request_handler'}
def my_func(a, b, *, c, d):
return a + b + c + d
my_func.my_property = 2
print(entity_properties(my_func))
>> {'my_property'}
Args: entity (_type_): _description_
Returns: Set[str]: _description_
568def class_properties(entity: Type) -> Set[str]: 569 """ 570 Example: 571 572 Args: 573 entity (_type_): _description_ 574 575 Returns: 576 Set[str]: _description_ 577 """ 578 entity_type_items = set(dir(type(entity))) 579 entity_items = set(dir(entity)) 580 mro = inspect.getmro(entity) 581 base_members: Set = set() 582 for base in mro: 583 if base is entity: 584 continue 585 586 base_members |= set(dir(base)) 587 588 return (entity_items - entity_type_items) - base_members
Example:
Args: entity (_type_): _description_
Returns: Set[str]: _description_
599def class_properties_withot_object(entity: Type) -> Set[str]: 600 """ 601 Example: 602 603 Args: 604 entity (_type_): _description_ 605 606 Returns: 607 Set[str]: _description_ 608 """ 609 object_type_items = set(dir(object)) 610 entity_items = set(dir(entity)) 611 return entity_items - object_type_items
Example:
Args: entity (_type_): _description_
Returns: Set[str]: _description_
622def class_properties_including_overrided(entity: Type) -> Set[str]: 623 """ 624 Example: 625 626 Args: 627 entity (_type_): _description_ 628 629 Returns: 630 Set[str]: _description_ 631 """ 632 entity_type_items = set(dir(type(entity))) 633 entity_items = set(entity.__dict__.keys()) 634 return entity_items - entity_type_items
Example:
Args: entity (_type_): _description_
Returns: Set[str]: _description_
645def intro_frame_repr_limited(frame_instance, verbose: bool = False): 646 func_name = code_name(frame_instance.f_code) 647 params_with_values = intro_frame_params_with_values(frame_instance) 648 function_params_str = code_params_with_values_to_signature(params_with_values, verbose) 649 return f'{func_name}({function_params_str})'
652def intro_frame_repr(frame_instance, verbose: bool = False): 653 code = frame_instance.f_code 654 func_name = code_name(code) 655 module = inspect.getmodule(code) 656 owner_repr = normalized_code_owner_repr(code, module) 657 params_with_values = intro_frame_params_with_values(frame_instance) 658 function_params_str = code_params_with_values_to_signature(params_with_values, verbose) 659 return f'{owner_repr}.{func_name}({function_params_str})'
684def get_str_of_data_info(data): 685 """Returns string with data info: type and value 686 687 Args: 688 data (_type_): _description_ 689 690 Returns: 691 _type_: _description_ 692 """ 693 return f'type: {type(data)}; value: {data}'
Returns string with data info: type and value
Args: data (_type_): _description_
Returns: _type_: _description_
684def get_str_of_data_info(data): 685 """Returns string with data info: type and value 686 687 Args: 688 data (_type_): _description_ 689 690 Returns: 691 _type_: _description_ 692 """ 693 return f'type: {type(data)}; value: {data}'
Returns string with data info: type and value
Args: data (_type_): _description_
Returns: _type_: _description_
699def get_multistr_of_data_info(data, shift_num: Optional[int] = None, shift_char: str = '\t'): 700 """Returns multiline string with data info: type and value 701 702 Args: 703 data (_type_): _description_ 704 705 Returns: 706 _type_: _description_ 707 """ 708 shift_num = shift_num or 0 709 shift_str = shift_char * shift_num 710 from pprint import pformat 711 data_str = pformat(data) 712 data_str_lines = data_str.split('\n') 713 data_str = '\n'.join([f'{shift_str}{line}' for line in data_str_lines]) 714 return f'type: {type(data)}; value: \n{data_str}'
Returns multiline string with data info: type and value
Args: data (_type_): _description_
Returns: _type_: _description_
699def get_multistr_of_data_info(data, shift_num: Optional[int] = None, shift_char: str = '\t'): 700 """Returns multiline string with data info: type and value 701 702 Args: 703 data (_type_): _description_ 704 705 Returns: 706 _type_: _description_ 707 """ 708 shift_num = shift_num or 0 709 shift_str = shift_char * shift_num 710 from pprint import pformat 711 data_str = pformat(data) 712 data_str_lines = data_str.split('\n') 713 data_str = '\n'.join([f'{shift_str}{line}' for line in data_str_lines]) 714 return f'type: {type(data)}; value: \n{data_str}'
Returns multiline string with data info: type and value
Args: data (_type_): _description_
Returns: _type_: _description_
720def get_multistr_of_data_value(data, shift_num: Optional[int] = None, shift_char: str = '\t'): 721 """Returns multiline string with data value 722 723 Args: 724 data (_type_): _description_ 725 726 Returns: 727 _type_: _description_ 728 """ 729 shift_num = shift_num or 0 730 shift_str = shift_char * shift_num 731 from pprint import pformat 732 data_str = pformat(data) 733 data_str_lines = data_str.split('\n') 734 data_str = '\n'.join([f'{shift_str}{line}' for line in data_str_lines]) 735 return data_str
Returns multiline string with data value
Args: data (_type_): _description_
Returns: _type_: _description_
720def get_multistr_of_data_value(data, shift_num: Optional[int] = None, shift_char: str = '\t'): 721 """Returns multiline string with data value 722 723 Args: 724 data (_type_): _description_ 725 726 Returns: 727 _type_: _description_ 728 """ 729 shift_num = shift_num or 0 730 shift_str = shift_char * shift_num 731 from pprint import pformat 732 data_str = pformat(data) 733 data_str_lines = data_str.split('\n') 734 data_str = '\n'.join([f'{shift_str}{line}' for line in data_str_lines]) 735 return data_str
Returns multiline string with data value
Args: data (_type_): _description_
Returns: _type_: _description_
741def print_data_info(data): 742 """Print data info: type and value 743 744 Args: 745 data (_type_): _description_ 746 """ 747 print(get_str_of_data_info(data))
Print data info: type and value
Args: data (_type_): _description_
741def print_data_info(data): 742 """Print data info: type and value 743 744 Args: 745 data (_type_): _description_ 746 """ 747 print(get_str_of_data_info(data))
Print data info: type and value
Args: data (_type_): _description_
791def is_filled_descriptor(owning_object, entity) -> bool: 792 """ 793 class _foo: 794 __slots__ = ['foo', 'bar'] 795 796 def __init__(self): 797 self.bar = 2 798 799 'foo' - not filled 800 'bar' - filled 801 802 Args: 803 owning_object (_type_): _description_ 804 entity (_type_): _description_ 805 806 Returns: 807 _type_: _description_ 808 """ 809 try: 810 entity.__get__(owning_object) 811 except AttributeError: 812 return False 813 814 return True
class _foo: __slots__ = ['foo', 'bar']
def __init__(self):
self.bar = 2
'foo' - not filled 'bar' - filled
Args: owning_object (_type_): _description_ entity (_type_): _description_
Returns: _type_: _description_
817def filled_slots_names(owning_object) -> Optional[List[str]]: 818 try: 819 slots_names = owning_object.__slots__ 820 except AttributeError: 821 return None 822 823 result = list() 824 for slot_name in slots_names: 825 slot = inspect.getattr_static(owning_object, slot_name) 826 if is_filled_descriptor(owning_object, slot): 827 result.append(slot_name) 828 829 return result
832def filled_slots(owning_object) -> Optional[List[Any]]: 833 try: 834 slots_names = owning_object.__slots__ 835 except AttributeError: 836 return None 837 838 result = list() 839 for slot_name in slots_names: 840 slot = inspect.getattr_static(owning_object, slot_name) 841 if is_filled_descriptor(owning_object, slot): 842 result.append(slot) 843 844 return result
847def filled_slots_with_names(owning_object) -> Optional[List[Tuple[str, Any]]]: 848 try: 849 slots_names = owning_object.__slots__ 850 except AttributeError: 851 return None 852 853 result = list() 854 for slot_name in slots_names: 855 slot = inspect.getattr_static(owning_object, slot_name) 856 if is_filled_descriptor(owning_object, slot): 857 result.append((slot_name, slot)) 858 859 return result
862def filled_slots_with_names_gen(owning_object) -> Generator[Tuple[str, Any], Any, Any]: 863 try: 864 slots_names = owning_object.__slots__ 865 for slot_name in slots_names: 866 slot = inspect__getattr_static(owning_object, slot_name) 867 try: 868 slot.__get__(owning_object) 869 yield (slot_name, slot) 870 except AttributeError: 871 pass 872 except AttributeError: 873 pass
876def filled_slot_names_with_values_gen(owning_object) -> Generator[Tuple[str, Any], Any, Any]: 877 try: 878 slots_names = owning_object.__slots__ 879 for slot_name in slots_names: 880 try: 881 yield (slot_name, getattr(owning_object, slot_name)) 882 except AttributeError: 883 pass 884 except AttributeError: 885 pass
924def getattr_ex(entity, attr_name: str) -> Any: 925 try: 926 return getattr(entity, attr_name) 927 except AttributeError: # See code of the `inspect.getmembers()` 928 if attr_name in entity.__dict__: 929 return entity.__dict__[attr_name] 930 else: 931 raise AttributeError(f'Attribute "{attr_name}" was not found in the entity "{entity}"')
934def entity_is_function(entity) -> bool: 935 owner: Optional[Union[Type, ModuleType]] = entity_owner(entity) 936 if owner is None: 937 return False 938 939 if inspect.ismodule(owner): 940 entity_name_str: str = entity_name(entity) 941 if hasattr(owner, entity_name_str): 942 possible_entity = getattr_ex(owner, entity_name_str) 943 possible_entity_code = get_code(possible_entity) 944 entity_code = get_code(entity) 945 if possible_entity_code is entity_code: 946 return True 947 else: 948 return False 949 else: 950 return False 951 else: 952 return False
955def get_function_by_entity(entity) -> Optional[Callable]: 956 owner: Optional[Union[Type, ModuleType]] = entity_owner(entity) 957 if owner is None: 958 return None 959 960 if inspect.ismodule(owner): 961 entity_name_str: str = entity_name(entity) 962 if hasattr(owner, entity_name_str): 963 possible_entity = getattr_ex(owner, entity_name_str) 964 possible_entity_code = get_code(possible_entity) 965 entity_code = get_code(entity) 966 if possible_entity_code is entity_code: 967 return possible_entity 968 else: 969 return None 970 else: 971 return None 972 else: 973 return None
976def entity_is_method(entity) -> bool: 977 owner: Optional[Union[Type, ModuleType]] = entity_owner(entity) 978 if owner is None: 979 return False 980 981 if inspect.isclass(owner): 982 entity_name_str: str = entity_name(entity) 983 if hasattr(owner, entity_name_str): 984 possible_entity = getattr_ex(owner, entity_name_str) 985 possible_entity_code = get_code(possible_entity) 986 entity_code = get_code(entity) 987 if possible_entity_code is entity_code: 988 return True 989 else: 990 return False 991 else: 992 return False 993 else: 994 return False
997def get_method_by_entity(entity) -> Optional[Callable]: 998 owner: Optional[Union[Type, ModuleType]] = entity_owner(entity) 999 if owner is None: 1000 return None 1001 1002 if inspect.isclass(owner): 1003 entity_name_str: str = entity_name(entity) 1004 if hasattr(owner, entity_name_str): 1005 possible_entity = getattr_ex(owner, entity_name_str) 1006 possible_entity_code = get_code(possible_entity) 1007 entity_code = get_code(entity) 1008 if possible_entity_code is entity_code: 1009 return possible_entity 1010 else: 1011 return None 1012 else: 1013 return None 1014 else: 1015 return None
1018def entity_is_unbound_method(entity): 1019 owner: Optional[Union[Type, ModuleType]] = entity_owner(entity) 1020 if owner is None: 1021 return False 1022 1023 if inspect.ismodule(owner): 1024 entity_name_str: str = entity_name(entity) 1025 if hasattr(owner, entity_name_str): 1026 possible_entity = getattr_ex(owner, entity_name_str) 1027 possible_entity_code = get_code(possible_entity) 1028 entity_code = get_code(entity) 1029 if possible_entity_code is entity_code: 1030 return False 1031 else: 1032 return True 1033 else: 1034 return True 1035 else: 1036 return False
Common base class for all non-exit exceptions.
Inherited Members
- builtins.Exception
- Exception
- builtins.BaseException
- with_traceback
- args
1047class PossibleOwnerParameterDoesNotMatchError(AnAppropriateOwnerParameterWasNotFoundError): 1048 pass
Common base class for all non-exit exceptions.
Inherited Members
- builtins.Exception
- Exception
- builtins.BaseException
- with_traceback
- args
1051class EntityHasNoPositionalParametersError(AnAppropriateOwnerParameterWasNotFoundError): 1052 pass
Common base class for all non-exit exceptions.
Inherited Members
- builtins.Exception
- Exception
- builtins.BaseException
- with_traceback
- args
1055def get_owner_parameter(entity, owner_parameter_name: str, return_even_if_not_match: bool = False): 1056 if entity_is_function(entity): 1057 raise TypeError(f'Function has no {owner_parameter_name} parameter') 1058 1059 if entity_is_method(entity): 1060 return entity.__self__ 1061 elif entity_is_unbound_method(entity): 1062 if isinstance(entity, FrameType): 1063 entity_name_str: str = entity_name(entity) 1064 params_with_values: CodeParamsWithValues = intro_frame_params_with_values(entity) 1065 positional, positional_only, keyword_only = params_with_values 1066 if positional: 1067 possible_positional_self = positional[0][1] 1068 elif positional_only: 1069 possible_positional_self = positional_only[0][1] 1070 else: 1071 raise EntityHasNoPositionalParametersError 1072 1073 if hasattr(possible_positional_self, entity_name_str): 1074 possible_entity = getattr_ex(possible_positional_self, entity_name_str) 1075 possible_entity_code = get_code(possible_entity) 1076 entity_code = get_code(entity) 1077 if possible_entity_code is entity_code: 1078 return possible_positional_self 1079 else: 1080 if return_even_if_not_match: 1081 return possible_positional_self 1082 else: 1083 raise PossibleOwnerParameterDoesNotMatchError 1084 1085 raise AnAppropriateOwnerParameterWasNotFoundError(f'Can not find an appropriate {owner_parameter_name} parameter in {entity}') 1086 else: 1087 raise TypeError(f'{entity} of type {type(entity)} is not supported')
1098def get_any_owner_parameter(entity, owner_parameter_name: str, any_positional: bool = True, any_keyword: bool = True): 1099 if entity_is_function(entity): 1100 raise TypeError(f'Function has no {owner_parameter_name} parameter') 1101 1102 if entity_is_method(entity): 1103 return entity.__self__ 1104 elif entity_is_unbound_method(entity): 1105 if isinstance(entity, FrameType): 1106 entity_name_str: str = entity_name(entity) 1107 params_with_values: CodeParamsWithValues = intro_frame_params_with_values(entity) 1108 positional, positional_only, keyword_only = params_with_values 1109 1110 if any_positional: 1111 all_positional = positional + positional_only 1112 for param in all_positional: 1113 possible_positional_self_name, possible_positional_self = param 1114 if hasattr(possible_positional_self, entity_name_str): 1115 possible_entity = getattr_ex(possible_positional_self, entity_name_str) 1116 possible_entity_code = get_code(possible_entity) 1117 entity_code = get_code(entity) 1118 if possible_entity_code is entity_code: 1119 return possible_positional_self 1120 else: 1121 if positional: 1122 possible_positional_self = positional[0][1] 1123 elif positional_only: 1124 possible_positional_self = positional_only[0][1] 1125 1126 if hasattr(possible_positional_self, entity_name_str): 1127 possible_entity = getattr_ex(possible_positional_self, entity_name_str) 1128 possible_entity_code = get_code(possible_entity) 1129 entity_code = get_code(entity) 1130 if possible_entity_code is entity_code: 1131 return possible_positional_self 1132 1133 if any_keyword: 1134 for possible_keyword_self_name, possible_keyword_self in keyword_only: 1135 if hasattr(possible_keyword_self, entity_name_str): 1136 possible_entity = getattr_ex(possible_keyword_self, entity_name_str) 1137 possible_entity_code = get_code(possible_entity) 1138 entity_code = get_code(entity) 1139 if possible_entity_code is entity_code: 1140 return possible_keyword_self 1141 else: 1142 keyword_only_dict: Dict[str, Any] = dict(keyword_only) 1143 if owner_parameter_name in keyword_only_dict: 1144 possible_keyword_self = keyword_only_dict[owner_parameter_name] 1145 if hasattr(possible_keyword_self, entity_name_str): 1146 possible_entity = getattr_ex(possible_keyword_self, entity_name_str) 1147 possible_entity_code = get_code(possible_entity) 1148 entity_code = get_code(entity) 1149 if possible_entity_code is entity_code: 1150 return possible_keyword_self 1151 1152 raise AnAppropriateOwnerParameterWasNotFoundError(f'Can not find {owner_parameter_name} parameter in {entity}')
1163def find_method_in_module_by_code(module, code_to_find: CodeType) -> Optional[CodeType]: 1164 for entity_name_str in dir(module): 1165 entity = getattr_ex(module, entity_name_str) 1166 if inspect.isclass(entity): 1167 possible_method = find_method_in_class_by_code(entity, code_to_find) 1168 if possible_method is not None: 1169 return possible_method 1170 1171 return None
1174def find_method_in_class_by_code(class_to_search_in, code_to_find: CodeType) -> Optional[CodeType]: 1175 subclassess = list() 1176 for entity_name_str in class_properties_including_overrided(class_to_search_in): 1177 entity = getattr_ex(class_to_search_in, entity_name_str) 1178 if inspect.isclass(entity): 1179 subclassess.append(entity) 1180 elif inspect.isfunction(entity) or inspect.ismethod(entity): 1181 if get_code(entity) is code_to_find: 1182 return entity 1183 1184 for subclass in subclassess: 1185 possible_method = find_method_in_class_by_code(subclass, code_to_find) 1186 if possible_method is not None: 1187 return possible_method 1188 1189 return None
Common base class for all non-exit exceptions.
Inherited Members
- builtins.Exception
- Exception
- builtins.BaseException
- with_traceback
- args
1196def find_entity(entity: Union[Callable, FrameType, CodeType]) -> Callable: 1197 if not (inspect.isfunction(entity) or inspect.ismethod(entity) or isinstance(entity, FrameType) or isinstance(entity, CodeType)): 1198 raise TypeError(f'Only functions, methods, frames and codes are supported. {type(entity)} was provided instead') 1199 1200 result = get_function_by_entity(entity) 1201 if result is not None: 1202 return result 1203 1204 result = get_method_by_entity(entity) 1205 if result is not None: 1206 return result 1207 1208 entity_name_str: str = entity_name(entity) 1209 entity_instance: Callable = None 1210 if isinstance(entity, FrameType): 1211 owner = None 1212 need_to_try_clr: bool = False 1213 try: 1214 owner = get_self_parameter(entity) 1215 except AnAppropriateOwnerParameterWasNotFoundError: 1216 need_to_try_clr = True 1217 1218 if need_to_try_clr: 1219 try: 1220 owner = get_cls_parameter(entity) 1221 except AnAppropriateOwnerParameterWasNotFoundError: 1222 pass 1223 1224 entity_code = entity.f_code 1225 if owner is not None: 1226 entity_instance = getattr_ex(owner, entity_name_str) 1227 if get_code(entity_instance) is entity_code: 1228 return entity_instance 1229 1230 entity = entity_code 1231 1232 if isinstance(entity, CodeType): 1233 entity_owner_instance = entity_owner(entity) 1234 entity_instance = find_method_in_module_by_code(entity_owner_instance, entity) 1235 if entity_instance is not None: 1236 return entity_instance 1237 1238 raise EntityWasNotFoundError