标签: monkeypatching

要(猴子)补丁还是不要(猴子)补丁,这就是问题所在

我正在和一位同事谈论我们使用的某个包的一个意外/不期望的行为.尽管我们有一个简单的解决方法(或至少是解决方法)而没有任何明显的副作用,但他强烈建议通过硬修补并在上游发布补丁来扩展相关代码,希望将来某些时候可以接受.实际上,我们针对在每个新构建上自动应用的多个软件包的特定版本维护补丁.主要论点是,这是正确的做法,而不是"丑陋"的解决方法或脆弱的猴子补丁.另一方面,我赞成实用性而非纯度,我的一般经验法则是"无补丁">"猴子补丁">"硬补丁",至少除了(关键)错误修复之外的其他任何东西.

所以我想知道是否就什么时候(硬)补丁,猴子补丁或只是尝试解决一个不完全符合人们想要的第三方软件包达成共识.它是否主要与补丁的原因(例如修复错误,修改行为,添加缺少的功能),给定的包(大小,复杂性,成熟度,开发人员响应性),其他或没有一般规则和一个应根据具体情况决定?

language-agnostic oop patch monkeypatching

7
推荐指数
1
解决办法
716
查看次数

Python:在初始评估后向类中添加父类

一般Python问题

我正在使用以下类结构导入Python库(称为animals.py):

class Animal(object): pass

class Rat(Animal): pass

class Bat(Animal): pass

class Cat(Animal): pass

...
Run Code Online (Sandbox Code Playgroud)

我想一个父类(添加Pet)到每个品种类(的Rat,Bat,Cat,...); 但是,我无法更改我导入的库的实际来源,因此它必须是运行时更改.

以下似乎有效:

import animals

class Pet(object): pass

for klass in (animals.Rat, animals.Bat, animals.Cat, ...): 
    klass.__bases__ = (Pet,) + klass.__bases__
Run Code Online (Sandbox Code Playgroud)

这是将父类注入Python中的继承树而不修改要修改的类的源定义的最佳方法吗?

激励情节

我正试图将持久性移植到控制实验室设备的大型库中.弄乱它是不可能的.我想Persistent试试ZODB 吧.我不想编写mixin/facade包装器库,因为我正在处理需要更新的应用程序代码中的100多个类和大量导入.我只是通过攻击我的入口点来测试选项:如上所示设置数据库,修补(但是在动物模块上拉动物种类而不是显式列表)然后在我退出时关闭数据库.

Mea Culpa /要求

这是一个故意的一般性问题.我对注入父母的不同方法以及对这些方法的利弊的评论感兴趣.我同意这种运行时的诡计会让代码变得非常混乱.如果我选择ZODB,我会做一些明确的事情.现在,作为python的普通用户,我对一般情况感到好奇.

python oop inheritance monkeypatching

7
推荐指数
1
解决办法
1539
查看次数

Monkey-patch内置函数用于单元测试?

我不想在我的unittest中创建真实文件.所以我发现自己经常修补无意义的样板并为伪文件创建模拟工厂.我想知道这些毫无意义的努力是否会更好(在这种情况下)并尝试类似于本地unittest方法的范围:

open = lambda x: StringIO()
Run Code Online (Sandbox Code Playgroud)

这样可以吗?或者是否存在重大警告/不采用这种方法并且更好地使用模拟工厂?

python unit-testing monkeypatching

7
推荐指数
1
解决办法
1080
查看次数

在python中将基类添加到现有对象

我有几个不同种类的对象(不同的函数名称,不同的签名),我对它们进行修补,以便有一种从不同函数访问它们的通用方法.简而言之,有一个调度程序可以获取我想要修补的对象,并根据它调用不同修补程序的对象类型.修补程序将向对象添加方法:

def patcher_of_some_type(object):

    def target(self, value):
        # do something and call self methods

    object.target = types.MethodType(target, object)

    # many more of these
Run Code Online (Sandbox Code Playgroud)

随着程序变得越来越复杂,围绕对象(或对象类)的包装似乎更好.一些修补程序共享公共代码或相互关联.但我不控制对象创建,也不控制类创建.我只得到了这些物品.即使我能做到这一点,我只想包装(或修补)某些对象,而不是所有对象.

一种解决方案可能是为现有对象添加基类,但我不确定这是多么可维护和安全.还有其他解决方案吗?

python inheritance monkeypatching metaclass

7
推荐指数
2
解决办法
6838
查看次数

如何monkeypatch静态方法?

虽然将实例方法monkeypatch到类很简单,例如

class A(object):
    pass

def a(self):
    print "a"

A.a = a
Run Code Online (Sandbox Code Playgroud)

与其他类的这样做@staticmethod点菜

class B(object):
    @staticmethod
    def b():
        print "static b"

A.b = B.b
Run Code Online (Sandbox Code Playgroud)

导致A.b()产生一个

TypeError:b()必须使用A实例作为第一个参数调用unbound方法(没有任何东西)

python static-methods monkeypatching

7
推荐指数
1
解决办法
2469
查看次数

py.test的monkeypatch.setattr(...)在某些情况下不起作用

conftest中(在autouse夹具中):

monkeypatch.setattr('collector.util.download_data', lambda url:"Winning" )
Run Code Online (Sandbox Code Playgroud)

collector/util.py中:

def download_data(url):
    assert False
Run Code Online (Sandbox Code Playgroud)

the_caller.py中:

from collector.util import download_data
def some_function():
    download_data("blah")
Run Code Online (Sandbox Code Playgroud)

当我调用some_function()时,我得到断言.但是,如果我将the_caller.py更改为:

import collector
def some_function():
    collector.util.download_data("blah")
Run Code Online (Sandbox Code Playgroud)

然后我得到"胜利".

为什么这种行为有所不同,我如何使monkeypatch适用于这两种情况?

python monkeypatching pytest python-2.7

7
推荐指数
1
解决办法
3328
查看次数

单个对象上的猴子补丁方法

我想update_attributes在模型类的单个实例上覆盖方法的行为.假设变量被称为@alert什么是最好的方法呢?为了清楚起见,我不想为整个类修改此方法的行为.


免责声明:

我需要这样做以强制方法false在我想要时返回,以便我可以为后面的错误处理代码编写单元测试.我知道这可能不是最好的做法.

ruby monkeypatching ruby-on-rails

7
推荐指数
1
解决办法
2043
查看次数

猴子修补时放置代码的位置

我读到的关于猴子修补的一切都说要做这样的事情:

class String
  def foo
    #your special code 
  end
end
Run Code Online (Sandbox Code Playgroud)

但我找不到任何关于放置此代码的说明.在rails应用程序中,我可以把它放在我想要的任何疯狂的地方吗?在模块中?一个模型?

我是否需要在我定义monkeypatch的文件中包含一些内容?我是否需要在我想要使用它的地方包含我的monkeypatch?

ruby monkeypatching ruby-on-rails

7
推荐指数
2
解决办法
6322
查看次数

如何模拟从不同模块导入的方法中导入的函数

我有以下功能来测试:

my_package.db_engine.db_functions.py:

from ..utils import execute_cmd
from my_package.db_engine.db_functions import dbinfo 

def dbinfo(db_name):
    params = (cmd_cfg.DB, add_pj_suffix(db_name))
    cmd = get_db_cmd_string(cmd_cfg.DBINFO, params=params)
    cmd_result = execute_cmd(cmd)
    result_dict = map_cmd_output_to_dict(cmd_result)
    return result_dict
Run Code Online (Sandbox Code Playgroud)

此函数获取数据库的名称,然后从中构建命令字符串并像subprocess使用该execute_cmd方法一样执行此命令.我想在不实际执行的情况下测试此函数subprocess.我只想检查命令是否正确构建并正确传递给execute_cmd.因此我需要模拟execute_cmd从模块导入的方法utils.

我的文件夹结构如下:

my_project
|_src
| |_my_package
| | |_db_engine
| | | |_db_functions.py
| | | |_ __init__.py
| | |_utils.py
| | |_ __init__.py
| | |_ ....
| |_ __init__.py
|_tests
  |_test_db_engine.py
Run Code Online (Sandbox Code Playgroud)

所以对于我的测试我尝试了以下内容test_db_engine.py:

import unittest
from …
Run Code Online (Sandbox Code Playgroud)

python unit-testing monkeypatching mocking

7
推荐指数
1
解决办法
3504
查看次数

在Python中将方法从一个类安全地绑定到另一个类

我知道我可以将一个函数附加到一个类并使其成为一个方法:

 >>> def is_not_bound(inst, name):
...     print("Hello %s" % name)
... 
>>> 
>>> class NoMethods:
...     pass
... 
>>> 
>>> setattr(NoMethods, 'bound', is_not_bound)
>>> 
>>> NoMethods().bound("oz") # prints: Hello oz
Hello oz
Run Code Online (Sandbox Code Playgroud)

令我惊讶的是,这也适用于从一个类到另一个类的绑定方法:

>>> class Foo:
...     def foo(self, name):
...         print("Hello %s" % name)
... 
>>> class B:
...     pass
... 
>>> setattr(B, 'bound_to_b', getattr(Foo, 'foo'))
>>> B().bound_to_b("confused?")
Hello confused?
>>> 
Run Code Online (Sandbox Code Playgroud)

我能安全地使用它吗?有什么我在监督的吗?

更新

我发现的一个警告:

>>> B.bound_to_b
<function Foo.foo at 0x7fc997e8b730>
Run Code Online (Sandbox Code Playgroud)

虽然我从B调用了这个方法,但它似乎与Foo有关.

而且更令人惊讶的是:

>>> def new_method(self, addto):
...     return self.num …
Run Code Online (Sandbox Code Playgroud)

python oop monkeypatching python-3.x

6
推荐指数
1
解决办法
90
查看次数