pyapnsでnotifyしたときのエラー
ドキュメントを見るとpyapnsのnotify関数はdevice_tokenを文字列でも配列でも渡せることになっています
https://github.com/samuraisam/pyapns
ところが文字列で渡すと正常に通知ができて、配列で渡すとエラーになるというのにちょっとはまったのでメモを残しておきます。
テスト用にブラウザからリクエストして内部でnotifyを飛ばせるようにして試していたら、配列で渡した場合のみ、以下のようなエラーになりました。
twistd.logに表示されたエラー
2012-10-13 09:17:40+0900 [HTTPChannel,0,127.0.0.1] APNSService __init__ 2012-10-13 09:17:40+0900 [HTTPChannel,0,127.0.0.1] 127.0.0.1 - - [13/Oct/2012:00:17:40 +0000] "POST / HTTP/1.1" 200 114 "-" "xmlrpclib.py/1.0.1 (by www.pythonware.com)" 2012-10-13 09:17:40+0900 [HTTPChannel,1,127.0.0.1] Unhandled Error Traceback (most recent call last): File "/Users/yuhei/Documents/workspace/iridge/passbookapp/venv/lib/python2.7/site-packages/twisted/web/http.py", line 1349, in dataReceived finishCallback(data[contentLength:]) File "/Users/yuhei/Documents/workspace/iridge/passbookapp/venv/lib/python2.7/site-packages/twisted/web/http.py", line 1569, in _finishRequestBody self.allContentReceived() File "/Users/yuhei/Documents/workspace/iridge/passbookapp/venv/lib/python2.7/site-packages/twisted/web/http.py", line 1624, in allContentReceived req.requestReceived(command, path, version) File "/Users/yuhei/Documents/workspace/iridge/passbookapp/venv/lib/python2.7/site-packages/twisted/web/http.py", line 773, in requestReceived self.process() --- <exception caught here> --- File "/Users/yuhei/Documents/workspace/iridge/passbookapp/venv/lib/python2.7/site-packages/twisted/web/server.py", line 156, in process self.render(resrc) File "/Users/yuhei/Documents/workspace/iridge/passbookapp/venv/lib/python2.7/site-packages/twisted/web/server.py", line 191, in render body = resrc.render(self) File "/Users/yuhei/Documents/workspace/iridge/passbookapp/venv/lib/python2.7/site-packages/twisted/web/resource.py", line 216, in render return m(request) File "/Users/yuhei/Documents/workspace/iridge/passbookapp/venv/lib/python2.7/site-packages/twisted/web/xmlrpc.py", line 160, in render_POST function = self.lookupProcedure(functionPath) File "/Users/yuhei/Documents/workspace/iridge/passbookapp/venv/lib/python2.7/site-packages/twisted/web/xmlrpc.py", line 232, in lookupProcedure handler = self.getSubHandler(prefix) File "/Users/yuhei/Documents/workspace/iridge/passbookapp/venv/lib/python2.7/site-packages/twisted/web/xmlrpc.py", line 140, in getSubHandler return self.subHandlers.get(prefix, None) exceptions.AttributeError: APNSServer instance has no attribute 'subHandlers'
ブラウザに表示されたエラー
Traceback: File "/Users/yuhei/Documents/workspace/iridge/passbookapp/venv/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response 111. response = callback(request, *callback_args, **callback_kwargs) File "/Users/yuhei/Documents/workspace/iridge/iridge-passbook/src/passbookasp/apps/web/views.py" in notify 11. push_notify(pass_type_id=pass_type_id, serial_number=serial_number) File "/Users/yuhei/Documents/workspace/iridge/iridge-passbook/src/passbookasp/apps/api/api.py" in push_notify 25. notify(pass_type_id, push_tokens, [{}]) File "/Users/yuhei/Documents/workspace/iridge/passbookapp/venv/lib/python2.7/site-packages/pyapns/client.py" in wrapper 75. return func(*a, **kw) File "/Users/yuhei/Documents/workspace/iridge/passbookapp/venv/lib/python2.7/site-packages/pyapns/client.py" in wrapper 67. return func(*a, **kw) File "/Users/yuhei/Documents/workspace/iridge/passbookapp/venv/lib/python2.7/site-packages/pyapns/client.py" in notify 97. return _xmlrpc_thread(*f_args) File "/Users/yuhei/Documents/workspace/iridge/passbookapp/venv/lib/python2.7/site-packages/pyapns/client.py" in _xmlrpc_thread 122. return callback(proxy(*args)) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py" in __call__ 1224. return self.__send(self.__name, args) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py" in __request 1564. allow_none=self.__allow_none) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py" in dumps 1085. data = m.dumps(params) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py" in dumps 632. dump(v, write) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py" in __dump 654. f(self, value, write) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py" in dump_instance 756. self.dump_struct(value.__dict__, write) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py" in dump_struct 735. dump(v, write) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py" in __dump 654. f(self, value, write) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py" in dump_instance 756. self.dump_struct(value.__dict__, write) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py" in dump_struct 735. dump(v, write) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py" in __dump 646. raise TypeError, "cannot marshal %s objects" % type(value) Exception Type: TypeError at /notify/ Exception Value: cannot marshal <type 'set'> objects
setなんて渡してないぞ、と思って最初はよくわからなかったんですが、Pycharmのdebugで追いかけていったところ、エラーになるところで以下のことがわかりました
配列のつもりで渡していたオブジェクトが実はValueListQuerySetだったというオチでした。