_introspection.py 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. """
  2. Python introspection helpers.
  3. """
  4. from types import CodeType as code, FunctionType as function
  5. def copycode(template, changes):
  6. names = [
  7. "argcount", "nlocals", "stacksize", "flags", "code", "consts",
  8. "names", "varnames", "filename", "name", "firstlineno", "lnotab",
  9. "freevars", "cellvars"
  10. ]
  11. if hasattr(code, "co_kwonlyargcount"):
  12. names.insert(1, "kwonlyargcount")
  13. if hasattr(code, "co_posonlyargcount"):
  14. # PEP 570 added "positional only arguments"
  15. names.insert(1, "posonlyargcount")
  16. values = [
  17. changes.get(name, getattr(template, "co_" + name))
  18. for name in names
  19. ]
  20. return code(*values)
  21. def copyfunction(template, funcchanges, codechanges):
  22. names = [
  23. "globals", "name", "defaults", "closure",
  24. ]
  25. values = [
  26. funcchanges.get(name, getattr(template, "__" + name + "__"))
  27. for name in names
  28. ]
  29. return function(copycode(template.__code__, codechanges), *values)
  30. def preserveName(f):
  31. """
  32. Preserve the name of the given function on the decorated function.
  33. """
  34. def decorator(decorated):
  35. return copyfunction(decorated,
  36. dict(name=f.__name__), dict(name=f.__name__))
  37. return decorator