用于延迟对象和类上操作和动作的小工具
项目描述
介绍
Mimic是一个小工具,旨在延迟对对象或类执行的操作。然后可以在稍后日期执行这些操作。其主要目标是解决鸡生蛋的悖论。
当您在自己的代码中发现自己处于鸡生蛋的情况时,这很可能是由于项目设计不佳所致。如果情况如此,可能建议重新思考您的项目结构。
有时,当与第三方库一起工作时,您确实没有选择,并且一个库的设计与另一个库的设计不匹配。出于愤慨(我在看那些需要初始化实例来定义全局作用域装饰器的库),我开始编写这个库,这样我就可以控制“何时”初始化“什么”,同时能够在受控的局部作用域中执行操作,而不会失去使用全局定义的能力。
重要免责声明:我不会在生产代码中使用这个库,至少不是在当前的版本中 :) 在我能够舒适地说它稳定之前,它还需要更多的战斗测试。请随意为此战斗测试做出贡献。
快速入门
该库的核心是Deferred
对象,其行为基本上类似于模拟对象。唯一的区别是Deferred
对象没有保留名称,因此您可以对其进行 literally 任何 操作。
当然,这意味着您,作为用户,无法将此延迟对象用作驱动程序。为此,我们需要一个处理程序对象,它在需要时启动事物并连接事物。
from mimics import Mimic
# Make the handler object
mimic = Mimic()
# Make an object, using the factory on the handler object, that will record all actions
husk = mimic.husk()
# Do the deferred operations you want to do
result = husk + 3
# Replay anything done on the deferred object onto another object
mimic.absorb(husk).as_being(5)
# Doing an additional `is True` to ensure to result is a boolean and not a deferred object
# (because, yes, even these actions are deferred before playing)
assert (result == 8) is True
一个更详细的示例
这个例子可能不太容易理解,因为Flask-SQLAlchemy在控制局部作用域的同时执行全局操作时表现得相当好,但我认为这是一个很好的例子,展示了库的功能。在这里,我们将推迟创建、初始化和持久化一个SQLAlchemy模型。
完成我们想要做的所有事情后,我们可以在最合适的时机播放它。
# Make the handler and deferred object
mimic = Mimic()
husk = mimic.husk()
# Defer the making of an SQLA model using the deferred object
class MyModel(husk.Model):
id = husk.Column(husk.Integer, primary_key=True)
name = husk.Column(husk.String(255), nullable=False, unique=True)
# Defer the db creation
husk.create_all()
# Defer the initialization and persisting of an instance
my_model = MyModel(name="test")
husk.session.add(my_model)
husk.session.commit()
# Make the actual SQLA db object
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:///:memory:"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
# Replay deferred actions as being the db
mimic.absorb(husk).as_being(db)
# Verify it worked
models = MyModel.query.all()
assert len(models) == 1
assert models[0].name == "test"
它的工作原理
如上所述,整个库围绕着Deferred
对象展开。由于这个对象可以执行几乎所有操作,因此你很重要的一点是不要自己初始化deferred对象(除非你知道你在做什么)。重要的是要通过一个Mimic
实例上可用的工厂方法来创建这个类的实例。
基本上,Deferred
对象可以处于两种状态
- 挂起
- 未挂起
一个令人震惊的事实。当Deferred
对象挂起时,它将记录对该对象所执行的所有操作。每当访问一个属性、调用一个方法或返回一个值时,它都会创建并返回一个新的Deferred
对象,这个对象反过来也会记录与之相关的操作。
一旦你准备好播放你的deferred操作,将其状态变为未挂起,记录的操作将在选定的对象上重新播放。从那时起,产生的deferred对象将作为一个代理工作,将任何请求转发到与之相关的主题。
陷阱
代理对象
因为这个库并不是在玩黑魔法(或者至少不是很多),所以重要的是要知道,任何被Deferred
对象遮蔽的主题在取消挂起后永远不会再是它自己。我们不是在操作虚拟内存,也不是在操作局部和全局变量或修补导入的模块(请注意,我已经考虑过这一点)。
虽然你可能看起来像在与主题本身交互,但你始终是在与一个看起来和感觉都像其主题的代理对象交互。因此,在某些情况下可能会出现一些问题(请参阅重要免责声明)。
Deferred对象的限制
需要注意的是,只允许在deferred对象上执行操作。使用deferred对象执行操作将会出现严重错误。
例如
husk = Mimic().husk()
result = 5 + husk
将导致TypeError
项目详情
mimics-0.0.1.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | bff8361a1f089fb6edcd337a48fc77ac3db8f79d84bca800aa4735164b2d2b61 |
|
MD5 | ae9d55dcc43312191feb653bee1c9c67 |
|
BLAKE2b-256 | df99b64c396e084943b531c27d23dc20f028d8fd0a027b3f676ec8afa6ffbd21 |