【发布时间】:2011-07-03 15:27:03
【问题描述】:
httplib.HTTPMessage 和 email.message.Message 类[1] 都实现了 RFC822 标头解析方法。不幸的是,它们有不同的实现[2],并且它们没有提供相同级别的功能。
困扰我的一个例子是:
httplib.HTTPMessage缺少email.Message中存在的get_filename方法,该方法使您可以轻松地从Content-disposition: attachment; filename="fghi.xyz"标头中检索文件名;httplib.HTTPMessage具有getparam、getplist和parseplist方法,但 AFAIK,它们不能也不能在content-type标头解析之外使用;email.Message有一个通用的get_param方法来解析任何带有参数的RFC822 标头,例如content-disposition或content-type。
因此,我想要httplib.HTTPMessage 中的email.message.Message 的get_filename 或get_param 方法,但是,当然,我不能修补httplib.HTTPMessage,因为它在标准库中...... :-q
最后,装饰器主题来了……:-)
我成功地创建了一个monkeypatch_http_message 函数来用我缺少的解析方法来装饰一个httplib.HTTPMessage:
def monkeypatch_http_message(obj):
from email import utils
from email.message import (
_parseparam,
_unquotevalue,
)
cls = obj.__class__
# methods **copied** from email.message.Message source code
def _get_params_preserve(self, failobj, header): ...
def get_params(self, failobj=None, header='content-type',
unquote=True): ...
def get_param(self, param, failobj=None, header='content-type',
unquote=True): ...
def get_filename(self, failobj=None): ...
# monkeypatching httplib.Message
cls._get_params_preserve = _get_params_preserve
cls.get_params = get_params
cls.get_param = get_param
cls.get_filename = get_filename
现在我可以做:
import mechanize
from some.module import monkeypatch_http_message
browser = mechanize.Browser()
# in that form, browser.retrieve returns a temporary filename
# and an httplib.HTTPMessage instance
(tmp_filename, headers) = browser.retrieve(someurl)
# monkeypatch the httplib.HTTPMessage instance
monkeypatch_http_message(headers)
# yeah... my original filename, finally
filename = headers.get_filename()
这里的问题是我从字面上复制了源类中的装饰方法代码,我想避免这种情况。
所以,我尝试通过引用源方法来装饰:
def monkeypatch_http_message(obj):
from email import utils
from email.message import (
_parseparam,
_unquotevalue,
Message # XXX added
)
cls = obj.__class__
# monkeypatching httplib.Message
cls._get_params_preserve = Message._get_params_preserve
cls.get_params = Message.get_params
cls.get_param = Message.get_param
cls.get_filename = Message.get_filename
但这给了我:
Traceback (most recent call last):
File "client.py", line 224, in <module>
filename = headers.get_filename()
TypeError: unbound method get_filename() must be called with Message instance as first argument (got nothing instead)
我现在摸不着头脑...如何在不复制源方法的情况下装饰我的班级?
有什么建议吗? :-)
问候,
乔治·马丁
在 Python 2.6 中。我不能在生产中使用 2.7 或 3.x。
httplib.HTTPMessage继承自mimetools.Message和rfc822.Message而email.Message有自己的实现。
【问题讨论】:
标签: python class decorator monkeypatching rfc822