Generates random Python functions using Markov chains
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

107 lignes
3.4 KiB

  1. import opcode
  2. import sys
  3. import func_smash
  4. OP_HASLOAD = ("LOAD_FAST", "LOAD_CONST", "LOAD_GLOBAL")
  5. OP_HASBINARY = {"BINARY_ADD": "+", "BINARY_SUBTRACT": "-",
  6. "BINARY_MULTIPLY": "*", "BINARY_DIVIDE": "/",
  7. "BINARY_POWER": "**", "BINARY_MODULO": "%"}
  8. OP_HASBUILD = ("BUILD_TUPLE", "BUILD_LIST", "BUILD_MAP", "BUILD_SET")
  9. def prettify_function(func, indent=0):
  10. args = _get_func_args(func)
  11. _print(indent, "def {0}({1}):".format(func.func_name, args))
  12. prettify_code(func.__code__, indent=indent+4)
  13. def prettify_code(codeobj, indent=0):
  14. codes = []
  15. codestring = codeobj.co_code
  16. length = len(codestring)
  17. i = 0
  18. while i < length:
  19. code = ord(codestring[i])
  20. i += 1
  21. if code >= opcode.HAVE_ARGUMENT:
  22. arg = func_smash._get_argument(codeobj, codestring, i, code)
  23. i += 2
  24. codes.append((code, arg))
  25. else:
  26. codes.append((code, None))
  27. _print_codestring(codes, indent)
  28. def _print_codestring(codes, indent):
  29. stack = []
  30. print_buffer = []
  31. for instruction in codes:
  32. code, arg = instruction
  33. opname = opcode.opname[code]
  34. _print(indent, opname, arg, "; stack ==", stack, debug=True)
  35. if opname in OP_HASLOAD:
  36. stack.append(arg)
  37. elif opname in OP_HASBINARY:
  38. tos, tos1 = str(stack.pop()), str(stack.pop())
  39. stack.append(" ".join((tos1, OP_HASBINARY[opname], tos)))
  40. elif opname in OP_HASBUILD:
  41. args = []
  42. for i in xrange(arg):
  43. args.append(str(stack.pop()))
  44. if opname == "BUILD_TUPLE":
  45. stack.append("(" + ", ".join(args) + ")")
  46. elif opname == "STORE_FAST":
  47. _print(indent, arg, "=", stack.pop())
  48. elif opname == "POP_TOP":
  49. _print(indent, stack.pop())
  50. elif opname == "CALL_FUNCTION":
  51. numargs, numkwargs = arg
  52. args = []
  53. for i in xrange(numkwargs):
  54. value = str(stack.pop())
  55. key = str(stack.pop())
  56. args.append("=".join((key, value)))
  57. for i in xrange(numargs):
  58. args.append(str(stack.pop()))
  59. args.reverse()
  60. funcname = stack.pop()
  61. stack.append("{0}({1})".format(funcname, ", ".join(args)))
  62. elif opname == "PRINT_ITEM":
  63. print_buffer.append(stack.pop())
  64. elif opname == "PRINT_NEWLINE":
  65. _print(indent, "print", ", ".join(print_buffer))
  66. print_buffer = []
  67. elif opname == "RETURN_VALUE":
  68. _print(indent, "return", stack.pop())
  69. else:
  70. raise NotImplementedError(opname, arg, stack)
  71. def _get_func_args(func):
  72. codeobj = func.__code__
  73. count = codeobj.co_argcount
  74. if count == 0:
  75. return ""
  76. return ", ".join([arg for arg in codeobj.co_varnames[:count]])
  77. def _print(indentation, *args, **kwargs):
  78. argstring = " ".join([str(arg) for arg in args if str(arg)])
  79. if kwargs.get("debug"):
  80. # Ignore debug messages without -d flag
  81. if len(sys.argv) > 1 and sys.argv[1] == "-d":
  82. print " " * 40 + "#", argstring
  83. return
  84. print " " * indentation + argstring
  85. if __name__ == "__main__":
  86. def f1(a):
  87. b = a + 10 / 7.0
  88. d = long_func(a, b+9, c=42, d=43)
  89. print b, d
  90. v, z
  91. return d % 10
  92. def f2():
  93. pass
  94. prettify_function(f1)
  95. print
  96. prettify_function(f2)