#!/usr/bin/env python # -*- coding: utf-8 -*- """ 检查 ARTv2 的 Python 2/3 兼容性 """ from __future__ import print_function import os import sys import re def check_file(filepath): """检查单个文件的兼容性问题""" issues = [] try: with open(filepath, 'r', encoding='utf-8') as f: lines = f.readlines() for i, line in enumerate(lines, 1): # 跳过注释行 stripped = line.strip() if stripped.startswith('#') or stripped.startswith('"""') or stripped.startswith("'''"): continue # 检查 print 语句(不是函数) if re.match(r'^\s*print\s+[^(]', line) and 'from __future__ import print_function' not in ''.join(lines[:10]): issues.append((i, 'print_statement', line.strip())) # 检查 except Exception, e: (但不是注释中的) if re.search(r'except\s+\w+\s*,\s*\w+:', line) and not stripped.startswith('#'): issues.append((i, 'except_syntax', line.strip())) # 检查 dict.iteritems/iterkeys/itervalues if re.search(r'\.iter(items|keys|values)\(', line): issues.append((i, 'dict_iter', line.strip())) # 检查 xrange if re.search(r'\bxrange\(', line): issues.append((i, 'xrange', line.strip())) # 检查 long 类型使用 (但不是在 Qt.py 中的兼容性代码) if re.search(r'\blong\(', line) and 'long = int' not in ''.join(lines[:20]) and '_wrapinstance' not in line.lower(): issues.append((i, 'long_type', line.strip())) # 检查旧式 Qt 信号 (但不是注释或错误消息中的) if ('QtCore.SIGNAL' in line or 'QtCore.SLOT' in line) and 'NotImplementedError' not in line and not stripped.startswith('#'): issues.append((i, 'qt_signal', line.strip())) # 检查直接导入 shiboken if re.search(r'import shiboken[^2]', line) and 'QtCompat' not in ''.join(lines): issues.append((i, 'shiboken_import', line.strip())) except Exception as e: issues.append((0, 'file_error', str(e))) return issues def main(): """主函数""" base_path = os.path.dirname(os.path.abspath(__file__)) core_scripts = os.path.join(base_path, 'Core', 'Scripts') plugins_path = os.path.join(base_path, 'plug-ins') all_issues = {} # 检查所有 Python 文件 for root, dirs, files in os.walk(base_path): # 跳过 ThirdParty/github (第三方库) if 'github' in root: continue # 跳过 Qt.py (已经是兼容版本) if 'Qt.py' in root: continue for file in files: if file.endswith('.py'): # 跳过 Qt.py (已经是兼容版本) if file == 'Qt.py': continue filepath = os.path.join(root, file) issues = check_file(filepath) if issues: rel_path = os.path.relpath(filepath, base_path) all_issues[rel_path] = issues # 输出结果 if not all_issues: print("✓ No Python 2/3 compatibility issues found!") print("✓ ARTv2 is ready for Maya 2020-2025") return 0 else: print("=" * 80) print("Found Python 2/3 compatibility issues:") print("=" * 80) issue_types = { 'print_statement': 'Print statement (use print() function)', 'except_syntax': 'Old except syntax (use "as" instead of ",")', 'dict_iter': 'dict.iteritems/keys/values (use .items()/.keys()/.values())', 'xrange': 'xrange (use range)', 'long_type': 'long type (add "long = int" compatibility)', 'qt_signal': 'Old Qt signal syntax (use new-style signals)', 'shiboken_import': 'Direct shiboken import (use QtCompat)', 'file_error': 'File read error' } for filepath, issues in sorted(all_issues.items()): print(f"\n{filepath}:") for line_num, issue_type, line_content in issues: desc = issue_types.get(issue_type, issue_type) print(f" Line {line_num}: [{desc}]") print(f" {line_content}") print("\n" + "=" * 80) print(f"Total files with issues: {len(all_issues)}") return 1 if __name__ == '__main__': sys.exit(main())