Vendor debugpy for VS Code attach debugging
Bundles debugpy 1.7.0 directly in python/ so "Maya: Attach (debugpy)" works with no per-machine pip install step. Installed via Maya 2022's own pip so it resolved a version actually compatible with Python 3.7 (Maya 2022's interpreter), then verified import + listen() succeeds under all three target Maya Python versions (3.7/3.9/3.10). Also fixes a latent __file__-under-exec() bug in start_debug_server.py (same pitfall as Maya's own plugin loader, never hit until this exercised it) and corrects the README's Maya Python version claim -- 2022 ships Python 3.7, not 3.9 as previously stated, which was never independently verified until now. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
'''
|
||||
Helper to build pydevd.
|
||||
|
||||
It should:
|
||||
* recreate our generated files
|
||||
* compile cython deps (properly setting up the environment first).
|
||||
|
||||
Note that it's used in the CI to build the cython deps based on the PYDEVD_USE_CYTHON environment variable.
|
||||
'''
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from generate_code import remove_if_exists, root_dir, is_python_64bit, generate_dont_trace_files, generate_cython_module
|
||||
|
||||
|
||||
def validate_pair(ob):
|
||||
try:
|
||||
if not (len(ob) == 2):
|
||||
print("Unexpected result:", ob, file=sys.stderr)
|
||||
raise ValueError
|
||||
except:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def consume(it):
|
||||
try:
|
||||
while True:
|
||||
next(it)
|
||||
except StopIteration:
|
||||
pass
|
||||
|
||||
|
||||
def get_environment_from_batch_command(env_cmd, initial=None):
|
||||
"""
|
||||
Take a command (either a single command or list of arguments)
|
||||
and return the environment created after running that command.
|
||||
Note that if the command must be a batch file or .cmd file, or the
|
||||
changes to the environment will not be captured.
|
||||
|
||||
If initial is supplied, it is used as the initial environment passed
|
||||
to the child process.
|
||||
"""
|
||||
if not isinstance(env_cmd, (list, tuple)):
|
||||
env_cmd = [env_cmd]
|
||||
if not os.path.exists(env_cmd[0]):
|
||||
raise RuntimeError('Error: %s does not exist' % (env_cmd[0],))
|
||||
|
||||
# construct the command that will alter the environment
|
||||
env_cmd = subprocess.list2cmdline(env_cmd)
|
||||
# create a tag so we can tell in the output when the proc is done
|
||||
tag = 'Done running command'
|
||||
# construct a cmd.exe command to do accomplish this
|
||||
cmd = 'cmd.exe /s /c "{env_cmd} && echo "{tag}" && set"'.format(**vars())
|
||||
# launch the process
|
||||
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, env=initial)
|
||||
# parse the output sent to stdout
|
||||
lines = proc.stdout
|
||||
# consume whatever output occurs until the tag is reached
|
||||
for line in lines:
|
||||
line = line.decode('utf-8')
|
||||
if 'The specified configuration type is missing.' in line:
|
||||
raise AssertionError('Error executing %s. View http://blog.ionelmc.ro/2014/12/21/compiling-python-extensions-on-windows/ for details.' % (env_cmd))
|
||||
if tag in line:
|
||||
break
|
||||
if sys.version_info[0] > 2:
|
||||
# define a way to handle each KEY=VALUE line
|
||||
handle_line = lambda l: l.decode('utf-8').rstrip().split('=', 1)
|
||||
else:
|
||||
# define a way to handle each KEY=VALUE line
|
||||
handle_line = lambda l: l.rstrip().split('=', 1)
|
||||
# parse key/values into pairs
|
||||
pairs = map(handle_line, lines)
|
||||
# make sure the pairs are valid
|
||||
valid_pairs = filter(validate_pair, pairs)
|
||||
# construct a dictionary of the pairs
|
||||
result = dict(valid_pairs)
|
||||
# let the process finish
|
||||
proc.communicate()
|
||||
return result
|
||||
|
||||
|
||||
def remove_binaries(suffixes):
|
||||
for f in os.listdir(os.path.join(root_dir, '_pydevd_bundle')):
|
||||
for suffix in suffixes:
|
||||
if f.endswith(suffix):
|
||||
remove_if_exists(os.path.join(root_dir, '_pydevd_bundle', f))
|
||||
|
||||
|
||||
def build():
|
||||
if '--no-remove-binaries' not in sys.argv:
|
||||
remove_binaries(['.pyd', '.so'])
|
||||
|
||||
os.chdir(root_dir)
|
||||
|
||||
env = None
|
||||
if sys.platform == 'win32':
|
||||
# "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars64.bat"
|
||||
# set MSSdk=1
|
||||
# set DISTUTILS_USE_SDK=1
|
||||
# set VS100COMNTOOLS=C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\Tools
|
||||
|
||||
if 'GITHUB_ACTION' not in os.environ:
|
||||
env = os.environ.copy()
|
||||
if sys.version_info[:2] in ((3, 6), (3, 7), (3, 8), (3, 9), (3, 10), (3, 11)):
|
||||
FORCE_PYDEVD_VC_VARS = os.environ.get('FORCE_PYDEVD_VC_VARS')
|
||||
if FORCE_PYDEVD_VC_VARS:
|
||||
env.update(get_environment_from_batch_command([FORCE_PYDEVD_VC_VARS], initial=os.environ.copy()))
|
||||
else:
|
||||
import setuptools # We have to import it first for the compiler to be found
|
||||
from distutils import msvc9compiler
|
||||
|
||||
vcvarsall = msvc9compiler.find_vcvarsall(14.0)
|
||||
if vcvarsall is None or not os.path.exists(vcvarsall):
|
||||
msvc_version = msvc9compiler.get_build_version()
|
||||
print('msvc_version', msvc_version)
|
||||
vcvarsall = msvc9compiler.find_vcvarsall(msvc_version)
|
||||
|
||||
if vcvarsall is None or not os.path.exists(vcvarsall):
|
||||
raise RuntimeError('Error finding vcvarsall.')
|
||||
|
||||
if is_python_64bit():
|
||||
env.update(get_environment_from_batch_command(
|
||||
[vcvarsall, 'amd64'],
|
||||
initial=os.environ.copy()))
|
||||
else:
|
||||
env.update(get_environment_from_batch_command(
|
||||
[vcvarsall, 'x86'],
|
||||
initial=os.environ.copy()))
|
||||
|
||||
else:
|
||||
raise AssertionError('Unable to setup environment for Python: %s' % (sys.version,))
|
||||
|
||||
env['MSSdk'] = '1'
|
||||
env['DISTUTILS_USE_SDK'] = '1'
|
||||
|
||||
additional_args = []
|
||||
for arg in sys.argv:
|
||||
if arg.startswith('--target-pyd-name='):
|
||||
additional_args.append(arg)
|
||||
if arg.startswith('--target-pyd-frame-eval='):
|
||||
additional_args.append(arg)
|
||||
break
|
||||
else:
|
||||
additional_args.append('--force-cython') # Build always forces cython!
|
||||
|
||||
args = [
|
||||
sys.executable, os.path.join(os.path.dirname(__file__), '..', 'setup_pydevd_cython.py'), 'build_ext', '--inplace',
|
||||
] + additional_args
|
||||
print('Calling args: %s' % (args,))
|
||||
subprocess.check_call(args, env=env,)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
use_cython = os.getenv('PYDEVD_USE_CYTHON', '').lower()
|
||||
# Note: don't import pydevd during build (so, accept just yes/no in this case).
|
||||
if use_cython == 'yes':
|
||||
print("Building")
|
||||
build()
|
||||
elif use_cython == 'no':
|
||||
print("Removing binaries")
|
||||
remove_binaries(['.pyd', '.so'])
|
||||
elif not use_cython:
|
||||
# Regular process
|
||||
if '--no-regenerate-files' not in sys.argv:
|
||||
print("Generating dont trace files")
|
||||
generate_dont_trace_files()
|
||||
print("Generating cython modules")
|
||||
generate_cython_module()
|
||||
print("Building")
|
||||
build()
|
||||
else:
|
||||
raise RuntimeError('Unexpected value for PYDEVD_USE_CYTHON: %s (accepted: yes, no)' % (use_cython,))
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
miniconda64_envs = os.getenv('MINICONDA64_ENVS')
|
||||
python_installations = [
|
||||
r'%s/py34_64/bin/python' % miniconda64_envs,
|
||||
r'%s/py35_64/bin/python' % miniconda64_envs,
|
||||
r'%s/py36_64/bin/python' % miniconda64_envs,
|
||||
r'%s/py37_64/bin/python' % miniconda64_envs,
|
||||
]
|
||||
root_dir = os.path.dirname(os.path.dirname(__file__))
|
||||
|
||||
|
||||
def list_binaries():
|
||||
for f in os.listdir(os.path.join(root_dir, '_pydevd_bundle')):
|
||||
if f.endswith('.so'):
|
||||
yield f
|
||||
|
||||
|
||||
def extract_version(python_install):
|
||||
return python_install.split('/')[-3][2:]
|
||||
|
||||
|
||||
def main():
|
||||
from generate_code import generate_dont_trace_files
|
||||
from generate_code import generate_cython_module
|
||||
|
||||
# First, make sure that our code is up to date.
|
||||
generate_dont_trace_files()
|
||||
generate_cython_module()
|
||||
|
||||
for python_install in python_installations:
|
||||
assert os.path.exists(python_install)
|
||||
|
||||
from build import remove_binaries
|
||||
remove_binaries(['.so'])
|
||||
|
||||
for f in list_binaries():
|
||||
raise AssertionError('Binary not removed: %s' % (f,))
|
||||
|
||||
for i, python_install in enumerate(python_installations):
|
||||
new_name = 'pydevd_cython_%s_%s' % (sys.platform, extract_version(python_install))
|
||||
args = [
|
||||
python_install, os.path.join(root_dir, 'build_tools', 'build.py'), '--no-remove-binaries', '--target-pyd-name=%s' % new_name, '--force-cython']
|
||||
if i != 0:
|
||||
args.append('--no-regenerate-files')
|
||||
version_number = extract_version(python_install)
|
||||
if version_number.startswith('36') or version_number.startswith('37'):
|
||||
name_frame_eval = 'pydevd_frame_evaluator_%s_%s' % (sys.platform, extract_version(python_install))
|
||||
args.append('--target-pyd-frame-eval=%s' % name_frame_eval)
|
||||
print('Calling: %s' % (' '.join(args)))
|
||||
subprocess.check_call(args)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,85 @@
|
||||
r'''
|
||||
Creating the needed environments for creating the pre-compiled distribution on Windows:
|
||||
|
||||
See:
|
||||
|
||||
build_tools\pydevd_release_process.txt
|
||||
|
||||
for building binaries/release process.
|
||||
'''
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
miniconda_envs = os.getenv('MINICONDA_ENVS', r'C:\bin\Miniconda3\envs')
|
||||
|
||||
python_installations = [
|
||||
r'%s\py36_64\python.exe' % miniconda_envs,
|
||||
r'%s\py37_64\python.exe' % miniconda_envs,
|
||||
r'%s\py38_64\python.exe' % miniconda_envs,
|
||||
r'%s\py39_64\python.exe' % miniconda_envs,
|
||||
r'%s\py310_64\python.exe' % miniconda_envs,
|
||||
r'%s\py311_64\python.exe' % miniconda_envs,
|
||||
]
|
||||
|
||||
root_dir = os.path.dirname(os.path.dirname(__file__))
|
||||
|
||||
|
||||
def list_binaries():
|
||||
for f in os.listdir(os.path.join(root_dir, '_pydevd_bundle')):
|
||||
if f.endswith('.pyd'):
|
||||
yield f
|
||||
|
||||
|
||||
def extract_version(python_install):
|
||||
return python_install.split('\\')[-2][2:]
|
||||
|
||||
|
||||
def main():
|
||||
from generate_code import generate_dont_trace_files
|
||||
from generate_code import generate_cython_module
|
||||
|
||||
# First, make sure that our code is up to date.
|
||||
generate_dont_trace_files()
|
||||
generate_cython_module()
|
||||
|
||||
for python_install in python_installations:
|
||||
assert os.path.exists(python_install), '%s does not exist.' % (python_install,)
|
||||
|
||||
from build import remove_binaries
|
||||
remove_binaries(['.pyd'])
|
||||
|
||||
for f in list_binaries():
|
||||
raise AssertionError('Binary not removed: %s' % (f,))
|
||||
|
||||
for i, python_install in enumerate(python_installations):
|
||||
print()
|
||||
print('*' * 80)
|
||||
print('*' * 80)
|
||||
print()
|
||||
new_name = 'pydevd_cython_%s_%s' % (sys.platform, extract_version(python_install))
|
||||
args = [
|
||||
python_install, os.path.join(root_dir, 'build_tools', 'build.py'), '--no-remove-binaries', '--target-pyd-name=%s' % new_name, '--force-cython']
|
||||
if i != 0:
|
||||
args.append('--no-regenerate-files')
|
||||
name_frame_eval = 'pydevd_frame_evaluator_%s_%s' % (sys.platform, extract_version(python_install))
|
||||
args.append('--target-pyd-frame-eval=%s' % name_frame_eval)
|
||||
print('Calling: %s' % (' '.join(args)))
|
||||
|
||||
env = os.environ.copy()
|
||||
python_exe_dir = os.path.dirname(python_install)
|
||||
env['PATH'] = env['PATH'] + ';' + os.path.join(python_exe_dir, 'DLLs') + ';' + os.path.join(python_exe_dir, 'Library', 'bin')
|
||||
subprocess.check_call(args, env=env)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
# To run do:
|
||||
# See:
|
||||
#
|
||||
# build_tools\pydevd_release_process.txt
|
||||
#
|
||||
# for building binaries/release process.
|
||||
@@ -0,0 +1,32 @@
|
||||
import sys
|
||||
|
||||
|
||||
def main():
|
||||
import subprocess
|
||||
process = subprocess.Popen(
|
||||
'git status --porcelain'.split(), stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
|
||||
output, _ = process.communicate()
|
||||
if output:
|
||||
if sys.version_info[0] > 2:
|
||||
output = output.decode('utf-8')
|
||||
|
||||
files = set()
|
||||
for line in output.splitlines():
|
||||
filename = line[3:]
|
||||
files.add(filename.strip())
|
||||
|
||||
files.discard('.travis_install_python_deps.sh')
|
||||
files.discard('miniconda.sh')
|
||||
if files:
|
||||
# If there are modifications, show a diff of the modifications and fail the script.
|
||||
# (we're mostly interested in modifications to the .c generated files by cython).
|
||||
print('Found modifications in git:\n%s ' % (output,))
|
||||
print('Files: %s' % (files,))
|
||||
print('----------- diff -------------')
|
||||
subprocess.call('git diff'.split())
|
||||
print('----------- end diff -------------')
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -0,0 +1,233 @@
|
||||
'''
|
||||
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()
|
||||
@@ -0,0 +1,318 @@
|
||||
'''
|
||||
Helper module to hold the names to rename while doing refactoring to convert to pep8.
|
||||
'''
|
||||
NAMES = '''
|
||||
# sendCaughtExceptionStack
|
||||
# sendBreakpointConditionException
|
||||
# setSuspend
|
||||
# processThreadNotAlive
|
||||
# sendCaughtExceptionStackProceeded
|
||||
# doWaitSuspend
|
||||
# SetTraceForFrameAndParents
|
||||
# prepareToRun
|
||||
# processCommandLine
|
||||
# initStdoutRedirect
|
||||
# initStderrRedirect
|
||||
# OnRun
|
||||
# doKillPydevThread
|
||||
# stopTrace
|
||||
# handleExcept
|
||||
# processCommand
|
||||
# processNetCommand
|
||||
# addCommand
|
||||
# StartClient
|
||||
# getNextSeq
|
||||
# makeMessage
|
||||
# StartServer
|
||||
# threadToXML
|
||||
# makeErrorMessage
|
||||
# makeThreadCreatedMessage
|
||||
# makeCustomFrameCreatedMessage
|
||||
# makeListThreadsMessage
|
||||
# makeVariableChangedMessage
|
||||
# makeIoMessage
|
||||
# makeVersionMessage
|
||||
# makeThreadKilledMessage
|
||||
# makeThreadSuspendStr
|
||||
# makeValidXmlValue
|
||||
# makeThreadSuspendMessage
|
||||
# makeThreadRunMessage
|
||||
# makeGetVariableMessage
|
||||
# makeGetArrayMessage
|
||||
# makeGetFrameMessage
|
||||
# makeEvaluateExpressionMessage
|
||||
# makeGetCompletionsMessage
|
||||
# makeGetFileContents
|
||||
# makeSendBreakpointExceptionMessage
|
||||
# makeSendCurrExceptionTraceMessage
|
||||
# makeSendCurrExceptionTraceProceededMessage
|
||||
# makeSendConsoleMessage
|
||||
# makeCustomOperationMessage
|
||||
# makeLoadSourceMessage
|
||||
# makeShowConsoleMessage
|
||||
# makeExitMessage
|
||||
# canBeExecutedBy
|
||||
# doIt
|
||||
# additionalInfo
|
||||
# cmdFactory
|
||||
# GetExceptionTracebackStr
|
||||
# _GetStackStr
|
||||
# _InternalSetTrace
|
||||
# ReplaceSysSetTraceFunc
|
||||
# RestoreSysSetTraceFunc
|
||||
|
||||
|
||||
|
||||
# AddContent
|
||||
# AddException
|
||||
# AddObserver
|
||||
# # Call -- skip
|
||||
# # Call1 -- skip
|
||||
# # Call2 -- skip
|
||||
# # Call3 -- skip
|
||||
# # Call4 -- skip
|
||||
# ChangePythonPath
|
||||
# CheckArgs
|
||||
# CheckChar
|
||||
# CompleteFromDir
|
||||
# CreateDbFrame
|
||||
# CustomFramesContainerInit
|
||||
# DictContains
|
||||
# DictItems
|
||||
# DictIterItems
|
||||
# DictIterValues
|
||||
# DictKeys
|
||||
# DictPop
|
||||
# DictValues
|
||||
|
||||
|
||||
# DoExit
|
||||
# DoFind
|
||||
# EndRedirect
|
||||
# # Exec -- skip
|
||||
# ExecuteTestsInParallel
|
||||
# # Find -- skip
|
||||
# FinishDebuggingSession
|
||||
# FlattenTestSuite
|
||||
# GenerateCompletionsAsXML
|
||||
# GenerateImportsTipForModule
|
||||
# GenerateTip
|
||||
|
||||
|
||||
# testAddExec
|
||||
# testComplete
|
||||
# testCompleteDoesNotDoPythonMatches
|
||||
# testCompletionSocketsAndMessages
|
||||
# testConsoleHello
|
||||
# testConsoleRequests
|
||||
# testDotNetLibraries
|
||||
# testEdit
|
||||
# testGetCompletions
|
||||
# testGetNamespace
|
||||
# testGetReferrers1
|
||||
# testGetReferrers2
|
||||
# testGetReferrers3
|
||||
# testGetReferrers4
|
||||
# testGetReferrers5
|
||||
# testGetReferrers6
|
||||
# testGetReferrers7
|
||||
# testGettingInfoOnJython
|
||||
# testGui
|
||||
# testHistory
|
||||
# testImports
|
||||
# testImports1
|
||||
# testImports1a
|
||||
# testImports1b
|
||||
# testImports1c
|
||||
# testImports2
|
||||
# testImports2a
|
||||
# testImports2b
|
||||
# testImports2c
|
||||
# testImports3
|
||||
# testImports4
|
||||
# testImports5
|
||||
# testInspect
|
||||
# testIt
|
||||
# testMessage
|
||||
# testPrint
|
||||
# testProperty
|
||||
# testProperty2
|
||||
# testProperty3
|
||||
# testQuestionMark
|
||||
# testSearch
|
||||
# testSearchOnJython
|
||||
# testServer
|
||||
# testTipOnString
|
||||
# toXML
|
||||
# updateCustomFrame
|
||||
# varToXML
|
||||
|
||||
#
|
||||
# GetContents
|
||||
# GetCoverageFiles
|
||||
# GetFile
|
||||
# GetFileNameAndBaseFromFile
|
||||
# GetFilenameAndBase
|
||||
# GetFrame
|
||||
# GetGlobalDebugger # -- renamed but kept backward-compatibility
|
||||
# GetNormPathsAndBase
|
||||
# GetNormPathsAndBaseFromFile
|
||||
# GetTestsToRun -- skip
|
||||
# GetThreadId
|
||||
# GetVmType
|
||||
# IPythonEditor -- skip
|
||||
# ImportName
|
||||
# InitializeServer
|
||||
# IterFrames
|
||||
|
||||
|
||||
# Method1 -- skip
|
||||
# Method1a -- skip
|
||||
# Method2 -- skip
|
||||
# Method3 -- skip
|
||||
|
||||
# NewConsolidate
|
||||
# NormFileToClient
|
||||
# NormFileToServer
|
||||
# # Notify -- skip
|
||||
# # NotifyFinished -- skip
|
||||
# OnFunButton
|
||||
# # OnInit -- skip
|
||||
# OnTimeToClose
|
||||
# PydevdFindThreadById
|
||||
# PydevdLog
|
||||
# # RequestInput -- skip
|
||||
|
||||
|
||||
# Search -- manual: search_definition
|
||||
# ServerProxy -- skip
|
||||
# SetGlobalDebugger
|
||||
|
||||
# SetServer
|
||||
# SetUp
|
||||
# SetTrace -- skip
|
||||
|
||||
|
||||
# SetVmType
|
||||
# SetupType
|
||||
# StartCoverageSupport
|
||||
# StartCoverageSupportFromParams
|
||||
# StartPydevNosePluginSingleton
|
||||
# StartRedirect
|
||||
# ToTuple
|
||||
|
||||
# addAdditionalFrameById
|
||||
# removeAdditionalFrameById
|
||||
# removeCustomFrame
|
||||
# addCustomFrame
|
||||
# addError -- skip
|
||||
# addExec
|
||||
# addFailure -- skip
|
||||
# addSuccess -- skip
|
||||
# assertArgs
|
||||
# assertIn
|
||||
|
||||
# basicAsStr
|
||||
# changeAttrExpression
|
||||
# # changeVariable -- skip (part of public API for console)
|
||||
# checkOutput
|
||||
# checkOutputRedirect
|
||||
# clearBuffer
|
||||
|
||||
# # connectToDebugger -- skip (part of public API for console)
|
||||
# connectToServer
|
||||
# consoleExec
|
||||
# createConnections
|
||||
# createStdIn
|
||||
# customOperation
|
||||
# dirObj
|
||||
# doAddExec
|
||||
# doExecCode
|
||||
# dumpFrames
|
||||
|
||||
# # enableGui -- skip (part of public API for console)
|
||||
# evalInContext
|
||||
# evaluateExpression
|
||||
# # execLine -- skip (part of public API for console)
|
||||
# # execMultipleLines -- skip (part of public API for console)
|
||||
# findFrame
|
||||
# orig_findFrame
|
||||
# finishExec
|
||||
# fixGetpass
|
||||
|
||||
# forceServerKill
|
||||
# formatArg
|
||||
# formatCompletionMessage
|
||||
# formatParamClassName
|
||||
# frameVarsToXML
|
||||
# fullyNormalizePath
|
||||
|
||||
# getArray -- skip (part of public API for console)
|
||||
# getAsDoc
|
||||
# getCapturedOutput
|
||||
# getCompletions -- skip (part of public API for console)
|
||||
|
||||
# getCompletionsMessage
|
||||
# getCustomFrame
|
||||
# # getDescription -- skip (part of public API for console)
|
||||
# getDictionary
|
||||
# # getFrame -- skip (part of public API for console)
|
||||
# getFrameName
|
||||
|
||||
|
||||
|
||||
# getFrameStack
|
||||
# getFreeAddresses
|
||||
# getInternalQueue
|
||||
# getIoFromError
|
||||
# getNamespace
|
||||
# getTestName
|
||||
# getTokenAndData
|
||||
# getType
|
||||
|
||||
# getVariable -- skip (part of public API for console)
|
||||
|
||||
# # haveAliveThreads -> has_threads_alive
|
||||
# initializeNetwork
|
||||
# isThreadAlive
|
||||
# # iterFrames -> _iter_frames
|
||||
# # keyStr -> key_to_str
|
||||
# killAllPydevThreads
|
||||
# longRunning
|
||||
# # metA -- skip
|
||||
# nativePath
|
||||
|
||||
# needMore
|
||||
# needMoreForCode
|
||||
# # notifyCommands -- skip (part of public API)
|
||||
# # notifyConnected -- skip (part of public API)
|
||||
# # notifyStartTest -- skip (part of public API)
|
||||
# # notifyTest -- skip (part of public API)
|
||||
# # notifyTestRunFinished -- skip (part of public API)
|
||||
# # notifyTestsCollected -- skip (part of public API)
|
||||
# postInternalCommand
|
||||
# processInternalCommands
|
||||
# readMsg
|
||||
|
||||
|
||||
# redirectStdout
|
||||
# removeInvalidChars
|
||||
# reportCond
|
||||
# resolveCompoundVariable
|
||||
# resolveVar
|
||||
# restoreStdout
|
||||
# sendKillMsg
|
||||
# sendSignatureCallTrace
|
||||
# setTracingForUntracedContexts
|
||||
# startClientThread
|
||||
# startDebuggerServerThread
|
||||
# startExec
|
||||
|
||||
# startTest -- skip
|
||||
# stopTest -- skip
|
||||
# setUp -- skip
|
||||
# setUpClass -- skip
|
||||
# setUpModule -- skip
|
||||
# tearDown -- skip
|
||||
|
||||
'''
|
||||
@@ -0,0 +1,131 @@
|
||||
'''
|
||||
Helper module to do refactoring to convert names to pep8.
|
||||
'''
|
||||
import re
|
||||
import os
|
||||
import names_to_rename
|
||||
|
||||
_CAMEL_RE = re.compile(r'(?<=[a-z])([A-Z])')
|
||||
_CAMEL_DEF_RE = re.compile(r'(def )((([A-Z0-9]+|[a-z0-9])[a-z][a-z0-9]*[A-Z]|[a-z0-9]*[A-Z][A-Z0-9]*[a-z])[A-Za-z0-9]*)')
|
||||
|
||||
|
||||
def _normalize(name):
|
||||
return _CAMEL_RE.sub(lambda x: '_' + x.group(1).lower(), name).lower()
|
||||
|
||||
|
||||
def find_matches_in_contents(contents):
|
||||
return [x[1] for x in re.findall(_CAMEL_DEF_RE, contents)]
|
||||
|
||||
|
||||
def iter_files_in_dir(dirname):
|
||||
for root, dirs, files in os.walk(dirname):
|
||||
for name in ('pydevd_attach_to_process', '.git', 'stubs', 'pydev_ipython', 'third_party', 'pydev_ipython'):
|
||||
try:
|
||||
dirs.remove(name)
|
||||
except:
|
||||
pass
|
||||
for filename in files:
|
||||
if filename.endswith('.py') and filename not in ('rename_pep8.py', 'names_to_rename.py'):
|
||||
path = os.path.join(root, filename)
|
||||
with open(path, 'rb') as stream:
|
||||
initial_contents = stream.read()
|
||||
|
||||
yield path, initial_contents
|
||||
|
||||
|
||||
def find_matches():
|
||||
found = set()
|
||||
for path, initial_contents in iter_files_in_dir(os.path.dirname(os.path.dirname(__file__))):
|
||||
found.update(find_matches_in_contents(initial_contents))
|
||||
print('\n'.join(sorted(found)))
|
||||
print('Total', len(found))
|
||||
|
||||
|
||||
def substitute_contents(re_name_to_new_val, initial_contents):
|
||||
contents = initial_contents
|
||||
for key, val in re_name_to_new_val.iteritems():
|
||||
contents = re.sub(key, val, contents)
|
||||
return contents
|
||||
|
||||
|
||||
def make_replace():
|
||||
re_name_to_new_val = load_re_to_new_val(names_to_rename.NAMES)
|
||||
# traverse root directory, and list directories as dirs and files as files
|
||||
for path, initial_contents in iter_files_in_dir(os.path.dirname(os.path.dirname(__file__))):
|
||||
contents = substitute_contents(re_name_to_new_val, initial_contents)
|
||||
if contents != initial_contents:
|
||||
print('Changed something at: %s' % (path,))
|
||||
|
||||
for val in re_name_to_new_val.itervalues():
|
||||
# Check in initial contents to see if it already existed!
|
||||
if re.findall(r'\b%s\b' % (val,), initial_contents):
|
||||
raise AssertionError('Error in:\n%s\n%s is already being used (and changes may conflict).' % (path, val,))
|
||||
|
||||
with open(path, 'wb') as stream:
|
||||
stream.write(contents)
|
||||
|
||||
|
||||
def load_re_to_new_val(names):
|
||||
name_to_new_val = {}
|
||||
for n in names.splitlines():
|
||||
n = n.strip()
|
||||
if not n.startswith('#') and n:
|
||||
name_to_new_val[r'\b' + n + r'\b'] = _normalize(n)
|
||||
return name_to_new_val
|
||||
|
||||
|
||||
def test():
|
||||
assert _normalize('RestoreSysSetTraceFunc') == 'restore_sys_set_trace_func'
|
||||
assert _normalize('restoreSysSetTraceFunc') == 'restore_sys_set_trace_func'
|
||||
assert _normalize('Restore') == 'restore'
|
||||
matches = find_matches_in_contents('''
|
||||
def CamelCase()
|
||||
def camelCase()
|
||||
def ignore()
|
||||
def ignore_this()
|
||||
def Camel()
|
||||
def CamelCaseAnother()
|
||||
''')
|
||||
assert matches == ['CamelCase', 'camelCase', 'Camel', 'CamelCaseAnother']
|
||||
re_name_to_new_val = load_re_to_new_val('''
|
||||
# Call -- skip
|
||||
# Call1 -- skip
|
||||
# Call2 -- skip
|
||||
# Call3 -- skip
|
||||
# Call4 -- skip
|
||||
CustomFramesContainerInit
|
||||
DictContains
|
||||
DictItems
|
||||
DictIterItems
|
||||
DictIterValues
|
||||
DictKeys
|
||||
DictPop
|
||||
DictValues
|
||||
''')
|
||||
assert re_name_to_new_val == {'\\bDictPop\\b': 'dict_pop', '\\bDictItems\\b': 'dict_items', '\\bDictIterValues\\b': 'dict_iter_values', '\\bDictKeys\\b': 'dict_keys', '\\bDictContains\\b': 'dict_contains', '\\bDictIterItems\\b': 'dict_iter_items', '\\bCustomFramesContainerInit\\b': 'custom_frames_container_init', '\\bDictValues\\b': 'dict_values'}
|
||||
assert substitute_contents(re_name_to_new_val, '''
|
||||
CustomFramesContainerInit
|
||||
DictContains
|
||||
DictItems
|
||||
DictIterItems
|
||||
DictIterValues
|
||||
DictKeys
|
||||
DictPop
|
||||
DictValues
|
||||
''') == '''
|
||||
custom_frames_container_init
|
||||
dict_contains
|
||||
dict_items
|
||||
dict_iter_items
|
||||
dict_iter_values
|
||||
dict_keys
|
||||
dict_pop
|
||||
dict_values
|
||||
'''
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# find_matches()
|
||||
make_replace()
|
||||
# test()
|
||||
|
||||
Reference in New Issue
Block a user