Uhm, I was just thinking to return a string instead of the open stream. attached the patch (some refactoring bits added)
@Paolo: turns out that wiki has it's own "download()" function to handle files ..... in order to return cache headers you should do: def yourwikiindex(): zero = request.args(0) or 'index' if zero and zero.isdigit(): response.headers['Cache-Control'] = 'max-age=315360000' response.headers['Expires'] = 'Thu, 31 Dec 2037 23:59:59 GMT' return auth.wiki() On Monday, February 4, 2013 7:34:58 PM UTC+1, Massimo Di Pierro wrote: > > Honestly I would like to refactor all this logic in web2py. It was already > done for web3py: > > https://github.com/mdipierro/web3py/blob/master/web3py/stream.py > > Anyway, if you can help fix it in web2py, we can merge everything later > > Massimo > > On Monday, 4 February 2013 11:46:03 UTC-6, Paolo valleri wrote: >> >> I thought the same about postponing the opening of the file. Moreover, >> just after globals:344 in the stream(...) function I have added >> >> if isinstance(stream, file): >> stream_file_or_304_or_206(stream.name, >> chunk_size=chunk_size, >> request=request, >> headers=headers, >> status=self.status) >> >> and finally I got a 304 :-). As a result we are on the right direction, >> although there is no reason to open the file and take only its name. We >> need definitely something better >> >> >> >> Paolo >> >> >> 2013/2/4 Niphlod <nip...@gmail.com> >> >>> >>> >>> On Monday, February 4, 2013 3:38:29 PM UTC+1, Paolo valleri wrote: >>>> >>>> Hi Niphlod, I am still trying to understand why the wiki uploads are >>>> not returned as 304. >>>> The function in charged to return either 200 or 304 is >>>> stream_file_or_304_or_206 in streamer.py. Moreover, this function is only >>>> called in globals.py inside stream(...). Please have a look at >>>> globals.py:344, In order to be called the parameter 'stream' must be a >>>> string but with 'common' downloads the stream is an open file. This is >>>> also >>>> documented by the comment in dal.py:9096. is what I've written correct ? >>>> >>> >>> seems so, but in this case I think it should be patched (as soon as I'll >>> get home). >>> >>> For downloads that on the table are merely strings (i.e. on the table >>> there's the path to the actual file, usually in the "uploads" folder) the >>> correct way should be to "defer" the opening of the file down the line to >>> gluon.streamer. >>> A lot of logic has been added to store files on pyfilesystem (and >>> without much tests on that, I hope I won't brake anything) but I think that >>> for default "upload" file the logic needs to be revisited. >>> >>> -- >>> >>> --- >>> You received this message because you are subscribed to the Google >>> Groups "web2py-users" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to web2py+un...@googlegroups.com. >>> For more options, visit https://groups.google.com/groups/opt_out. >>> >>> >>> >> >> -- --- You received this message because you are subscribed to the Google Groups "web2py-users" group. To unsubscribe from this group and stop receiving emails from it, send an email to web2py+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
diff -r f137cf18b70a gluon/dal.py --- a/gluon/dal.py lun feb 04 10:03:29 2013 -0600 +++ b/gluon/dal.py lun feb 04 22:01:31 2013 +0100 @@ -876,7 +876,7 @@ # The reason is that we do not want to trigger # a migration simply because a default value changes. not_null = self.NOT_NULL(field.default, field_type) - ftype = ftype.replace('NOT NULL', not_null) + ftype = ftype.replace('NOT NULL', not_null) sql_fields_aux[field_name] = dict(sql=ftype) # Postgres - PostGIS: # geometry fields are added after the table has been created, not now @@ -1234,7 +1234,7 @@ self.expand('%'+second, 'string')) def CONTAINS(self, first, second, case_sensitive=False): - if isinstance(second,Expression): + if isinstance(second,Expression): field = self.expand(first) expr = self.expand(second,'string') if first.type.startswith('list:'): @@ -3265,7 +3265,7 @@ def execute(self,a): return self.log_execute(a.decode('utf8')) - + class SybaseAdapter(MSSQLAdapter): drivers = ('Sybase',) @@ -5037,7 +5037,7 @@ 'list:reference': list, } - error_messages = {"javascript_needed": "This must yet be replaced" + + error_messages = {"javascript_needed": "This must yet be replaced" + " with javascript in order to work."} def __init__(self,db,uri='mongodb://127.0.0.1:5984/db', @@ -5116,12 +5116,12 @@ raise ValueError( "invalid objectid argument string: %s" % e) else: - raise ValueError("Invalid objectid argument string. " + + raise ValueError("Invalid objectid argument string. " + "Requires an integer or base 16 value") elif isinstance(arg, self.ObjectId): return arg if not isinstance(arg, (int, long)): - raise TypeError("object_id argument must be of type " + + raise TypeError("object_id argument must be of type " + "ObjectId or an objectid representable integer") if arg == 0: hexvalue = "".zfill(24) @@ -5153,7 +5153,7 @@ return value return value - # Safe determines whether a asynchronious request is done or a + # Safe determines whether a asynchronious request is done or a # synchronious action is done # For safety, we use by default synchronious requests def insert(self, table, fields, safe=None): @@ -5273,7 +5273,7 @@ elif len(fields) != 0: tablename = fields[0].tablename else: - raise SyntaxError("The table name could not be found in " + + raise SyntaxError("The table name could not be found in " + "the query nor from the select statement.") mongoqry_dict = self.expand(query) @@ -5299,7 +5299,7 @@ sort=mongosort_list, snapshot=snapshot).count()} else: # pymongo cursor object - mongo_list_dicts = ctable.find(mongoqry_dict, + mongo_list_dicts = ctable.find(mongoqry_dict, mongofields_dict, skip=limitby_skip, limit=limitby_limit, sort=mongosort_list, snapshot=snapshot) @@ -5396,7 +5396,7 @@ if safe is None: safe = self.safe amount = 0 - amount = self.count(query, False) + amount = self.count(query, False) if not isinstance(query, Query): raise RuntimeError("query type %s is not supported" % \ type(query)) @@ -5695,7 +5695,7 @@ # This avoids the extra server names retrieval imapdb.define_tables({"inbox": "INBOX"}) - + # Selects without content/attachments/email columns will only # fetch header and flags @@ -6088,7 +6088,7 @@ # keep the requests small for header/flags if any([(field.name in ["content", "size", - "attachments", "email"]) for + "attachments", "email"]) for field in fields]): imap_fields = "(RFC822 FLAGS)" else: @@ -7293,14 +7293,14 @@ "/{person.name}/pets[pet.ownedby]/{pet.name}", "/{person.name}/pets[pet.ownedby]/{pet.name}/:field", ("/dogs[pet]", db.pet.info=='dog'), - ("/dogs[pet]/{pet.name.startswith}", db.pet.info=='dog'), + ("/dogs[pet]/{pet.name.startswith}", db.pet.info=='dog'), ] parser = db.parse_as_rest(patterns,args,vars) if parser.status == 200: return dict(content=parser.response) else: raise HTTP(parser.status,parser.error) - + def POST(table_name,**vars): if table_name == 'person': return db.person.validate_and_insert(**vars) @@ -8797,7 +8797,7 @@ return Expression(db, db._adapter.AS, self, alias, self.type) # GIS expressions - + def st_asgeojson(self, precision=15, options=0, version=1): return Expression(self.db, self.db._adapter.ST_ASGEOJSON, self, dict(precision=precision, options=options, @@ -9131,7 +9131,7 @@ stream = self.uploadfs.open(name, 'rb') else: # ## if file is on regular filesystem - stream = open(pjoin(file_properties['path'], name), 'rb') + stream = pjoin(file_properties['path'], name) return (filename, stream) def retrieve_file_properties(self, name, path=None): diff -r f137cf18b70a gluon/globals.py --- a/gluon/globals.py lun feb 04 10:03:29 2013 -0600 +++ b/gluon/globals.py lun feb 04 22:01:38 2013 +0100 @@ -308,8 +308,8 @@ chunk_size=DEFAULT_CHUNK_SIZE, request=None, attachment=False, - filename=None, - ): + filename=None + ): """ if a controller function:: @@ -403,8 +403,8 @@ raise HTTP(404) headers = self.headers headers['Content-Type'] = contenttype(name) - if download_filename == None: - download_filename = filename + if download_filename == None: + download_filename = filename if attachment: headers['Content-Disposition'] = \ 'attachment; filename="%s"' % download_filename.replace('"','\"') diff -r f137cf18b70a gluon/streamer.py --- a/gluon/streamer.py lun feb 04 10:03:29 2013 -0600 +++ b/gluon/streamer.py lun feb 04 22:01:43 2013 +0100 @@ -46,8 +46,8 @@ request=None, headers={}, status=200, - error_message=None, -): + error_message=None + ): if error_message is None: error_message = rewrite.THREAD_LOCAL.routes.error_message % 'invalid request' try: