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))
class WrongDepth(builtins.Exception):
50class WrongDepth(Exception):
51    pass

Common base class for all non-exit exceptions.

Inherited Members
builtins.Exception
Exception
builtins.BaseException
with_traceback
args
class CanNotRetrieveFrame(builtins.Exception):
54class CanNotRetrieveFrame(Exception):
55    pass

Common base class for all non-exit exceptions.

Inherited Members
builtins.Exception
Exception
builtins.BaseException
with_traceback
args
def frame(depth: typing.Union[int, NoneType] = 1) -> frame:
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:

def get_exception() -> Exception:
77def get_exception() -> Exception:
78    ex_type, ex_value, ex_traceback = sys.exc_info()
79    return ex_value.with_traceback(ex_traceback)
def get_exception_tripple() -> Tuple[Type, Exception, Any]:
82def get_exception_tripple() -> Tuple[Type, Exception, Any]:
83    return sys.exc_info()
def exception_to_printable_text(exception: Exception) -> str:
86def exception_to_printable_text(exception: Exception) -> str:
87    # return ''.join(traceback.format_exception(type(exception), exception, exception.__traceback__))
88    return ''.join(traceback.TracebackException.from_exception(exception).format())
def is_async(entity) -> bool:
91def is_async(entity) -> bool:
92    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)
def is_callable(entity) -> bool:
95def is_callable(entity) -> bool:
96    return callable(entity)
def func_param_names( func) -> cengal.code_flow_control.python_bytecode_manipulator.versions.v_0.python_bytecode_manipulator.CodeParamNames:
 99def func_param_names(func) -> CodeParamNames:
