From 5b6348d7d9195064fd0b5e2cc710adb1d541860d Mon Sep 17 00:00:00 2001 From: Elmo Todurov Date: Thu, 29 Aug 2013 15:22:37 +0300 Subject: [PATCH] Changed FileRef upload to manage error conditions --- spinoff/contrib/filetransfer/fileref.py | 21 ++++++++++++++++----- spinoff/contrib/filetransfer/server.py | 17 ++++++++++++----- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/spinoff/contrib/filetransfer/fileref.py b/spinoff/contrib/filetransfer/fileref.py index a0a8b4c..fd533ac 100644 --- a/spinoff/contrib/filetransfer/fileref.py +++ b/spinoff/contrib/filetransfer/fileref.py @@ -99,11 +99,18 @@ def fetch(self, dst_path=None, on_progress=None): assert reasonable_get_mtime(ret) == self.mtime return ret - def upload(self, url): - success, response = self.server.ask(('upload', self.file_id, url)) - if not success: - raise FileNotFound - return response + def upload(self, url, expect_response=200): + ok, response = self.server.ask(('upload', self.file_id, url, expect_response)) + if ok: + return response + else: + reason = response[0] + if reason == 'file-not-found': + raise FileNotFound + elif reason == 'exception': + raise UploadFailed(response[1]) + elif reason == 'bad-status-code': + raise UploadFailed("Bad status code: %s" % (response[1])) def delete(self): if not self.server.ask(('delete', self.file_id)): @@ -143,6 +150,10 @@ class FileNotFound(Exception): pass +class UploadFailed(Exception): + pass + + def move_or_copy(src, dst): try: os.rename(src, dst) diff --git a/spinoff/contrib/filetransfer/server.py b/spinoff/contrib/filetransfer/server.py index 7d00ddf..d5a0237 100644 --- a/spinoff/contrib/filetransfer/server.py +++ b/spinoff/contrib/filetransfer/server.py @@ -1,5 +1,6 @@ import datetime import os +import traceback from gevent.threadpool import ThreadPool import requests @@ -53,15 +54,21 @@ def receive(self, msg): elif ('terminated', IN(self.responses)) == msg: _, sender = msg self._touch_file(file_id=self.responses.pop(sender)) - elif ('upload', ANY, ANY) == msg: - _, file_id, url = msg + elif ('upload', ANY, ANY, ANY) == msg: + _, file_id, url, expect_response = msg if file_id not in self.published: - self.reply((False, None)) + self.reply((False, ('file-not-found',))) else: self._touch_file(file_id) file_path, _ = self.published[file_id] - r = requests.post(url, files={'file': open(file_path, 'rb')}) - self.reply((True, (r.status_code, dict(r.headers), r.text))) + try: + r = requests.post(url, files={'file': open(file_path, 'rb')}) + except Exception as e: + self.reply((False, ('exception', (type(e).__name__, e.message, traceback.format_exc())))) + if r.status_code != expect_response: + self.reply((False, ('bad-status-code', r.status_code))) + else: + self.reply((True, (r.status_code, dict(r.headers), r.text))) elif ('delete', ANY) == msg: _, file_id = msg if file_id not in self.published: