''' This module should be run to recreate the files that we generate automatically (i.e.: modules that shouldn't be traced and cython .pyx) ''' from __future__ import print_function import os import struct import re def is_python_64bit(): return (struct.calcsize('P') == 8) root_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) def get_cython_contents(filename): if filename.endswith('.pyc'): filename = filename[:-1] state = 'regular' replacements = [] new_contents = [] with open(filename, 'r') as stream: for line in stream: strip = line.strip() if state == 'regular': if strip == '# IFDEF CYTHON': state = 'cython' new_contents.append('%s -- DONT EDIT THIS FILE (it is automatically generated)\n' % line.replace('\n', '').replace('\r', '')) continue new_contents.append(line) elif state == 'cython': if strip == '# ELSE': state = 'nocython' new_contents.append(line) continue elif strip == '# ENDIF': state = 'regular' new_contents.append(line) continue if strip == '#': continue assert strip.startswith('# '), 'Line inside # IFDEF CYTHON must start with "# ". Found: %s' % (strip,) strip = strip.replace('# ', '', 1).strip() if strip.startswith('cython_inline_constant:'): strip = strip.replace('cython_inline_constant:', '') word_to_replace, replacement = strip.split('=') replacements.append((word_to_replace.strip(), replacement.strip())) continue line = line.replace('# ', '', 1) new_contents.append(line) elif state == 'nocython': if strip == '# ENDIF': state = 'regular' new_contents.append(line) continue new_contents.append('# %s' % line) assert state == 'regular', 'Error: # IFDEF CYTHON found without # ENDIF' ret = ''.join(new_contents) for (word_to_replace, replacement) in replacements: ret = re.sub(r"\b%s\b" % (word_to_replace,), replacement, ret) return ret def _generate_cython_from_files(target, modules): contents = ['''from __future__ import print_function # Important: Autogenerated file. # DO NOT edit manually! # DO NOT edit manually! '''] found = [] for mod in modules: found.append(mod.__file__) contents.append(get_cython_contents(mod.__file__)) print('Generating cython from: %s' % (found,)) with open(target, 'w') as stream: stream.write(''.join(contents)) def generate_dont_trace_files(): template = '''# Important: Autogenerated file. # DO NOT edit manually! # DO NOT edit manually! LIB_FILE = 1 PYDEV_FILE = 2 DONT_TRACE_DIRS = { %(pydev_dirs)s } DONT_TRACE = { # commonly used things from the stdlib that we don't want to trace 'Queue.py':LIB_FILE, 'queue.py':LIB_FILE, 'socket.py':LIB_FILE, 'weakref.py':LIB_FILE, '_weakrefset.py':LIB_FILE, 'linecache.py':LIB_FILE, 'threading.py':LIB_FILE, 'dis.py':LIB_FILE, # things from pydev that we don't want to trace %(pydev_files)s } # if we try to trace io.py it seems it can get halted (see http://bugs.python.org/issue4716) DONT_TRACE['io.py'] = LIB_FILE # Don't trace common encodings too DONT_TRACE['cp1252.py'] = LIB_FILE DONT_TRACE['utf_8.py'] = LIB_FILE DONT_TRACE['codecs.py'] = LIB_FILE ''' pydev_files = [] pydev_dirs = [] exclude_dirs = [ '.git', '.settings', 'build', 'build_tools', 'dist', 'pydevd.egg-info', 'pydevd_attach_to_process', 'pydev_sitecustomize', 'stubs', 'tests', 'tests_mainloop', 'tests_python', 'tests_runfiles', 'test_pydevd_reload', 'third_party', '__pycache__', 'pydev_ipython', 'vendored', '.mypy_cache', 'pydevd.egg-info', ] for root, dirs, files in os.walk(root_dir): for d in dirs: if 'pydev' in d and d != 'pydevd.egg-info': # print(os.path.join(root, d)) pydev_dirs.append(" '%s': PYDEV_FILE," % (d,)) for d in exclude_dirs: try: dirs.remove(d) except: pass for f in files: if f.endswith('.py'): if f not in ( '__init__.py', 'runfiles.py', 'pydev_coverage.py', 'pydev_pysrc.py', 'setup.py', 'setup_pydevd_cython.py', 'interpreterInfo.py', 'conftest.py', ): pydev_files.append(" '%s': PYDEV_FILE," % (f,)) contents = template % (dict( pydev_files='\n'.join(sorted(set(pydev_files))), pydev_dirs='\n'.join(sorted(set(pydev_dirs))), )) assert 'pydevd.py' in contents assert 'pydevd_dont_trace.py' in contents with open(os.path.join(root_dir, '_pydevd_bundle', 'pydevd_dont_trace_files.py'), 'w') as stream: stream.write(contents) def remove_if_exists(f): try: if os.path.exists(f): os.remove(f) except: import traceback;traceback.print_exc() def generate_cython_module(): print('Removing pydevd_cython.pyx') remove_if_exists(os.path.join(root_dir, '_pydevd_bundle', 'pydevd_cython.pyx')) target = os.path.join(root_dir, '_pydevd_bundle', 'pydevd_cython.pyx') curr = os.environ.get('PYDEVD_USE_CYTHON') try: os.environ['PYDEVD_USE_CYTHON'] = 'NO' from _pydevd_bundle import pydevd_additional_thread_info_regular from _pydevd_bundle import pydevd_frame, pydevd_trace_dispatch_regular _generate_cython_from_files(target, [pydevd_additional_thread_info_regular, pydevd_frame, pydevd_trace_dispatch_regular]) finally: if curr is None: del os.environ['PYDEVD_USE_CYTHON'] else: os.environ['PYDEVD_USE_CYTHON'] = curr if __name__ == '__main__': generate_dont_trace_files() generate_cython_module()