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