100    return code_param_names(get_code(func))
def entity_arguments_description( entity: typing.Callable) -> Tuple[Set[str], Sequence[str], Sequence[str], Sequence[str]]:
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
def func_code_name(func):
113def func_code_name(func):
114    code = get_code(func)
115    return code_name(code)
def func_name(func):
118def func_name(func):
119    try:
120        return func.__name__
121    except AttributeError:
122        return str()
def func_qualname(func):
125def func_qualname(func):
126    try:
127        return func.__qualname__
128    except AttributeError:
129        return str()
def entity_name(entity):
132def entity_name(entity):
133    if isinstance(entity, FrameType):
134        entity = entity.f_code
135    
136    if isinstance(entity, CodeType):
137        return code_name(entity)
138    else:
139        return func_name(entity)
def entity_qualname(entity):
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)
def entity_class(func) -> Union[Type, NoneType]:
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)
def entity_owner(func) -> Union[Type, module, NoneType]:
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
module_repr_importable_str_bracket_pair: cengal.text_processing.brackets_processing.versions.v_0.brackets.BracketPair = <cengal.text_processing.brackets_processing.versions.v_0.brackets.BracketPair object>
module_repr_full_file_path_bracket_pair: cengal.text_processing.brackets_processing.versions.v_0.brackets.BracketPair = <cengal.text_processing.brackets_processing.versions.v_0.brackets.BracketPair object>
def get_module_importable_str_and_path(module) -> Tuple[str, str]:
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
def entity_owning_module_info_and_owning_path(entity) -> Tuple[module, str, str, List[Union[Type, module]]]:
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
def entity_owning_module_importable_str(entity) -> str:
245def entity_owning_module_importable_str(entity) -> str:
246    _, module_importable_str, _, _ = entity_owning_module_info_and_owning_path(entity)
247    return module_importable_str
def entity_module_importable_str_and_owning_names_path(entity) -> Tuple[str, List[str]]:
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
def entity_by_name_module_importable_str_and_owning_names_path( entity_name: str, module_importable_str: str, owning_names_path: typing.List[str]) -> Any:
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)
module_repr_limited_bracket_pair: cengal.text_processing.brackets_processing.versions.v_0.brackets.BracketPair = <cengal.text_processing.brackets_processing.versions.v_0.brackets.BracketPair object>
def normalized_owner_repr(owner: typing.Union[typing.Type, module, NoneType]) -> str:
268def normalized_owner_repr(owner: Optional[Union[Type, ModuleType]]) -> str:
269    if owner is None:
270        return str()
271    
272    owner_repr: str = repr(owner)
273    result, _ = replace_text_with_brackets(owner_repr, module_repr_limited_bracket_pair, ">", 1)
274    return result
def normalized_code_owner_repr(code: code, owner: typing.Union[typing.Type, module, NoneType]) -> str:
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
def entity_owner_repr(entity):
286def entity_owner_repr(entity):
287    if isinstance(entity, FrameType):
288        entity = entity.f_code
289    
290    if isinstance(entity, CodeType):
291        return normalized_code_owner_repr(entity, entity_owner(entity))
292    else:
293        return normalized_owner_repr(entity_owner(entity))
def owner_name(owner: typing.Union[typing.Type, module, NoneType]) -> str:
296def owner_name(owner: Optional[Union[Type, ModuleType]]) -> str:
297    if owner is None:
298        return str()
299    
300    return owner.__name__
def entity_owner_name(entity):
303def entity_owner_name(entity):
304    return owner_name(entity_owner(entity))
def frame_param_names( frame_instance: frame) -> cengal.code_flow_control.python_bytecode_manipulator.versions.v_0.python_bytecode_manipulator.CodeParamNames:
307def frame_param_names(frame_instance: FrameType) -> CodeParamNames:
308    return code_param_names(frame_instance.f_code)
def intro_func_param_names( depth: typing.Union[int, NoneType] = 1) -> cengal.code_flow_control.python_bytecode_manipulator.versions.v_0.python_bytecode_manipulator.CodeParamNames:
311def intro_func_param_names(depth: Optional[int] = 1) -> CodeParamNames:
312    return frame_param_names(frame(depth + 1))
CodeParamsWithValues = <class 'cengal.code_flow_control.python_bytecode_manipulator.versions.v_0.python_bytecode_manipulator.CodeParamNames'>
ParamWithValue = typing.Tuple[str, typing.Any]
def fill_code_params_with_values( code_params: cengal.code_flow_control.python_bytecode_manipulator.versions.v_0.python_bytecode_manipulator.CodeParamNames, args, kwargs) -> Tuple[cengal.code_flow_control.python_bytecode_manipulator.versions.v_0.python_bytecode_manipulator.CodeParamNames, Tuple, Dict]:
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
def func_params_with_values( func: typing.Union[typing.Callable, typing.Awaitable], args, kwargs) -> Tuple[cengal.code_flow_control.python_bytecode_manipulator.versions.v_0.python_bytecode_manipulator.CodeParamNames, Tuple, Dict]:
345def func_params_with_values(func: Union[Callable, Awaitable], args, kwargs) -> Tuple[CodeParamsWithValues, Tuple, Dict]:
346    return fill_code_params_with_values(func_param_names(func), args, kwargs)
def intro_frame_params_with_values( frame_instance) -> cengal.code_flow_control.python_bytecode_manipulator.versions.v_0.python_bytecode_manipulator.CodeParamNames:
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)))
def intro_func_params_with_values( depth: typing.Union[int, NoneType] = 1) -> cengal.code_flow_control.python_bytecode_manipulator.versions.v_0.python_bytecode_manipulator.CodeParamNames:
357def intro_func_params_with_values(depth: Optional[int] = 1) -> CodeParamsWithValues:
358    return intro_frame_params_with_values(frame(depth + 1))
def intro_frame_all_params_with_values(frame_instance) -> Tuple[Tuple[str, Any]]:
361def intro_frame_all_params_with_values(frame_instance) -> Tuple[ParamWithValue]:
362    positional, _, keyword_only = frame_param_names(frame_instance)
363    all_params = positional + keyword_only
364    fr_locals = frame_instance.f_locals
365    return tuple(((arg, fr_locals[arg]) for arg in all_params))
def intro_func_all_params_with_values(depth: typing.Union[int, NoneType] = 1) -> Tuple[Tuple[str, Any]]:
368def intro_func_all_params_with_values(depth: Optional[int] = 1) -> Tuple[ParamWithValue]:
369    return intro_frame_all_params_with_values(frame(depth + 1))
def intro_frame_all_params_with_values_as_ordered_dict(frame_instance) -> OrderedDict[str, Any]:
372def intro_frame_all_params_with_values_as_ordered_dict(frame_instance) -> OrderedDictType[str, Any]:
373    return OrderedDict(intro_frame_all_params_with_values(frame_instance))
def intro_func_all_params_with_values_as_ordered_dict(depth: typing.Union[int, NoneType] = 1) -> OrderedDict[str, Any]:
376def intro_func_all_params_with_values_as_ordered_dict(depth: Optional[int] = 1) -> OrderedDictType[str, Any]:
377    return intro_frame_all_params_with_values_as_ordered_dict(frame(depth + 1))
def code_params_with_values_to_signature_items_gen( code_params_with_values: cengal.code_flow_control.python_bytecode_manipulator.versions.v_0.python_bytecode_manipulator.CodeParamNames, verbose: bool = False) -> Generator[str, NoneType, NoneType]:
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}'
def code_params_to_signature_items_gen( code_params: cengal.code_flow_control.python_bytecode_manipulator.versions.v_0.python_bytecode_manipulator.CodeParamNames) -> Generator[str, NoneType, NoneType]:
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
def code_params_with_values_to_signature( params_with_values: cengal.code_flow_control.python_bytecode_manipulator.versions.v_0.python_bytecode_manipulator.CodeParamNames, verbose: bool = False, formatted: bool = False) -> str:
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))
def code_params_to_signature( param_names: cengal.code_flow_control.python_bytecode_manipulator.versions.v_0.python_bytecode_manipulator.CodeParamNames, formatted: bool = False) -> str:
438def code_params_to_signature(param_names: CodeParamNames, formatted: bool = False) -> str:
439    if formatted:
440        delimiter = ',\n\t'
441    else:
442        delimiter = ', '
443    
444    return delimiter.join(code_params_to_signature_items_gen(param_names))
def entity_repr_limited(entity, formatted: bool = False):
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})'
def entity_repr_limited_try_qualname(entity, formatted: bool = False):
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})'
def entity_repr_owner_based(entity, formatted: bool = False):
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)
def entity_repr(entity, formatted: bool = False):
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)
def entity_properties(entity) -> Set[str]:
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_

def entity_properties_values(entity) -> Dict[str, Any]:
560def entity_properties_values(entity) -> Dict[str, Any]:
561    result = dict()
562    for property_name in sorted(entity_properties(entity)):
563        result[property_name] = getattr(entity, property_name)
564    
565    return result
def class_properties(entity: typing.Type) -> Set[str]:
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_

def class_properties_values(entity) -> Dict[str, Any]:
591def class_properties_values(entity) -> Dict[str, Any]:
592    result = dict()
593    for property_name in sorted(class_properties(entity)):
594        result[property_name] = getattr(entity, property_name)
595    
596    return result
def class_properties_withot_object(entity: typing.Type) -> Set[str]:
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_

def class_properties_withot_object_values(entity) -> Dict[str, Any]:
614def class_properties_withot_object_values(entity) -> Dict[str, Any]:
615    result = dict()
616    for property_name in sorted(class_properties_withot_object(entity)):
617        result[property_name] = getattr(entity, property_name)
618    
619    return result
def class_properties_including_overrided(entity: typing.Type) -> Set[str]:
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_

def class_properties_values_including_overrided(entity) -> Dict[str, Any]:
637def class_properties_values_including_overrided(entity) -> Dict[str, Any]:
638    result = dict()
639    for property_name in sorted(class_properties_including_overrided(entity)):
640        result[property_name] = getattr(entity, property_name)
641    
642    return result
def intro_frame_repr_limited(frame_instance, verbose: bool = False):
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})'
def intro_frame_repr(frame_instance, verbose: bool = False):
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})'
def intro_func_repr_limited(verbose: bool = False, depth: typing.Union[int, NoneType] = 1):
662def intro_func_repr_limited(verbose: bool = False, depth: Optional[int] = 1):
663    return intro_frame_repr_limited(frame(depth + 1), verbose)
def pifrl(verbose: bool = False, depth: typing.Union[int, NoneType] = 1):
666def print_intro_func_repr_limited(verbose: bool = False, depth: Optional[int] = 1):
667    print(intro_func_repr_limited(verbose, depth + 1))
def intro_func_repr(verbose: bool = False, depth: typing.Union[int, NoneType] = 1):
673def intro_func_repr(verbose: bool = False, depth: Optional[int] = 1):
674    return intro_frame_repr(frame(depth + 1), verbose)
def pifr(verbose: bool = False, depth: typing.Union[int, NoneType] = 1):
677def print_intro_func_repr(verbose: bool = False, depth: Optional[int] = 1):
678    print(intro_func_repr(verbose, depth + 1))
def get_str_of_data_info(data):
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_

