Giter Site home page Giter Site logo

bottlepy / bottle Goto Github PK

View Code? Open in Web Editor NEW
8.3K 312.0 1.5K 6.29 MB

bottle.py is a fast and simple micro-framework for python web-applications.

Home Page: http://bottlepy.org/

License: MIT License

Makefile 0.66% Python 98.78% Shell 0.38% Smarty 0.18%
python wsgi rest web-framework bottle

bottle's People

Contributors

agalera avatar avelino avatar babs avatar braedon avatar cassiobotaro avatar davidwtbuxton avatar defnull avatar eric-wieser avatar federicoceratto avatar foxx avatar fredj avatar hanaasagi avatar hartwork avatar ifduyue avatar inndy avatar iurisilvio avatar jonashaag avatar michael-k avatar myzhan avatar nayuki avatar oz123 avatar provinzkraut avatar sc68cal avatar sergbobrovsky avatar sgala avatar sideffect0 avatar tirkarthi avatar vaultah avatar zhangyoufu avatar ziadsawalha avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bottle's Issues

AutoServer adapters

class AutoServer(ServerAdapter):
""" Untested. """
adapters = [FapwsServer, TornadoServer, CherryPyServer, PasteServer,
TwistedServer, GunicornServer, WSGIRefServer]
def run(self, handler):
for sa in adapters:
try:
return sa(self.host, self.port, **self.options).run()
except ImportError:
pass

adapters isn't defined in run. So either you put it into the method or use self.adapters instead.

If I had not fount the function, I have asked you abaout that.

SyntaxError using SimpleTemplate with AppEngine

The flowing template raises a SyntaxError exception when using it in a Google AppEngine environment. I have no idea, why... Need more input

%items = ['Hello', 'f']
<h1>Hello {{username}}</h1>
<p>How are you?</p> 

Yielding content doesn't send cookies responses

If you do something like that :

@route('/')
def index():
    bottle.response.COOKIES['gato'] = 'hello'
    yield "hello"

