我怎样才能替换ORM类 - 所以它不应该导致递归!
问题:
原始类具有超级调用,当它被替换时 - 它会导致自我继承并导致最大递归深度超过异常.
即类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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
import test
def main(app):
print "Running..."
__import__(app, globals(), locals())
Run Code Online (Sandbox Code Playgroud)
from osv import orm …
Run Code Online (Sandbox Code Playgroud) 我遇到了一个已经解决的 ActiveResource 问题,并试图将它修补到我的应用程序中而没有太多运气.
我在config/initializers /中添加了一个包含以下内容的文件:
class ActiveResource::Errors < ActiveModel::Errors
# https://github.com/rails/rails/commit/b09b2a8401c18d1efff21b3919ac280470a6eb8b
def from_hash(messages, save_cache = false)
clear unless save_cache
messages.each do |(key,errors)|
errors.each do |error|
if @base.attributes.keys.include?(key)
add key, error
elsif key == 'base'
self[:base] << error
else
# reporting an error on an attribute not in attributes
# format and add themActive to base
self[:base] << "#{key.humanize} #{error}"
end
end
end
end
# Grabs errors from a json response.
def from_json(json, save_cache = false)
decoded = ActiveSupport::JSON.decode(json) …
Run Code Online (Sandbox Code Playgroud) 我正在努力WWW::Mechanize
自动化基于网络的后台点击我需要做的是让我的测试电子商务订单进入我需要的状态来测试我对长的多部分的特定部分所做的更改流程.要批量处理大量订单,我需要Home
经常点击链接.为了缩短这一点,我WWW::Mechanize
在运行时将这样的方法入侵(基于brian d foy 掌握Perl的示例):
{ # Shortcut to go back to the home page by calling $mech->go_home
# I know I'll get a warning and do not want it!
no warnings 'once';
my $homeLink = $mech->find_link( text => 'Home' )->url_abs();
$homeLink =~ s/system=0/system=1/;
*WWW::Mechanize::go_home = sub {
my ($self) = @_;
return $self->get($homeLink);
};
}
Run Code Online (Sandbox Code Playgroud)
这很好用,并且不会伤害任何人,因为我使用它的脚本仅供我使用,而不是更大系统的一部分.
但现在我想知道是否有可能实际上只告诉一个$mech
具有此方法的WWW::Mechanize
对象,而另一个可能稍后创建的对象(比如说,做一些交叉引用而不混淆另一个具有活动会话的对象)我的后台办公室)不能使用那种方法.
我不确定这是否可行,因为如果我理解对象在Perl中的工作方式,那么->
操作符会告诉它go_home
在包中查找子例程并将第一个参数WWW::Mechanize
传递$mech
给它.如果这种理解是错误的,请纠正我.
我通过添加一种硬编码检查进行了实验,该检查只允许原始$mech
对象使用该功能. …
关于这个问题,我试图覆盖postgresql_version
定义的方法ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
返回PostgreSQL版本:
module ActiveRecord
module ConnectionAdapters
class PostgreSQLAdapter < AbstractAdapter
protected
# Returns the version of the connected PostgreSQL server.
def postgresql_version
80200
end
end
end
end
Run Code Online (Sandbox Code Playgroud)
但补丁未应用.我尝试在config/initializer中并在/ lib文件中要求它.救命?
我正在尝试使用 pytest 为类方法开发一个测试,该方法从字符串列表中随机选择一个字符串。
它看起来本质上类似于下面的 givemeannumber 方法:
import os.path
from random import choice
class Bob(object):
def getssh():
return os.path.join(os.path.expanduser("~admin"), '.ssh')
def givemeanumber():
nos = [1, 2, 3, 4]
chosen = choice(nos)
return chosen
Run Code Online (Sandbox Code Playgroud)
第一种方法,getssh,在 Bob 类中只是pytest 文档中的例子
我的生产代码从数据库中获取字符串列表,然后随机选择一个。所以我希望我的测试获取字符串,然后选择第一个字符串而不是随机选择。这样我就可以针对已知字符串进行测试。
根据我的阅读,我认为我需要使用monkeypatching 来伪造随机化。
这是我到目前为止所得到的
import os.path
from random import choice
from _pytest.monkeypatch import MonkeyPatch
from bob import Bob
class Testbob(object):
monkeypatch = MonkeyPatch()
def test_getssh(self):
def mockreturn(path):
return '/abc'
Testbob.monkeypatch.setattr(os.path, 'expanduser', mockreturn)
x = Bob.getssh()
assert x == '/abc/.ssh'
def test_givemeanumber(self):
Testbob.monkeypatch.setattr('random.choice', …
Run Code Online (Sandbox Code Playgroud) 我一直在尝试解决第三方模块中的错误。该错误最近已修复,但我一直想知道我的问题。也许这个问题将来会对我或其他人有所帮助。
该模块定义了一个类 Runtime,其中包含我使用的几种方法。导入模块后,它会自动创建一个运行时实例,加载配置并将该实例提供给用户(我)使用。
# thirdPartyModule.py
class Runtime:
def __init__(self, a):
self.a = a
def configuration(self, ...):
...
def fun(self):
print(self.a)
rt = Runtime("twice")
rt.configuration(...)
Run Code Online (Sandbox Code Playgroud)
不幸的是,其中一个运行时方法包含一个错误。我曾经通过用一个工作替代品覆盖实例的方法来修补这个错误,如下所示:
# mycode.py
import types
from thirdPartyModule import rt
def newfun(self):
print(self.a, self.a)
rt.fun = types.MethodType(newfun, rt)
rt.fun()
Run Code Online (Sandbox Code Playgroud)
当我等待开发人员修复错误时,这一切都很好。__slots__
或者至少在开发人员添加到类中之前它是这样的:
# thirdPartyModule.py
class Runtime:
__slots__ = ("a", )
def __init__(self, a):
self.a = a
...
Run Code Online (Sandbox Code Playgroud)
从那时起,我在这个论坛上尝试了几种方法覆盖解决方案,但都被拒绝了(“AttributeError:'Runtime'对象属性'fun'是只读的”)。
这可能unittest.mock
可以帮助我,但我对嘲笑不太熟悉。我尝试了以下方法但没有成功:
import unittest.mock
rt.fun = mock.Mock(rt.fun, side_effect=newfun)
Run Code Online (Sandbox Code Playgroud)
这会导致相同的 AttributeError。也许我可以模拟整个实例 ( rt = mock.Mock(rt)
) …
我正在尝试__str__
通过以下装饰器修补类的特殊方法:
def str_patcher(klass):
def decorator(*args, **kwargs):
def __str__(self):
items = {key: value for key, value in self.__dict__.items() if not key.startswith("_")}
return f"{type(self).__qualname__}({items})"
klass.__str__ = __str__
return klass
return decorator
Run Code Online (Sandbox Code Playgroud)
然后,我做了一个MyClass
装饰的类str_patcher
:
@str_patcher
class MyClass:
def __init__(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
Run Code Online (Sandbox Code Playgroud)
但是当我打印出来时MyClass(a=1, b=2, c=3)
,我希望看到,MyClass({a: 1, b: 2, c: 3})
但我却看到了<class __main__.MyClass>
。
为什么是这样?
所以我试图monkeypatch shutil模块,以便使用最新的make_archive函数修复,允许创建大型zip文件.
我是一个概念性的证据,所以想到一个快速的黑客来解决这个问题会让我继续我想做的事情.
我的代码:
import shutil
import os
def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None):
zip_filename = base_name + ".zip"
archive_dir = os.path.dirname(base_name)
if not os.path.exists(archive_dir):
if logger is not None:
logger.info("creating %s", archive_dir)
if not dry_run:
os.makedirs(archive_dir)
# If zipfile module is not available, try spawning an external 'zip'
# command.
try:
import zipfile
except ImportError:
zipfile = None
if zipfile is None:
shutil._call_external_zip(base_dir, zip_filename, verbose, dry_run)
else:
if logger is not None:
logger.info("creating '%s' and adding '%s' to it", …
Run Code Online (Sandbox Code Playgroud) 是否有可能在最后使用爆炸来修补方法?
我想要猴子补丁String.upcase!
,但我不知道如何实现.
问题是我想要更改原始字符串对象.
这是一个例子:
class String
def upcase!
self.mb_chars.upcase.to_s
end
end
Run Code Online (Sandbox Code Playgroud)
现在,如果我在控制台中输入并尝试它,它不起作用:
[1] pry(main)> asd="asd"
=> "asd"
[2] pry(main)> asd.upcase
=> "ASD"
[3] pry(main)> asd
=> "asd"
[4] pry(main)> asd.upcase!
=> "ASD"
[5] pry(main)> asd
=> "asd"
Run Code Online (Sandbox Code Playgroud) 我是猴子修补__eq__
类的方法。我发现以下作品:
def eq(obj, other):
if isinstance(other, str):
return obj.name.upper() == other.upper()
else:
return object.__eq__(obj, other)
Run Code Online (Sandbox Code Playgroud)
这不起作用:
def eq(obj, other):
if isinstance(other, str):
return obj.name.upper() == other.upper()
else:
return super().__eq__(other)
Run Code Online (Sandbox Code Playgroud)
这有时可行,但有时会引发错误:
def eq(obj, other):
if isinstance(other, str):
return obj.name.upper() == other.upper()
else:
return super().__eq__(self, other)
Run Code Online (Sandbox Code Playgroud)
错误:
<ipython-input-128-91287536205d> in eq(obj, other)
3 return obj.name.upper() == other.upper()
4 else:
----> 5 return super().__eq__(self, other)
6
7
RuntimeError: super(): __class__ cell not found
Run Code Online (Sandbox Code Playgroud)
您能解释一下这里发生了什么吗?如何正确替换object
为super()
?
monkeypatching ×10
python ×6
class ×2
python-3.x ×2
activerecord ×1
methods ×1
overloading ×1
perl ×1
pytest ×1
python-2.7 ×1
ruby ×1
shutil ×1
slots ×1
super ×1