构建可插拔应用程序:如何包含流行库的分支并防止名称冲突?
Posted
技术标签:
【中文标题】构建可插拔应用程序:如何包含流行库的分支并防止名称冲突?【英文标题】:Building pluggable apps: how to include forks of popular libraries and prevent name conflicts? 【发布时间】:2012-08-10 09:28:10 【问题描述】:我正在构建一个我试图保持可插拔的应用程序。唯一的问题是我需要稍微修改django-mailer
,以便我的应用程序可以跟踪已发送/未发送的电子邮件并访问电子邮件内容。
确保这不会与使用 django-mailer
的其他人或我决定为自己的应用分叉/调整的任何其他 python 库冲突的最佳方法是什么?
我应该重命名我的 fork 中的 mailer 及其所有相关导入吗?我错过了一些更容易的东西吗?
【问题讨论】:
你的 django-mailer 模块是否会为其他应用程序破坏它?如果没有,那么别担心,每个人都可以使用你的版本。 您可以在自己的应用程序中接收来自 django-mailer 的信号并且保持不变?听起来你试图用它做的事情不需要实际修改。 @Spacedman 它会破坏它,因为我想修改MessageLog
对象上的字段。问题是核心邮件engine
类在创建MessageLog
时立即delete()
s 消息对象。我想我可以编写自己的模型来存储 MessageLog -> 消息关系,并基本上复制并粘贴 mailer.engine
以添加 ML->M 关系。
@moopet - 信号短暂地掠过我的脑海。您将如何从 Message 到 MessageLog 进行通信?
【参考方案1】:
你可以用一个函数来解决它。创建一个同时做这两件事的函数:
确保事后可以得到想要的东西 确保消息已发送。或者你可以做一些更重的管道。确保把它记录好,并尽量让其他人不要在家里为了每一个徒劳的目的尝试这个,而是联系 Django 或 Django-mailer 团队,询问他们是否可以安排更好的解决方案。
装饰来自 django.core.mail 模块的 EmailMessage 类:确保在成功发送消息后,您想要的信息也会传递到其他地方。
# wrappedmailer.py
from django.core.mail import EmailMessage
class WrappedEmailMessage(object):
def __init__(self, message):
self.__message = message
# more initialization
# override all EmailMessage methods:
# do what you want with what is provided,
# then return self.__message.method(...)
然后当你的应用程序初始化时,在加载 django-mailer 之前,你可以执行以下操作:
import django.core.mail
import newmailer
django.core.mail.EmailMessage = newmailer.WrappedEmailMessage
django.core.mail 模块保留在同一个 Python 进程中的缓存中,因此每当导入 django.core.mail 时,EmailMessage 类实际上就是 WrappedEmailMessage 类。
【讨论】:
我喜欢包装EmailMessage
的想法。不幸的是,我的主要问题仍然存在:我需要修改 django-mailer
本身(或任何其他应用程序)并好奇如何处理它。这些是无法猴子修补的更改:模型级别的更改。如何防止它与 django-mailers 冲突?重命名包和其中定义的每个导入是否标准?
如果更改django-mailer
是主要要求,请将其复制到包mypackages.mymailer
(不是mypackages.mailer,这样内容类型框架就不会太混乱)。然后根据需要更改代码。然后您仍然可以使用这两个版本,但您将始终知道您使用的是原始版本还是修改后的版本。
所以重命名所有内容是标准的,这样新邮件程序就不会导入旧邮件程序?保持所有导入行更新似乎是一项不错的工作,但我真的看不到另一个解决方案(这个问题的目的)。这在包含大量代码的更大包中会非常糟糕。
所以,小就是美。以上是关于构建可插拔应用程序:如何包含流行库的分支并防止名称冲突?的主要内容,如果未能解决你的问题,请参考以下文章