File size: 3,290 Bytes
8a2feb8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#!/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<std::string>() +\n                    "\\n"',
            '"  [unknown file]\\n"'
        )
        content = content.replace(
            'handle(frame->f_code->co_name).cast<std::string>() + "\\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!')