标签: monkeypatching

修补Django表单类的猴子?

给定一个表单类(在您的巨型Django应用程序的某个深处)

class ContactForm(forms.Form):
    name = ...
    surname = ...
Run Code Online (Sandbox Code Playgroud)

并且考虑到您希望在不扩展或修改表单类本身的情况下向此表单添加另一个字段,为什么以下方法不起作用?

ContactForm.another_field = forms.CharField(...)
Run Code Online (Sandbox Code Playgroud)

(我的第一个猜测是Django使用的元类hackery仅在第一次构造表单类时应用.如果是这样,是否有办法重新声明类以克服这个问题?)

python django monkeypatching django-forms

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

Python猴子补丁私有功能

我有一个带有函数(调用它a())的模块,它调用在同一模块中定义的另一个函数(调用它__b()). __b()是一个通过网站说话urllib2并获取一些数据的功能.现在我正在尝试测试a(),但当然不希望我的单元测试与公共互联网对话.因此,我在想,如果我可以__b()使用返回固定数据的函数来修补补丁,那么我可以编写测试a().

更具体一点,我的模块看起来有点像:

def a():
    return __b("someval")

def __b(args):
    return something_complex_with_args
Run Code Online (Sandbox Code Playgroud)

所以现在我想测试a(),但我需要修补__b.问题是A)关于猴子补丁的绝大多数信息适用于类的方法,而不适用于模块中的函数,以及B)我想要猴子补丁的函数是私有的.__b如果它使这个过程更可行,我愿意改为非私人,但不愿意.

建议?

编辑:因为它代表测试类看起来像:

from unittest import TestCase

import mymodule

def newfn(args):
    return {"a" : "b"}

mymodule._b = newfn

class TestMyModule(TestCase):
    def test_basic(self):
        print(mymodule.a('somearg'))
Run Code Online (Sandbox Code Playgroud)

当我运行它时,如果没有完成猴子修补,我会看到输出,而不是看到{'a': 'b'}打印出来.

python monkeypatching

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

Monkey Patching Float Infix操作员产生了意想不到的结果

重新定义Float#/似乎没有效果:

class Float
  def /(other)
    "magic!"
  end
 end
 puts 10.0/2.0 # => 5.0
Run Code Online (Sandbox Code Playgroud)

但是当Float#*重新定义另一个中缀运算符时,Float#/突然采用新的定义:

class Float
  def /(other)
    "magic!"
  end
  def *(other)
    "spooky"
  end
end
puts 10.0/2.0 # => "magic!"
Run Code Online (Sandbox Code Playgroud)

我很想知道是否有人可以解释这种行为的来源以及是否有其他人得到相同的结果.

  • Ruby:ruby 2.0.0p353(2013-11-22)[x64-mingw32]

要快速确认错误,请运行此脚本.

ruby monkeypatching arithmetic-expressions

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

使用forbiddenfruit使int可迭代

我知道,这是错的,但有可能吗?我认为当一个对象.__iter__返回一个迭代器时,它被认为是一个可迭代的对象?那么为什么这不起作用呢?

>>> from forbiddenfruit import curse
>>> def __iter__(self):
...     for i in range(self):
...         yield i
>>> curse(int, "__iter__", __iter__)
>>> for x in 5:
...     print x
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not iterable
Run Code Online (Sandbox Code Playgroud)

int 似乎有一个__iter__现在的方法:

>>> int(5).__iter__
<bound method int.__iter__ of 5>
Run Code Online (Sandbox Code Playgroud)

python monkeypatching python-2.7 forbiddenfruit

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

在 devtools 扩展中猴子修补反应的渲染方法

我正在尝试从 devtool 扩展中为 React 的渲染方法创建一个猴子补丁,因为我正在尝试为我的扩展中的一个功能重新创建类似于 react_devtool 的 api 的东西。我用这两行代码欺骗了被检查窗口的虚拟 DOM

var reactRoot = document.querySelector("[data-reactroot]")
var dom = reactRoot[Object.getOwnPropertyNames(reactRoot)[0]]
Run Code Online (Sandbox Code Playgroud)

我还听说通过访问窗口的__REACT_DEVTOOLS_GLOBAL_HOOK__. 我需要能够在页面更新时从 React 的 internalInstance 访问一组新数据(setState/rerender)。

这是我对 React 的渲染方法进行猴子修补的尝试。此代码从通过 my 注入的单独文件运行,该文件content-scripts.js能够在检查的窗口中访问 React 应用程序的 dom。