cookie is not created ... the workaround is to use return instead of yield ;-(
it would be better if cookies can be created in all cases

redirect problem

Now, after post something, redirect a page, you should get the page by "POST" method, not "GET".
For example:
i upload a file , then i want to goto list file page:

@route('/files', method='GET')

def file_list():
pass

so i use "redirect("/files"),
it right? Not, i have to add a post rule on the function "list":

@route('/files', method='GET')
@route('/files', method='POST') # the new route

def file_list():
pass

And, another problem.
when the explorer redirecting, it always pop a confirm window. That 's unuseful, i think.

Substitution with Unicode values do not work in SimpleTemplate

Let's say we have a minimal template:
{{foo}} saved in a file called called minimal.tpl

Now, in the main code trying something like:
template('minimal',foo='å') will result in an error like this:
Unhandled Exception: UnicodeEncodeError('ascii', u'\xe5', 0, 1, 'ordinal not in range(128)')

Traceback:
Traceback (most recent call last):
File "/home/pafcu/projects/testpod/bottle.py", line 401, in handle
return handler(**args)
File "testpod.py", line 9, in rss2
return template('minimal',foo=u'å')
File "/home/pafcu/projects/testpod/bottle.py", line 1301, in template
return TEMPLATES[tpl].render(**args)
File "/home/pafcu/projects/testpod/bottle.py", line 1279, in render
self.execute(stdout, **args)
File "/home/pafcu/projects/testpod/bottle.py", line 1268, in execute
eval(self.co, args)
File "./minimal.tpl", line 1, in
{{foo}}
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe5' in position 0: ordinal not in range(128)

The reason is probably the following line (in SimpleTemplate.prepare):
def repr(self): return 'str(' + self + ')'

Here the use of "str" forces the string to ascii since no encoding is given, and since it's not possible to represent the character 'å' in ascii an exception is raised.

Template lookup not working with mod_wsgi

The template, jinja2_template, and mako_template modules don't seem to be able to find template files correctly in a mod_wsgi setup.

I have even tried appending my template path to the bottle.TEMPLATE_PATH object.

This stopped working for me right after 0.5.8.

Thanks,
Seth

NameError: name 'view' is not defined

@route('/hello/template/:names')
@view('hello')
def template_hello(names):
names = names.split(',')
return dict(title='Hello World', names=names)

created hello.tpl in the same directory as the bottle app and also in ./views directory . But view is not found.

Traceback (most recent call last):
File "index.py", line 12, in
@view('hello')
NameError: name 'view' is not defined

Anything behind %... causes a syntax error using default templates

Using the examples (or any stripped down version) with a %... line returns an syntax error:

Error 500: Internal Server Error

Sorry, the requested URL /hello/jan,me caused an error:

Unhandled Exception: SyntaxError('invalid syntax', ('./views/hello.tpl', 6, 19, 'for name in names:\r\n'))

Traceback:

Traceback (most recent call last):
File "/usr/lib/python2.5/site-packages/bottle.py", line 309, in __call__
return ''.join(out)
File "/home/jan/jouz/app.wsgi", line 15, in pretty_hello
return template('hello', title='Hello World', names=names)
File "/usr/lib/python2.5/site-packages/bottle.py", line 955, in template
environ = os.environ.copy()
File "/usr/lib/python2.5/site-packages/bottle.py", line 758, in __init__
if sig[1:] == hmac.new(key, msg).digest().encode('base64').strip():
File "/usr/lib/python2.5/site-packages/bottle.py", line 863, in prepare
File "./views/hello.tpl", line 6
for name in names:

^
SyntaxError: invalid syntax

(used the code from the http://bottle.paws.de/ frontpage (fixed the decorator from get to request)

sqlite in Tutorial

In the tutorial sqlite3 is used. For the creation of the database the extern sqlite3-Shell creates the db. Why isn't it solved with python (since sqlite is installed in Python >2.4)? Windows users have to download sqlite_win to follow this tutorial step by step.

Canonical way of splitting routes across multiple files

I'm currently developing a large application using bottle and I was wondering if there was a right way of splitting routes across multiple files.

For example, I have an /admin section I'd like to put into a specific admin.py file. Importing the admin module just doesn't do the trick.

More broadly, I'd like to be able to do something along the lines of :

import bottle 
import admin
bottle.delegate('/admin', admin)

and in admin.py

import bottle
@bottle.route()
def login():
   pass

where /admin/login would map to login.

Form inputs with same name, but multiple values

I have a case where i want to have 4 types eg: Fruit, Veg, Meat, Dairy. That then have their own values to submit to a form. It uses check boxes with the form like this:

<form submit>
    <input type="checkbox" name="fruit" value="apple"/>
    <input type="checkbox" name="fruit" value="banana"/>
    <input type="checkbox" name="fruit" value="cherry"/>
    <input type="checkbox" name="fruit" value="kiwi"/>
</form>

If I select multiples the last selected is the only one that the POST method sets for that item.name.

I've made some changes to that post method to get this case to work for me, but it sets the default value of a _POST[key] to an empty list.

Here's the patch:

diff --git a/bottle.py b/bottle.py
index d97cc23..ba726ef 100755
--- a/bottle.py
+++ b/bottle.py
@@ -694,7 +694,11 @@ class Request(threading.local, DictMixin):
             data = cgi.FieldStorage(fp=fb, environ=save_env)
             self._POST = MultiDict()
             for item in data.list:
-                self._POST[item.name] = item if item.filename else item.value
+                #default being a list
+                if item.name not in self._POST.keys():
+                    self._POST[item.name] = []
+                self._POST[item.name].append(item if item.filename else item.value)
+
         return self._POST

     @property

Just wanted to see if that was a case you'd be interested in rolling into the framework, or that name's have to be unique as a note in the docs? Only because it was a bit hard to track down. I'll admit too that may way may not be a very standard way of working, but w3m examples of check boxes, do have some with non-unique names.

wrong defaults on MakoTemplate

http://tinyurl.com/yar7dly -> default_filters=[] is wrong, the default filter for mako is ['unicode'].
If the attr is [], Mako will render only str or unicode, throwing an exception on other types (int, for example).

In my opinion the default for output_encoding and input_encoding should be 'utf-8', this would prevent encoding errors (at least... for me :P ). Keep up the good work!

0.7.0a BaseTemplate error

BaseTemplate class in init has no more argument 'filename' but in function 'template' is:

        elif '.' in tpl:
                    TEMPLATES[tpl] = template_adapter(filename=tpl, lookup=lookup) 

which generates error if in template name is '.'

Handle HTTP POST pseudo-arrays correctly

Many HTTP clients "encode" arrays sent via HTTP POST like this:
variable_name[0] = first_element
variable_name[1] = second_element
...
variable_name[n] = nth_element

For example, when using notable Javascript frameworks, var foo = ["Hi", "there", "what's", "up?"] is "encoded" into
foo[0] = "Hi"
foo[1] = "there"
foo[2] = "what's"
foo[3] = "up?"

when sending the array via POST.

Bottle should recognize such pseudo-arrays and try to handle them correctly (convert into Python list).

Parentheses in routes don't match

I have a use case where I need to support something like:
@route('/:collection(:key)')

I'm perfectly happy to use a regexp route, but even that seems to not support it correctly. I think it is due to the yieldroutes function having '/' in it's pattern spec.

ideas?

request.GET: Multiple values per key are not possible

Hello,

First of all, thanks you for this piece of nice code. Very pleasant to use.
To me there is a bug in the request.GET function. It seems that it doesn't accept multiple value for a single key.

For instance:
/?fq=val1&fq=val2

To me the expected value of :
request.GET.get('fq') shoud be ['val1', 'val2']

Be returned value is : 'val2'

Seems that there is something going on here or with the MuliDict()
http://github.com/defnull/bottle/blob/master/bottle.py#L625

Doing :
/?fq=val1&fq=val2

Regards,

xav

Reloading and SIGTERM

If bottle had spawned a child process to handle reloading and the parent process is killed (with SIGTERM as done by start-stop-deamon) the child survive and blocks the network port.

abort and simple text or json response

it would be great when developing services, if abort() could render responses other than html, such as plain text or json, perhaps based on accept header or how the route where abort() is raised is configured.

Proposal for asynchronous responses in Bottle

If the Issue tracker is wrong place to discuss this, just let me know.

Preface:

I'm recently obsessed with Bottle and using it in every web project that allows me to use Python. I love its shocking simplicity and transparency, and the fact that each web request probably only goes through about a hundred lines of python code before getting to my response handler. Totally subjectively, I just love the way it "feels" and developing with it makes me all warm and fuzzy inside (as opposed to Twisted, which just rubs me the wrong way; or Tornado, which has perfectly reasonable syntax but just not the style I prefer).

Issue:

I have a few new projects that require a client "push" feature, aka comet, long polling, all that stuff. As you probably know, basically all of the possible ways to implement push in the pre-WebSockets era require a web response handler on the backend to block for an extended period of time in some form or another. As you also probably know, a stock WSGI environment will be largely ruined by this, since the entire process will be blocked on a single response handler.

I also use Redis with redis-py and potentially other blocking client libraries. Scaling for concurrent requests in a non-threaded environment becomes more complicated with any libraries that block on network I/O; it's not always sufficient to just run a whole bunch of Bottle processes. For example, some clients have already had their requests routed by the load balancer to a particular server instance, and if another client on that instance blocks, then the network packets will just sit in the queue for a while, causing slow response times and making poor use of the machine's CPU resources (since it could be doing something else while blocked on network I/O).

Right now I am serving the push feed in a separate Diesel app. This is not ideal, as I would prefer for the load balancer to distribute across a homogeneous pool of servers all running the same code for simplicity and maintainability reasons (and I don't want to have to monitor multiple process types if I can avoid it). I also don't seem to be able to flush the output buffer and keep going with Diesel's server, killing persistent-request feed options like MXHR, but that's possibly just something I'm doing wrong.

Proposal:

I propose light-weight support for asynchronous response handlers, possibly with an @async decorator. There seem to be two general camps about the syntax for asynchronous code in this kind of Python environment: callbacks and coroutines. Tornado uses callbacks, which are probably easier to understand but not as elegant and do not really support progressive output (like flushing the output buffer). Diesel uses coroutines, which can make some pretty elegant "pythonic" code and supports pausing repeatedly but can also be hard to wrap one's brain around and be tricky to implement cleanly on the backend. Note that there is also a project called Swirl that brings the coroutine style to Tornado.

Here is a possible syntax style for each option:

Callback

from bottle import route, async
import time

@route()
@async
def response():
    def doStuff():
        body = "I like sleep."
        time.sleep(3)
        body = body + " Alot."
        time.sleep(3)
        return body

    def callback():     # Maybe with request & response args?
        return "OK, I'm awake."
    # Always return a 2-tuple of a worker callable and a callback callable
    return (doStuff, callback)

Coroutine

from bottle import route, async

@route()
@async
def response():
    yield "I like sleep."
    time.sleep(3)    # Or something like yield diesel.sleep(3)
    yield " Alot."
    time.sleep(3)    # Or something like yield diesel.sleep(3)
    yield "OK, I'm awake."

I'd vote for the coroutine option, but it's possible there are implementation issues with it I'm not thinking of.

The hard part

The really tricky part is that Bottle is not a WSGI server; it always uses another WSGI server (which is usually quite handy). This means that the main application loop is not handled by Bottle but the server (which may be using epoll or libevent or libev or eventlets or Stackless Python or ...).

Option 1: Do almost nothing in Bottle

It is possible that really minor modifications to Bottle would allow it to pass through generator return types to the underlying server and hope it supports it. However, builtin libs will still block the entire process (like time.sleep). Diesel and Cogen work around this by offering custom functions you have to call instead: yield diesel.sleep(3). Eventlet can actually modify/wrap the builtin packages to be asynchronous, which is pretty nifty. With the minor modification route, the @async decorator might not even be necessary, since Diesel will accept generators automatically. On a side note, Fapws3 claims to be asynchronous, but I have no idea what part of it is asynchronous. It does not seem to support any method of having an asynchronous response handler that I could find; I'll have to ask that community about it since I really like Fapws3 otherwise.

Option 2: Do everything in Bottle

It would be awesome if there were a magical way to handle it cleanly all inside of Bottle in a way that worked with all of the possible servers. Bottle would need to track async responses that had not finished, and probably execute async responses in a closure with local request/response object copies. However, I don't know if the underlying WSGI servers (or the rest of the WSGI) would handle having more than one request at a time; I'm not very familiar with WSGI yet. If they also have single global request/response objects like Bottle, they would almost certainly break.

If this approach is possible, Eventlet, Concurrence, and Cogen seem like the most likely candidates. Greenlet would probably do the Bottle part at least as efficiently, but it does not directly assist with things like networking.

The theory would be that Bottle would spawn two thread-like-things at the same time: one that just calls the WSGI server's main loop, and one for the pending response book-keeping. Whenever a synchronous response finishes, or an async response yields, the microthread's equivalent of switch() would be called (in the case of Concurrence or Eventlet), or yield (in the case of a Cogen coroutine).

Option 3: Require specific WSGI server[s]

I suspect that being asynchronous in Bottle simply will not work with most WSGI servers, and it will require using the WSGI server that comes with the particular async library. Fortunately, Concurrence, Eventlet, and Cogen all offer a WSGI server. There might need to be a global flag in Bottle like the debug flag that enables asynchronous support, and the async decorator would just do pass-through. In asynchronous mode, Bottle could throw an error if the given WSGI server callable is not in a list of known supported async servers.

My plan

If you don't hate the idea of supporting async requests in Bottle, I would love to make a temporary fork and do some or all of the implementation myself. I would attempt option 3, since it seems the easiest/safest, and I would first attempt with either Cogen or Eventlet. I'm somewhat torn between the two, but I'm leaning towards Cogen since I feel coroutines are more pythonic and elegant than explicit microthread switching (and it doesn't even require hacking the builtin packages like socket or time). Eventlet could make redis-py async automatically, but then it's not clear while looking at the code that a call like val = redis.get('mykey') is going to yield. With Cogen you would have to manually yield like val = yield redis.get('mykey'), but it's more clear what is happening.

If you've managed to continue reading all the way through this, I'm going to start a fork and play around with it in the hopes that it could get merged into Bottle master. I will probably attempt to first use Cogen, using this guide.

What are your thoughts? Do have any interest in Bottle supporting async requests, especially via coroutines? If so, how do you feel about an @async decorator vs. automatically detecting via something like inspect.isgenerator()? Also, once async works, would flushing the output buffer be possible for persistent requests?

Tutorial and Sqlite query building

Even though the tutorial says that the code should not be used in the wild I find it rather disturbing to see SQL statements being build via string formatting. It will only encourage newbies to do things they should never be doing.

Currently used:
query = "INSERT INTO todo (task,status) VALUES ('%s',1)" %new
c.execute(query)

suggested:
query = "INSERT INTO todo (task,status) VALUES (?,1)"
c.execute(query, (new,))

Add template inheritance and/or blocks

Any chance to add Mako/Django/Tempita style template inheritance to SimpleTemplate?

Actually, real "inheritance" wouldn't even be necessary if there were some sort of 'block' block. I tried to approximate this with the following, but couldn't get it to work.

%def body():
  <b>{{stuff}}</b>
%end
%include base body=body()

Cheers!

How do i run a bottle app with Tornado

Tried importing TornadoServer like this

from bottle import route, run, debug, template, view, TornadoServer

but got an import error

Traceback (most recent call last):
File "index.py", line 1, in
from bottle import route, run, debug, template, view, TornadoServer
ImportError: cannot import name TornadoServer

checked bottle.py there was TornadoServer block.

Any suggetions !!!

send_file(): maximum recursion depth exceeded

This is NOT ab bug in Bottle, but a Python stdlib bug.

Python bug: Issue #5853: calling a function of the mimetypes module from several threads
at once could hit the recursion limit if the mimetypes database hadn't been
initialized before.

Add mimetype.init() to your start up script or update your Python stdlib.

Allow access to POST body

Currently there's no way to get the body of a POST request. This is especially necessary when the body is not form data.

Adding a body property is trivial, but it gets tricky if POST and body are both accessed. Not that I see much use for that.

request keys are different in fapws3 server

for example, request['REMOTE_ADDR'] will give error, the server use 'fapws.remote_addr' instead. other keys needs to be mapped too.

besides, the redirect method when using fapws3 gives
Traceback (most recent call last):
File "/bottle.py", line 653, in app
return handler(environ, start_response)
File "/bottle.py", line 331, in call
status = '%d %s' % (response.status, HTTP_CODES[response.status])
KeyError: '200'

E-Tags for static_file() and Request/Response

Bottles send_file() helper already supports Last-Modfied and If-Modified-Since headers and sends a 304 Not Modified response if applicable. A file-name and modification-time based Etag and If-None-Match support would be easy to implement.

I also want to add support for etags and mtime to normal handler functions. The Idea: Request.check_mtime() and Request.check_etag() methods that automatically abort execution of the handler function (by throwing a HTTPResponse(code=304) exception) on a match and do nothing but adding the header to the response object on a non-match. I'm not sure about the API and its hard to predict side-effects, though.

send_file always returns 401 on Windows #2

hello
I tested send_file on winXP and python 2.6.2
But send_file show 401 error with Access denied.

My code is below

@route('/static/:filename')
def sending_file(filename):
send_file(filename, root='d:')

So I modify send_file following code to access root directory files.

Before
def send_file(filename, root, guessmime = True, mimetype = None):
""" Aborts execution and sends a static files as response. """
root = os.path.abspath(root) + os.sep

After
def send_file(filename, root, guessmime = True, mimetype = None):
""" Aborts execution and sends a static files as response. """
root = os.path.abspath(root)
if not root.endswith(os.sep):
root = root + os.sep

What do you think you?

Automatically escape SimpleTemplate expansion values

SimpleTemplate doesn't have an option to automatically escape any HTML characters in user input within a template (it looks like some of the examples would be vulnerable to XSS vulnerabilities as a result).

To fix this it would be useful if we could include a {{!...}} option to the syntax which automatically escaped expanded values. This would be backwards compatible with the existing syntax and make writing safe templates much easier.

>>> bottle.template("{{x}}",x="<script...>")
[u'<script...>']
>>> bottle.template("{{!x}}",x="<script...>")
[u'&lt;script...&gt;']

A simple patch to add a {{!...}} option to the syntax is attached below (patch is against the stplunicode branch)

--- bottle.py.orig  2010-02-27 19:49:27.000000000 +0000
+++ bottle.py   2010-02-27 19:48:35.000000000 +0000
@@ -1361,6 +1361,11 @@
             def __repr__(self): return '%s(%s)' % (self.f, self.s)
             def __str__(self): return self.s

+        class EscapedPyStmt(PyStmt):
+            def __repr__(self):
+                return '%s(%s)' % (self.f, self.s) + \
+                    '.replace("&","&amp;").replace("<","&lt;").replace(">","&gt;")'
+
         def prt(txt): # Add a string or a PyStmt object to ptrbuffer
             if ptrbuffer and isinstance(txt, str) \
             and isinstance(ptrbuffer[-1], str): # Requied for line preserving
@@ -1428,7 +1433,14 @@
                 if line.strip().startswith('%%'):
                     line = line.replace('%%', '%', 1)
                 for i, part in enumerate(re.split(r'\{\{(.*?)\}\}', line)):
-                    if part: prt(PyStmt(part) if i%2 else part)
+                    if part:
+                        if i%2:
+                            if part.startswith("!"):
+                                prt(EscapedPyStmt(part[1:]))
+                            else:
+                                prt(PyStmt(part))
+                        else:
+                            prt(part)
         flush()
         return '\n'.join(codebuffer) + '\n'

~

request.POST['var'] is always empty

I upgraded from 0.6.4 to trunk and POST variables always seem to be empty. The code below works on 0.6.4 but not on trunk.

@route('/')
def index():
    return """
    <form method="post">
      <input type="text" name="name" />
      <input type="submit" />
    </form>
    """

@route('/', method='POST')
def hello_post():
    name = request.POST['name']
    return 'Hello %s!' % name

Stange Mako lookup problems

Bottle.template() excepts lookup paths to be either absolute or relative to the current working directory. Makos expects all template search paths in TemplateLookup to be relative to the template file who inherits or includes something. After looking at the sources I can't see how to properly use absolute paths in TemplateLookup without rewriting it from scratch. But it is also not possible to use <%include/> or <%inherit/> without a properly set up TemplateLookup. So basically the TemplateLookup settings depends on the location of the template file, which means that bottle.template(lookup=...) settings cannot be used without modification.

Next thing is that TemplateLookup settings have no effect on finding templates when you try to load them by filename. Mako has no Tempate-Lookup-By-Name feature, so Bottle has to do that.

What does this mean? Bottle has to justify all the lookup-paths to be relative to the current template in order to configure TemplateLookup for mako. My tests work, but it is a kind of dirty hack. If you use mako and have any problems related to template lookups, please report them here.

View + return dict + accept json header

It would be great if a request handler decorated with @view would revert to standard json output casting if http accept header is set to application/json. This way the same request handler can respond to html and json requests.

Be able to force a download on known mime types.

Add an option to bottle.send_file() to force a download, even if the mime type is connected to an application on client side by adding a Content-disposition: attachment; filename=... header.

send_file always returns 401 on Windows

simply replace the literal '/' with os.sep in line 493.

Also, I'm not sure what the purpose of the strip on the next line is, but it should probable be strip('/\\') to be effective on Windows, since os.path.join accepts both slashes and backslashes.

Critial error while processing request

When there is a critical error, a helpful error message comes up 'Critial error while processing request', could someone just find and replace that to fix it to 'Critical error while processing request'

Error report

Errors are not properly reported when an exception is raised.

HTTPError::str() calls repr(self.output), which escapes the multi-line string. Then it's embedded inside a

 block, so it's printed as a single line error (quite hard to read and understand).

The fastest workaround is: s/repr(self.output)/self.output/ , but of course that is very insecure.

Bottle.route

Argument method to Bottle.route should default to "ANY".

routing function should support unicode

When returning a unicode object from a routing function, the "bottle breaks" and WSGI complains that it will only accept str objects. The framework could assume that I really want to return this UTF-8 encoded. Then, however, it also has to add/modify a content-type header, I guess. This is Python 2.6. What happens in 3.1 where all you have are "real" unicode strings?

TypeError exception on accessing request.POST in python 3

I am using python 3.1.1 and attempting a simple POST request. This results in an exception - the stacktrace is provided below. I understand that this is related to Python 3 being stricter about byte to str conversion - the question is - how best to handle this issue (and whether this warrants a fix to bottle's code prior to urlparse getting fixed.

Thanks
ign

Traceback (most recent call last):
File "c:\python31\lib\site-packages\bottle.py", line 309, in call
output = handler(**args)
File "dispatcher.py", line 44, in proxygateway
print(type(request.POST))
File "c:\python31\lib\site-packages\bottle.py", line 390, in POST
environ=self._environ, keep_blank_values=True)
File "c:\python31\lib\cgi.py", line 489, in init
self.read_urlencoded()
File "c:\python31\lib\cgi.py", line 589, in read_urlencoded
self.strict_parsing):
File "c:\python31\lib\urllib\parse.py", line 377, in parse_qsl
pairs = [s2 for s1 in qs.split('&') for s2 in s1.split(';')]
TypeError: Type str doesn't support the buffer API

URL fragment parameters should be unicode

most if not all browsers will pass URLs utf-8 encoded (curl does). I shouldn't be required to decode that manually. Example:

@route(r"/:name")
def test(name):
    print `name`, type(name)
    return name

Now call this with curl http://localhost:8080/äöüß. A UnicodeDecodeError exception is raised. I can workaround this error by adding

@validate(name=lambda n:n.decode("utf-8"))

but I don't want to ;)

Jinja2 line statement prefix

Are you open to changing the default options you're using for jinja2 templates, or providing a simpler way to override them? The following line is where you setup the jinja2 environment:
self.env = Environment(line_statement_prefix="#", loader=FunctionLoader(self.loader))

However, using '#' as the line statement prefix breaks a common use case (at least it's common for me): inline css definitions with ID selectors. Here's an example of html that will break on it (with jinja2 error "Encountered unknown tag 'container'"):

<html>
<head>
    <style type="text/css">
        #container {
            width: 960px;
        }
    </style>
</head>
</html>

There are ways for me work around it by hacking the classes or subclassing Jinja2Template, but it's a number of lines of code and hampers the nice clean code I could normally use with Bottle.

HTTPErrors fail when @view is used

The @view decorator expects to get a dict-like object that it pushes into the template.

If, instead, the method returns a HTTPResponse or HTTPError (say because a redirect is needed or something bad happened), @view will pass it to the template, which will error out with a 500 hiding the original error. See, for example, http://bottle.paws.de/page/dont_exist for such an error.

Commit http://github.com/sgala/bottle/commit/20ed798ac0d72a3d9590ad91ccc63622f2414261 offers both a fix (in the wrapper) and a workaround (in the homepage app).

In the commit:

  • the wrapper only invokes the template if it gets a dict (it could be made safer using a less strict test...), and
  • the app raises the exception instead of returning it to bypass @view processing...

(Note this commit won't apply cleanly as kargs was changed to kwargs in fcc614d, and also that I have not written a testcase, which I should do...

Mako templates not found in 0.6.2

With 0.6.2 I am getting "template not found" when trying to use Mako. Reverting back to 0.5.8 corrects this issue without any code changes.

-Seth

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.