diff --git a/sagemath-sagenb-python3.patch b/sagemath-sagenb-python3.patch new file mode 100644 index 0000000..8ba9206 --- /dev/null +++ b/sagemath-sagenb-python3.patch @@ -0,0 +1,351 @@ +diff -up build/pkgs/sagenb/src/sagenb/flask_version/base.py.orig build/pkgs/sagenb/src/sagenb/flask_version/base.py +--- build/pkgs/sagenb/src/sagenb/flask_version/base.py.orig 2019-09-05 13:19:45.878376777 -0300 ++++ build/pkgs/sagenb/src/sagenb/flask_version/base.py 2019-09-05 13:27:08.353250002 -0300 +@@ -140,7 +140,7 @@ def localization_js(): + locale=repr(get_locale()) + if _localization_cache.get(locale,None) is None: + data = render_template(os.path.join('js/localization.js'), N_=N_, nN_=nN_) +- _localization_cache[locale] = (data, sha1(repr(data)).hexdigest()) ++ _localization_cache[locale] = (data, sha1(repr(data).encode('ascii')).hexdigest()) + data,datahash = _localization_cache[locale] + + if request.environ.get('HTTP_IF_NONE_MATCH', None) == datahash: +@@ -158,7 +158,7 @@ def mathjax_js(): + if _mathjax_js_cache is None: + from sagenb.misc.misc import mathjax_macros + data = render_template('js/mathjax_sage.js', theme_mathjax_macros=mathjax_macros) +- _mathjax_js_cache = (data, sha1(repr(data)).hexdigest()) ++ _mathjax_js_cache = (data, sha1(repr(data).encode('ascii')).hexdigest()) + data,datahash = _mathjax_js_cache + + if request.environ.get('HTTP_IF_NONE_MATCH', None) == datahash: +@@ -173,7 +173,7 @@ def mathjax_js(): + def keyboard_js(browser_os): + from sagenb.notebook.keyboards import get_keyboard + data = get_keyboard(browser_os) +- datahash=sha1(data).hexdigest() ++ datahash=sha1(str(data).encode('ascii')).hexdigest() + if request.environ.get('HTTP_IF_NONE_MATCH', None) == datahash: + response = make_response('',304) + else: +@@ -490,7 +490,7 @@ def create_app(path_to_notebook, *args, + filename = os.path.join(SRC, path) + if os.path.isfile(filename): + from cgi import escape +- src = escape(open(filename).read().decode('utf-8','ignore')) ++ src = escape(open(filename).read().decode('ascii')) + if (os.path.splitext(filename)[1] in + ['.py','.c','.cc','.h','.hh','.pyx','.pxd']): + return render_template(os.path.join('html', 'source_code.html'), +diff -up build/pkgs/sagenb/src/sagenb/misc/format.py.orig build/pkgs/sagenb/src/sagenb/misc/format.py +--- build/pkgs/sagenb/src/sagenb/misc/format.py.orig 2019-09-05 13:20:21.507608139 -0300 ++++ build/pkgs/sagenb/src/sagenb/misc/format.py 2019-09-05 13:27:08.353250002 -0300 +@@ -126,7 +126,7 @@ import sys + sys.ps1 = "%s" + print("START%s") + %s +-""" % (prompt, number, displayhook_hack(string).encode('utf-8', 'ignore')) ++""" % (prompt, number, displayhook_hack(string).encode('ascii')) + try: + string = '# -*- coding: utf-8 -*-\n' + relocate_future_imports(string) + except SyntaxError: +diff -up build/pkgs/sagenb/src/sagenb/misc/misc.py.orig build/pkgs/sagenb/src/sagenb/misc/misc.py +--- build/pkgs/sagenb/src/sagenb/misc/misc.py.orig 2019-09-05 13:20:31.231671284 -0300 ++++ build/pkgs/sagenb/src/sagenb/misc/misc.py 2019-09-05 13:27:08.354250008 -0300 +@@ -424,7 +424,7 @@ def set_permissive_permissions(filename) + stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | \ + stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP) + +-def encoded_str(obj, encoding='utf-8'): ++def encoded_str(obj, encoding='ascii'): + r""" + Takes an object and returns an encoded str human-readable representation. + +@@ -445,7 +445,7 @@ def encoded_str(obj, encoding='utf-8'): + return binary_type(obj) + + +-def unicode_str(obj, encoding='utf-8'): ++def unicode_str(obj, encoding='ascii'): + r""" + Takes an object and returns a unicode human-readable representation. + +diff -up build/pkgs/sagenb/src/sagenb/misc/support.py.orig build/pkgs/sagenb/src/sagenb/misc/support.py +--- build/pkgs/sagenb/src/sagenb/misc/support.py.orig 2019-09-05 13:20:40.258729902 -0300 ++++ build/pkgs/sagenb/src/sagenb/misc/support.py 2019-09-05 13:27:08.356250022 -0300 +@@ -279,7 +279,7 @@ def docstring(obj_name, globs, system='s + s += newline + s += sageinspect.sage_getdoc(obj, obj_name) + s = s.rstrip() +- return html_markup(s.decode('utf-8')) ++ return html_markup(s.decode('ascii')) + + + def html_markup(s): +@@ -433,7 +433,7 @@ def syseval(system, cmd, dir=None): + if hasattr(system.__class__, 'chdir'): + system.chdir(dir) + if isinstance(cmd, text_type): +- cmd = cmd.encode('utf-8', 'ignore') ++ cmd = cmd.encode('ascii') + return system.eval(cmd, sage_globals, locals=sage_globals) + + ###################################################################### +diff -up build/pkgs/sagenb/src/sagenb/misc/worksheet2rst.py.orig build/pkgs/sagenb/src/sagenb/misc/worksheet2rst.py +--- build/pkgs/sagenb/src/sagenb/misc/worksheet2rst.py.orig 2019-09-05 13:20:49.848792176 -0300 ++++ build/pkgs/sagenb/src/sagenb/misc/worksheet2rst.py 2019-09-05 13:27:08.356250022 -0300 +@@ -200,5 +200,5 @@ if __name__=='__main__': + text = sys.stdin.read() + images_dir = sys.argv[2] if len(sys.argv)>2 else '' + +- print(worksheet2rst(text, images_dir).encode('utf-8')) ++ print(worksheet2rst(text, images_dir).encode('ascii')) + +diff -up build/pkgs/sagenb/src/sagenb/notebook/challenge.py.orig build/pkgs/sagenb/src/sagenb/notebook/challenge.py +--- build/pkgs/sagenb/src/sagenb/notebook/challenge.py.orig 2019-09-05 13:20:58.515848457 -0300 ++++ build/pkgs/sagenb/src/sagenb/notebook/challenge.py 2019-09-05 13:27:08.356250022 -0300 +@@ -529,7 +529,7 @@ class reCAPTCHAChallenge(AbstractChallen + + def encode_if_necessary(s): + if isinstance(s, unicode): +- return s.encode('utf-8') ++ return s.encode('ascii') + return s + + params = urlencode({ +diff -up build/pkgs/sagenb/src/sagenb/notebook/css.py.orig build/pkgs/sagenb/src/sagenb/notebook/css.py +--- build/pkgs/sagenb/src/sagenb/notebook/css.py.orig 2019-09-05 13:21:08.792915193 -0300 ++++ build/pkgs/sagenb/src/sagenb/notebook/css.py 2019-09-05 13:27:08.357250028 -0300 +@@ -58,5 +58,5 @@ def css(color='default'): + user_css = '\n' + open(user_css_path).read() + + data = main_css + user_css +- _css_cache = (data, sha1(data).hexdigest()) ++ _css_cache = (data, sha1(str(data).encode('ascii')).hexdigest()) + return _css_cache +diff -up build/pkgs/sagenb/src/sagenb/notebook/js.py.orig build/pkgs/sagenb/src/sagenb/notebook/js.py +--- build/pkgs/sagenb/src/sagenb/notebook/js.py.orig 2019-09-05 13:21:17.511971810 -0300 ++++ build/pkgs/sagenb/src/sagenb/notebook/js.py 2019-09-05 13:27:08.357250028 -0300 +@@ -84,7 +84,7 @@ def javascript(): + if debug_mode: + # TODO: maybe we should return a random hash so that the code + # is reloaded on every refresh +- return s, sha1(s).hexdigest() ++ return s, sha1(str(s).encode('ascii')).hexdigest() + + # TODO: use minify here, which is more standard (and usually safer + # and with gzip compression, smaller); But first inquire about the +@@ -92,7 +92,7 @@ def javascript(): + # Evil" clause in the license. Does that prevent us from + # distributing it (i.e., it adds an extra condition to the + # software)? See http://www.crockford.com/javascript/jsmin.py.txt +- s = JavaScriptCompressor().getPacked(s.encode('utf-8')) ++ s = JavaScriptCompressor().getPacked(s.encode('ascii')) + _cache_javascript = (s, sha1(s).hexdigest()) + + return _cache_javascript +diff -up build/pkgs/sagenb/src/sagenb/notebook/register.py.orig build/pkgs/sagenb/src/sagenb/notebook/register.py +--- build/pkgs/sagenb/src/sagenb/notebook/register.py.orig 2019-09-05 13:21:26.247028528 -0300 ++++ build/pkgs/sagenb/src/sagenb/notebook/register.py 2019-09-05 13:27:08.358250034 -0300 +@@ -22,7 +22,7 @@ def build_msg(key, username, addr, port, + '%(url_prefix)s://%(addr)s:%(port)s/confirm?key=%(key)s\n\n' + 'You will be taken to a page which will confirm that you have indeed registered.', + url_prefix=url_prefix, addr=addr, port=port, key=key) +- return s.encode('utf-8') ++ return s.encode('ascii') + + def build_password_msg(key, username, addr, port, secure): + url_prefix = "https" if secure else "http" +@@ -31,7 +31,7 @@ def build_password_msg(key, username, ad + 'Sign in at %(url_prefix)s://%(addr)s:%(port)s/\n\n' + 'Make sure to reset your password by going to Settings in the upper right bar.', + key=key, url_prefix=url_prefix, addr=addr, port=port) +- return s.encode('utf-8') ++ return s.encode('ascii') + + def make_key(): + from random import randint +diff -up build/pkgs/sagenb/src/sagenb/notebook/smtpsend.py.orig build/pkgs/sagenb/src/sagenb/notebook/smtpsend.py +--- build/pkgs/sagenb/src/sagenb/notebook/smtpsend.py.orig 2019-09-05 13:21:35.087085930 -0300 ++++ build/pkgs/sagenb/src/sagenb/notebook/smtpsend.py 2019-09-05 13:27:08.358250034 -0300 +@@ -18,20 +18,15 @@ AUTHOR: + + Bobby Moretti + """ +-from twisted.mail import smtp, relaymanager # problematic with python 3 +-from email.mime.base import MIMEBase +-from email.mime.multipart import MIMEMultipart +-import sys +- ++from twisted.mail.smtp import sendmail ++from twisted.internet.task import react ++from email.mime.text import MIMEText + + def buildMessage(fromaddr, toaddr, subject, body): +- message = MIMEMultipart() ++ message = MIMEText(body) + message['From'] = fromaddr + message['To'] = toaddr + message['Subject'] = subject +- textPart = MIMEBase('text', 'plain') +- textPart.set_payload(body) +- message.attach(textPart) + return message + + def sendComplete(result): +@@ -42,16 +37,10 @@ def handleError(error): + + def send_mail(fromaddr, toaddr, subject, body, on_success=sendComplete, on_failure=handleError): + try: +- recpt_domain = toaddr.split('@')[1].encode("ascii") +- except (ValueError, IndexError, UnicodeDecodeError): +- raise ValueError("mal-formed destination address") +- message = buildMessage(fromaddr, toaddr, subject, body) +- messageData = message.as_string(unixfrom=False) +- +- def on_found_record(mx_rec): +- smtp_server = str(mx_rec.name) +- sending = smtp.sendmail(smtp_server, fromaddr, [toaddr], messageData) +- sending.addCallback(on_success).addErrback(on_failure) +- +- relaymanager.MXCalculator().getMX(recpt_domain).addCallback(on_found_record) ++ d = sendmail("localhost", fromaddr, toaddr, message) ++ d.addBoth(print) ++ except: ++ handleError(sys.exc_info()[0]) ++ return ++ sendComplete() + +diff -up build/pkgs/sagenb/src/sagenb/notebook/user_manager.py.orig build/pkgs/sagenb/src/sagenb/notebook/user_manager.py +--- build/pkgs/sagenb/src/sagenb/notebook/user_manager.py.orig 2019-09-05 13:21:45.143151229 -0300 ++++ build/pkgs/sagenb/src/sagenb/notebook/user_manager.py 2019-09-05 13:27:08.360250047 -0300 +@@ -461,7 +461,7 @@ class SimpleUserManager(UserManager): + if encrypt: + salt = user.generate_salt() + new_password = 'sha256${0}${1}'.format(salt, +- hashlib.sha256(salt + new_password).hexdigest()) ++ hashlib.sha256(str(salt + new_password).encode('ascii')).hexdigest()) + self._passwords[username] = new_password + # need to make sure password in the user object is synced + # for compatibility only the user object data is stored in the 'users.pickle' +diff -up build/pkgs/sagenb/src/sagenb/notebook/user.py.orig build/pkgs/sagenb/src/sagenb/notebook/user.py +--- build/pkgs/sagenb/src/sagenb/notebook/user.py.orig 2019-09-05 13:21:54.855214298 -0300 ++++ build/pkgs/sagenb/src/sagenb/notebook/user.py 2019-09-05 13:27:08.360250047 -0300 +@@ -185,7 +185,7 @@ class User(object): + if encrypt: + salt = generate_salt() + self._password = 'sha256${0}${1}'.format(salt, +- hashlib.sha256(salt + password).hexdigest()) ++ hashlib.sha256(str(salt + password).encode('ascii')).hexdigest()) + else: + self._password = password + self._temporary_password = '' +diff -up build/pkgs/sagenb/src/sagenb/notebook/worksheet.py.orig build/pkgs/sagenb/src/sagenb/notebook/worksheet.py +--- build/pkgs/sagenb/src/sagenb/notebook/worksheet.py.orig 2019-09-05 13:26:14.467900092 -0300 ++++ build/pkgs/sagenb/src/sagenb/notebook/worksheet.py 2019-09-05 13:27:08.361250054 -0300 +@@ -313,7 +313,7 @@ class Worksheet(object): + + d = {############# + # basic identification +- 'name': unicode(self.name()), ++ 'name': str(self.name().encode('ascii')), + 'id_number': int(self.id_number()), + + ############# +@@ -2157,9 +2157,9 @@ class Worksheet(object): + filename = self.worksheet_html_filename() + + if os.path.exists(filename): +- contents = open(filename).read().decode('utf-8', 'ignore') ++ contents = open(filename).read().decode('ascii') + else: +- contents = u' ' ++ contents = ' ' + + try: + r = [unicode(x.lower()) for x in [self.owner(), self.publisher(), self.name(), contents]] +@@ -2190,8 +2190,8 @@ class Worksheet(object): + if E is None: + E = self.edit_text() + worksheet_html = self.worksheet_html_filename() +- open(filename, 'w').write(bz2.compress(E.encode('utf-8', 'ignore'))) +- open(worksheet_html, 'w').write(self.body().encode('utf-8', 'ignore')) ++ open(filename, 'w').write(bz2.compress(E.encode('ascii'))) ++ open(worksheet_html, 'w').write(self.body().encode('ascii')) + self.limit_snapshots() + try: + X = self.__saved_by_info +@@ -3930,7 +3930,7 @@ except (KeyError, IOError): + """ + # The extra newline below is necessary, since otherwise source + # code introspection doesn't include the last line. +- return 'open("%s","w").write("# -*- coding: utf-8 -*-\\n" + _support_.preparse_worksheet_cell(base64.b64decode("%s"),globals())+"\\n"); execfile(os.path.abspath("%s"))'%(CODE_PY, base64.b64encode(s.encode('utf-8', 'ignore')), CODE_PY) ++ return 'open("%s","w").write("# -*- coding: utf-8 -*-\\n" + _support_.preparse_worksheet_cell(base64.b64decode("%s"),globals())+"\\n"); execfile(os.path.abspath("%s"))'%(CODE_PY, base64.b64encode(s.encode('ascii')), CODE_PY) + + ########################################################## + # Loading and attaching files +@@ -4114,7 +4114,7 @@ except (KeyError, IOError): + os.makedirs(code) + spyx = os.path.abspath(os.path.join(code, 'sage%s.spyx'%id)) + if not (os.path.exists(spyx) and open(spyx).read() == cmd): +- open(spyx,'w').write(cmd.encode('utf-8', 'ignore')) ++ open(spyx,'w').write(cmd.encode('ascii')) + return '_support_.cython_import_all("%s", globals())'%spyx + + def check_for_system_switching(self, input, cell): +diff -up build/pkgs/sagenb/src/sagenb/storage/filesystem_storage.py.orig build/pkgs/sagenb/src/sagenb/storage/filesystem_storage.py +--- build/pkgs/sagenb/src/sagenb/storage/filesystem_storage.py.orig 2019-09-05 13:22:17.198359375 -0300 ++++ build/pkgs/sagenb/src/sagenb/storage/filesystem_storage.py 2019-09-05 13:27:08.361250054 -0300 +@@ -106,7 +106,7 @@ class FilesystemDatastore(Datastore): + + def _deep_user_path(self, username): + from hashlib import md5 +- h = md5(username).hexdigest() ++ h = md5(str(username).encode('ascii')).hexdigest() + base = ['__store__', h[:1], h[:2], h[:3], h[:4]] + path = os.path.join(*base) + self._makepath(self._abspath(os.path.join(self._home_path, path))) +@@ -397,7 +397,7 @@ class FilesystemDatastore(Datastore): + # todo -- add check if changed + filename = self._worksheet_html_filename(username, id_number) + with atomic_write(self._abspath(filename)) as f: +- f.write(worksheet.body().encode('utf-8', 'ignore')) ++ f.write(str(worksheet.body())) + + def create_worksheet(self, username, id_number): + """ +@@ -548,7 +548,7 @@ class FilesystemDatastore(Datastore): + + worksheet_txt = members[0].name + W = self.load_worksheet(username, id_number) +- W.edit_save_old_format(T.extractfile(worksheet_txt).read().decode('utf-8', 'ignore')) ++ W.edit_save_old_format(T.extractfile(worksheet_txt).read().decode('ascii')) + # '/' is right, since old worksheets always unix + dir = worksheet_txt.split('/')[0] + +diff -up build/pkgs/sagenb/src/sagenb/testing/selenium/selenium.py.orig build/pkgs/sagenb/src/sagenb/testing/selenium/selenium.py +--- build/pkgs/sagenb/src/sagenb/testing/selenium/selenium.py.orig 2019-09-05 13:22:27.220424454 -0300 ++++ build/pkgs/sagenb/src/sagenb/testing/selenium/selenium.py 2019-09-05 13:27:08.361250054 -0300 +@@ -199,9 +199,9 @@ class selenium: + + def do_command(self, verb, args): + conn = http.client.HTTPConnection(self.host, self.port) +- body = u'cmd=' + urllib.quote_plus(unicode(verb).encode('utf-8')) ++ body = u'cmd=' + urllib.quote_plus(unicode(verb).encode('ascii')) + for i in range(len(args)): +- body += '&' + unicode(i+1) + '=' + urllib.quote_plus(unicode(args[i]).encode('utf-8')) ++ body += '&' + unicode(i+1) + '=' + urllib.quote_plus(unicode(args[i]).encode('ascii')) + if (None != self.sessionId): + body += "&sessionId=" + unicode(self.sessionId) + headers = {"Content-Type": "application/x-www-form-urlencoded; charset=utf-8"} +diff -up build/pkgs/sagenb/src/sagenb/data/sage/html/worksheet_listing.html.orig ./build/pkgs/sagenb/src/sagenb/data/sage/html/worksheet_listing.html +--- build/pkgs/sagenb/src/sagenb/data/sage/html/worksheet_listing.html.orig 2019-09-05 15:39:56.829175774 -0300 ++++ build/pkgs/sagenb/src/sagenb/data/sage/html/worksheet_listing.html 2019-09-05 15:40:26.822369920 -0300 +@@ -45,6 +45,7 @@ INPUT: +
$ sage -n jupyter