const reactInstances = window.__REACT_DEVTOOLS_GLOBAL_HOOK__._renderers
const instance = reactInstances[Object.keys(reactInstances)[0]]
console.log('current windows React INSTANCE: ', instance)
var reactRender = instance.Mount.render
console.log('reacts render method: ', reactRender)
reactRender = (function (original) {
  return function (nextElement, container, callback) {
    var result = original.apply(this, arguments)
    console.log(original, result)
    return result
  } …
Run Code Online (Sandbox Code Playgroud)

javascript monkeypatching content-script reactjs react-devtools

6
推荐指数
0
解决办法
436
查看次数

在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
查看次数

如何为多个测试猴子修补一个函数

考虑我的模块 "mymodule.py"

# contents of "mymodule.py"

def func1(x):
    return x * 2
Run Code Online (Sandbox Code Playgroud)

我想模拟这个函数并改变它的返回值。根据文档,我可以这样做:

# contents of "test_mymodule.py"

import mymodule
import pytest

@pytest.fixture
def mock_func1():
    def mock_ret(*args, **kwargs):
        return 2

def test_func1_a(monkeypatch, mock_func1):
    monkeypatch.setattr(mymodule, "func1", mock_func1)
    assert mymodule.func1(1) == 2 

def test_func1_b(monkeypatch, mock_func1):
    monkeypatch.setattr(mymodule, "func1", mock_func1)
    assert mymodule.func1(1) != 37 
Run Code Online (Sandbox Code Playgroud)

但是,我不想为每个测试修补模块。monkeypatch.setattr对整个测试模块的范围进行一次的正确方法是什么test_mymodule.py

我期待这样的事情

# contents of "test_mymodule.py"

import mymodule
import pytest

@pytest.fixture
def mock_func1():
    def mock_ret(*args, **kwargs):
        return 2

monkeypatch.setattr(mymodule, "func1", mock_func1)

def test_func1_a():
    assert mymodule.func1(1) == 2 …
Run Code Online (Sandbox Code Playgroud)

python monkeypatching pytest

6
推荐指数
3
解决办法
3950
查看次数

Python:猴子修补函数的源代码

我可以在函数的源代码中添加前缀和后缀吗?

我知道装饰器并且不想使用它们(下面的最小例子没有说明原因,但我有我的理由).

def f():
    print('world')
g = patched(f,prefix='print("Hello, ");',suffix='print("!");')
g() # Hello, world!
Run Code Online (Sandbox Code Playgroud)

这是我到目前为止:

import inspect
import ast
import copy
def patched(f,prefix,suffix):
    source = inspect.getsource(f)
    tree = ast.parse(source)
    new_body = [
        ast.parse(prefix).body[0],
        *tree.body[0].body,
        ast.parse(suffix).body[0]
    ]
    tree.body[0].body = new_body
    g = copy.deepcopy(f)
    g.__code__ = compile(tree,g.__code__.co_filename,'exec')
    return g
Run Code Online (Sandbox Code Playgroud)

不幸的是,如果我使用它然后g()如上所述调用就没有任何反应; 既不印刷world也不Hello, world!印刷.

python monkeypatching abstract-syntax-tree

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

如何在pytest中使用monkeypatch或mock删除库?

如果我的库中有一个contrib附加程序,其中包含依赖项(例如requests),我希望用户必须安装该附加程序才能访问 CLI API,但我在 CI 测试期间安装了 contrib 附加程序,我如何使用pytestMonkeyPatch删除测试期间的依赖关系以确保我的检测正确?

例如,如果contrib额外的内容会另外安装requests,那么我希望用户必须这样做

$ python -m pip install mylib[contrib]
Run Code Online (Sandbox Code Playgroud)

然后能够在命令行上使用 CLI API,如下所示

$ mylib contrib myfunction
Run Code Online (Sandbox Code Playgroud)

wheremyfunction使用requests依赖项

$ python -m pip install mylib[contrib]
Run Code Online (Sandbox Code Playgroud)

我如何在测试中模拟或猴子补丁 ,以便我可以确保用户正确地收到警告以及如果他们这样做requestspytestModuleNotFoundError

$ python -m pip install mylib
$ mylib contrib myfunction
Run Code Online (Sandbox Code Playgroud)

?在阅读了有关 pytest 标签的其他一些问题后,我仍然认为我不明白如何做到这一点,所以我在这里问。

python monkeypatching pytest pytest-mock

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

unsafeWindow是如何通过用户脚本扩展来实现的?

今天我遇到了一种情况,我需要进行扩展以对网页中的某些对象进行猴子修补。

然而,我几乎没有找到关于如何实际实现它的文档,我尝试使用该userScriptsAPI(目前仅适用于 Firefox),但该对象与页面的 HTML DOM 上的window上下文隔离。window

我知道这是可能的,因为像 GreaseMonkey 这样的用户脚本管理器实现了一个unsafeWindow对象,该对象使脚本可以直接访问网页的非隔离上下文中的对象,从而使猴子修补变得非常容易。

所以我想知道这是如何实现的。我试图研究名为ViolentMonkey的用户脚本管理器的源代码,我发现它定义unsafeWindowsrc/injected/web/gm-api-wrapper.js:53global对象的引用,但我无法找到它在源代码中定义的位置。

我知道这不是通过简单地<script>在页面中注入一个元素来实现的,因为根据我的检查,页面的 DOM 中没有可见的元素。

我对这个很酷的机制的实现很好奇,我很确定我错过了一些明显的东西,所以我需要你的帮助来摘掉我的眼罩!

javascript monkeypatching google-chrome-extension tampermonkey firefox-addon-webextensions

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