def gsodi(data):
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_

def get_multistr_of_data_info( data, shift_num: typing.Union[int, NoneType] = None, shift_char: str = '\t'):
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_

def gmsodi( data, shift_num: typing.Union[int, NoneType] = None, shift_char: str = '\t'):
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_

def get_multistr_of_data_value( data, shift_num: typing.Union[int, NoneType] = None, shift_char: str = '\t'):
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_

def gmsodv( data, shift_num: typing.Union[int, NoneType] = None, shift_char: str = '\t'):
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_

def pdi(data):
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_

def get_str_of_data_info_named(name, data):
753def get_str_of_data_info_named(name, data):
754    return f'<<{name}>> type: {type(data)}; value: {data}'
def gsodin(name, data):
753def get_str_of_data_info_named(name, data):
754    return f'<<{name}>> type: {type(data)}; value: {data}'
def pdin(name, data):
760def print_data_info_named(name, data):
761    print(get_str_of_data_info_named(name, data))
def get_str_of_data_info_by_name(name, depth: typing.Union[int, NoneType] = 1):
767def get_str_of_data_info_by_name(name, depth: Optional[int] = 1):
768    fr = frame(depth + 1)
769    data = fr.f_locals[name]
770    return get_str_of_data_info_named(name, data)
def gsodibn(name, depth: typing.Union[int, NoneType] = 1):
767def get_str_of_data_info_by_name(name, depth: Optional[int] = 1):
768    fr = frame(depth + 1)
769    data = fr.f_locals[name]
770    return get_str_of_data_info_named(name, data)
def pdibn(name, depth: typing.Union[int, NoneType] = 1):
776def print_data_info_by_name(name, depth: Optional[int] = 1):
777    print(get_str_of_data_info_by_name(name, depth + 1))
def is_descriptor(entity):
783def is_descriptor(entity):
784    return hasattr(entity, '__get__') or hasattr(entity, '__set__') or hasattr(entity, '__delete__')
def is_setable_data_descriptor(entity):
787def is_setable_data_descriptor(entity):
788    return hasattr(entity, '__get__') and hasattr(entity, '__set__')
def is_filled_descriptor(owning_object, entity) -> bool:
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_

def filled_slots_names(owning_object) -> Union[List[str], NoneType]:
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
def filled_slots(owning_object) -> Union[List[Any], NoneType]:
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
def filled_slots_with_names(owning_object) -> Union[List[Tuple[str, Any]], NoneType]:
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
def filled_slots_with_names_gen(owning_object) -> Generator[Tuple[str, Any], Any, Any]:
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
def filled_slot_names_with_values_gen(owning_object) -> Generator[Tuple[str, Any], Any, Any]:
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
def current_entity_name(depth: typing.Union[int, NoneType] = 1):
888def current_entity_name(depth: Optional[int] = 1):
889    fr = frame(depth + 1)
890    return entity_name(fr)
891    # entity_name = code_name(fr.f_code)
892    # # print(dir(fr.f_code))
893    # # print(fr.f_code.__class__)
894    # # print(dir(fr))
895    # # print(fr.__class__)
896    # return entity_name
def cen(depth: typing.Union[int, NoneType] = 1):
888def current_entity_name(depth: Optional[int] = 1):
889    fr = frame(depth + 1)
890    return entity_name(fr)
891    # entity_name = code_name(fr.f_code)
892    # # print(dir(fr.f_code))
893    # # print(fr.f_code.__class__)
894    # # print(dir(fr))
895    # # print(fr.__class__)
896    # return entity_name
def pcen(depth: typing.Union[int, NoneType] = 1):
902def print_current_entity_name(depth: Optional[int] = 1):
903    print(current_entity_name(depth + 1))
def current_entity_owner_name(depth: typing.Union[int, NoneType] = 1):
910def current_entity_owner_name(depth: Optional[int] = 1):
911    fr = frame(depth + 1)
912    return owner_name(entity_owner(fr.f_code))
def getattr_ex(entity, attr_name: str) -> Any:
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}"')
def entity_is_function(entity) -> bool:
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
def get_function_by_entity(entity) -> Union[Callable, NoneType]:
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
def entity_is_method(entity) -> bool:
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
def get_method_by_entity(entity) -> Union[Callable, NoneType]:
 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
