[Python-modules-commits] [webpy] 01/07: Import webpy_0.38+20170615.orig.tar.gz
Wolfgang Borgert
debacle at moszumanska.debian.org
Mon Aug 21 22:07:18 UTC 2017
This is an automated email from the git hooks/post-receive script.
debacle pushed a commit to branch master
in repository webpy.
commit 8e5f710ea392ce595b2075b4420f6379da0cefe8
Author: W. Martin Borgert <debacle at debian.org>
Date: Mon Aug 21 20:53:42 2017 +0200
Import webpy_0.38+20170615.orig.tar.gz
---
.gitignore | 7 +-
.travis.yml | 9 +-
setup.py | 4 +-
test/{README => README.md} | 0
test/alltests.py | 2 +-
test/application.py | 80 +-
test/db.py | 32 +-
test/requirements.txt | 4 +-
test/requirements2.txt | 3 +-
test/session.py | 20 +-
test/template.py | 50 +
test/wsgi.py | 52 +
tools/makedoc.py | 8 +-
web/__init__.py | 30 +-
web/application.py | 143 +-
web/browser.py | 86 +-
web/db.py | 161 +-
web/debugerror.py | 28 +-
web/form.py | 41 +-
web/http.py | 19 +-
web/httpserver.py | 66 +-
web/net.py | 80 +-
web/py3helpers.py | 42 +
web/python23.py | 46 -
web/session.py | 37 +-
web/template.py | 302 ++--
web/test.py | 25 +-
web/utils.py | 260 ++-
web/webapi.py | 41 +-
web/wsgi.py | 22 +-
web/wsgiserver/__init__.py | 2226 +-----------------------
web/wsgiserver/ssl_builtin.py | 69 +-
web/wsgiserver/ssl_pyopenssl.py | 101 +-
web/wsgiserver/{__init__.py => wsgiserver2.py} | 1208 ++++++++-----
web/wsgiserver/{__init__.py => wsgiserver3.py} | 1605 +++++++++--------
35 files changed, 2654 insertions(+), 4255 deletions(-)
diff --git a/.gitignore b/.gitignore
index d0a113f..5a92924 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,7 @@
*.pyc
-.DS_Store
\ No newline at end of file
+.DS_Store
+build/
+dist/
+docs/_build/
+*.egg-info
+
diff --git a/.travis.yml b/.travis.yml
index f76de70..6053812 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,9 +2,12 @@ language: python
python:
- "2.6"
- "2.7"
-# - "3.1"
-# - "3.2"
-install: pip install -r test/requirements.txt --use-mirrors; if [ $TRAVIS_PYTHON_VERSION == 2* ] ; then pip install -r test/requirements2.txt --use-mirrors; fi
+ - "3.5"
+ - "3.6"
+ - "3.7-dev"
+install:
+ - pip install -r test/requirements.txt
+ - if [[ $TRAVIS_PYTHON_VERSION = 2* ]] ; then pip install -r test/requirements2.txt; fi
script: python test/alltests.py
before_install:
- "sudo mkdir -p /usr/include/postgresql/8.4/server"
diff --git a/setup.py b/setup.py
index 62fd74d..5b57043 100644
--- a/setup.py
+++ b/setup.py
@@ -1,8 +1,6 @@
#!/usr/bin/env python
-# ...
-
-from distutils.core import setup
+from setuptools import setup
from web import __version__
setup(name='web.py',
diff --git a/test/README b/test/README.md
similarity index 100%
rename from test/README
rename to test/README.md
diff --git a/test/alltests.py b/test/alltests.py
index 9e2ad75..f0b7d57 100644
--- a/test/alltests.py
+++ b/test/alltests.py
@@ -1,7 +1,7 @@
import webtest
def suite():
- modules = ["doctests", "db", "application", "session"]
+ modules = ["doctests", "db", "application", "session", "template", "wsgi"]
return webtest.suite(modules)
if __name__ == "__main__":
diff --git a/test/application.py b/test/application.py
index e0a7231..bcf3272 100644
--- a/test/application.py
+++ b/test/application.py
@@ -5,6 +5,13 @@ import threading
import web
import urllib
+try:
+ from urllib.parse import urlencode
+except ImportError:
+ from urllib import urlencode
+
+from web.py3helpers import PY2
+
data = """
import web
@@ -40,17 +47,17 @@ class ApplicationTest(webtest.TestCase):
import foo
app = foo.app
- self.assertEquals(app.request('/').data, 'a')
+ self.assertEquals(app.request('/').data, b'a')
# test class change
time.sleep(1)
write('foo.py', data % dict(classname='a', output='b'))
- self.assertEquals(app.request('/').data, 'b')
+ self.assertEquals(app.request('/').data, b'b')
# test urls change
time.sleep(1)
write('foo.py', data % dict(classname='c', output='c'))
- self.assertEquals(app.request('/').data, 'c')
+ self.assertEquals(app.request('/').data, b'c')
def testUppercaseMethods(self):
urls = ("/", "hello")
@@ -85,6 +92,20 @@ class ApplicationTest(webtest.TestCase):
response = app.request('/b/foo?x=2')
self.assertEquals(response.status, '301 Moved Permanently')
self.assertEquals(response.headers['Location'], 'http://0.0.0.0:8080/hello/foo?x=2')
+
+ def test_routing(self):
+ urls = (
+ "/foo", "foo"
+ )
+
+ class foo:
+ def GET(self):
+ return "foo"
+
+ app = web.application(urls, {"foo": foo})
+
+ self.assertEquals(app.request('/foo\n').data, b'not found')
+ self.assertEquals(app.request('/foo').data, b'foo')
def test_subdirs(self):
urls = (
@@ -104,13 +125,13 @@ class ApplicationTest(webtest.TestCase):
return "hello " + path
app = web.application(urls, locals())
- self.assertEquals(app.request('/blog/foo').data, 'blog foo')
- self.assertEquals(app.request('/foo').data, 'hello foo')
+ self.assertEquals(app.request('/blog/foo').data, b'blog foo')
+ self.assertEquals(app.request('/foo').data, b'hello foo')
def processor(handler):
return web.ctx.path + ":" + handler()
app.add_processor(processor)
- self.assertEquals(app.request('/blog/foo').data, '/blog/foo:blog foo')
+ self.assertEquals(app.request('/blog/foo').data, b'/blog/foo:blog foo')
def test_subdomains(self):
def create_app(name):
@@ -131,10 +152,10 @@ class ApplicationTest(webtest.TestCase):
result = app.request('/', host=host)
self.assertEquals(result.data, expected_result)
- test('a.example.com', 'a')
- test('b.example.com', 'b')
- test('c.example.com', '*')
- test('d.example.com', '*')
+ test('a.example.com', b'a')
+ test('b.example.com', b'b')
+ test('c.example.com', b'*')
+ test('d.example.com', b'*')
def test_redirect(self):
urls = (
@@ -216,24 +237,29 @@ class ApplicationTest(webtest.TestCase):
return i.file.value
else:
i = web.input()
- return repr(dict(i))
+ return repr(dict(i)).replace('u','')
app = web.application(urls, locals())
def f(name):
- path = '/?' + urllib.urlencode({"name": name.encode('utf-8')})
- self.assertEquals(app.request(path).data, repr(name))
+ path = '/?' + urlencode({"name": name.encode('utf-8')})
+ self.assertEquals(app.request(path).data.decode('utf-8'), repr(name))
f(u'\u1234')
f(u'foo')
response = app.request('/', method='POST', data=dict(name='foo'))
- self.assertEquals(response.data, "{'name': u'foo'}")
+
+ self.assertEquals(response.data, b"{'name': 'foo'}")
+
- data = '--boundary\r\nContent-Disposition: form-data; name="x"\r\nfoo\r\n--boundary\r\nContent-Disposition: form-data; name="file"; filename="a.txt"\r\nContent-Type: text/plain\r\n\r\na\r\n--boundary--\r\n'
+ data = '--boundary\r\nContent-Disposition: form-data; name="x"\r\n\r\nfoo\r\n--boundary\r\nContent-Disposition: form-data; name="file"; filename="a.txt"\r\nContent-Type: text/plain\r\n\r\na\r\n--boundary--\r\n'
headers = {'Content-Type': 'multipart/form-data; boundary=boundary'}
response = app.request('/multipart', method="POST", data=data, headers=headers)
- self.assertEquals(response.data, 'a')
+
+
+ self.assertEquals(response.data, b'a')
+
def testCustomNotFound(self):
urls_a = ("/", "a")
@@ -255,19 +281,19 @@ class ApplicationTest(webtest.TestCase):
self.assertEquals(response.status.split()[0], "404")
self.assertEquals(response.data, message)
- assert_notfound("/a/foo", "not found 1")
- assert_notfound("/b/foo", "not found")
+ assert_notfound("/a/foo", b"not found 1")
+ assert_notfound("/b/foo", b"not found")
app.notfound = lambda: web.HTTPError("404 Not Found", {}, "not found 2")
- assert_notfound("/a/foo", "not found 1")
- assert_notfound("/b/foo", "not found 2")
+ assert_notfound("/a/foo", b"not found 1")
+ assert_notfound("/b/foo", b"not found 2")
def testIter(self):
- self.assertEquals(app.request('/iter').data, 'hello, world')
- self.assertEquals(app.request('/iter?name=web').data, 'hello, web')
+ self.assertEquals(app.request('/iter').data, b'hello, world')
+ self.assertEquals(app.request('/iter?name=web').data, b'hello, web')
- self.assertEquals(app.request('/iter', method='POST').data, 'hello, world')
- self.assertEquals(app.request('/iter', method='POST', data='name=web').data, 'hello, web')
+ self.assertEquals(app.request('/iter', method='POST').data, b'hello, world')
+ self.assertEquals(app.request('/iter', method='POST', data='name=web').data, b'hello, web')
def testUnload(self):
x = web.storage(a=0)
@@ -306,8 +332,10 @@ class ApplicationTest(webtest.TestCase):
def f(path):
return app.request(path).data
- self.assertEquals(f('/?x=2'), '/?x=1')
- self.assertEquals(f('/?y=1&y=2&x=2'), '/?y=1&y=2&x=1')
+ self.assertEquals(f('/?x=2'), b'/?x=1')
+
+ p = f('/?y=1&y=2&x=2')
+ self.assertTrue(p == b'/?y=1&y=2&x=1' or p == b'/?x=1&y=1&y=2')
def test_setcookie(self):
urls = (
diff --git a/test/db.py b/test/db.py
index 5fb631c..b480218 100644
--- a/test/db.py
+++ b/test/db.py
@@ -1,7 +1,12 @@
"""DB test"""
+from __future__ import print_function
+
import webtest
import web
+from web.py3helpers import PY2
+
+
class DBTest(webtest.TestCase):
dbname = 'postgres'
driver = None
@@ -18,9 +23,10 @@ class DBTest(webtest.TestCase):
def _testable(self):
try:
webtest.setup_database(self.dbname, driver=self.driver)
+ print("Running tests for %s" % self.__class__.__name__, file=web.debug)
return True
- except ImportError, e:
- print >> web.debug, str(e), "(ignoring %s)" % self.__class__.__name__
+ except ImportError as e:
+ print(str(e), "(ignoring %s)" % self.__class__.__name__, file=web.debug)
return False
def testUnicode(self):
@@ -58,12 +64,12 @@ class DBTest(webtest.TestCase):
except:
pass
self.db.select('person')
-
+
def testNestedTransactions(self):
t1 = self.db.transaction()
self.db.insert('person', False, name='user1')
- self.assertRows(1)
-
+ self.assertRows(1)
+
t2 = self.db.transaction()
self.db.insert('person', False, name='user2')
self.assertRows(2)
@@ -94,10 +100,11 @@ class DBTest(webtest.TestCase):
assert db.select("person", where="name='b'").list()
def test_result_is_unicode(self):
+ #TODO : not sure this test has still meaning with Py3
db = webtest.setup_database(self.dbname)
self.db.insert('person', False, name='user')
name = db.select('person')[0].name
- self.assertEquals(type(name), unicode)
+ self.assertEquals(type(name), unicode if PY2 else str)
def test_result_is_true(self):
db = webtest.setup_database(self.dbname)
@@ -150,8 +157,9 @@ class SqliteTest(DBTest):
class SqliteTest_pysqlite2(SqliteTest):
driver = "pysqlite2.dbapi2"
-class MySQLTest(DBTest):
+class MySQLTest_MySQLdb(DBTest):
dbname = "mysql"
+ driver = "MySQLdb"
def setUp(self):
self.db = webtest.setup_database(self.dbname)
@@ -162,6 +170,10 @@ class MySQLTest(DBTest):
# boolean datatype is not suppoted in MySQL (at least until v5.0)
pass
+class MySQLTest_PyMySQL(MySQLTest_MySQLdb):
+ driver="pymysql"
+class MySQLTest_MySQLConnector(MySQLTest_MySQLdb):
+ driver="mysql.connector"
del DBTest
def is_test(cls):
@@ -169,15 +181,15 @@ def is_test(cls):
return inspect.isclass(cls) and webtest.TestCase in inspect.getmro(cls)
# ignore db tests when the required db adapter is not found.
-for t in globals().values():
+for t in list(globals().values()):
if is_test(t) and not t('_testable')._testable():
del globals()[t.__name__]
del t
try:
import DBUtils
-except ImportError, e:
- print >> web.debug, str(e) + "(ignoring testPooling)"
+except ImportError as e:
+ print(str(e) + "(ignoring testPooling)", file=web.debug)
if __name__ == '__main__':
webtest.main()
diff --git a/test/requirements.txt b/test/requirements.txt
index 8eae619..0d8de54 100644
--- a/test/requirements.txt
+++ b/test/requirements.txt
@@ -1,4 +1,4 @@
psycopg2
-MySQL-python
-PyGreSQL
+PyMySQL
+mysql-connector==2.1.4
DBUtils
diff --git a/test/requirements2.txt b/test/requirements2.txt
index cd3e80b..5c0a295 100644
--- a/test/requirements2.txt
+++ b/test/requirements2.txt
@@ -1,2 +1,3 @@
-pysqlite
+pysqlite; python_version >= '2.7'
MySQL-python
+PyGreSQL
diff --git a/test/session.py b/test/session.py
index 8e0e92b..7afb6b8 100644
--- a/test/session.py
+++ b/test/session.py
@@ -36,11 +36,11 @@ class SessionTest(webtest.TestCase):
def testSession(self):
b = self.app.browser()
- self.assertEquals(b.open('/count').read(), '1')
- self.assertEquals(b.open('/count').read(), '2')
- self.assertEquals(b.open('/count').read(), '3')
+ self.assertEquals(b.open('/count').read(), b'1')
+ self.assertEquals(b.open('/count').read(), b'2')
+ self.assertEquals(b.open('/count').read(), b'3')
b.open('/reset')
- self.assertEquals(b.open('/count').read(), '1')
+ self.assertEquals(b.open('/count').read(), b'1')
def testParallelSessions(self):
b1 = self.app.browser()
@@ -49,23 +49,23 @@ class SessionTest(webtest.TestCase):
b1.open('/count')
for i in range(1, 10):
- self.assertEquals(b1.open('/count').read(), str(i+1))
- self.assertEquals(b2.open('/count').read(), str(i))
+ self.assertEquals(b1.open('/count').read(), str(i+1).encode('utf8'))
+ self.assertEquals(b2.open('/count').read(), str(i).encode('utf8'))
def testBadSessionId(self):
b = self.app.browser()
- self.assertEquals(b.open('/count').read(), '1')
- self.assertEquals(b.open('/count').read(), '2')
+ self.assertEquals(b.open('/count').read(), b'1')
+ self.assertEquals(b.open('/count').read(), b'2')
cookie = b.cookiejar._cookies['0.0.0.0']['/']['webpy_session_id']
cookie.value = '/etc/password'
- self.assertEquals(b.open('/count').read(), '1')
+ self.assertEquals(b.open('/count').read(), b'1')
def testRedirect(self):
b = self.app.browser()
b.open("/redirect")
b.open("/session/request_token")
- assert b.data == '123'
+ self.assertEquals(b.data, b'123')
class DBSessionTest(SessionTest):
"""Session test with db store."""
diff --git a/test/template.py b/test/template.py
new file mode 100644
index 0000000..6fd5352
--- /dev/null
+++ b/test/template.py
@@ -0,0 +1,50 @@
+import webtest
+import web
+from web.template import SecurityError, Template
+from web.py3helpers import PY2
+
+class TestResult:
+ def __init__(self, t):
+ self.t = t
+
+ def __getattr__(self, name):
+ return getattr(self.t, name)
+
+ def __repr__(self):
+ return repr(unicode(self.t) if PY2 else str(self.t))
+
+def t(code, **keywords):
+ tmpl = Template(code, **keywords)
+ return lambda *a, **kw: TestResult(tmpl(*a, **kw))
+
+class TemplateTest(webtest.TestCase):
+ """Tests for the template security feature."""
+
+ def testPrint(self):
+ if PY2:
+ tpl = "$code:\n print 'blah'"
+ #print_function has been imported from __future__ so the print statement doesn't exist anymore
+ self.assertRaises(SyntaxError, t, tpl)
+ else:
+ tpl = "$code:\n print('blah')"
+ self.assertRaises(NameError, t(tpl))
+
+ def testRepr(self):
+ if PY2: #this feature doesn't exist in Py3 anymore
+ tpl = "$code:\n `1`"
+ self.assertRaises(SecurityError, t, tpl)
+
+ def testAttr(self):
+ tpl = '$code:\n (lambda x: x+1).func_code'
+ self.assertRaises(SecurityError, t, tpl)
+
+ tpl = '$def with (a)\n$code:\n a.b = 3'
+ self.assertRaises(SecurityError, t, tpl)
+
+ #these two should execute themselves flawlessly
+ t("$code:\n foo = {'a': 1}.items()")()
+ if not PY2:
+ t("$code:\n bar = {k:0 for k in [1,2,3]}")()
+
+if __name__ == "__main__":
+ webtest.main()
diff --git a/test/wsgi.py b/test/wsgi.py
new file mode 100644
index 0000000..e719159
--- /dev/null
+++ b/test/wsgi.py
@@ -0,0 +1,52 @@
+import webtest, web
+import threading, time
+
+class WSGITest(webtest.TestCase):
+ def test_layers_unicode(self):
+ urls = (
+ '/', 'uni',
+ )
+
+ class uni:
+ def GET(self):
+ return u"\u0C05\u0C06"
+
+ app = web.application(urls, locals())
+
+ thread = threading.Thread(target=app.run)
+ thread.start()
+ time.sleep(0.5)
+
+ b = web.browser.Browser()
+ r = b.open('/').read()
+ s = r.decode('utf8')
+ self.assertEqual(s, u"\u0C05\u0C06")
+
+ app.stop()
+ thread.join()
+
+
+ def test_layers_bytes(self):
+ urls = (
+ '/', 'bytes',
+ )
+
+ class bytes:
+ def GET(self):
+ return b'abcdef'
+
+ app = web.application(urls, locals())
+
+ thread = threading.Thread(target=app.run)
+ thread.start()
+ time.sleep(0.5)
+
+ b = web.browser.Browser()
+ r = b.open('/')
+ self.assertEqual(r.read(), b'abcdef')
+
+ app.stop()
+ thread.join()
+
+if __name__ == '__main__':
+ webtest.main()
diff --git a/tools/makedoc.py b/tools/makedoc.py
index 8573ead..6d002cd 100644
--- a/tools/makedoc.py
+++ b/tools/makedoc.py
@@ -164,8 +164,12 @@ def main(modules=None):
print '<li><a href="#%(name)s">%(name)s</a></li>' % dict(name=name)
print '</ul>'
for name in modules:
- mod = __import__(name, {}, {}, 'x')
- recurse_over(mod, name)
+ try:
+ mod = __import__(name, {}, {}, 'x')
+ recurse_over(mod, name)
+ except ImportError as e:
+ print >> sys.stderr, "Unable to import module %s (Error: %s)" % (name, e)
+ pass
print '</div>'
if __name__ == '__main__':
diff --git a/web/__init__.py b/web/__init__.py
index 670dacb..2d2f1b6 100644
--- a/web/__init__.py
+++ b/web/__init__.py
@@ -3,7 +3,7 @@
from __future__ import generators
-__version__ = "0.38"
+__version__ = "0.40-dev0"
__author__ = [
"Aaron Swartz <me at aaronsw.com>",
"Anand Chitipothu <anandology at gmail.com>"
@@ -11,23 +11,23 @@ __author__ = [
__license__ = "public domain"
__contributors__ = "see http://webpy.org/changes"
-import utils, db, net, wsgi, http, webapi, httpserver, debugerror
-import template, form
+from . import utils, db, net, wsgi, http, webapi, httpserver, debugerror
+from . import template, form
-import session
+from . import session
-from utils import *
-from db import *
-from net import *
-from wsgi import *
-from http import *
-from webapi import *
-from httpserver import *
-from debugerror import *
-from application import *
-from browser import *
+from .utils import *
+from .db import *
+from .net import *
+from .wsgi import *
+from .http import *
+from .webapi import *
+from .httpserver import *
+from .debugerror import *
+from .application import *
+#from browser import *
try:
- import webopenid as openid
+ from . import webopenid as openid
except ImportError:
pass # requires openid module
diff --git a/web/application.py b/web/application.py
index f30d322..a85b031 100644
--- a/web/application.py
+++ b/web/application.py
@@ -2,12 +2,14 @@
Web application
(from web.py)
"""
-import webapi as web
-import webapi, wsgi, utils
-import debugerror
-import httpserver
-
-from utils import lstrips, safeunicode
+from __future__ import print_function
+
+from . import webapi as web
+from . import webapi, wsgi, utils, browser
+from .debugerror import debugerror
+from . import httpserver
+from .utils import lstrips, safeunicode
+from .py3helpers import iteritems, string_types, is_iter, PY2, text_type
import sys
import urllib
@@ -15,12 +17,25 @@ import traceback
import itertools
import os
import types
-from exceptions import SystemExit
+from inspect import isclass
+
+import wsgiref.handlers
+
+try:
+ from urllib.parse import splitquery, urlencode, quote, unquote
+except ImportError:
+ from urllib import splitquery, urlencode, quote, unquote
try:
- import wsgiref.handlers
+ from importlib import reload #Since Py 3.4 reload is in importlib
except ImportError:
- pass # don't break people with old Pythons
+ try:
+ from imp import reload #Since Py 3.0 and before 3.4 reload is in imp
+ except ImportError:
+ pass #Before Py 3.0 reload is a global function
+
+from io import BytesIO
+
__all__ = [
"application", "auto_application",
@@ -39,7 +54,7 @@ class application:
... def GET(self): return "hello"
>>>
>>> app.request("/hello").data
- 'hello'
+ b'hello'
"""
def __init__(self, mapping=(), fvars={}, autoreload=None):
if autoreload is None:
@@ -131,7 +146,7 @@ class application:
...
>>> app.add_processor(hello)
>>> app.request("/web.py").data
- 'hello, web.py'
+ b'hello, web.py'
"""
self.processors.append(processor)
@@ -149,7 +164,7 @@ class application:
...
>>> response = app.request("/hello")
>>> response.data
- 'hello'
+ b'hello'
>>> response.status
'200 OK'
>>> response.headers['Content-Type']
@@ -181,10 +196,10 @@ class application:
>>> app.request('/ua', headers = {
... 'User-Agent': 'a small jumping bean/1.0 (compatible)'
... }).data
- 'your user-agent is a small jumping bean/1.0 (compatible)'
+ b'your user-agent is a small jumping bean/1.0 (compatible)'
"""
- path, maybe_query = urllib.splitquery(localpart)
+ path, maybe_query = splitquery(localpart)
query = maybe_query or ""
if 'env' in kw:
@@ -205,24 +220,27 @@ class application:
if method not in ["HEAD", "GET"]:
data = data or ''
- import StringIO
+
if isinstance(data, dict):
- q = urllib.urlencode(data)
+ q = urlencode(data)
else:
q = data
- env['wsgi.input'] = StringIO.StringIO(q)
- if not env.get('CONTENT_TYPE', '').lower().startswith('multipart/') and 'CONTENT_LENGTH' not in env:
+
+ env['wsgi.input'] = BytesIO(q.encode('utf-8'))
+ if 'CONTENT_LENGTH' not in env:
+ #if not env.get('CONTENT_TYPE', '').lower().startswith('multipart/') and 'CONTENT_LENGTH' not in env:
env['CONTENT_LENGTH'] = len(q)
response = web.storage()
def start_response(status, headers):
response.status = status
response.headers = dict(headers)
response.header_items = headers
- response.data = "".join(self.wsgifunc()(env, start_response))
+
+ data = self.wsgifunc()(env, start_response)
+ response.data = b"".join(data)
return response
def browser(self):
- import browser
return browser.AppBrowser(self)
def handle(self):
@@ -242,7 +260,7 @@ class application:
except (KeyboardInterrupt, SystemExit):
raise
except:
- print >> web.debug, traceback.format_exc()
+ print(traceback.format_exc(), file=web.debug)
raise self.internalerror()
# processors must be applied in the resvere order. (??)
@@ -258,14 +276,12 @@ class application:
# so we need to do an iteration
# and save the result for later
try:
- firstchunk = iterator.next()
+ firstchunk = next(iterator)
except StopIteration:
firstchunk = ''
return itertools.chain([firstchunk], iterator)
- def is_generator(x): return x and hasattr(x, 'next')
-
def wsgi(env, start_resp):
# clear threadlocal to avoid inteference of previous requests
self._cleanup()
@@ -277,21 +293,33 @@ class application:
raise web.nomethod()
result = self.handle_with_processors()
- if is_generator(result):
+ if is_iter(result):
result = peep(result)
else:
result = [result]
- except web.HTTPError, e:
+ except web.HTTPError as e:
result = [e.data]
- result = web.safestr(iter(result))
+ def build_result(result):
+ for r in result:
+ if PY2:
+ yield utils.safestr(r)
+ else:
+ if isinstance(r, bytes):
+ yield r
+ elif isinstance(r, string_types):
+ yield r.encode('utf-8')
+ else:
+ yield str(r).encode('utf-8')
+
+ result = build_result(result)
status, headers = web.ctx.status, web.ctx.headers
start_resp(status, headers)
def cleanup():
self._cleanup()
- yield '' # force this function to be a generator
+ yield b'' # force this function to be a generator
return itertools.chain(result, cleanup())
@@ -407,7 +435,7 @@ class application:
ctx.path = lstrips(env.get('REQUEST_URI').split('?')[0], ctx.homepath)
# Apache and CherryPy webservers unquote the url but lighttpd doesn't.
# unquote explicitly for lighttpd to make ctx.path uniform across all servers.
- ctx.path = urllib.unquote(ctx.path)
+ ctx.path = unquote(ctx.path)
if env.get('QUERY_STRING'):
ctx.query = '?' + env.get('QUERY_STRING', '')
@@ -416,11 +444,11 @@ class application:
ctx.fullpath = ctx.path + ctx.query
- for k, v in ctx.iteritems():
+ for k, v in iteritems(ctx):
# convert all string values to unicode values and replace
# malformed data with a suitable replacement marker.
- if isinstance(v, str):
- ctx[k] = v.decode('utf-8', 'replace')
+ if isinstance(v, bytes):
+ ctx[k] = v.decode('utf-8', 'replace')
# status must always be str
ctx.status = '200 OK'
@@ -437,15 +465,13 @@ class application:
tocall = getattr(cls(), meth)
return tocall(*args)
- def is_class(o): return isinstance(o, (types.ClassType, type))
-
if f is None:
raise web.notfound()
elif isinstance(f, application):
return f.handle_with_processors()
- elif is_class(f):
+ elif isclass(f):
return handle_class(f)
- elif isinstance(f, basestring):
+ elif isinstance(f, string_types):
if f.startswith('redirect '):
url = f.split(' ', 1)[1]
if web.ctx.method == "GET":
@@ -473,10 +499,10 @@ class application:
return f, None
else:
continue
- elif isinstance(what, basestring):
- what, result = utils.re_subm('^' + pat + '$', what, value)
+ elif isinstance(what, string_types):
+ what, result = utils.re_subm(r'^%s\Z' % (pat,), what, value)
else:
- result = utils.re_compile('^' + pat + '$').match(value)
+ result = utils.re_compile(r'^%s\Z' % (pat,)).match(value)
if result: # it's a match
return what, [x for x in result.groups()]
@@ -516,14 +542,22 @@ class application:
if parent:
return parent.internalerror()
elif web.config.get('debug'):
- import debugerror
- return debugerror.debugerror()
+ return debugerror()
else:
return web._InternalError()
+def with_metaclass(mcls):
+ def decorator(cls):
+ body = vars(cls).copy()
+ # clean out class body
+ body.pop('__dict__', None)
+ body.pop('__weakref__', None)
+ return mcls(cls.__name__, cls.__bases__, body)
+ return decorator
+
class auto_application(application):
"""Application similar to `application` but urls are constructed
- automatiacally using metaclass.
+ automatically using metaclass.
>>> app = auto_application()
>>> class hello(app.page):
@@ -533,9 +567,9 @@ class auto_application(application):
... path = '/foo/.*'
... def GET(self): return "foo"
>>> app.request("/hello").data
- 'hello, world'
+ b'hello, world'
>>> app.request('/foo/bar').data
- 'foo'
+ b'foo'
"""
def __init__(self):
application.__init__(self)
@@ -550,9 +584,10 @@ class auto_application(application):
if path is not None:
self.add_mapping(path, klass)
- class page:
+
+ @with_metaclass(metapage) #little hack needed or Py2 and Py3 compatibility
+ class page():
path = None
- __metaclass__ = metapage
self.page = page
@@ -571,12 +606,12 @@ class subdomain_application(application):
>>> mapping = (r"hello\.example\.com", app)
>>> app2 = subdomain_application(mapping)
>>> app2.request("/hello", host="hello.example.com").data
- 'hello'
+ b'hello'
>>> response = app2.request("/hello", host="something.example.com")
>>> response.status
'404 Not Found'
>>> response.data
- 'not found'
+ b'not found'
"""
def handle(self):
host = web.ctx.host.split(':')[0] #strip port
@@ -585,7 +620,7 @@ class subdomain_application(application):
def _match(self, mapping, value):
for pat, what in mapping:
- if isinstance(what, basestring):
+ if isinstance(what, string_types):
what, result = utils.re_subm('^' + pat + '$', what, value)
else:
result = utils.re_compile('^' + pat + '$').match(value)
@@ -621,22 +656,22 @@ def unloadhook(h):
def processor(handler):
try:
result = handler()
- is_generator = result and hasattr(result, 'next')
+ is_gen = is_iter(result)
except:
# run the hook even when handler raises some exception
h()
raise
- if is_generator:
+ if is_gen:
return wrap(result)
else:
h()
return result
def wrap(result):
- def next():
+ def next_hook():
try:
- return result.next()
+ return next(result)
except:
# call the hook at the and of iterator
h()
@@ -644,7 +679,7 @@ def unloadhook(h):
result = iter(result)
while True:
- yield next()
+ yield next_hook()
return processor
diff --git a/web/browser.py b/web/browser.py
index 66d859e..18158fb 100644
--- a/web/browser.py
+++ b/web/browser.py
@@ -1,12 +1,41 @@
"""Browser to test web applications.
(from web.py)
"""
-from utils import re_compile
-from net import htmlunquote
+from .utils import re_compile
... 10719 lines suppressed ...
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/webpy.git
More information about the Python-modules-commits
mailing list