diff --git a/applications/admin/controllers/pythonanywhere.py b/applications/admin/controllers/pythonanywhere.py
index e61b06ab..d9989cee 100644
--- a/applications/admin/controllers/pythonanywhere.py
+++ b/applications/admin/controllers/pythonanywhere.py
@@ -5,7 +5,7 @@ import re
import gzip
import tarfile
from gluon.contrib.simplejsonrpc import ServerProxy
-from gluon._compat import StringIO, ProtocolError
+from gluon._compat import StringIO, ProtocolError, urlencode, urllib2
def deploy():
response.title = T('Deploy to pythonanywhere')
@@ -26,9 +26,8 @@ def create_account():
except ProtocolError as error:
pass
- import urllib, urllib2
url = 'https://www.pythonanywhere.com/api/web2py/create_account'
- data = urllib.urlencode(request.vars)
+ data = urlencode(request.vars)
req = urllib2.Request(url, data)
try:
diff --git a/applications/welcome/views/layout.html b/applications/welcome/views/layout.html
index ab477415..9f664c45 100644
--- a/applications/welcome/views/layout.html
+++ b/applications/welcome/views/layout.html
@@ -39,7 +39,7 @@
web2py
-
+
{{for _item in response.menu or []:}}
{{if len(_item)<4 or not _item[3]:}}
diff --git a/gluon/contrib/login_methods/rpx_account.py b/gluon/contrib/login_methods/rpx_account.py
index dcfdc114..e79d17df 100644
--- a/gluon/contrib/login_methods/rpx_account.py
+++ b/gluon/contrib/login_methods/rpx_account.py
@@ -13,12 +13,11 @@
import os
import re
-import urllib
from gluon import *
from gluon.tools import fetch
from gluon.storage import Storage
import json
-
+from gluon._compat import urlencode
class RPXAccount(object):
@@ -83,7 +82,7 @@ class RPXAccount(object):
token = request.post_vars.token or request.get_vars.token
if token:
user = Storage()
- data = urllib.urlencode(
+ data = urlencode(
dict(apiKey=self.api_key, token=token))
auth_info_json = fetch(self.auth_url + '?' + data)
auth_info = json.loads(auth_info_json)
diff --git a/gluon/contrib/login_methods/saml2_auth.py b/gluon/contrib/login_methods/saml2_auth.py
index 462d9845..ea650463 100644
--- a/gluon/contrib/login_methods/saml2_auth.py
+++ b/gluon/contrib/login_methods/saml2_auth.py
@@ -104,11 +104,12 @@ def obj2dict(obj, processed=None):
types.BuiltinFunctionType,
types.BuiltinMethodType))
-def saml2_handler(session, request, config_filename = None):
+def saml2_handler(session, request, config_filename = None, entityid = None):
config_filename = config_filename or os.path.join(request.folder,'private','sp_conf')
client = Saml2Client(config_file = config_filename)
- idps = client.metadata.with_descriptor("idpsso")
- entityid = idps.keys()[0]
+ if not entityid:
+ idps = client.metadata.with_descriptor("idpsso")
+ entityid = idps.keys()[0]
bindings = [BINDING_HTTP_REDIRECT, BINDING_HTTP_POST]
binding, destination = client.pick_binding(
"single_sign_on_service", bindings, "idpsso", entity_id=entityid)
@@ -119,7 +120,7 @@ def saml2_handler(session, request, config_filename = None):
if not request.vars.SAMLResponse:
req_id, req = client.create_authn_request(destination, binding=binding)
relay_state = web2py_uuid().replace('-','')
- session.saml_outstanding_queries = {req_id: request.url}
+ session.saml_outstanding_queries = {req_id: request.url}
session.saml_req_id = req_id
http_args = client.apply_binding(binding, str(req), destination,
relay_state=relay_state)
@@ -145,7 +146,7 @@ class Saml2Auth(object):
username=lambda v:v['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn'][0],
email=lambda v:v['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn'][0],
user_id=lambda v:v['http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn'][0],
- ), logout_url=None, change_password_url=None):
+ ), logout_url=None, change_password_url=None, entityid=None):
self.config_file = config_file
self.maps = maps
@@ -154,9 +155,12 @@ class Saml2Auth(object):
# URL to let users change their password in the IDP system
self.saml_change_password_url = change_password_url
+
+ # URL to specify an IDP if using federation metadata or an MDQ
+ self.entityid = entityid
def login_url(self, next="/"):
- d = saml2_handler(current.session, current.request)
+ d = saml2_handler(current.session, current.request, entityid=self.entityid)
if 'url' in d:
redirect(d['url'])
elif 'error' in d:
diff --git a/gluon/html.py b/gluon/html.py
index 73eae9b8..4adf287c 100644
--- a/gluon/html.py
+++ b/gluon/html.py
@@ -1419,20 +1419,21 @@ class LINK(DIV):
class SCRIPT(DIV):
- tag = 'script'
+ tag = b'script'
+ tagname = to_bytes(tag)
def xml(self):
(fa, co) = self._xml()
- fa = to_native(fa)
+ fa = to_bytes(fa)
# no escaping of subcomponents
- co = '\n'.join([str(component) for component in
+ co = b'\n'.join([to_bytes(component) for component in
self.components])
if co:
#
# return '<%s%s>%s>' % (self.tag, fa, co, self.tag)
- return '<%s%s>%s>' % (self.tag, fa, co, self.tag)
+ return b'<%s%s>%s>' % (self.tagname, fa, co, self.tagname)
else:
return DIV.xml(self)
@@ -1440,18 +1441,19 @@ class SCRIPT(DIV):
class STYLE(DIV):
tag = 'style'
+ tagname = to_bytes(tag)
def xml(self):
(fa, co) = self._xml()
- fa = to_native(fa)
+ fa = to_bytes(fa)
# no escaping of subcomponents
- co = '\n'.join([str(component) for component in
+ co = b'\n'.join([to_bytes(component) for component in
self.components])
if co:
#
- return '<%s%s>%s>' % (self.tag, fa, co, self.tag)
+ return b'<%s%s>%s>' % (self.tagname, fa, co, self.tagname)
else:
return DIV.xml(self)
diff --git a/gluon/scheduler.py b/gluon/scheduler.py
index 710815db..79d22c0f 100644
--- a/gluon/scheduler.py
+++ b/gluon/scheduler.py
@@ -525,7 +525,7 @@ class MetaScheduler(threading.Thread):
self.have_heartbeat = True # set to False to kill
self.empty_runs = 0
- def async(self, task):
+ def local_async(self, task):
"""Start the background process.
Args:
@@ -913,7 +913,7 @@ class Scheduler(MetaScheduler):
self.w_stats.empty_runs = 0
self.w_stats.status = RUNNING
self.w_stats.total += 1
- self.wrapped_report_task(task, self.async(task))
+ self.wrapped_report_task(task, self.local_async(task))
if not self.w_stats.status == DISABLED:
self.w_stats.status = ACTIVE
else:
diff --git a/gluon/sqlhtml.py b/gluon/sqlhtml.py
index aef106ff..b4ba4051 100644
--- a/gluon/sqlhtml.py
+++ b/gluon/sqlhtml.py
@@ -15,12 +15,11 @@ Holds:
"""
import datetime
-import urllib
import re
import copy
import os
-from gluon._compat import StringIO, unichr, urllib_quote, iteritems, basestring, long, unicodeT, to_native, to_unicode
+from gluon._compat import StringIO, unichr, urllib_quote, iteritems, basestring, long, unicodeT, to_native, to_unicode, urlencode
from gluon.http import HTTP, redirect
from gluon.html import XmlComponent, truncate_string
from gluon.html import XML, SPAN, TAG, A, DIV, CAT, UL, LI, TEXTAREA, BR, IMG
@@ -3550,7 +3549,7 @@ class SQLTABLE(TABLE):
if ref.find('.') >= 0:
tref, fref = ref.split('.')
if hasattr(sqlrows.db[tref], '_primarykey'):
- href = '%s/%s?%s' % (linkto, tref, urllib.urlencode({fref: r}))
+ href = '%s/%s?%s' % (linkto, tref, urlencode({fref: r}))
r = A(represent(field, r, record), _href=str(href))
elif field.represent:
if field not in repr_cache:
@@ -3561,7 +3560,7 @@ class SQLTABLE(TABLE):
elif linkto and hasattr(field._table, '_primarykey')\
and fieldname in field._table._primarykey:
# have to test this with multi-key tables
- key = urllib.urlencode(dict([
+ key = urlencode(dict([
((tablename in record
and isinstance(record, Row)
and isinstance(record[tablename], Row)) and
diff --git a/gluon/tests/test_html.py b/gluon/tests/test_html.py
index 26693efb..4cca19e2 100644
--- a/gluon/tests/test_html.py
+++ b/gluon/tests/test_html.py
@@ -340,18 +340,20 @@ class TestBareHelpers(unittest.TestCase):
def test_SCRIPT(self):
self.assertEqual(SCRIPT('<>', _a='1', _b='2').xml(),
- '''''')
self.assertEqual(SCRIPT('<>').xml(),
- '''''')
self.assertEqual(SCRIPT().xml(), b'')
+ self.assertEqual(SCRIPT(';').xml() + DIV().xml(),
+ b'')
def test_STYLE(self):
self.assertEqual(STYLE('<>', _a='1', _b='2').xml(),
- '')
+ b'')
# Try to hit : return DIV.xml(self)
self.assertEqual(STYLE().xml(), b'')
diff --git a/gluon/tools.py b/gluon/tools.py
index 716dafcd..c138242d 100644
--- a/gluon/tools.py
+++ b/gluon/tools.py
@@ -12,7 +12,7 @@ Auth, Mail, PluginManager and various utilities
import base64
from functools import reduce
-from gluon._compat import pickle, thread, urllib2, Cookie, StringIO
+from gluon._compat import pickle, thread, urllib2, Cookie, StringIO, urlencode
from gluon._compat import configparser, MIMEBase, MIMEMultipart, MIMEText, Header
from gluon._compat import Encoders, Charset, long, urllib_quote, iteritems
from gluon._compat import to_bytes, to_native, add_charset
@@ -27,7 +27,6 @@ import time
import fnmatch
import traceback
import smtplib
-import urllib
import email.utils
import random
import hmac
@@ -873,7 +872,7 @@ class Recaptcha(DIV):
and len(recaptcha_challenge_field)):
self.errors['captcha'] = self.error_message
return False
- params = urllib.urlencode({
+ params = urlencode({
'privatekey': private_key,
'remoteip': remoteip,
'challenge': recaptcha_challenge_field,
@@ -1026,7 +1025,7 @@ class Recaptcha2(DIV):
if not recaptcha_response_field:
self.errors['captcha'] = self.error_message
return False
- params = urllib.urlencode({
+ params = urlencode({
'secret': self.private_key,
'remoteip': remoteip,
'response': recaptcha_response_field,
@@ -4738,7 +4737,7 @@ def fetch(url, data=None, headers=None,
user_agent='Mozilla/5.0'):
headers = headers or {}
if data is not None:
- data = urllib.urlencode(data)
+ data = urlencode(data)
if user_agent:
headers['User-agent'] = user_agent
headers['Cookie'] = ' '.join(
diff --git a/scripts/access.wsgi b/scripts/access.wsgi
index 86285070..8cc6b40b 100644
--- a/scripts/access.wsgi
+++ b/scripts/access.wsgi
@@ -35,11 +35,17 @@
#
URL_CHECK_ACCESS = 'http://127.0.0.1:8002/%(app)s/default/check_access'
+PY2 = sys.version_info[0] == 2
def allow_access(environ,host):
+ if PY2:
+ import urllib2
+ from urllib import urlencode
+ else:
+ from urllib import request as urllib2
+ from urllib.parse import urlencode
+
import os
- import urllib
- import urllib2
import datetime
header = '%s @ %s ' % (datetime.datetime.now(),host) + '='*20
pprint = '\n'.join('%s:%s' % item for item in environ.items())
@@ -56,7 +62,7 @@ def allow_access(environ,host):
if key.startswith('HTTP_'):
headers[key[5:]] = environ[key] # this passes the cookies through!
try:
- data = urllib.urlencode({'request_uri':environ['REQUEST_URI']})
+ data = urlencode({'request_uri':environ['REQUEST_URI']})
request = urllib2.Request(URL_CHECK_ACCESS % dict(app=app),data,headers)
response = urllib2.urlopen(request).read().strip().lower()
if response.startswith('true'): return True
diff --git a/scripts/tickets2db.py b/scripts/tickets2db.py
index ecb1b4cd..da499483 100755
--- a/scripts/tickets2db.py
+++ b/scripts/tickets2db.py
@@ -31,7 +31,7 @@ hashes = {}
while 1:
if request.tickets_db:
- print "You're storing tickets yet in database"
+ print("You're storing tickets yet in database")
sys.exit(1)
for file in os.listdir(errors_path):
diff --git a/scripts/tickets2slack.py b/scripts/tickets2slack.py
index 692dce2b..c9d181bb 100755
--- a/scripts/tickets2slack.py
+++ b/scripts/tickets2slack.py
@@ -22,7 +22,7 @@ import json
try:
import requests
except ImportError as e:
- print "missing module 'Requests', aborting."
+ print("missing module 'Requests', aborting.")
sys.exit(1)
from gluon import URL
diff --git a/scripts/zip_static_files.py b/scripts/zip_static_files.py
index 57054e5b..170ef12a 100644
--- a/scripts/zip_static_files.py
+++ b/scripts/zip_static_files.py
@@ -14,7 +14,7 @@ def zip_static(filelist=[]):
extension = os.path.splitext(fi)
extension = len(extension) > 1 and extension[1] or None
if not extension or extension not in ALLOWED_EXTS:
- print 'skipping %s' % os.path.basename(fi)
+ print('skipping %s' % os.path.basename(fi))
continue
fstats = os.stat(fi)
atime, mtime = fstats.st_atime, fstats.st_mtime
@@ -23,10 +23,10 @@ def zip_static(filelist=[]):
zstats = os.stat(gfi)
zatime, zmtime = zstats.st_atime, zstats.st_mtime
if zatime == atime and zmtime == mtime:
- print 'skipping %s, already gzipped to the latest version' % os.path.basename(fi)
+ print('skipping %s, already gzipped to the latest version' % os.path.basename(fi))
continue
- print 'gzipping %s to %s' % (
- os.path.basename(fi), os.path.basename(gfi))
+ print('gzipping %s to %s' % (
+ os.path.basename(fi), os.path.basename(gfi)))
f_in = open(fi, 'rb')
f_out = gzip.open(gfi, 'wb')
f_out.writelines(f_in)
@@ -36,7 +36,7 @@ def zip_static(filelist=[]):
saved = fstats.st_size - os.stat(gfi).st_size
tsave += saved
- print 'saved %s KB' % (int(tsave) / 1000.0)
+ print('saved %s KB' % (int(tsave) / 1000.0))
if __name__ == '__main__':
ALLOWED_EXTS = ['.css', '.js']