def entity_is_unbound_method(entity):
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
def get_unbound_method_by_entity(entity) -> Union[Callable, NoneType]:
1039def get_unbound_method_by_entity(entity) -> Optional[Callable]:
1040    raise NotImplementedError()
class AnAppropriateOwnerParameterWasNotFoundError(builtins.Exception):
1043class AnAppropriateOwnerParameterWasNotFoundError(Exception):
1044    pass

Common base class for all non-exit exceptions.

Inherited Members
builtins.Exception
Exception
builtins.BaseException
with_traceback
args
class PossibleOwnerParameterDoesNotMatchError(AnAppropriateOwnerParameterWasNotFoundError):
1047class PossibleOwnerParameterDoesNotMatchError(AnAppropriateOwnerParameterWasNotFoundError):
1048    pass

Common base class for all non-exit exceptions.

Inherited Members
builtins.Exception
Exception
builtins.BaseException
with_traceback
args
class EntityHasNoPositionalParametersError(AnAppropriateOwnerParameterWasNotFoundError):
1051class EntityHasNoPositionalParametersError(AnAppropriateOwnerParameterWasNotFoundError):
1052    pass

Common base class for all non-exit exceptions.

Inherited Members
builtins.Exception
Exception
builtins.BaseException
with_traceback
args
def get_owner_parameter( entity, owner_parameter_name: str, return_even_if_not_match: bool = False):
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')
def get_self_parameter(entity):
1090def get_self_parameter(entity):
1091    return get_owner_parameter(entity, 'self')
def get_cls_parameter(entity):
1094def get_cls_parameter(entity):
1095    return get_owner_parameter(entity, 'cls')
def get_any_owner_parameter( entity, owner_parameter_name: str, any_positional: bool = True, any_keyword: bool = True):
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}')
def get_any_self_parameter(entity, any_positional: bool = True, any_keyword: bool = True):
1155def get_any_self_parameter(entity, any_positional: bool = True, any_keyword: bool = True):
1156    return get_owner_parameter(entity, 'self', any_positional, any_keyword)
def get_any_cls_parameter(entity, any_positional: bool = True, any_keyword: bool = True):
1159def get_any_cls_parameter(entity, any_positional: bool = True, any_keyword: bool = True):
1160    return get_owner_parameter(entity, 'cls' , any_positional, any_keyword)
def find_method_in_module_by_code(module, code_to_find: code) -> Union[code, NoneType]:
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
def find_method_in_class_by_code(class_to_search_in, code_to_find: code) -> Union[code, NoneType]:
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
class EntityWasNotFoundError(builtins.Exception):
1192class EntityWasNotFoundError(Exception):
1193    pass

Common base class for all non-exit exceptions.

Inherited Members
builtins.Exception
Exception
builtins.BaseException
with_traceback
args
def find_entity(entity: typing.Union[typing.Callable, frame, code]) -> Callable:
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
def find_current_entity(depth: typing.Union[int, NoneType] = 1) -> Callable:
1241def find_current_entity(depth: Optional[int] = 1) -> Callable:
1242    return find_entity(frame(depth + 1))