|
6 | 6 | import os |
7 | 7 | import pickle |
8 | 8 | import re |
| 9 | +import subprocess |
| 10 | +import sys |
9 | 11 | import tempfile |
10 | 12 | import zipfile |
11 | 13 | from functools import reduce |
|
22 | 24 | from django.utils.translation import gettext_lazy as _ |
23 | 25 | from langchain_core.messages import HumanMessage, AIMessage |
24 | 26 | from langchain_mcp_adapters.client import MultiServerMCPClient |
25 | | -from pylint.lint import Run |
26 | | -from pylint.reporters import JSON2Reporter |
27 | 27 | from rest_framework import serializers, status |
28 | 28 |
|
29 | 29 | from application.models import Application |
@@ -737,17 +737,81 @@ def run(self, instance, is_valid=True): |
737 | 737 | if is_valid: |
738 | 738 | self.is_valid(raise_exception=True) |
739 | 739 | PylintInstance(data=instance).is_valid(raise_exception=True) |
740 | | - code = instance.get('code') |
| 740 | + |
| 741 | + code = instance.get('code') or '' |
741 | 742 | file_name = get_file_name() |
742 | | - with open(file_name, 'w') as file: |
743 | | - file.write(code) |
744 | | - reporter = JSON2Reporter(output=io.StringIO()) |
745 | | - Run([file_name, |
746 | | - "--disable=line-too-long", |
747 | | - '--module-rgx=[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}'], |
748 | | - reporter=reporter, exit=False) |
749 | | - os.remove(file_name) |
750 | | - return [to_dict(m, os.path.basename(file_name)) for m in reporter.messages] |
| 743 | + if not file_name.endswith('.py'): |
| 744 | + file_name = file_name + '.py' |
| 745 | + |
| 746 | + try: |
| 747 | + with open(file_name, 'w', encoding='utf-8') as file: |
| 748 | + file.write(code) |
| 749 | + result = subprocess.run( |
| 750 | + [ |
| 751 | + sys.executable, |
| 752 | + '-m', |
| 753 | + 'ruff', |
| 754 | + 'check', |
| 755 | + file_name, |
| 756 | + '--output-format=json', |
| 757 | + '--ignore=E501', |
| 758 | + '--extend-select=PL', |
| 759 | + '--no-cache', |
| 760 | + ], |
| 761 | + stdout=subprocess.PIPE, |
| 762 | + stderr=subprocess.PIPE, |
| 763 | + text=True, |
| 764 | + timeout=10, |
| 765 | + ) |
| 766 | + |
| 767 | + if result.returncode not in (0, 1): |
| 768 | + raise Exception(result.stderr or result.stdout) |
| 769 | + |
| 770 | + if not result.stdout.strip(): |
| 771 | + return [] |
| 772 | + |
| 773 | + messages = json.loads(result.stdout) |
| 774 | + base_name = os.path.basename(file_name) |
| 775 | + return [ |
| 776 | + { |
| 777 | + 'type': 'error' if ( |
| 778 | + item.get('code') == 'E999' |
| 779 | + or str(item.get('code') or '').startswith('E9') |
| 780 | + or item.get('code') in ['F821', 'F822', 'F823'] |
| 781 | + ) else 'warning', |
| 782 | + 'module': '', |
| 783 | + 'obj': '', |
| 784 | + 'line': item.get('location', {}).get('row', 1), |
| 785 | + |
| 786 | + # Ruff column 是 1-based,前端 CodeMirror 用 0-based |
| 787 | + 'column': max(item.get('location', {}).get('column', 1) - 1, 0), |
| 788 | + |
| 789 | + 'endLine': item.get('end_location', {}).get( |
| 790 | + 'row', |
| 791 | + item.get('location', {}).get('row', 1) |
| 792 | + ), |
| 793 | + 'endColumn': max( |
| 794 | + item.get('end_location', {}).get( |
| 795 | + 'column', |
| 796 | + item.get('location', {}).get('column', 1) + 1 |
| 797 | + ) - 1, |
| 798 | + 0 |
| 799 | + ), |
| 800 | + |
| 801 | + 'path': base_name, |
| 802 | + 'symbol': item.get('code') or '', |
| 803 | + 'message': ( |
| 804 | + f"{item.get('code')}: {item.get('message')}" |
| 805 | + if item.get('code') |
| 806 | + else item.get('message') |
| 807 | + ), |
| 808 | + } |
| 809 | + for item in messages |
| 810 | + ] |
| 811 | + |
| 812 | + finally: |
| 813 | + if os.path.exists(file_name): |
| 814 | + os.remove(file_name) |
751 | 815 |
|
752 | 816 | class Import(serializers.Serializer): |
753 | 817 | file = UploadedFileField(required=True, label=_("file")) |
|
0 commit comments