我想为我的独立应用程序生成由 Django 模板系统预处理的人类可读的 HTML 和 CSS 代码(正确缩进)。
我修改了 django.template.base 模块中 NodeList 类的 render 方法。我的代码似乎工作正常,但我使用猴子修补来替换旧的渲染方法。
在这种情况下,是否有一种更优雅的方式不使用猴子修补?或者也许猴子补丁是最好的方法?
我的代码如下所示:
'''
This module monkey-patches Django template system to preserve
indentation when rendering templates.
'''
import re
from django.utils.encoding import force_text
from django.utils.safestring import mark_safe
from django.template.loader import render_to_string
from django.template import Node, NodeList, TextNode
from django.template.loader_tags import (BlockNode, ConstantIncludeNode,
IncludeNode)
NEWLINES = re.compile(r'(\r\n|\r|\n)')
INDENT = re.compile(r'(?:\r\n|\r|\n)([\ \t]+)')
def get_indent(text, i=0):
'''
Depending on value of `i`, returns first or last indent
(or any other …
Run Code Online (Sandbox Code Playgroud) 我的用例:我想使用不同的 DateInput。但我想减少代码重复。我希望所有没有明确需要不同 DateInput 小部件的表单都使用我的自定义小部件。
没有猴子补丁的情况下有什么改变可以解决这个问题吗?
例子
模型.py:
class MyModel(models.Model):
date=models.DateField()
Run Code Online (Sandbox Code Playgroud)
形式.py:
class MyForm(forms.ModelForm):
class Meta:
model=MyModel
Run Code Online (Sandbox Code Playgroud)
上面的代码应该使用我的自定义小部件。我不想更改上面的 models.py 和 forms.py,因为有很多。
src/mainDir/mainFile.py
mainFile.py 的内容
import src.tempDir.tempFile as temp
data = 'someData'
def foo(self):
ans = temp.boo(data)
return ans
Run Code Online (Sandbox Code Playgroud)
src/tempDir/tempFile.py
def boo(data):
ans = data
return ans
Run Code Online (Sandbox Code Playgroud)
现在我想测试foo()
并在方法中src/tests/test_mainFile.py
模拟temp.boo(data)
方法foo()
import src.mainDir.mainFile as mainFunc
testData = 'testData'
def test_foo(monkeypatch):
monkeypatch.setattr('src.tempDir.tempFile', 'boo', testData)
ans = mainFunc.foo()
assert ans == testData
Run Code Online (Sandbox Code Playgroud)
但我收到错误
属性错误:“src.tempDir.tempFile”没有属性“boo”
我期望 ans = testData.
我想知道我是否正确地模拟了我的 tempDir.boo() 方法,或者我应该使用 pytest 的模拟程序而不是 Monkeypatch。
假设我想编写一个小型解释器,可以使用二元运算
Plus
、一元运算Negate
和整数常量来计算表达式。
我目前只对 AST 的解释感兴趣,因此为了简单起见,让我们跳过标记化和解析。
在 Haskell 中,有一种或多或少规范的方法来做到这一点:
data Ast = Plus Ast Ast | Negate Ast | IntConst Int
ev :: Ast -> Int
ev (Plus a b) = (ev a) + (ev b)
ev (Negate x) = - (ev x)
ev (IntConst i) = i
main = print $ show $ ev $ (Plus (IntConst 50) (Negate $ IntConst 8))
Run Code Online (Sandbox Code Playgroud)
现在,Python 3.6 似乎没有代数数据类型。我的问题是似乎有很多可能的解决方法。最明显的一个是使用isinstance
:
class Plus:
def __init__(self, first, second):
self.first = first
self.second …
Run Code Online (Sandbox Code Playgroud) python monkeypatching visitor-pattern algebraic-data-types python-3.x
我想f(*args, **kwargs)
从已安装的模块中进行猴子修补。我在自己的代码中使用了装饰器的想法,但是已安装模块中的其他方法无法f
正确调用。
这是一个例子:
import numpy as np
def log(func):
def wrapper(*args, **kwargs):
print('logging')
return func(*args, **kwargs)
return wrapper
if __name__ == "__main__":
a1 = np.asarray([0, 1, 2])
print(f'a1={a1}')
a2 = np.array([0, 1, 2])
print(f'a2={a2}')
np.array = log(np.array)
a3 = np.asarray([0, 1, 2])
print(f'a3={a3}')
a4 = np.array([0, 1, 2])
print(f'a4={a4}')
Run Code Online (Sandbox Code Playgroud)
输出是:
a1=[0 1 2]
a2=[0 1 2]
a3=[0 1 2]
logging
a4=[0 1 2]
Run Code Online (Sandbox Code Playgroud)
我希望结果是:
a1=[0 1 2]
a2=[0 1 2]
logging
a3=[0 1 2]
logging
a4=[0 …
Run Code Online (Sandbox Code Playgroud) monkeypatching metaprogramming python-import python-3.x python-internals
我正在导入其他人制作的库,并且想要更改该库中特定类方法的工作方式,因此我已将该类方法复制到我自己的文件中,并希望在运行时替换它。这对于函数来说似乎工作得很好,但对于类方法来说似乎就不行了。
a.library.package.library_file.py
class LibraryClass(ParentClass):
@classmethod
def get_cost(cls, time):
return int(time * cls.hourly)
Run Code Online (Sandbox Code Playgroud)
我想用这个替换它
class LibraryClass(ParentClass):
@classmethod
def get_cost(cls, time):
return 1234
Run Code Online (Sandbox Code Playgroud)
我尝试只进行正常的替换,这对于常规功能来说效果很好
import a.library.package.library_file
...
a.library.package.library_file.LibraryClass.get_cost = get_cost
Run Code Online (Sandbox Code Playgroud)
但它似乎根本无法正常工作,该方法在错误的时间使用错误的参数调用并导致崩溃。在对 Google、StackOverflow 和 Python 进行一些研究之后,我开始尝试使用模拟类。
from unittest.mock import patch
@patch.object('a.library.package.library_file.LibraryClass', 'get_cost')
def get_cost(cls, time):
return 1234
Run Code Online (Sandbox Code Playgroud)
好消息是它不会崩溃,坏消息是它没有做任何事情,旧代码仍然存在,就像我的代码不存在一样。
我尝试过各种其他方法来做到这一点,例如
import a.library.package.library_file
@patch.object(a.library.package.library_file.LibraryClass, 'get_cost')
...
Run Code Online (Sandbox Code Playgroud)
或者
from a.library.package.library_file import LibraryClass
@patch.object(LibraryClass, 'get_cost')
...
Run Code Online (Sandbox Code Playgroud)
但每次方法都没有碰过。就像我的代码不存在并且使用旧代码一样。
我将我们的应用程序升级到 Rails 6.1.4.4 和 Ruby 3.0.2。我有这颗古老的宝石
\ngem 'acts_as_commentable'\n
Run Code Online (Sandbox Code Playgroud)\n锁定在 4.0.2 版本。该 gem 似乎不再受支持,这很遗憾,因为当我启动我的应用程序或控制台时,我现在收到此错误
\n$ rails c\nYour Gemfile lists the gem rspec-rails (>= 0) more than once.\nYou should probably keep only one of them.\nRemove any duplicate entries and specify the gem only once.\nWhile it's not a problem now, it could cause errors if you change the version of one of them later.\n/Users/myuser/.rvm/gems/ruby-3.0.2/gems/hash_dot-2.5.0/lib/hash.rb:19:in `method_missing': undefined method `arity' for {:as=>:commentable, :dependent=>:destroy}:Hash (NoMethodError)\n from /Users/myuser/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.4/lib/active_record/associations/builder/association.rb:53:in `build_scope'\n from /Users/myuser/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.4/lib/active_record/associations/builder/association.rb:47:in `create_reflection'\n from /Users/myuser/.rvm/gems/ruby-3.0.2/gems/activerecord-6.1.4.4/lib/active_record/associations/builder/association.rb:32:in …
Run Code Online (Sandbox Code Playgroud) monkeypatching ruby-on-rails acts-as-commentable ruby-on-rails-6 ruby-3
我最近在业余时间开始尝试使用Django来处理一些Web应用程序.在为一个设计数据模型时,我遇到了使用继承来定义网站用户或使用已经由框架提供的User类进行猴子修补的技术的困境.
我尝试通过(根据以下方式定义了所有模型等而没有错误python manage.py validate
)添加字段:
User.add_to_class('location', models.CharField(max_length=250,blank=True))
并执行了syncdb
命令.但是,我一直收到这个错误
OperationalError:没有这样的列:auth_user.location
我是在网站的管理员视图还是manage.py shell.必须有一个我缺少的额外步骤,但似乎有关整个猴子修补技术的文档有限.所以,在我诉诸继承之前,我会请求你的帮助.当然欢迎任何代码,提示或指向其他文档的链接.
提前致谢.
PS.我知道这种技术很难看,而且可能是不明智的.;)
我有一个应用程序,为了测试,我需要用特定的时间戳替换time.time()调用,我过去使用ruby完成了
(可在此处获取代码:http://github.com/zemariamm/Back-to-Future/blob/master/back_to_future.rb)
但是我不知道如何使用Python来做到这一点.
任何提示?干杯,泽玛丽亚
我在我的代码中进行了大量的数组求和,所以我想要修补Array类以包含sum方法(它对数组中的所有元素求和):
class Array
def sum
self.inject{ |s, t| s + t }
end
end
Run Code Online (Sandbox Code Playgroud)
但是,我以前从来没有在共享代码中修补任何东西,我怀疑这是一个"安全"的事情(例如,也许其他人已经定义了一个sum
方法Array
).
那么什么是能够在我正在编写的代码中对数组求和的最佳方法,而不必arr.inject{ |s, t| s + t }
每次都写入?猴子补丁有安全的方法吗?我能以某种方式使用模块吗?或者我应该在某个地方编写一个辅助方法,它接收一个数组并返回总和(即def sum_array(arr); return arr.inject{ |s, t| s + t }; end
)?(或者还有其他一些方法吗?)
monkeypatching ×10
python ×5
django ×3
python-3.x ×2
ruby ×2
datetime ×1
forms ×1
indentation ×1
pytest ×1
ruby-3 ×1
time ×1