Skip to content

Commit 5d1ce40

Browse files
committed
Merge remote-tracking branch 'upstream/master' into import-object
2 parents 7dabdd5 + 067e465 commit 5d1ce40

37 files changed

+1146
-298
lines changed

.coveragerc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Test coverage configuration.
2+
# Usage:
3+
# pip install coverage
4+
# coverage erase # clears previous data if any
5+
# coverage run -m tornado.test.runtests
6+
# coverage report # prints to stdout
7+
# coverage html # creates ./htmlcov/*.html including annotated source
8+
[run]
9+
branch = true
10+
source = tornado
11+
omit =
12+
tornado/platform/*
13+
tornado/test/*
14+
*/_auto2to3*
15+
16+
[report]
17+
# Ignore missing source files, i.e. fake template-generated "files"
18+
ignore_errors = true

.gitignore

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
*.pyc
22
*.so
33
*~
4-
build
5-
dist/
4+
build/
5+
/dist/
66
MANIFEST
7-
tornado.egg-info
7+
/tornado.egg-info/
88
_auto2to3*
9-
.tox
9+
.tox/
1010
.vagrant
11+
/.coverage
12+
/htmlcov/
13+
/env/

demos/websocket/chatdemo.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ class ChatSocketHandler(tornado.websocket.WebSocketHandler):
5757
cache = []
5858
cache_size = 200
5959

60+
def allow_draft76(self):
61+
# for iOS 5.0 Safari
62+
return True
63+
6064
def open(self):
6165
ChatSocketHandler.waiters.add(self)
6266

