Skip to content

Commit

Permalink
Merge branch 'master' into python3
Browse files Browse the repository at this point in the history
  • Loading branch information
bdarnell committed May 14, 2011
2 parents 338ba14 + 2b417a1 commit 70f08bf
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 11 deletions.
14 changes: 11 additions & 3 deletions tornado/httputil.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,16 +128,24 @@ def update(self, *args, **kwargs):
self[k] = v

_NORMALIZED_HEADER_RE = re.compile(r'^[A-Z0-9][a-z0-9]*(-[A-Z0-9][a-z0-9]*)*$')
_normalized_headers = {}

@staticmethod
def _normalize_name(name):
"""Converts a name to Http-Header-Case.
>>> HTTPHeaders._normalize_name("coNtent-TYPE")
'Content-Type'
"""
if HTTPHeaders._NORMALIZED_HEADER_RE.match(name):
return name
return "-".join([w.capitalize() for w in name.split("-")])
try:
return HTTPHeaders._normalized_headers[name]
except KeyError:
if HTTPHeaders._NORMALIZED_HEADER_RE.match(name):
normalized = name
else:
normalized = "-".join([w.capitalize() for w in name.split("-")])
HTTPHeaders._normalized_headers[name] = normalized
return normalized


def doctests():
Expand Down
8 changes: 8 additions & 0 deletions tornado/ioloop.py
Original file line number Diff line number Diff line change
Expand Up @@ -397,10 +397,18 @@ def __init__(self, deadline, callback):
self.deadline = deadline
self.callback = callback

# Comparison methods to sort by deadline, with object id as a tiebreaker
# to guarantee a consistent ordering. The heapq module uses __le__
# in python2.5, and __lt__ in 2.6+ (sort() and most other comparisons
# use __lt__).
def __lt__(self, other):
return ((self.deadline, id(self)) <
(other.deadline, id(other)))

def __le__(self, other):
return ((self.deadline, id(self)) <=
(other.deadline, id(other)))


class PeriodicCallback(object):
"""Schedules the given callback to be called periodically.
Expand Down
2 changes: 2 additions & 0 deletions tornado/iostream.py
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,8 @@ def _merge_prefix(deque, size):
>>> _merge_prefix(d, 100); print d
deque(['abcdefghij'])
"""
if len(deque) == 1 and len(deque[0]) < size:
return
prefix = []
remaining = size
while deque and remaining > 0:
Expand Down
21 changes: 13 additions & 8 deletions tornado/stack_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ def die_on_error():

from __future__ import with_statement

from types import NoneType

import contextlib
import functools
import itertools
Expand Down Expand Up @@ -136,6 +138,9 @@ def __enter__(self):
def __exit__(self, type, value, traceback):
_state.contexts = self.old_contexts

class _StackContextWrapper(functools.partial):
pass

def wrap(fn):
'''Returns a callable object that will resore the current StackContext
when executed.
Expand All @@ -144,18 +149,21 @@ def wrap(fn):
different execution context (either in a different thread or
asynchronously in the same thread).
'''
if fn is None:
return None
# functools.wraps doesn't appear to work on functools.partial objects
#@functools.wraps(fn)
def wrapped(callback, contexts, *args, **kwargs):
if contexts is _state.contexts or not contexts:
callback(*args, **kwargs)
return
if not _state.contexts:
new_contexts = [cls(arg) for (cls, arg) in contexts]
# If we're moving down the stack, _state.contexts is a prefix
# of contexts. For each element of contexts not in that prefix,
# create a new StackContext object.
# If we're moving up the stack (or to an entirely different stack),
# _state.contexts will have elements not in contexts. Use
# NullContext to clear the state and then recreate from contexts.
if (len(_state.contexts) > len(contexts) or
elif (len(_state.contexts) > len(contexts) or
any(a[1] is not b[1]
for a, b in itertools.izip(_state.contexts, contexts))):
# contexts have been removed or changed, so start over
Expand All @@ -172,12 +180,9 @@ def wrapped(callback, contexts, *args, **kwargs):
callback(*args, **kwargs)
else:
callback(*args, **kwargs)
if getattr(fn, 'stack_context_wrapped', False):
if isinstance(fn, (_StackContextWrapper, NoneType)):
return fn
contexts = _state.contexts
result = functools.partial(wrapped, fn, contexts)
result.stack_context_wrapped = True
return result
return _StackContextWrapper(wrapped, fn, _state.contexts)

@contextlib.contextmanager
def _nested(*managers):
Expand Down
1 change: 1 addition & 0 deletions tornado/websocket.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ def _on_end_delimiter(self, frame):
if not self.client_terminated:
self.async_callback(self.on_message)(
frame[:-1].decode("utf-8", "replace"))
if not self.client_terminated:
self._receive_message()

def _on_length_indicator(self, byte):
Expand Down

0 comments on commit 70f08bf

Please sign in to comment.