幕后,集成开发环境(IDE)不过是带有许多窗口和附加二进制文件以执行各种任务的文本编辑器,例如编译、调试、代码标记、静态代码分析等。最终,其中一个库可以用于重构代码。其中一个这样的库是Jedi,但有一个专门用于处理重构的库,它是rope。
pip3 install rope
命令行解决方案
你可以尝试使用他们的API,但是既然你要求一个命令行工具而且没有提供,那么请将以下文件保存在任何可访问的地方(已知相对文件夹、用户bin等)并使其可执行chmod +x pyrename.py
。
from rope.base.project import Project
from rope.refactor.rename import Rename
from argparse import ArgumentParser
def renamodule(old, new):
prj.do(Rename(prj, prj.find_module(old)).get_changes(new))
def renamethod(mod, old, new, instance=None):
mod = prj.find_module(mod)
modtxt = mod.read()
pos, inst = -1, 0
while True:
pos = modtxt.find('def '+old+'(', pos+1)
if pos < 0:
if instance is None and prepos > 0:
pos = prepos+4
break
print('found', inst, 'instances of method', old+',', ('tell which to rename by using an extra integer argument in the range 0..' if (instance is None) else 'could not use instance=')+str(inst-1))
pos = -1
break
if (type(instance) is int) and inst == instance:
pos += 4
break
if instance is None:
if inst == 0:
prepos = pos
else:
prepos = -1
inst += 1
if pos > 0:
prj.do(Rename(prj, mod, pos).get_changes(new))
argparser = ArgumentParser()
subparsers = argparser.add_subparsers()
subparsermod = subparsers.add_parser('module', help='moduledottedpath newname')
subparsermod.add_argument('moduledottedpath', help='old module full dotted path')
subparsermod.add_argument('newname', help='new module name only')
subparsermet = subparsers.add_parser('method', help='moduledottedpath oldname newname')
subparsermet.add_argument('moduledottedpath', help='module full dotted path')
subparsermet.add_argument('oldname', help='old method name')
subparsermet.add_argument('newname', help='new method name')
subparsermet.add_argument('instance', nargs='?', help='instance count')
args = argparser.parse_args()
if 'moduledottedpath' in args:
prj = Project('.')
if 'oldname' not in args:
renamodule(args.moduledottedpath, args.newname)
else:
renamethod(args.moduledottedpath, args.oldname, args.newname)
else:
argparser.error('nothing to do, please choose module or method')
让我们创建一个测试环境,与问题中显示的情景完全相同(这里假设使用Linux用户):
cd /some/folder/
ls pyrename.py
mkdir prj; cd prj; cat << EOF >> main.py
#!/usr/bin/env python3
from a.b import foo_method
foo_method()
EOF
mkdir a; touch a/__init__.py; cat << EOF >> a/b.py
def foo_method():
print('yesterday i was foo, tomorrow i will be bar')
EOF
chmod +x main.py
./main.py
cat main.py
cat a/b.py
现在使用重命名模块和方法的脚本:
../pyrename.py module a b
../pyrename.py module b.b d
../pyrename.py method b.d foo_method bar_method
./main.py
cat main.py
cat b/d.py
这个例子完全做到了问题所要求的。
只实现了重命名模块和方法,因为这是问题的范围。如果您需要更多,可以增加脚本或从头开始创建一个新的脚本,学习他们的文档和这个脚本本身。为了简单起见,我们使用当前文件夹作为项目文件夹,但您可以在脚本中添加额外的参数使其更加灵活。
import a.b; foo = a.b.foo_method
这样的东西不存在?或者getattr(a.b, 'foo_method')
?或者调用exec
? - a_guestImportError
和AttributeError
。然后可以使用这些信息来更新相应的文件,或者至少通知开发人员进行更新。当然,剩下的用法不应该太多,否则这将是非常计算密集型的。否则,您还可以尝试ast
解析以识别重构的可能候选项。 - a_guest