demos/websocket/static/chat.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,11 @@ var updater = {
5050
socket: null,
5151

5252
start: function() {
53+
var url = "ws://" + location.host + "/chatsocket";
5354
if ("WebSocket" in window) {
54-
updater.socket = new WebSocket("ws://localhost:8888/chatsocket");
55+
updater.socket = new WebSocket(url);
5556
} else {
56-
updater.socket = new MozWebSocket("ws://localhost:8888/chatsocket");
57+
updater.socket = new MozWebSocket(url);
5758
}
5859
updater.socket.onmessage = function(event) {
5960
updater.showMessage(JSON.parse(event.data));

maint/requirements.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Frozen pip requirements for tools used in the development of tornado
2+
3+
# Tornado's optional dependencies
4+
MySQL-python==1.2.3
5+
Twisted==11.1.0
6+
pycurl==7.19.0
7+
8+
# Other useful tools
9+
Sphinx==1.1.2
10+
coverage==3.5.1
11+
pyflakes==0.5.0
12+
tox==1.3
13+
virtualenv==1.7
14+
15+
# Indirect dependencies
16+
Jinja2==2.6
17+
Pygments==1.4
18+
docutils==0.8.1
19+
py==1.4.6
20+
wsgiref==0.1.2
21+
zope.interface==3.8.0

maint/test/websocket/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
define('cases', type=str, multiple=True,
1212
default=["*"])
1313
define('exclude', type=str, multiple=True,
14-
default=[])
14+
default=["9.*"])
1515

1616
if __name__ == '__main__':
1717
parse_command_line()

maint/test/websocket/run.sh

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
# python2 and python3. Output goes in ./reports/servers/index.html.
55
#
66
# The --cases and --exclude arguments can be used to run only part of
7-
# the suite. --exclude="9.*" is useful to skip the relatively slow
8-
# performance tests.
7+
# the suite. The default is --exclude="9.*" to skip the relatively slow
8+
# performance tests; pass --exclude="" to override and include them.
99

1010
set -e
1111

@@ -21,13 +21,17 @@ PY27_SERVER_PID=$!
2121
.tox/py32/bin/python server.py --port=9003 &
2222
PY32_SERVER_PID=$!
2323

24+
.tox/pypy/bin/python server.py --port=9004 &
25+
PYPY_SERVER_PID=$!
26+
2427
sleep 1
2528

26-
.tox/py27/bin/python ./client.py --servers=Tornado/py25=ws://localhost:9001,Tornado/py27=ws://localhost:9002,Tornado/py32=ws://localhost:9003 "$@"
29+
.tox/py27/bin/python ./client.py --servers=Tornado/py25=ws://localhost:9001,Tornado/py27=ws://localhost:9002,Tornado/py32=ws://localhost:9003,Tornado/pypy=ws://localhost:9004 "$@" || true
2730

2831
kill $PY25_SERVER_PID
2932
kill $PY27_SERVER_PID
3033
kill $PY32_SERVER_PID
34+
kill $PYPY_SERVER_PID
3135
wait
3236

3337
echo "Tests complete. Output is in ./reports/servers/index.html"

maint/test/websocket/server.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,20 @@
22

33
from tornado.ioloop import IOLoop
44
from tornado.options import define, options, parse_command_line
5+
from tornado.util import bytes_type
56
from tornado.websocket import WebSocketHandler
67
from tornado.web import Application
78

89
define('port', default=9000)
910

1011
class EchoHandler(WebSocketHandler):
1112
def on_message(self, message):
12-
self.write_message(message)
13+
self.write_message(message, binary=isinstance(message, bytes_type))
1314

1415
if __name__ == '__main__':
1516
parse_command_line()
1617
app = Application([
1718
('/', EchoHandler),
1819
])
19-
app.listen(options.port, address='localhost')
20+
app.listen(options.port, address='127.0.0.1')
2021
IOLoop.instance().start()

maint/test/websocket/tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# to install autobahn and deal with 2to3 for the python3 version.
33
# See run.sh for the real test runner.
44
[tox]
5-
envlist = py27, py32, py25
5+
envlist = py27, py32, py25, pypy
66
setupdir=../../..
77

88
[testenv]

maint/vm/ubuntu11.04/Vagrantfile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Vagrant::Config.run do |config|
2+
config.vm.box = "ubuntu11.04"
3+
4+
config.vm.network "172.19.1.4"
5+
config.vm.share_folder("tornado", "/tornado", "../../..", :nfs=> true)
6+
7+
config.vm.provision :shell, :path => "setup.sh"
8+
end

maint/vm/ubuntu11.04/setup.sh

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#!/bin/sh
2+
3+
set -e
4+
5+
# Ubuntu 10.10+ do some extra permissions checks for hard links.
6+
# Vagrant's nfs shared folders come through with funny uids, but
7+
# attempts to access them still work despite the visible permissions
8+
# being incorrect.
9+
sysctl -w kernel.yama.protected_nonaccess_hardlinks=0
10+
11+
apt-get update
12+
13+
# libcurl4-gnutls-dev is the default if you ask for libcurl4-dev, but it
14+
# has bugs that make our tests deadlock (the relevant tests detect this and
15+
# disable themselves, but it means that to get full coverage we have to use
16+
# the openssl version).
17+
# The oddly-named python-software-properties includes add-apt-repository.
18+
APT_PACKAGES="
19+
python-pip
20+
python-dev
21+
libmysqlclient-dev
22+
libcurl4-openssl-dev
23+
python-software-properties
24+
"
25+
26+
apt-get -y install $APT_PACKAGES
27+
28+
29+
# Ubuntu 11.04 has python 2.7 as default; install more from here.
30+
# The most important thing is to have both 2.5 and a later version so we
31+
# test with both tornado.epoll and 2.6+ stdlib's select.epoll.
32+
add-apt-repository ppa:fkrull/deadsnakes
33+
apt-get update
34+
35+
DEADSNAKES_PACKAGES="
36+
python2.5
37+
python2.5-dev
38+
python2.6
39+
python2.6-dev
40+
python3.2
41+
python3.2-dev
42+
"
43+
apt-get -y install $DEADSNAKES_PACKAGES
44+
45+
46+
PIP_PACKAGES="
47+
virtualenv
48+
tox
49+
MySQL-python
50+
pycurl
51+
twisted
52+
"
53+
54+
pip install $PIP_PACKAGES
55+
56+
/tornado/maint/vm/shared-setup.sh

maint/vm/ubuntu11.04/tox.ini

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
[tox]
2+
envlist = py27-full, py25-full, py32, py25, py26, py26-full, py27
3+
setupdir=/tornado
4+
toxworkdir=/home/vagrant/tox-tornado
5+
6+
[testenv]
7+
commands = python -m tornado.test.runtests {posargs:}
8+
9+
[testenv:py25]
10+
basepython = python2.5
11+
deps = simplejson
12+
13+
[testenv:py25-full]
14+
basepython = python2.5
15+
deps =
16+
MySQL-python
17+
pycurl
18+
simplejson
19+
twisted==11.0.0
20+
21+
[testenv:py26-full]
22+
deps =
23+
MySQL-python
24+
pycurl
25+
twisted==11.0.0
26+
27+
[testenv:py27-full]
28+
basepython = python2.7
29+
deps =
30+
MySQL-python
31+
pycurl
32+
twisted==11.0.0

tornado/__init__.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,12 @@
1616

1717
"""The Tornado web server and tools."""
1818

19+
# version is a human-readable version number.
20+
21+
# version_info is a four-tuple for programmatic comparison. The first
22+
# three numbers are the components of the version number. The fourth
23+
# is zero for an official release, positive for a development branch,
24+
# or negative for a release candidate (after the base version number
25+
# has been incremented)
1926
version = "2.1.1git"
20-
version_info = (2, 1, 1)
27+
version_info = (2, 1, 1, 1)

tornado/auth.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -451,14 +451,14 @@ def _on_auth(self, user):
451451
_OAUTH_NO_CALLBACKS = False
452452

453453

454-
def authenticate_redirect(self):
454+
def authenticate_redirect(self, callback_uri = None):
455455
"""Just like authorize_redirect(), but auto-redirects if authorized.
456456
457457
This is generally the right interface to use if you are using
458458
Twitter for single-sign on.
459459
"""
460460
http = httpclient.AsyncHTTPClient()
461-
http.fetch(self._oauth_request_token_url(), self.async_callback(
461+
http.fetch(self._oauth_request_token_url(callback_uri = callback_uri), self.async_callback(
462462
self._on_request_token, self._OAUTH_AUTHENTICATE_URL, None))
463463

464464
def twitter_request(self, path, callback, access_token=None,
@@ -499,8 +499,13 @@ def _on_post(self, new_entry):
499499
self.finish("Posted a message!")
500500
501501
"""
502+
if path.startswith('http:') or path.startswith('https:'):
503+
# Raw urls are useful for e.g. search which doesn't follow the
504+
# usual pattern: http://search.twitter.com/search.json
505+
url = path
506+
else:
507+
url = "http://api.twitter.com/1" + path + ".json"
502508
# Add the OAuth resource request signature if we have credentials
503-
url = "http://api.twitter.com/1" + path + ".json"
504509
if access_token:
505510
all_args = {}
506511
all_args.update(args)

tornado/curl_httpclient.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ def _curl_create(max_simultaneous_connections=None):
271271

272272

273273
def _curl_setup_request(curl, request, buffer, headers):
274-
curl.setopt(pycurl.URL, request.url)
274+
curl.setopt(pycurl.URL, utf8(request.url))
275275

276276
# libcurl's magic "Expect: 100-continue" behavior causes delays
277277
# with servers that don't support it (which include, among others,
@@ -307,8 +307,8 @@ def _curl_setup_request(curl, request, buffer, headers):
307307
curl.setopt(pycurl.WRITEFUNCTION, buffer.write)
308308
curl.setopt(pycurl.FOLLOWLOCATION, request.follow_redirects)
309309
curl.setopt(pycurl.MAXREDIRS, request.max_redirects)
310-
curl.setopt(pycurl.CONNECTTIMEOUT, int(request.connect_timeout))
311-
curl.setopt(pycurl.TIMEOUT, int(request.request_timeout))
310+
curl.setopt(pycurl.CONNECTTIMEOUT_MS, int(1000 * request.connect_timeout))
311+
curl.setopt(pycurl.TIMEOUT_MS, int(1000 * request.request_timeout))
312312
if request.user_agent:
313313
curl.setopt(pycurl.USERAGENT, utf8(request.user_agent))
314314
else:
@@ -383,10 +383,10 @@ def ioctl(cmd):
383383
else:
384384
curl.setopt(pycurl.INFILESIZE, len(request.body))
385385

386-
if request.auth_username and request.auth_password:
387-
userpwd = "%s:%s" % (request.auth_username, request.auth_password)
386+
if request.auth_username is not None:
387+
userpwd = "%s:%s" % (request.auth_username, request.auth_password or '')
388388
curl.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_BASIC)
389-
curl.setopt(pycurl.USERPWD, userpwd)
389+
curl.setopt(pycurl.USERPWD, utf8(userpwd))
390390
logging.debug("%s %s (username: %r)", request.method, request.url,
391391
request.auth_username)
392392
else:

tornado/gen.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,12 @@ def engine(func):
8282
Any generator that yields objects from this module must be wrapped
8383
in this decorator. The decorator only works on functions that are
8484
already asynchronous. For `~tornado.web.RequestHandler`
85-
``get``/``post``/etc methods, this means that both the `tornado.gen.engine`
86-
and `tornado.web.asynchronous` decorators must be used (in either order).
87-
In most other cases, it means that it doesn't make sense to use
88-
``gen.engine`` on functions that don't already take a callback argument.
85+
``get``/``post``/etc methods, this means that both the
86+
`tornado.web.asynchronous` and `tornado.gen.engine` decorators
87+
must be used (for proper exception handling, ``asynchronous``
88+
should come before ``gen.engine``). In most other cases, it means
89+
that it doesn't make sense to use ``gen.engine`` on functions that
90+
don't already take a callback argument.
8991
"""
9092
@functools.wraps(func)
9193
def wrapper(*args, **kwargs):

tornado/httpclient.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,11 @@ class HTTPClient(object):
5454
except httpclient.HTTPError, e:
5555
print "Error:", e
5656
"""
57-
def __init__(self):
57+
def __init__(self, async_client_class=None):
5858
self._io_loop = IOLoop()
59-
self._async_client = AsyncHTTPClient(self._io_loop)
59+
if async_client_class is None:
60+
async_client_class = AsyncHTTPClient
61+
self._async_client = async_client_class(self._io_loop)
6062
self._response = None
6163
self._closed = False
6264

@@ -391,12 +393,14 @@ def main():
391393
define("print_headers", type=bool, default=False)
392394
define("print_body", type=bool, default=True)
393395
define("follow_redirects", type=bool, default=True)
396+
define("validate_cert", type=bool, default=True)
394397
args = parse_command_line()
395398
client = HTTPClient()
396399
for arg in args:
397400
try:
398401
response = client.fetch(arg,
399-
follow_redirects=options.follow_redirects
402+
follow_redirects=options.follow_redirects,
403+
validate_cert=options.validate_cert,
400404
)
401405
except HTTPError, e:
402406
if e.response is not None:

0 commit comments

Comments
 (0)