Trival changes to support Python 3.
This commit is contained in:
parent
efe8e3d235
commit
660d72d1f2
|
@ -12,7 +12,7 @@ different server scripts may be found in the scripts themselves and in
|
|||
web-server.txt. To start, though, the easiest way to view the demos
|
||||
is as follows: in a terminal window, run::
|
||||
|
||||
python -m quixote.server.simple_server
|
||||
python3 -m quixote.server.simple_server
|
||||
|
||||
and in a browser, open http://localhost:8080. If you wish to run the
|
||||
demo on a remote computer, you will need to ask the server to listen
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
A small and flexible Python web application framework.
|
||||
"""
|
||||
|
||||
__version__ = '2.9'
|
||||
__version__ = '3.0'
|
||||
|
||||
# These are frequently needed by Quixote applications.
|
||||
from quixote.publish import \
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
+#!/usr/bin/env python3
|
||||
+
|
||||
"""An alternative Quixote demo. This version is contained in a single module
|
||||
and does not use PTL. The easiest way to run this demo is to use the
|
||||
simple HTTP server included with Quixote. For example:
|
||||
|
@ -54,9 +56,8 @@ class RootDirectory(Directory):
|
|||
content += htmltext(
|
||||
'<p>Hello, %s.</p>') % get_user()
|
||||
content += htmltext('<p>%s</p>' % href('logout', 'logout'))
|
||||
sessions = get_session_manager().items()
|
||||
sessions = sorted(get_session_manager().items())
|
||||
if sessions:
|
||||
sessions.sort()
|
||||
content += htmltext('<table><tr>'
|
||||
'<th></th>'
|
||||
'<th>Session</th>'
|
||||
|
@ -177,17 +178,17 @@ try:
|
|||
session_class=PersistentSession,
|
||||
session_mapping=sessions)
|
||||
def forget_changes(self, session):
|
||||
print 'abort changes', get_session()
|
||||
print('abort changes', get_session())
|
||||
connection.abort()
|
||||
|
||||
def commit_changes(self, session):
|
||||
print 'commit changes', get_session()
|
||||
print('commit changes', get_session())
|
||||
connection.commit()
|
||||
|
||||
def create_durus_publisher():
|
||||
global connection
|
||||
filename = os.path.join(tempfile.gettempdir(), 'quixote-demo.durus')
|
||||
print 'Opening %r as a Durus database.' % filename
|
||||
print('Opening %r as a Durus database.' % filename)
|
||||
connection = Connection(FileStorage(filename))
|
||||
root = connection.get_root()
|
||||
session_manager = root.get('session_manager', None)
|
||||
|
|
|
@ -4,7 +4,7 @@ from quixote.directory import Directory, export
|
|||
from quixote.errors import TraversalError
|
||||
|
||||
def fact(n):
|
||||
f = 1L
|
||||
f = 1
|
||||
while n > 1:
|
||||
f *= n
|
||||
n -= 1
|
||||
|
@ -15,7 +15,7 @@ class IntegerUI(Directory):
|
|||
def __init__(self, component):
|
||||
try:
|
||||
self.n = int(component)
|
||||
except ValueError, exc:
|
||||
except ValueError as exc:
|
||||
raise TraversalError(str(exc))
|
||||
|
||||
@export
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
A minimal Quixote demo. If you have the 'quixote' package in your Python
|
||||
path, you can run it like this:
|
||||
|
@ -35,5 +35,5 @@ def create_publisher():
|
|||
|
||||
if __name__ == '__main__':
|
||||
from quixote.server.simple_server import run
|
||||
print 'creating demo listening on http://localhost:8080/'
|
||||
print('creating demo listening on http://localhost:8080/')
|
||||
run(create_publisher, host='localhost', port=8080)
|
||||
|
|
|
@ -13,7 +13,7 @@ class RootDirectory(Directory):
|
|||
|
||||
@export(name='')
|
||||
def index [html] (self):
|
||||
print "debug message from the index page"
|
||||
print("debug message from the index page")
|
||||
"""
|
||||
<html>
|
||||
<head>
|
||||
|
@ -65,7 +65,7 @@ class RootDirectory(Directory):
|
|||
|
||||
@export
|
||||
def error(self):
|
||||
raise ValueError, "this is a Python exception"
|
||||
raise ValueError("this is a Python exception")
|
||||
|
||||
@export
|
||||
def publish_error(self):
|
||||
|
|
|
@ -28,13 +28,11 @@ class DirectoryClass(type):
|
|||
return cls
|
||||
|
||||
|
||||
class Directory(object):
|
||||
class Directory(object, metaclass=DirectoryClass):
|
||||
"""
|
||||
Instance attributes: none
|
||||
"""
|
||||
|
||||
__metaclass__ = DirectoryClass
|
||||
|
||||
# A list containing strings or 2-tuples of strings that map external
|
||||
# names to internal names. Note that the empty string will be
|
||||
# implicitly mapped to '_q_index'.
|
||||
|
@ -99,7 +97,7 @@ class Directory(object):
|
|||
if "" in self._q_exports and not quixote.get_request().form:
|
||||
# Fix missing trailing slash.
|
||||
path = quixote.get_path()
|
||||
print "Adding slash to: %r " % path
|
||||
print("Adding slash to: %r " % path)
|
||||
return quixote.redirect(path + "/", permanent=True)
|
||||
else:
|
||||
raise TraversalError(private_msg=('directory %r is not '
|
||||
|
@ -143,7 +141,7 @@ def export(func=None, name=None):
|
|||
"""
|
||||
def do_export(func):
|
||||
if name is None:
|
||||
func._q_name = func.func_name
|
||||
func._q_name = func.__name__
|
||||
else:
|
||||
func._q_name = name
|
||||
return func
|
||||
|
@ -160,7 +158,7 @@ def subdir(func=None, name=None):
|
|||
"""
|
||||
def do_export(func):
|
||||
if name is None:
|
||||
func._q_name = func.func_name
|
||||
func._q_name = func.__name__
|
||||
else:
|
||||
func._q_name = name
|
||||
return property(func)
|
||||
|
|
|
@ -69,7 +69,7 @@ class Form(_Form):
|
|||
return values
|
||||
|
||||
def action(self, submit, values):
|
||||
raise NotImplementedError, "sub-classes must implement 'action()'"
|
||||
raise NotImplementedError("sub-classes must implement 'action()'")
|
||||
|
||||
def handle(self):
|
||||
"""handle() -> string
|
||||
|
|
|
@ -88,7 +88,7 @@ class Form(object):
|
|||
|
||||
if enctype is not None and enctype not in (
|
||||
"application/x-www-form-urlencoded", "multipart/form-data"):
|
||||
raise ValueError, ("Form enctype must be "
|
||||
raise ValueError("Form enctype must be "
|
||||
"'application/x-www-form-urlencoded' or "
|
||||
"'multipart/form-data', not %r" % enctype)
|
||||
self.enctype = enctype
|
||||
|
@ -117,14 +117,11 @@ class Form(object):
|
|||
try:
|
||||
return self._names[name].parse()
|
||||
except KeyError:
|
||||
raise KeyError, 'no widget named %r' % name
|
||||
|
||||
def has_key(self, name):
|
||||
"""Return true if the widget named 'name' is in the form."""
|
||||
return name in self._names
|
||||
raise KeyError('no widget named %r' % name)
|
||||
|
||||
def __contains__(self, name):
|
||||
return self.has_key(name)
|
||||
"""Return true if the widget named 'name' is in the form."""
|
||||
return name in self._names
|
||||
|
||||
def get(self, name, default=None):
|
||||
"""(name:string, default=None) -> any
|
||||
|
@ -156,7 +153,7 @@ class Form(object):
|
|||
does not include sub-widgets (e.g. widgets that are part of
|
||||
CompositeWidgets)
|
||||
"""
|
||||
return self._names.values()
|
||||
return list(self._names.values())
|
||||
|
||||
# -- Form processing and error checking ----------------------------
|
||||
|
||||
|
@ -223,14 +220,14 @@ class Form(object):
|
|||
"""
|
||||
widget = self._names.get(name)
|
||||
if not widget:
|
||||
raise KeyError, "unknown name %r" % name
|
||||
raise KeyError("unknown name %r" % name)
|
||||
widget.set_error(error)
|
||||
|
||||
# -- Form population methods ---------------------------------------
|
||||
|
||||
def add(self, widget_class, name, *args, **kwargs):
|
||||
if name in self._names:
|
||||
raise ValueError, "form already has '%s' widget" % name
|
||||
raise ValueError("form already has '%s' widget" % name)
|
||||
# add 'id' attribute if not already present
|
||||
if 'id' not in kwargs:
|
||||
kwargs['id'] = name
|
||||
|
@ -348,8 +345,7 @@ class Form(object):
|
|||
sorted by code_id.
|
||||
"""
|
||||
form_code = []
|
||||
code_ids = javascript_code.keys()
|
||||
code_ids.sort()
|
||||
code_ids = sorted(javascript_code.keys())
|
||||
for code_id in code_ids:
|
||||
code = javascript_code[code_id]
|
||||
if code:
|
||||
|
|
|
@ -133,7 +133,7 @@ class Widget(object):
|
|||
if submitted:
|
||||
try:
|
||||
self._parse(request)
|
||||
except WidgetValueError, exc:
|
||||
except WidgetValueError as exc:
|
||||
self.set_error(stringify(exc))
|
||||
if (self.required and self.value is None and
|
||||
not self.has_error()):
|
||||
|
@ -143,7 +143,7 @@ class Widget(object):
|
|||
def _parse(self, request):
|
||||
# subclasses may override but this is not part of the public API
|
||||
value = request.form.get(self.name)
|
||||
if isinstance(value, basestring) and value.strip():
|
||||
if isinstance(value, str) and value.strip():
|
||||
self.value = value
|
||||
else:
|
||||
self.value = None
|
||||
|
@ -311,7 +311,7 @@ class SelectWidget(Widget):
|
|||
if not options:
|
||||
# The HTML and XHTML specifications require select elements to
|
||||
# contain at least one option.
|
||||
raise ValueError, "a non-empty list of 'options' is required"
|
||||
raise ValueError("a non-empty list of 'options' is required")
|
||||
else:
|
||||
self.set_options(options, sort)
|
||||
self.verify_selection = verify_selection
|
||||
|
@ -350,10 +350,10 @@ class SelectWidget(Widget):
|
|||
return keys
|
||||
# can't use OIDs, try using descriptions
|
||||
used_keys = {}
|
||||
keys = map(stringify, descriptions)
|
||||
keys = list(map(stringify, descriptions))
|
||||
for key in keys:
|
||||
if key in used_keys:
|
||||
raise ValueError, "duplicated descriptions (provide keys)"
|
||||
raise ValueError("duplicated descriptions (provide keys)")
|
||||
used_keys[key] = 1
|
||||
return keys
|
||||
|
||||
|
@ -391,14 +391,14 @@ class SelectWidget(Widget):
|
|||
descriptions.append(description)
|
||||
keys.append(stringify(key))
|
||||
else:
|
||||
raise ValueError, 'invalid options %r' % options
|
||||
raise ValueError('invalid options %r' % options)
|
||||
else:
|
||||
values = descriptions = options
|
||||
|
||||
if not keys:
|
||||
keys = self._generate_keys(values, descriptions)
|
||||
|
||||
options = zip(values, descriptions, keys)
|
||||
options = list(zip(values, descriptions, keys))
|
||||
|
||||
if sort:
|
||||
def make_sort_key(option):
|
||||
|
@ -407,8 +407,7 @@ class SelectWidget(Widget):
|
|||
return ('', option)
|
||||
else:
|
||||
return (stringify(description).lower(), option)
|
||||
doptions = map(make_sort_key, options)
|
||||
doptions.sort()
|
||||
doptions = sorted(map(make_sort_key, options))
|
||||
options = [item[1] for item in doptions]
|
||||
self.options = options
|
||||
|
||||
|
@ -439,7 +438,7 @@ class SelectWidget(Widget):
|
|||
self.set_options(allowed_values, sort)
|
||||
else:
|
||||
assert len(descriptions) == len(allowed_values)
|
||||
self.set_options(zip(allowed_values, descriptions), sort)
|
||||
self.set_options(list(zip(allowed_values, descriptions)), sort)
|
||||
|
||||
def is_selected(self, value):
|
||||
return value == self.value
|
||||
|
@ -613,7 +612,7 @@ class HiddenWidget(Widget):
|
|||
|
||||
def set_error(self, error):
|
||||
if error is not None:
|
||||
raise TypeError, 'error not allowed on hidden widgets'
|
||||
raise TypeError('error not allowed on hidden widgets')
|
||||
|
||||
def render_content(self):
|
||||
if self.value is None:
|
||||
|
@ -769,7 +768,7 @@ class CompositeWidget(Widget):
|
|||
|
||||
def add(self, widget_class, name, *args, **kwargs):
|
||||
if name in self._names:
|
||||
raise ValueError, 'the name %r is already used' % name
|
||||
raise ValueError('the name %r is already used' % name)
|
||||
if self.attrs.get('disabled') and 'disabled' not in kwargs:
|
||||
kwargs['disabled'] = True
|
||||
widget = widget_class(subname(self.name, name), *args, **kwargs)
|
||||
|
@ -805,7 +804,7 @@ class WidgetList(CompositeWidget):
|
|||
assert type(element_kwargs) is dict, (
|
||||
"value '%s' element_kwargs not a dict: "
|
||||
"got %r" % (name, element_kwargs))
|
||||
assert isinstance(add_element_label, (basestring, htmltext)), (
|
||||
assert isinstance(add_element_label, (str, htmltext)), (
|
||||
"value '%s'add_element_label not a string: "
|
||||
"got %r" % (name, add_element_label))
|
||||
|
||||
|
@ -899,7 +898,7 @@ class WidgetDict(CompositeWidget):
|
|||
assert type(element_value_kwargs) is dict, (
|
||||
"value '%s' element_value_kwargs not a dict: "
|
||||
"got %r" % (name, element_value_kwargs))
|
||||
assert isinstance(add_element_label, (basestring, htmltext)), (
|
||||
assert isinstance(add_element_label, (str, htmltext)), (
|
||||
'value %r element_name not a string: '
|
||||
'got %r' % (name, add_element_label))
|
||||
|
||||
|
|
|
@ -89,7 +89,7 @@ class Form:
|
|||
|
||||
if enctype is not None and enctype not in (
|
||||
"application/x-www-form-urlencoded", "multipart/form-data"):
|
||||
raise ValueError, ("Form enctype must be "
|
||||
raise ValueError("Form enctype must be "
|
||||
"'application/x-www-form-urlencoded' or "
|
||||
"'multipart/form-data', not %r" % enctype)
|
||||
self.enctype = enctype
|
||||
|
@ -231,7 +231,7 @@ class Form:
|
|||
return r
|
||||
|
||||
def _render_required_notice(self, request):
|
||||
if filter(None, self.required.values()):
|
||||
if any(self.required.values()):
|
||||
r = htmltext('<tr><td colspan="3">'
|
||||
'<b>*</b> = <em>required field</em>'
|
||||
'</td></tr>')
|
||||
|
@ -256,8 +256,7 @@ class Form:
|
|||
javascript_code = request.response.javascript_code
|
||||
if javascript_code:
|
||||
form_code = []
|
||||
code_ids = javascript_code.keys()
|
||||
code_ids.sort()
|
||||
code_ids = sorted(javascript_code.keys())
|
||||
for code_id in code_ids:
|
||||
code = javascript_code[code_id]
|
||||
if code:
|
||||
|
@ -289,7 +288,7 @@ class Form:
|
|||
for widget in self.widget_order:
|
||||
try:
|
||||
val = widget.parse(request)
|
||||
except FormValueError, exc:
|
||||
except FormValueError as exc:
|
||||
self.error[widget.name] = exc.msg
|
||||
else:
|
||||
values[widget.name] = val
|
||||
|
@ -306,7 +305,7 @@ class Form:
|
|||
checking cannot be done here -- it must done in the 'process()'
|
||||
method.
|
||||
"""
|
||||
raise NotImplementedError, "sub-classes must implement 'action()'"
|
||||
raise NotImplementedError("sub-classes must implement 'action()'")
|
||||
|
||||
def handle(self, request):
|
||||
"""handle(request : HTTPRequest) -> string
|
||||
|
@ -396,7 +395,7 @@ class Form:
|
|||
"""
|
||||
try:
|
||||
return self.widgets[name].parse(request)
|
||||
except FormValueError, exc:
|
||||
except FormValueError as exc:
|
||||
self.error[name] = str(exc)
|
||||
return None
|
||||
|
||||
|
@ -440,14 +439,13 @@ class Form:
|
|||
mod(value)
|
||||
elif mode == "direct":
|
||||
if not hasattr(target, key):
|
||||
raise AttributeError, \
|
||||
("target object %s doesn't have attribute %s" %
|
||||
(`target`, key))
|
||||
raise AttributeError("target object %s doesn't have attribute %s" %
|
||||
(repr(target), key))
|
||||
setattr(target, key, value)
|
||||
elif mode == "dict":
|
||||
target[key] = value
|
||||
else:
|
||||
raise ValueError, "unknown update mode %s" % `mode`
|
||||
raise ValueError("unknown update mode %s" % repr(mode))
|
||||
|
||||
def clear_widget(self, widget_name):
|
||||
self.widgets[widget_name].clear()
|
||||
|
@ -479,9 +477,9 @@ class Form:
|
|||
Returns the new Widget.
|
||||
"""
|
||||
if name in self.widgets:
|
||||
raise ValueError, "form already has '%s' variable" % name
|
||||
raise ValueError("form already has '%s' variable" % name)
|
||||
klass = get_widget_class(widget_type)
|
||||
new_widget = apply(klass, (name, value), args)
|
||||
new_widget = klass(*(name, value), **args)
|
||||
|
||||
self.widgets[name] = new_widget
|
||||
self.widget_order.append(new_widget)
|
||||
|
@ -493,7 +491,7 @@ class Form:
|
|||
def add_submit_button(self, name, value):
|
||||
global _widget_class
|
||||
if name in self.widgets:
|
||||
raise ValueError, "form already has '%s' variable" % name
|
||||
raise ValueError("form already has '%s' variable" % name)
|
||||
new_widget = _widget_class['submit_button'](name, value)
|
||||
|
||||
self.widgets[name] = new_widget
|
||||
|
@ -501,7 +499,7 @@ class Form:
|
|||
|
||||
def add_cancel_button(self, caption, url):
|
||||
if not isinstance(url, (StringType, htmltext)):
|
||||
raise TypeError, "url must be a string (got %r)" % url
|
||||
raise TypeError("url must be a string (got %r)" % url)
|
||||
self.add_submit_button("cancel", caption)
|
||||
self.cancel_url = url
|
||||
|
||||
|
|
|
@ -99,7 +99,7 @@ class Widget:
|
|||
from quixote.form.form import get_widget_class
|
||||
klass = get_widget_class(widget_type)
|
||||
name = self.get_subwidget_name(widget_name)
|
||||
return apply(klass, (name, value), args)
|
||||
return klass(*(name, value), **args)
|
||||
|
||||
# class Widget
|
||||
|
||||
|
@ -325,10 +325,10 @@ class SelectWidget (Widget):
|
|||
return keys
|
||||
# can't use OIDs, try using descriptions
|
||||
used_keys = {}
|
||||
keys = map(str, descriptions)
|
||||
keys = list(map(str, descriptions))
|
||||
for key in keys:
|
||||
if key in used_keys:
|
||||
raise ValueError, "duplicated descriptions (provide keys)"
|
||||
raise ValueError("duplicated descriptions (provide keys)")
|
||||
used_keys[key] = 1
|
||||
return keys
|
||||
|
||||
|
@ -367,14 +367,14 @@ class SelectWidget (Widget):
|
|||
descriptions.append(description)
|
||||
keys.append(str(key))
|
||||
else:
|
||||
raise ValueError, 'invalid options %r' % options
|
||||
raise ValueError('invalid options %r' % options)
|
||||
else:
|
||||
values = descriptions = options
|
||||
|
||||
if not keys:
|
||||
keys = self._generate_keys(values, descriptions)
|
||||
|
||||
options = zip(values, descriptions, keys)
|
||||
options = list(zip(values, descriptions, keys))
|
||||
|
||||
if sort:
|
||||
def make_sort_key(option):
|
||||
|
@ -383,8 +383,7 @@ class SelectWidget (Widget):
|
|||
return ('', option)
|
||||
else:
|
||||
return (str(description).lower(), option)
|
||||
doptions = map(make_sort_key, options)
|
||||
doptions.sort()
|
||||
doptions = sorted(map(make_sort_key, options))
|
||||
options = [item[1] for item in doptions]
|
||||
self.options = options
|
||||
|
||||
|
@ -395,7 +394,7 @@ class SelectWidget (Widget):
|
|||
return value
|
||||
else:
|
||||
if self.verify_selection:
|
||||
raise FormValueError, "invalid value selected"
|
||||
raise FormValueError("invalid value selected")
|
||||
else:
|
||||
return self.options[0][0]
|
||||
|
||||
|
@ -413,7 +412,7 @@ class SelectWidget (Widget):
|
|||
self.set_options(allowed_values, sort)
|
||||
else:
|
||||
assert len(descriptions) == len(allowed_values)
|
||||
self.set_options(zip(allowed_values, descriptions), sort)
|
||||
self.set_options(list(zip(allowed_values, descriptions)), sort)
|
||||
|
||||
|
||||
def is_selected(self, value):
|
||||
|
@ -456,7 +455,7 @@ class SingleSelectWidget (SelectWidget):
|
|||
self.value = None
|
||||
if parsed_key:
|
||||
if type(parsed_key) is ListType:
|
||||
raise FormValueError, "cannot select multiple values"
|
||||
raise FormValueError("cannot select multiple values")
|
||||
self.value = self.parse_single_selection(parsed_key)
|
||||
return self.value
|
||||
|
||||
|
@ -637,7 +636,7 @@ class NumberWidget (StringWidget):
|
|||
try:
|
||||
self.value = self.type_converter(value)
|
||||
except ValueError:
|
||||
raise FormValueError, self.type_error
|
||||
raise FormValueError(self.type_error)
|
||||
return self.value
|
||||
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ def url_quote(value, fallback=None):
|
|||
"""
|
||||
if value is None:
|
||||
if fallback is None:
|
||||
raise ValueError, "value is None and no fallback supplied"
|
||||
raise ValueError("value is None and no fallback supplied")
|
||||
else:
|
||||
return fallback
|
||||
return urllib.quote(stringify(value))
|
||||
|
|
|
@ -47,7 +47,7 @@ class htmltext(object):
|
|||
# raise AttributeError, 'immutable object'
|
||||
|
||||
def __getstate__(self):
|
||||
raise ValueError, 'htmltext objects should not be pickled'
|
||||
raise ValueError('htmltext objects should not be pickled')
|
||||
|
||||
def __repr__(self):
|
||||
return '<htmltext %r>' % self.s
|
||||
|
@ -71,14 +71,14 @@ class htmltext(object):
|
|||
return htmltext(self.s % _wraparg(args))
|
||||
|
||||
def format(self, *args, **kwargs):
|
||||
args = map(_wraparg, args)
|
||||
args = list(map(_wraparg, args))
|
||||
newkw = {}
|
||||
for k, v in kwargs.iteritems():
|
||||
for k, v in kwargs.items():
|
||||
newkw[k] = _wraparg(v)
|
||||
return htmltext(self.s.format(*args, **newkw))
|
||||
|
||||
def __add__(self, other):
|
||||
if isinstance(other, basestring):
|
||||
if isinstance(other, str):
|
||||
return htmltext(self.s + _escape_string(other))
|
||||
elif isinstance(other, htmltext):
|
||||
return htmltext(self.s + other.s)
|
||||
|
@ -86,7 +86,7 @@ class htmltext(object):
|
|||
return NotImplemented
|
||||
|
||||
def __radd__(self, other):
|
||||
if isinstance(other, basestring):
|
||||
if isinstance(other, str):
|
||||
return htmltext(_escape_string(other) + self.s)
|
||||
else:
|
||||
return NotImplemented
|
||||
|
@ -99,11 +99,10 @@ class htmltext(object):
|
|||
for item in items:
|
||||
if isinstance(item, htmltext):
|
||||
quoted_items.append(stringify(item))
|
||||
elif isinstance(item, basestring):
|
||||
elif isinstance(item, str):
|
||||
quoted_items.append(_escape_string(item))
|
||||
else:
|
||||
raise TypeError(
|
||||
'join() requires string arguments (got %r)' % item)
|
||||
raise TypeError('join() requires string arguments (got %r)' % item)
|
||||
return htmltext(self.s.join(quoted_items))
|
||||
|
||||
def startswith(self, s):
|
||||
|
@ -152,7 +151,7 @@ class _QuoteWrapper(object):
|
|||
return _escape_string(stringify(self.value))
|
||||
|
||||
def __repr__(self):
|
||||
return _escape_string(`self.value`)
|
||||
return _escape_string(repr(self.value))
|
||||
|
||||
def __getitem__(self, key):
|
||||
return _wraparg(self.value[key])
|
||||
|
@ -175,13 +174,12 @@ def _wraparg(arg):
|
|||
# necessary to work around a PyString_Format bug in Python. Should
|
||||
# be fixed in Python 2.5
|
||||
return stringify(arg)
|
||||
elif isinstance(arg, unicode):
|
||||
elif isinstance(arg, str):
|
||||
# again, work around PyString_Format bug
|
||||
return _UnicodeWrapper(arg)
|
||||
elif (isinstance(arg, int) or
|
||||
isinstance(arg, long) or
|
||||
isinstance(arg, float)):
|
||||
# ints, longs, floats are okay
|
||||
# ints, floats are okay
|
||||
return arg
|
||||
else:
|
||||
# everything is gets wrapped
|
||||
|
|
|
@ -25,10 +25,10 @@ class BrokenError(Exception):
|
|||
|
||||
class Broken:
|
||||
def __str__(self):
|
||||
raise BrokenError, 'eieee'
|
||||
raise BrokenError('eieee')
|
||||
|
||||
def __repr__(self):
|
||||
raise BrokenError, 'eieee'
|
||||
raise BrokenError('eieee')
|
||||
|
||||
htmltext = escape = htmlescape = TemplateIO = stringify = None
|
||||
|
||||
|
@ -104,7 +104,7 @@ class HTMLTextTest (UTest):
|
|||
assert s != 'bar'
|
||||
assert s == htmltext('foo')
|
||||
assert s != htmltext('bar')
|
||||
assert htmltext(u'\u1234') == u'\u1234'
|
||||
assert htmltext('\\u1234') == '\\u1234'
|
||||
assert htmltext('1') != 1
|
||||
assert 1 != s
|
||||
|
||||
|
@ -127,7 +127,7 @@ class HTMLTextTest (UTest):
|
|||
assert isinstance(s + markupchars, htmltext)
|
||||
assert markupchars + s == quotedchars + "foo"
|
||||
assert isinstance(markupchars + s, htmltext)
|
||||
assert markupchars + htmltext(u'') == quotedchars
|
||||
assert markupchars + htmltext('') == quotedchars
|
||||
try:
|
||||
s + 1
|
||||
assert 0
|
||||
|
@ -136,10 +136,8 @@ class HTMLTextTest (UTest):
|
|||
1 + s
|
||||
assert 0
|
||||
except TypeError: pass
|
||||
# mixing unicode and str
|
||||
|
||||
assert repr(htmltext('a') + htmltext('b')) == "<htmltext 'ab'>"
|
||||
assert repr(htmltext(u'a') + htmltext('b')) == "<htmltext u'ab'>"
|
||||
assert repr(htmltext('a') + htmltext(u'b')) == "<htmltext u'ab'>"
|
||||
|
||||
def check_repeat(self):
|
||||
s = htmltext('a')
|
||||
|
|
|
@ -92,7 +92,9 @@ def parse_query(qs, charset):
|
|||
Parse a query given as a string argument and return a dictionary.
|
||||
"""
|
||||
fields = {}
|
||||
for chunk in filter(None, qs.split('&')):
|
||||
for chunk in qs.split('&'):
|
||||
if not chunk:
|
||||
continue
|
||||
if '=' not in chunk:
|
||||
name = chunk
|
||||
value = ''
|
||||
|
@ -309,7 +311,7 @@ class HTTPRequest:
|
|||
return self.environ.get('REQUEST_METHOD', 'GET')
|
||||
|
||||
def formiter(self):
|
||||
return self.form.iteritems()
|
||||
return self.form.items()
|
||||
|
||||
def get_scheme(self):
|
||||
return self.scheme
|
||||
|
@ -370,7 +372,7 @@ class HTTPRequest:
|
|||
else:
|
||||
path_comps = path.split('/')
|
||||
if abs(n) > len(path_comps)-1:
|
||||
raise ValueError, "n=%d too big for path '%s'" % (n, path)
|
||||
raise ValueError("n=%d too big for path '%s'" % (n, path))
|
||||
if n > 0:
|
||||
return '/'.join(path_comps[:-n])
|
||||
elif n < 0:
|
||||
|
@ -471,21 +473,18 @@ class HTTPRequest:
|
|||
row='%-15s %s'
|
||||
|
||||
result.append("Form:")
|
||||
L = self.form.items() ; L.sort()
|
||||
for k,v in L:
|
||||
for k, v in sorted(self.form.items()):
|
||||
result.append(row % (k,v))
|
||||
|
||||
result.append("")
|
||||
result.append("Cookies:")
|
||||
L = self.cookies.items() ; L.sort()
|
||||
for k,v in L:
|
||||
for k, v in sorted(self.cookies.items()):
|
||||
result.append(row % (k,v))
|
||||
|
||||
|
||||
result.append("")
|
||||
result.append("Environment:")
|
||||
L = self.environ.items() ; L.sort()
|
||||
for k,v in L:
|
||||
for k, v in sorted(self.environ.items()):
|
||||
result.append(row % (k,v))
|
||||
return "\n".join(result)
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ try:
|
|||
except ImportError:
|
||||
pass
|
||||
import struct
|
||||
from rfc822 import formatdate
|
||||
from email.utils import formatdate
|
||||
import quixote
|
||||
from quixote.html import stringify
|
||||
|
||||
|
@ -82,7 +82,7 @@ _GZIP_EXCLUDE = set(["application/pdf",
|
|||
])
|
||||
|
||||
def _LOWU32(i):
|
||||
return i & 0xFFFFFFFFL
|
||||
return i & 0xFFFFFFFF
|
||||
|
||||
class HTTPResponse:
|
||||
"""
|
||||
|
@ -180,7 +180,7 @@ class HTTPResponse:
|
|||
if not charset:
|
||||
self.charset = None
|
||||
else:
|
||||
self.charset = str(charset).lower()
|
||||
self.charset = charset.lower()
|
||||
|
||||
def set_status(self, status, reason=None):
|
||||
"""set_status(status : int, reason : string = None)
|
||||
|
@ -193,9 +193,9 @@ class HTTPResponse:
|
|||
if status == 493, the reason for status 400 will be used.
|
||||
"""
|
||||
if not isinstance(status, int):
|
||||
raise TypeError, "status must be an integer"
|
||||
raise TypeError("status must be an integer")
|
||||
if not (100 <= status <= 599):
|
||||
raise ValueError, "status must be between 100 and 599"
|
||||
raise ValueError("status must be between 100 and 599")
|
||||
|
||||
self.status_code = status
|
||||
if reason is None:
|
||||
|
@ -233,9 +233,9 @@ class HTTPResponse:
|
|||
self.cache = seconds + 60*(minutes + 60*(hours + 24*days))
|
||||
|
||||
def _encode_chunk(self, chunk):
|
||||
"""(chunk : str | unicode) -> str
|
||||
"""(chunk : str) -> bytes
|
||||
"""
|
||||
if isinstance(chunk, unicode):
|
||||
if isinstance(chunk, str):
|
||||
if self.charset is None:
|
||||
# iso-8859-1 is the default for the HTTP protocol if charset
|
||||
# parameter of content-type header is not provided
|
||||
|
@ -265,13 +265,13 @@ class HTTPResponse:
|
|||
def _generate_compressed(self, body):
|
||||
co = zlib.compressobj(6, zlib.DEFLATED, -zlib.MAX_WBITS,
|
||||
zlib.DEF_MEM_LEVEL, 0)
|
||||
crc = zlib.crc32('') & 0xffffffffL
|
||||
crc = zlib.crc32('') & 0xffffffff
|
||||
n = 0
|
||||
yield _GZIP_HEADER
|
||||
for chunk in body:
|
||||
if not isinstance(chunk, str):
|
||||
if not isinstance(chunk, bytes):
|
||||
chunk = self._encode_chunk(stringify(chunk))
|
||||
crc = zlib.crc32(chunk, crc) & 0xffffffffL
|
||||
crc = zlib.crc32(chunk, crc) & 0xffffffff
|
||||
n += len(chunk)
|
||||
yield co.compress(chunk)
|
||||
crc = struct.pack("<LL", _LOWU32(crc), _LOWU32(n))
|
||||
|
@ -284,7 +284,8 @@ class HTTPResponse:
|
|||
is true then the body may be compressed.
|
||||
"""
|
||||
if not isinstance(body, Stream):
|
||||
body = self._encode_chunk(stringify(body))
|
||||
if not isinstance(body, bytes):
|
||||
body = self._encode_chunk(stringify(body))
|
||||
if compress and self.content_type not in _GZIP_EXCLUDE:
|
||||
body = self._compress_body(body)
|
||||
else:
|
||||
|
@ -350,10 +351,10 @@ class HTTPResponse:
|
|||
def redirect(self, location, permanent=False):
|
||||
"""Cause a redirection without raising an error"""
|
||||
if not isinstance(location, str):
|
||||
raise TypeError, "location must be a string (got %s)" % `location`
|
||||
raise TypeError("location must be a string (got %r)" % location)
|
||||
# Ensure that location is a full URL
|
||||
if location.find('://') == -1:
|
||||
raise ValueError, "URL must include the server name"
|
||||
raise ValueError("URL must include the server name")
|
||||
if permanent:
|
||||
status = 301
|
||||
else:
|
||||
|
@ -419,10 +420,10 @@ class HTTPResponse:
|
|||
# Date header
|
||||
now = time.time()
|
||||
if "date" not in self.headers:
|
||||
self.headers['date'] = formatdate(now)
|
||||
self.headers['date'] = formatdate(now, usegmt=True)
|
||||
|
||||
# Cache directives
|
||||
if self.cache is None or self.headers.has_key("expires"):
|
||||
if self.cache is None or "expires" in self.headers:
|
||||
pass # don't mess with the expires or cache control header
|
||||
else:
|
||||
# We add both an Expires header and a Cache-Control header
|
||||
|
@ -430,7 +431,7 @@ class HTTPResponse:
|
|||
# priority when both Expires and max-age are present (even
|
||||
# if Expires is more restrictive, RFC 2616 section 14.9.3).
|
||||
if self.cache > 0:
|
||||
expire_date = formatdate(now + self.cache)
|
||||
expire_date = formatdate(now + self.cache, usegmt=True)
|
||||
cache_control = "max-age=%d" % self.cache
|
||||
else:
|
||||
# This is the default case and makes sense for a
|
||||
|
@ -491,7 +492,7 @@ class HTTPResponse:
|
|||
pass
|
||||
elif isinstance(self.body, Stream):
|
||||
for chunk in self.body:
|
||||
if not isinstance(chunk, str):
|
||||
if not isinstance(chunk, bytes):
|
||||
chunk = self._encode_chunk(chunk)
|
||||
yield chunk
|
||||
else:
|
||||
|
|
|
@ -26,7 +26,7 @@ Here's a sample plain text template::
|
|||
def foo [plain] (x, y = 5):
|
||||
"This is a chunk of static text."
|
||||
greeting = "hello world" # statement, no PTL output
|
||||
print 'Input values:', x, y
|
||||
print('Input values:', x, y)
|
||||
z = x + y
|
||||
"""You can plug in variables like x (%s)
|
||||
in a variety of ways.""" % x
|
||||
|
@ -53,7 +53,7 @@ value of that template. Look at the first part of the example again::
|
|||
def foo [plain] (x, y = 5):
|
||||
"This is a chunk of static text."
|
||||
greeting = "hello world" # statement, no PTL output
|
||||
print 'Input values:', x, y
|
||||
print('Input values:', x, y)
|
||||
z = x + y
|
||||
"""You can plug in variables like x (%s)
|
||||
in a variety of ways.""" % x
|
||||
|
|
|
@ -92,9 +92,9 @@ class _Verbose:
|
|||
|
||||
def message(self, format, *args):
|
||||
if args:
|
||||
print format%args
|
||||
print(format%args)
|
||||
else:
|
||||
print format
|
||||
print(format)
|
||||
|
||||
|
||||
class BasicModuleLoader(_Verbose):
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
from quixote.ptl.ptl_compile import compile_template
|
||||
if __name__ == '__main__':
|
||||
exec compile_template(open(sys.argv[1]), sys.argv[1])
|
||||
|
||||
if __name__ == '__main__':
|
||||
exec(compile_template(open(sys.argv[1]), sys.argv[1]))
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ PTL files.
|
|||
|
||||
import os, string
|
||||
from glob import glob
|
||||
from types import StringType, ListType, TupleType
|
||||
from distutils.command.build_py import build_py
|
||||
|
||||
class qx_build_py(build_py):
|
||||
|
@ -26,11 +25,10 @@ class qx_build_py(build_py):
|
|||
return modules
|
||||
|
||||
def build_module(self, module, module_file, package):
|
||||
if type(package) is StringType:
|
||||
package = string.split(package, '.')
|
||||
elif type(package) not in (ListType, TupleType):
|
||||
raise TypeError, \
|
||||
"'package' must be a string (dot-separated), list, or tuple"
|
||||
if type(package) is str:
|
||||
package = package.split('.')
|
||||
elif type(package) not in (list, tuple):
|
||||
raise TypeError("'package' must be a string (dot-separated), list, or tuple")
|
||||
|
||||
# Now put the module source file into the "build" area -- this is
|
||||
# easy, we just copy it somewhere under self.build_lib (the build
|
||||
|
|
|
@ -68,7 +68,7 @@ class Publisher:
|
|||
self.session_manager = NullSessionManager()
|
||||
|
||||
if _publisher is not None:
|
||||
raise RuntimeError, "only one instance of Publisher allowed"
|
||||
raise RuntimeError("only one instance of Publisher allowed")
|
||||
_publisher = self
|
||||
|
||||
if not hasattr(getattr(root_directory, '_q_traverse'), '__call__'):
|
||||
|
@ -252,7 +252,7 @@ class Publisher:
|
|||
try:
|
||||
self.parse_request(request)
|
||||
output = self.try_publish(request)
|
||||
except PublishError, exc:
|
||||
except PublishError as exc:
|
||||
# Exit the publishing loop and return a result right away.
|
||||
output = self.finish_interrupted_request(exc)
|
||||
except:
|
||||
|
|
|
@ -23,7 +23,7 @@ class Publisher(_Publisher):
|
|||
|
||||
def __init__(self, root_namespace, config=None):
|
||||
from quixote.config import Config
|
||||
if type(root_namespace) is types.StringType:
|
||||
if isinstance(root_namespace, str):
|
||||
root_namespace = _get_module(root_namespace)
|
||||
self.namespace_stack = [root_namespace]
|
||||
if config is None:
|
||||
|
@ -67,7 +67,7 @@ class RootDirectory(Directory):
|
|||
elif hasattr(object, '__call__'):
|
||||
output = object(request)
|
||||
if output is None:
|
||||
raise RuntimeError, 'callable %s returned None' % repr(object)
|
||||
raise RuntimeError('callable %r returned None' % object)
|
||||
|
||||
# Uh-oh: 'object' is neither a string nor a callable.
|
||||
else:
|
||||
|
@ -199,7 +199,7 @@ def _get_component(container, component, request, namespace_stack):
|
|||
else:
|
||||
# check for an explicit external to internal mapping
|
||||
for value in container._q_exports:
|
||||
if type(value) is types.TupleType:
|
||||
if type(value) is tuple:
|
||||
if value[0] == component:
|
||||
internal_name = value[1]
|
||||
break
|
||||
|
@ -236,7 +236,7 @@ def _get_component(container, component, request, namespace_stack):
|
|||
elif hasattr(container, "_q_resolve"):
|
||||
object = container._q_resolve(internal_name)
|
||||
if object is None:
|
||||
raise RuntimeError, ("component listed in _q_exports, "
|
||||
raise RuntimeError("component listed in _q_exports, "
|
||||
"but not returned by _q_resolve(%r)"
|
||||
% internal_name)
|
||||
else:
|
||||
|
@ -264,4 +264,4 @@ def _get_component(container, component, request, namespace_stack):
|
|||
|
||||
|
||||
def isstring(x):
|
||||
return isinstance(x, (str, unicode, htmltext))
|
||||
return isinstance(x, (str, htmltext))
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
Tools for sending mail from Quixote applications.
|
||||
"""
|
||||
import re
|
||||
from types import ListType, TupleType
|
||||
from smtplib import SMTP
|
||||
import quixote
|
||||
|
||||
|
@ -36,7 +35,7 @@ class RFC822Mailbox:
|
|||
Create a new RFC822Mailbox instance. The variety of call
|
||||
signatures is purely for your convenience.
|
||||
"""
|
||||
if (len(args) == 1 and type(args[0]) is TupleType):
|
||||
if (len(args) == 1 and type(args[0]) is tuple):
|
||||
args = args[0]
|
||||
|
||||
if len(args) == 1:
|
||||
|
@ -193,9 +192,9 @@ def sendmail(subject, msg_body, to_addrs,
|
|||
if config is not None:
|
||||
mail_debug_addr = mail_debug_addr or config.mail_debug_addr
|
||||
|
||||
if not isinstance(to_addrs, ListType):
|
||||
if not isinstance(to_addrs, list):
|
||||
raise TypeError("'to_addrs' must be a list")
|
||||
if not (cc_addrs is None or isinstance(cc_addrs, ListType)):
|
||||
if not (cc_addrs is None or isinstance(cc_addrs, list)):
|
||||
raise TypeError("'cc_addrs' must be a list or None")
|
||||
|
||||
# Make sure we have a "From" address
|
||||
|
@ -205,9 +204,9 @@ def sendmail(subject, msg_body, to_addrs,
|
|||
|
||||
# Ensure all of our addresses are really RFC822Mailbox objects.
|
||||
from_addr = _ensure_mailbox(from_addr)
|
||||
to_addrs = map(_ensure_mailbox, to_addrs)
|
||||
to_addrs = list(map(_ensure_mailbox, to_addrs))
|
||||
if cc_addrs:
|
||||
cc_addrs = map(_ensure_mailbox, cc_addrs)
|
||||
cc_addrs = list(map(_ensure_mailbox, cc_addrs))
|
||||
|
||||
# Start building the message headers.
|
||||
headers = ["From: %s" % from_addr.format(),
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#------------------------------------------------------------------------
|
||||
|
||||
import os, sys, string, socket, errno, struct
|
||||
from StringIO import StringIO
|
||||
from io import StringIO
|
||||
import cgi
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
@ -158,7 +158,7 @@ class record:
|
|||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
_lowbits = ~(1L << 31) # everything but the 31st bit
|
||||
_lowbits = ~(1 << 31) # everything but the 31st bit
|
||||
|
||||
def readPair(s, pos):
|
||||
nameLen = ord(s[pos]) ; pos = pos+1
|
||||
|
@ -174,7 +174,7 @@ def readPair(s, pos):
|
|||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
_highbit = (1L << 31)
|
||||
_highbit = (1 << 31)
|
||||
|
||||
def writePair(name, value):
|
||||
l = len(name)
|
||||
|
@ -236,7 +236,7 @@ class FCGI:
|
|||
|
||||
if 'FCGI_WEB_SERVER_ADDRS' in os.environ:
|
||||
good_addrs = string.split(os.environ['FCGI_WEB_SERVER_ADDRS'], ',')
|
||||
good_addrs = map(string.strip, good_addrs) # Remove whitespace
|
||||
good_addrs = list(map(string.strip, good_addrs)) # Remove whitespace
|
||||
else:
|
||||
good_addrs = None
|
||||
|
||||
|
@ -248,7 +248,7 @@ class FCGI:
|
|||
|
||||
# Check if the connection is from a legal address
|
||||
if good_addrs != None and addr not in good_addrs:
|
||||
raise error, 'Connection from invalid server!'
|
||||
raise error('Connection from invalid server!')
|
||||
|
||||
while remaining:
|
||||
r = record()
|
||||
|
@ -388,7 +388,8 @@ def _startup():
|
|||
s = socket.fromfd(sys.stdin.fileno(), socket.AF_INET,
|
||||
socket.SOCK_STREAM)
|
||||
s.getpeername()
|
||||
except socket.error, (err, errmsg):
|
||||
except socket.error as xxx_todo_changeme:
|
||||
(err, errmsg) = xxx_todo_changeme.args
|
||||
if err != errno.ENOTCONN: # must be a non-fastCGI environment
|
||||
_isFCGI = 0
|
||||
return
|
||||
|
@ -419,8 +420,7 @@ def _test():
|
|||
if 'CONTENT_LENGTH' in req.env:
|
||||
cl = string.atoi(req.env['CONTENT_LENGTH'])
|
||||
doc.append('<br><b>POST data (%s):</b><br><pre>' % cl)
|
||||
keys = fs.keys()
|
||||
keys.sort()
|
||||
keys = sorted(fs.keys())
|
||||
for k in keys:
|
||||
val = fs[k]
|
||||
if type(val) == type([]):
|
||||
|
@ -433,8 +433,7 @@ def _test():
|
|||
|
||||
|
||||
doc.append('<P><HR><P><pre>')
|
||||
keys = req.env.keys()
|
||||
keys.sort()
|
||||
keys = sorted(req.env.keys())
|
||||
for k in keys:
|
||||
doc.append('<b>%-20s :</b> %s\n' % (k, req.env[k]))
|
||||
doc.append('\n</pre><P><HR>\n')
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
@ -13,7 +13,7 @@ def run(create_publisher):
|
|||
response = publisher.process(sys.__stdin__, os.environ)
|
||||
try:
|
||||
response.write(sys.__stdout__)
|
||||
except IOError, err:
|
||||
except IOError as err:
|
||||
publisher.log("IOError while sending response ignored: %s" % err)
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
"""Server for Quixote applications that use FastCGI. It should work
|
||||
for CGI too but the cgi_server module is preferred as it is more
|
||||
portable.
|
||||
|
@ -13,7 +13,7 @@ def run(create_publisher):
|
|||
response = publisher.process(f.inp, f.env)
|
||||
try:
|
||||
response.write(f.out)
|
||||
except IOError, err:
|
||||
except IOError as err:
|
||||
publisher.log("IOError while sending response ignored: %s" % err)
|
||||
f.Finish()
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ def run(publisher, req):
|
|||
apache.build_cgi_env(req))
|
||||
try:
|
||||
response.write(apache.CGIStdout(req))
|
||||
except IOError, err:
|
||||
except IOError as err:
|
||||
publisher.log("IOError while sending response ignored: %s" % err)
|
||||
return apache.OK
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
"""A SCGI server that uses Quixote to publish dynamic content.
|
||||
"""
|
||||
|
||||
|
@ -30,7 +30,7 @@ class QuixoteHandler(scgi_server.SCGIHandler):
|
|||
input.close()
|
||||
output.close()
|
||||
conn.close()
|
||||
except IOError, err:
|
||||
except IOError as err:
|
||||
self.publisher.log("IOError while sending response "
|
||||
"ignored: %s" % err)
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ class HTTPRequestHandler(BaseHTTPRequestHandler):
|
|||
else:
|
||||
accept = accept + line[7:].split(',')
|
||||
env['HTTP_ACCEPT'] = ','.join(accept)
|
||||
co = filter(None, self.headers.getheaders('cookie'))
|
||||
co = [c for c in self.headers.get_all('cookie') or [] if c]
|
||||
if co:
|
||||
env['HTTP_COOKIE'] = ', '.join(co)
|
||||
env.update(self.required_cgi_environment)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
"""An HTTP server for Twisted that publishes a Quixote application.
|
||||
"""
|
||||
|
||||
|
|
|
@ -104,23 +104,21 @@ class SessionManager:
|
|||
|
||||
Return the list of session IDs of sessions in this session manager.
|
||||
"""
|
||||
return self.sessions.keys()
|
||||
return list(self.sessions.keys())
|
||||
|
||||
def sorted_keys(self):
|
||||
"""() -> [string]
|
||||
|
||||
Return the same list as keys(), but sorted.
|
||||
"""
|
||||
keys = self.keys()
|
||||
keys.sort()
|
||||
return keys
|
||||
return sorted(self.keys())
|
||||
|
||||
def values(self):
|
||||
"""() -> [Session]
|
||||
|
||||
Return the list of sessions in this session manager.
|
||||
"""
|
||||
return self.sessions.values()
|
||||
return list(self.sessions.values())
|
||||
|
||||
def items(self):
|
||||
"""() -> [(string, Session)]
|
||||
|
@ -128,7 +126,7 @@ class SessionManager:
|
|||
Return the list of (session_id, session) pairs in this session
|
||||
manager.
|
||||
"""
|
||||
return self.sessions.items()
|
||||
return list(self.sessions.items())
|
||||
|
||||
def get(self, session_id, default=None):
|
||||
"""(session_id : string, default : any = None) -> Session
|
||||
|
@ -139,7 +137,7 @@ class SessionManager:
|
|||
return self.sessions.get(session_id, default)
|
||||
|
||||
def __iter__(self):
|
||||
return self.sessions.itervalues()
|
||||
return iter(self.sessions.values())
|
||||
|
||||
def __getitem__(self, session_id):
|
||||
"""(session_id : string) -> Session
|
||||
|
@ -149,7 +147,7 @@ class SessionManager:
|
|||
"""
|
||||
return self.sessions[session_id]
|
||||
|
||||
def has_key(self, session_id):
|
||||
def __contains__(self, session_id):
|
||||
"""(session_id : string) -> boolean
|
||||
|
||||
Return true if a session identified by 'session_id' exists in
|
||||
|
@ -157,9 +155,6 @@ class SessionManager:
|
|||
"""
|
||||
return session_id in self.sessions
|
||||
|
||||
def __contains__(self, session_id):
|
||||
return self.has_key(session_id)
|
||||
|
||||
def has_session(self, session_id):
|
||||
return self.has_key(session_id)
|
||||
|
||||
|
|
|
@ -24,6 +24,6 @@ if __name__ == '__main__':
|
|||
req = HTTPRequest(None, env)
|
||||
(name, version) = req.guess_browser_version()
|
||||
if name is None:
|
||||
print "%s -> ???" % line
|
||||
print("%s -> ???" % line)
|
||||
else:
|
||||
print "%s -> (%s, %s)" % (line, name, version)
|
||||
print("%s -> (%s, %s)" % (line, name, version))
|
||||
|
|
|
@ -163,7 +163,7 @@ class StaticFile:
|
|||
# be followed
|
||||
self.path = path
|
||||
if not os.path.isabs(path):
|
||||
raise ValueError, "Path %r is not absolute" % path
|
||||
raise ValueError("Path %r is not absolute" % path)
|
||||
# Decide the Content-Type of the file
|
||||
guess_mime, guess_enc = mimetypes.guess_type(os.path.basename(path),
|
||||
strict=False)
|
||||
|
@ -174,8 +174,7 @@ class StaticFile:
|
|||
|
||||
def __call__(self):
|
||||
if not self.follow_symlinks and os.path.islink(self.path):
|
||||
raise errors.TraversalError(private_msg="Path %r is a symlink"
|
||||
% self.path)
|
||||
raise errors.TraversalError(private_msg="Path %r is a symlink" % self.path)
|
||||
request = quixote.get_request()
|
||||
response = quixote.get_response()
|
||||
|
||||
|
@ -192,7 +191,7 @@ class StaticFile:
|
|||
stat = os.stat(self.path)
|
||||
except OSError:
|
||||
raise errors.TraversalError
|
||||
last_modified = formatdate(stat.st_mtime)
|
||||
last_modified = formatdate(stat.st_mtime, usegmt=True)
|
||||
if last_modified == request.get_header('If-Modified-Since'):
|
||||
# handle exact match of If-Modified-Since header
|
||||
response.set_status(304)
|
||||
|
@ -241,7 +240,7 @@ class StaticDirectory(Directory):
|
|||
# Check that the supplied path is absolute
|
||||
self.path = path
|
||||
if not os.path.isabs(path):
|
||||
raise ValueError, "Path %r is not absolute" % path
|
||||
raise ValueError("Path %r is not absolute" % path)
|
||||
|
||||
self.use_cache = use_cache
|
||||
self.cache = {}
|
||||
|
|
|
@ -10,7 +10,7 @@ import urllib
|
|||
_server_url = None
|
||||
|
||||
testdir = os.path.dirname(__file__)
|
||||
print 'testdir is:', testdir
|
||||
print('testdir is:', testdir)
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(testdir, '..')))
|
||||
|
||||
import twill
|
||||
|
@ -53,7 +53,7 @@ def run_server(create_fn, PORT=None):
|
|||
|
||||
outfd = tempfile.mkstemp('quixote_tst')[0]
|
||||
|
||||
print 'STARTING:', sys.executable, 'tests/qx_testserver.py', os.getcwd()
|
||||
print('STARTING:', sys.executable, 'tests/qx_testserver.py', os.getcwd())
|
||||
process = subprocess.Popen([sys.executable, '-u', 'qx_testserver.py'],
|
||||
stderr=subprocess.STDOUT,
|
||||
stdout=outfd)
|
||||
|
|
|
@ -25,7 +25,7 @@ class TestServer(Directory):
|
|||
if __name__ == '__main__':
|
||||
from quixote.server.simple_server import run
|
||||
port = int(os.environ.get('QX_TEST_PORT', '8080'))
|
||||
print 'starting qx_testserver on port %d.' % (port,)
|
||||
print('starting qx_testserver on port %d.' % (port,))
|
||||
try:
|
||||
run(create_publisher, port=port)
|
||||
except KeyboardInterrupt:
|
||||
|
|
Loading…
Reference in New Issue