#!/usr/bin/env python3 """Fix diffvg setup.py and C++ source files for Python 3.12 compatibility.""" import os def fix_setup_py(diffvg_dir): setup_path = os.path.join(diffvg_dir, 'setup.py') with open(setup_path, 'r') as f: content = f.read() # Fix the CXXFLAGS line to add -std=c++14 old_line = " env['CXXFLAGS'] = '{} -DVERSION_INFO=\\\"{}\\\"'.format(env.get('CXXFLAGS', ''),\n self.distribution.get_version())" new_line = " env['CXXFLAGS'] = '{} -std=c++14 -DVERSION_INFO=\\\"{}\\\"'.format(env.get('CXXFLAGS', ''),\n self.distribution.get_version())" if old_line in content: content = content.replace(old_line, new_line) print('Fixed CXXFLAGS in setup.py') else: # Try a simpler pattern content = content.replace( "env['CXXFLAGS'] = '{}", "env['CXXFLAGS'] = '{} -std=c++14".replace('{}', "env.get('CXXFLAGS', '')") ) print('Tried alternative CXXFLAGS fix') with open(setup_path, 'w') as f: f.write(content) def fix_pybind11_python312(diffvg_dir): """Fix pybind11 for Python 3.12 by removing frame-dependent code.""" cast_path = os.path.join(diffvg_dir, 'pybind11', 'include', 'pybind11', 'cast.h') pybind11_path = os.path.join(diffvg_dir, 'pybind11', 'include', 'pybind11', 'pybind11.h') # Fix cast.h - error_string function if os.path.exists(cast_path): with open(cast_path, 'r') as f: content = f.read() # Replace frame access with NULL in error_string content = content.replace( '" " + handle(frame->f_code->co_filename).cast() +\n "\\n"', '" [unknown file]\\n"' ) content = content.replace( 'handle(frame->f_code->co_name).cast() + "\\n";', '" [unknown function]\\n";' ) content = content.replace('frame = frame->f_back;', 'frame = NULL;') with open(cast_path, 'w') as f: f.write(content) print('Fixed cast.h') # Fix pybind11.h - get_type_overload function if os.path.exists(pybind11_path): with open(pybind11_path, 'r') as f: content = f.read() content = content.replace( 'PyFrameObject *frame = PyThreadState_Get()->frame;', 'PyFrameObject *frame = NULL;' ) # Remove frame checks that use f_code content = content.replace( 'if (frame && (std::string) str(frame->f_code->co_name) == name &&\n frame->f_code->co_argcount > 0) {', 'if (0) {' ) content = content.replace( 'frame->f_locals, PyTuple_GET_ITEM(frame->f_code->co_varnames, 0));', 'nullptr' ) with open(pybind11_path, 'w') as f: f.write(content) print('Fixed pybind11.h') if __name__ == '__main__': import sys diffvg_dir = sys.argv[1] if len(sys.argv) > 1 else '/tmp/diffvg' fix_setup_py(diffvg_dir) fix_pybind11_python312(diffvg_dir) print('All fixes applied!')