Page 44 - 《软件学报》2025年第4期
P. 44

1450                                                       软件学报  2025  年第  36  卷第  4  期


                 被传入的关键字集合. 第       11、12  行的  TravelExceptionAboutKwargs 表示遍历与关键字参数有关的异常流信息, 若
                 P.kwargs 没有关键字   key  时  API 会抛出异常, 则将  key  存入  KY; 若  P.kwargs 有关键字  key  时, API 会抛出异常,
                 则将  key  存入  KN. 若  v1  版本和  v2  版本的  KY  或  KN  存在差异, 则该  API 存在关键字参数的键增删   (CI2).
                    第  18–21  行检测参数的范围改变      (CI5). 其中, 第  19  行的  Raise(condition, E) 表示通过分析  API 的异常流信息
                 E, 判断条件   condition  成立时  API 是否会抛出异常. 如果会抛出异常, Raise(condition, E) 返回相应的异常类型; 否
                 则返回   False. 如果某异常仅在    v2  版本抛出而不在    v1  版本抛出  (第  19  行), 并且该异常的触发条件与某参数的输
                 入有关   (第  20、21  行), 则该  API 存在参数的范围改变    (CI5).
                    例  7: 示例代码   2  中, 算法  1  第  2  行  P D 、P A  和  P M  分别初始化为{‘fname’, ‘encoding’}、{‘path’}和{‘self’,
                 ‘convert_dates’, ‘write_index’, ‘byteorder’}. 由  M.change∪M.unchange={<s 3 , s 3 >, <s 4 , s 5 >, <s 6 , s 6 >}, S 1 .FP[‘fname’]
                 ={s 4 , s 6 }, S 2 .FP[‘path’]={s 5 , s 6 }, 可知参数  fname 和参数  path 前向切片中的保留语句之间存在对应关系. 因此, 第  3、
                 4  行认为参数   fname 被重命名为   path, 并更新  P D  为{‘encoding’}, P A  为{}, CI 为{CI3}. 由于  Len(P D )>0, 第  5  行更
                 新  CI 为{CI1, CI3}.
                    例  8: 示例代码  6  中, E 1 .R={}, E 2 .R={s 4 : <TypeError, ‘labels’ in kwargs>}, 所以算法  1  第  11、12  行中  KN2=
                 {‘labels’}, KY1=KY2=KN1={}. 由于  KN1  与  KN2  不相等, 更新  CI 为{CI2}.
                    例  9: 示例代码  3  中, S 2 .FP[‘self’]={s 3 , s 4 }, E 1 .R={s 4 : <ValueError, not self.index.is_monotonic>}, E 2 .R={s 4 :
                 <ValueError, not self.index.is_monotonic_increasing>}. 当第  18  行中  s  为  s 4  时, Raise(not self.index.is_
                 monotonic_increasing, E 1 ) 为  False, 而  s 4 ∈S 2 .FP[‘self’], 所以参数  self 的范围发生改变, 更新  CI 为{CI5}.

                 3.3.2    检测与异常有关的兼容性问题       (CI6)
                    检测与异常有关兼容性问题如算法             2  所示, 其输入为异常流信息      E, 输出为兼容性问题产生原因集合           CI, 包括
                 抛出不同的异常      (CI6).

                 算法  2. 检测与异常有关的兼容性问题.

                 输入: E;
                 输出: CI.

                 Function DetectException       AttributeError, 这导致算法
                 1.  for each s in E 2 .R then:
                 2.  exception 1  = Raise(E 2 .R[s].condition, E 1 )
                 3.  CI ← {CI6} if exception 1  != False and exception 1  != E 2 .R[s].exception
                 4.  return CI
                 Function End
                    算法  2  展示了检测抛出不同的异常         (CI6) 的具体流程. 如果相同条件       E 2 .R[s].condition  下, v1  版本和  v2  版本
                 均抛出异常, 但抛出的异常类型不同, 则认为该             API 存在抛出不同的异常       (CI6).
                    例  10: 示例代码  5  中, E 1 .R={s 5 : <AttributeError, AttributeNotFound(ctx, app) OR AttributeNotFound(ctx.app,
                 update_template_context)>}, E 2 .R={s 4 : <RuntimeError, ctx is None>}. 当  ctx is None 条件在  v1  版本成立时, 会在  s 5
                 抛出异常   AttributeError, 即  exception 1 为             2  第  3  行的条件成立, 更新  CI 为{CI6}.

                 3.3.3    检测与返回值有关的兼容性问题        (CI7)
                    检测与返回值有关的兼容性问题如算法               3  所示, 其输入为语句匹配信息        M、返回值信息      R、异常流信息     E、
                 切片信息   S、全局语句信息      G  以及条件分支信息     B, 输出为兼容性问题产生原因集合         CI, 包括输出不同的返回值      (CI7).
                    首先, 第  1–23  行计算  API 从  v1  版本更新至  v2  版本中的良性变化语句集合       BSC 1 和  BSC 2 . 根据文献  [12], 当
                 第三方库进行更新时, 由于修复缺陷、提升性能、重构方法等原因, 可能会发生良性的语义变化                               (benign semantic
                 change), 这些变化通常不被视为兼容性问题. 对于缺陷修复而言, 它不符合兼容性问题定义中的第                          1  个条件, 即在
   39   40   41   42   43   44   45   46   47   48   49