aboutsummaryrefslogblamecommitdiffstats
path: root/contrib/python/Automat/py3/automat/_introspection.py
blob: e433b2f9f9f7ed7283d61f77f63e4513cd22796e (plain) (tree)
1
2
3
4
5
6
7
8
9







                                                            
                                                                             
             












                      




                                                   
                                                                                   



                                                     


                   
              
                                                                                      






                                                                      
 
                             
                                                                                    
                    
"""
Python introspection helpers.
"""

from types import CodeType as code, FunctionType as function


def copycode(template, changes):
    if hasattr(code, "replace"):
        return template.replace(**{"co_" + k: v for k, v in changes.items()})
    names = [
        "argcount",
        "nlocals",
        "stacksize",
        "flags",
        "code",
        "consts",
        "names",
        "varnames",
        "filename",
        "name",
        "firstlineno",
        "lnotab",
        "freevars",
        "cellvars",
    ]
    if hasattr(code, "co_kwonlyargcount"):
        names.insert(1, "kwonlyargcount")
    if hasattr(code, "co_posonlyargcount"):
        # PEP 570 added "positional only arguments"
        names.insert(1, "posonlyargcount")
    values = [changes.get(name, getattr(template, "co_" + name)) for name in names]
    return code(*values)


def copyfunction(template, funcchanges, codechanges):
    names = [
        "globals",
        "name",
        "defaults",
        "closure",
    ]
    values = [
        funcchanges.get(name, getattr(template, "__" + name + "__")) for name in names
    ]
    return function(copycode(template.__code__, codechanges), *values)


def preserveName(f):
    """
    Preserve the name of the given function on the decorated function.
    """

    def decorator(decorated):
        return copyfunction(decorated, dict(name=f.__name__), dict(name=f.__name__))

    return decorator