# HG changeset patch # User Sylvain Thénault # Date 1276692677 -7200 # Node ID 730d458ec1bfae23f60f49cd2445b1188656e629 # Parent 51179e0bb25011ce63e3d2da5e1ea0e8ac78be1b# Parent 02bccbc4ff1c7be0b848252acbfd72711a355cdf backport stable diff -r 51179e0bb250 -r 730d458ec1bf devtools/devctl.py --- a/devtools/devctl.py Wed Jun 16 09:21:49 2010 +0200 +++ b/devtools/devctl.py Wed Jun 16 14:51:17 2010 +0200 @@ -650,7 +650,7 @@ except OSError, ex: raise BadCommandUsage("can't open rql log file %s: %s" % (filepath, ex)) - for lineno, line in enumerate(file): + for lineno, line in enumerate(stream): if not ' WHERE ' in line: continue try: diff -r 51179e0bb250 -r 730d458ec1bf doc/book/en/devrepo/profiling.rst --- a/doc/book/en/devrepo/profiling.rst Wed Jun 16 09:21:49 2010 +0200 +++ b/doc/book/en/devrepo/profiling.rst Wed Jun 16 14:51:17 2010 +0200 @@ -26,7 +26,7 @@ .. sourcecode:: sh - $ cubicweb-ctl exlog < ~/myapp-rql.log + $ cubicweb-ctl exlog ~/myapp-rql.log 0.07 50 Any A WHERE X eid %(x)s, X firstname A {} 0.05 50 Any A WHERE X eid %(x)s, X lastname A {} 0.01 1 Any X,AA ORDERBY AA DESC WHERE E eid %(x)s, E employees X, X modification_date AA {} diff -r 51179e0bb250 -r 730d458ec1bf entity.py --- a/entity.py Wed Jun 16 09:21:49 2010 +0200 +++ b/entity.py Wed Jun 16 14:51:17 2010 +0200 @@ -781,7 +781,10 @@ return self._cw_relation_cache(rtype, role, entities, limit) except KeyError: pass - assert self.has_eid() + if not self.has_eid(): + if entities: + return [] + return self.empty_rset() rql = self.cw_related_rql(rtype, role) rset = self._cw.execute(rql, {'x': self.eid}) self.cw_set_relation_cache(rtype, role, rset) diff -r 51179e0bb250 -r 730d458ec1bf etwist/server.py --- a/etwist/server.py Wed Jun 16 09:21:49 2010 +0200 +++ b/etwist/server.py Wed Jun 16 14:51:17 2010 +0200 @@ -203,6 +203,11 @@ def render_request(self, request): try: + # processing HUGE files (hundred of megabytes) in http.processReceived + # blocks other HTTP requests processing + # due to the clumsy & slow parsing algorithm of cgi.FieldStorage + # so we deferred that part to the cubicweb thread + request.process_multipart() return self._render_request(request) except: errorstream = StringIO() @@ -334,7 +339,6 @@ d.callback(None) self.notifications = [] - @monkeypatch(http.Request) def requestReceived(self, command, path, version): """Called by channel when all data has been received. @@ -359,30 +363,38 @@ self.host = self.channel.transport.getHost() # Argument processing ctype = self.getHeader('content-type') + self._do_process_multipart = False if self.method == "POST" and ctype: key, pdict = parse_header(ctype) if key == 'application/x-www-form-urlencoded': self.args.update(http.parse_qs(self.content.read(), 1)) elif key == 'multipart/form-data': - self.content.seek(0, 0) - form = FieldStorage(self.content, self.received_headers, - environ={'REQUEST_METHOD': 'POST'}, - keep_blank_values=1, - strict_parsing=1) - for key in form: - value = form[key] - if isinstance(value, list): - self.args[key] = [v.value for v in value] - elif value.filename: - if value.done != -1: # -1 is transfer has been interrupted - self.files[key] = (value.filename, value.file) - else: - self.files[key] = (None, None) - else: - self.args[key] = value.value + # defer this as it can be extremely time consumming + # with big files + self._do_process_multipart = True self.process() +@monkeypatch(http.Request) +def process_multipart(self): + if not self._do_process_multipart: + return + form = FieldStorage(self.content, self.received_headers, + environ={'REQUEST_METHOD': 'POST'}, + keep_blank_values=1, + strict_parsing=1) + for key in form: + value = form[key] + if isinstance(value, list): + self.args[key] = [v.value for v in value] + elif value.filename: + if value.done != -1: # -1 is transfer has been interrupted + self.files[key] = (value.filename, value.file) + else: + self.files[key] = (None, None) + else: + self.args[key] = value.value + from logging import getLogger from cubicweb import set_log_methods LOGGER = getLogger('cubicweb.twisted') diff -r 51179e0bb250 -r 730d458ec1bf server/test/data/schema.py --- a/server/test/data/schema.py Wed Jun 16 09:21:49 2010 +0200 +++ b/server/test/data/schema.py Wed Jun 16 14:51:17 2010 +0200 @@ -15,9 +15,7 @@ # # You should have received a copy of the GNU Lesser General Public License along # with CubicWeb. If not, see . -""" -""" from yams.buildobjs import (EntityType, RelationType, RelationDefinition, SubjectRelation, RichString, String, Int, Boolean, Datetime) from yams.constraints import SizeConstraint diff -r 51179e0bb250 -r 730d458ec1bf server/test/data/sources_multi --- a/server/test/data/sources_multi Wed Jun 16 09:21:49 2010 +0200 +++ b/server/test/data/sources_multi Wed Jun 16 14:51:17 2010 +0200 @@ -3,7 +3,7 @@ db-driver = sqlite db-host = adapter = native -db-name = tmpdb +db-name = tmpdb-multi db-encoding = UTF-8 db-user = admin db-password = gingkow diff -r 51179e0bb250 -r 730d458ec1bf server/test/unittest_undo.py --- a/server/test/unittest_undo.py Wed Jun 16 09:21:49 2010 +0200 +++ b/server/test/unittest_undo.py Wed Jun 16 14:51:17 2010 +0200 @@ -280,3 +280,7 @@ # 'required on CWUser (%s)' % self.toto.eid}) # test implicit 'replacement' of an inlined relation + +if __name__ == '__main__': + from logilab.common.testlib import unittest_main + unittest_main() diff -r 51179e0bb250 -r 730d458ec1bf web/formfields.py --- a/web/formfields.py Wed Jun 16 09:21:49 2010 +0200 +++ b/web/formfields.py Wed Jun 16 14:51:17 2010 +0200 @@ -82,6 +82,8 @@ it """ +def normalize_filename(filename): + return filename.split('\\')[-1] def vocab_sort(vocab): """sort vocabulary, considering option groups""" @@ -742,7 +744,7 @@ value = None else: # set filename on the Binary instance, may be used later in hooks - value.filename = filename + value.filename = normalize_filename(filename) return value diff -r 51179e0bb250 -r 730d458ec1bf web/views/basecontrollers.py --- a/web/views/basecontrollers.py Wed Jun 16 09:21:49 2010 +0200 +++ b/web/views/basecontrollers.py Wed Jun 16 14:51:17 2010 +0200 @@ -543,12 +543,12 @@ cookies[statename] = nodeeid self._cw.set_cookie(cookies, statename) else: - marked = set(filter(None, treestate.value.split(';'))) + marked = set(filter(None, treestate.value.split(':'))) if nodeeid in marked: marked.remove(nodeeid) else: marked.add(nodeeid) - cookies[statename] = ';'.join(marked) + cookies[statename] = ':'.join(marked) self._cw.set_cookie(cookies, statename) @jsonize diff -r 51179e0bb250 -r 730d458ec1bf web/views/treeview.py --- a/web/views/treeview.py Wed Jun 16 09:21:49 2010 +0200 +++ b/web/views/treeview.py Wed Jun 16 14:51:17 2010 +0200 @@ -216,7 +216,7 @@ cookies = self._cw.get_cookie() treestate = cookies.get(treecookiename(treeid)) if treestate: - return str(eeid) in treestate.value.split(';') + return str(eeid) in treestate.value.split(':') return self.default_branch_state_is_open def cell_call(self, row, col, treeid, vid='oneline', parentvid='treeview',