PCART  v1.4
Automated Repair of Python API Parameter Compatibility Issues
callsite.py
Go to the documentation of this file.
1 
12 
13 import hashlib
14 import json
15 import os
16 import re
17 from dataclasses import dataclass
18 from typing import Optional
19 
20 
21 
28 @dataclass(frozen=True)
30 
32  rel_path: str
33 
34 
36  lineno: int
37 
38 
40  col_offset: int
41 
42 
44  end_lineno: Optional[int]
45 
46 
48  end_col_offset: Optional[int]
49 
50 
52  call_text: str
53 
54 
56  normalized_call: str
57 
58 
60  def artifactPayload(self):
61  return {
62  'rel_path': self.rel_path,
63  'lineno': self.lineno,
64  'col_offset': self.col_offset,
65  'end_lineno': self.end_lineno,
66  'end_col_offset': self.end_col_offset,
67  'normalized_call': self.normalized_call,
68  }
69 
70 
72  def artifactHash(self):
73  payload = json.dumps(
74  self.artifactPayloadartifactPayload(),
75  sort_keys=True,
76  separators=(',', ':'),
77  ).encode('utf-8')
78  return hashlib.sha256(payload).hexdigest()
79 
80 
82  def artifactId(self):
83  MAX_REL = 64 # max slug length for relative path
84  MAX_CALL = 48 # max slug length for call name
85  # slugify relative path
86  rel_slug = re.sub(r'[^0-9A-Za-z]+', '_', str(self.rel_path)).strip('_').lower()
87  rel_slug = re.sub(r'_+', '_', rel_slug)[:MAX_REL].strip('_') or 'source'
88  # slugify call name (everything before the first '(')
89  call_name = str(self.normalized_call).split('(', 1)[0]
90  call_slug = re.sub(r'[^0-9A-Za-z]+', '_', call_name).strip('_').lower()
91  call_slug = re.sub(r'_+', '_', call_slug)[:MAX_CALL].strip('_') or 'call'
92  return f'{rel_slug}__L{self.lineno}C{self.col_offset}__{call_slug}__{self.artifactHash()}'
93 
94 
95 
102 @dataclass(frozen=True)
104 
106  identity: CallsiteIdentity
107 
108 
110  artifact_id: str
111 
112 
114  format_api: str
115 
116 
118  parameters: str
119 
120 
123  def toDict(self):
124  return {
125  'id': self.artifact_id,
126  'artifact_hash': self.identity.artifactHash(),
127  'rel_path': self.identity.rel_path,
128  'lineno': self.identity.lineno,
129  'col_offset': self.identity.col_offset,
130  'end_lineno': self.identity.end_lineno,
131  'end_col_offset': self.identity.end_col_offset,
132  'call_text': self.identity.call_text,
133  'normalized_call': self.identity.normalized_call,
134  'format_api': self.format_api,
135  'parameters': self.parameters,
136  }
137 
138 
139 
144 def normalizeCallText(call_text):
145  return call_text.replace(' ', '').replace('"', '').replace("'", '')
146 
147 
148 
154 def normalizeRelPath(file_path, proj_path=None):
155  normalized_file = os.path.abspath(file_path).replace('\\', '/')
156  if proj_path:
157  normalized_root = os.path.abspath(proj_path).replace('\\', '/').rstrip('/')
158  try:
159  rel_path = os.path.relpath(normalized_file, normalized_root).replace('\\', '/')
160  if not rel_path.startswith('..'):
161  return rel_path
162  except ValueError:
163  pass
164  return normalized_file
165 
166 
167 
181  file_path,
182  call_text,
183  format_api,
184  parameters,
185  lineno,
186  col_offset,
187  end_lineno=None,
188  end_col_offset=None,
189  proj_path=None,
190 ):
191  identity = CallsiteIdentity(
192  rel_path=normalizeRelPath(file_path, proj_path),
193  lineno=int(lineno),
194  col_offset=int(col_offset),
195  end_lineno=end_lineno,
196  end_col_offset=end_col_offset,
197  call_text=call_text,
198  normalized_call=normalizeCallText(call_text),
199  )
200  record = CallsiteRecord(
201  identity=identity,
202  artifact_id=identity.artifactId(),
203  format_api=format_api,
204  parameters=parameters,
205  )
206  return record.toDict()
Callsite identity class 调用点身份类
Definition: callsite.py:29
def artifactPayload(self)
The relative path from project root 相对于项目根目录的文件路径
Definition: callsite.py:60
def artifactId(self)
Return stable readable artifact id for a callsite 返回调用点稳定可读运行产物id.
Definition: callsite.py:82
def artifactHash(self)
Return stable artifact hash for a callsite 返回调用点稳定运行产物hash.
Definition: callsite.py:72
Callsite record class 调用点记录类
Definition: callsite.py:103
def toDict(self)
The structured callsite identity 结构化调用点身份
Definition: callsite.py:123
def normalizeRelPath(file_path, proj_path=None)
Normalize source file path to project relative path 将源码路径归一化为项目相对路径
Definition: callsite.py:154
def normalizeCallText(call_text)
Normalize call text for identity generation 归一化调用文本,用于生成调用点身份
Definition: callsite.py:144
def makeCallsiteRecord(file_path, call_text, format_api, parameters, lineno, col_offset, end_lineno=None, end_col_offset=None, proj_path=None)
Make callsite record 构造调用点记录
Definition: callsite.py:190