compiler.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. """Compiler helpers for the debugger."""
  2. import os
  3. import sys
  4. import tempfile
  5. from IPython.core.compilerop import CachingCompiler
  6. def murmur2_x86(data, seed):
  7. """Get the murmur2 hash."""
  8. m = 0x5BD1E995
  9. data = [chr(d) for d in str.encode(data, "utf8")]
  10. length = len(data)
  11. h = seed ^ length
  12. rounded_end = length & 0xFFFFFFFC
  13. for i in range(0, rounded_end, 4):
  14. k = (
  15. (ord(data[i]) & 0xFF)
  16. | ((ord(data[i + 1]) & 0xFF) << 8)
  17. | ((ord(data[i + 2]) & 0xFF) << 16)
  18. | (ord(data[i + 3]) << 24)
  19. )
  20. k = (k * m) & 0xFFFFFFFF
  21. k ^= k >> 24
  22. k = (k * m) & 0xFFFFFFFF
  23. h = (h * m) & 0xFFFFFFFF
  24. h ^= k
  25. val = length & 0x03
  26. k = 0
  27. if val == 3:
  28. k = (ord(data[rounded_end + 2]) & 0xFF) << 16
  29. if val in [2, 3]:
  30. k |= (ord(data[rounded_end + 1]) & 0xFF) << 8
  31. if val in [1, 2, 3]:
  32. k |= ord(data[rounded_end]) & 0xFF
  33. h ^= k
  34. h = (h * m) & 0xFFFFFFFF
  35. h ^= h >> 13
  36. h = (h * m) & 0xFFFFFFFF
  37. h ^= h >> 15
  38. return h
  39. convert_to_long_pathname = lambda filename: filename # noqa: E731
  40. if sys.platform == "win32":
  41. try:
  42. import ctypes
  43. from ctypes.wintypes import DWORD, LPCWSTR, LPWSTR, MAX_PATH
  44. _GetLongPathName = ctypes.windll.kernel32.GetLongPathNameW
  45. _GetLongPathName.argtypes = [LPCWSTR, LPWSTR, DWORD]
  46. _GetLongPathName.restype = DWORD
  47. def _convert_to_long_pathname(filename):
  48. buf = ctypes.create_unicode_buffer(MAX_PATH)
  49. rv = _GetLongPathName(filename, buf, MAX_PATH)
  50. if rv != 0 and rv <= MAX_PATH:
  51. filename = buf.value
  52. return filename
  53. # test that it works so if there are any issues we fail just once here
  54. _convert_to_long_pathname(__file__)
  55. except Exception:
  56. pass
  57. else:
  58. convert_to_long_pathname = _convert_to_long_pathname
  59. def get_tmp_directory():
  60. """Get a temp directory."""
  61. tmp_dir = convert_to_long_pathname(tempfile.gettempdir())
  62. pid = os.getpid()
  63. return tmp_dir + os.sep + "ipykernel_" + str(pid)
  64. def get_tmp_hash_seed():
  65. """Get a temp hash seed."""
  66. return 0xC70F6907
  67. def get_file_name(code):
  68. """Get a file name."""
  69. cell_name = os.environ.get("IPYKERNEL_CELL_NAME")
  70. if cell_name is None:
  71. name = murmur2_x86(code, get_tmp_hash_seed())
  72. cell_name = get_tmp_directory() + os.sep + str(name) + ".py"
  73. return cell_name
  74. class XCachingCompiler(CachingCompiler):
  75. """A custom caching compiler."""
  76. def __init__(self, *args, **kwargs):
  77. """Initialize the compiler."""
  78. super().__init__(*args, **kwargs)
  79. self.log = None
  80. def get_code_name(self, raw_code, code, number):
  81. """Get the code name."""
  82. return get_file_name(raw_code)