如何通过猴子修补来替换类?
我如何替换 ORM 类 - 所以它不应该导致递归!
问题:
原始类有 super 调用,当它被替换时 - 它会导致自继承并导致最大递归深度超出异常。
即类orm正在调用super(orm, self)....并且orm已被另一个继承原始orm的类替换....
包!
addons __init__.py osv run_app.py
./addons:
__init__.py test_app1.py test.py
./osv:
__init__.py orm.py
orm.py 的内容
class orm_template(object):
def __init__(self, *args, **kw):
super(orm_template, self).__init__()
def fields_get(self, fields):
return fields
def browse(self, id):
return id
class orm(orm_template):
def __init__(self, *args, **kw):
super(orm, self).__init__(*args, **kw)
def fields_get(self, fields, context = None):
return super(orm, self).fields_get(fields)
def read(self, fields):
return fields
addons/init.py
import test
def main(app):
print "Running..."
__import__(app, globals(), locals())
的内容 addons/test.py
from osv import orm
import osv
class orm(orm.orm):
def __init__(self, *args, **kw):
super(orm, self).__init__(*args, **kw)
def fields_get(self, *args, **kw):
print "my fields get................."
return super(orm, self).fields_get(*args, **kw)
osv.orm.orm = orm
print "replaced.........................."
的内容 test_app1.py 的
from osv.orm import orm
class hello(orm):
_name = 'hellos'
def __init__(self, *args, **kw):
super(hello, self).__init__(*args, **kw)
print hello('test').fields_get(['name'])
内容 run_app.py 的内容
import addons
addons.main('test_app1')
输出
>>>python run_app.py
replaced..........................
Running...
...
...
super(orm, self).__init__(*args, **kw)
RuntimeError: maximum recursion depth exceeded
我见过类似的 问题
How can I replace the ORM class - so it should not cause recursion !!!
Problem:
original class has the super call, when its got replaced - it causes self inheritance and causes maximum recursion depth exceed exception.
i.e. class orm is calling super(orm, self).... and orm has been replaced by another class which inherits original orm....
Package !
addons __init__.py osv run_app.py
./addons:
__init__.py test_app1.py test.py
./osv:
__init__.py orm.py
contents of orm.py
class orm_template(object):
def __init__(self, *args, **kw):
super(orm_template, self).__init__()
def fields_get(self, fields):
return fields
def browse(self, id):
return id
class orm(orm_template):
def __init__(self, *args, **kw):
super(orm, self).__init__(*args, **kw)
def fields_get(self, fields, context = None):
return super(orm, self).fields_get(fields)
def read(self, fields):
return fields
contents of addons/init.py
import test
def main(app):
print "Running..."
__import__(app, globals(), locals())
contents of addons/test.py
from osv import orm
import osv
class orm(orm.orm):
def __init__(self, *args, **kw):
super(orm, self).__init__(*args, **kw)
def fields_get(self, *args, **kw):
print "my fields get................."
return super(orm, self).fields_get(*args, **kw)
osv.orm.orm = orm
print "replaced.........................."
contents of test_app1.py
from osv.orm import orm
class hello(orm):
_name = 'hellos'
def __init__(self, *args, **kw):
super(hello, self).__init__(*args, **kw)
print hello('test').fields_get(['name'])
contents of run_app.py
import addons
addons.main('test_app1')
OUTPUT
>>>python run_app.py
replaced..........................
Running...
...
...
super(orm, self).__init__(*args, **kw)
RuntimeError: maximum recursion depth exceeded
I've seen the similar question
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的
addons/test.py
需要获取并保留对原始orm.orm
的引用,并使用它而不是替换的版本。即:因此,monkeypatched-in 类继承自原始类,而不是继承自自身,就像您在设置中所拥有的那样。顺便说一句,如果您可以通过更好地设计 osv 模块(例如,使用 setter 函数来设置 orm)来避免猴子修补,您会更高兴;-)。
Your
addons/test.py
needs to get and keep a reference to the originalorm.orm
and use that instead of the replaced version. I.e.:so the monkeypatched-in class inherit from the original rather than from itself, as you had it in your setup. BTW, if you can avoid monkey-patching by better design of the
osv
module (e.g. w/a setter function to set what's the orm) you'll be happier;-).