跳转到主要内容

用于延迟对象和类上操作和动作的小工具

项目描述

Build Status codecov PyPI version

介绍

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 (10.6 kB 查看哈希值

上传时间

支持者: