--- build/pkgs/sagenb/src/sagenb/flask_version/worksheet_listing.py.orig	2018-01-24 04:17:47.000000000 -0700
+++ build/pkgs/sagenb/src/sagenb/flask_version/worksheet_listing.py	2018-10-17 09:36:47.843468652 -0600
@@ -2,7 +2,14 @@
 """
 from __future__ import absolute_import
 import os
-import urllib, urlparse
+
+try:
+    from urllib.request import urlopen
+    from urllib.parse import urlparse
+except ImportError:
+    from urlparse import urlparse
+    from urllib import urlopen
+
 from flask import Blueprint, url_for, render_template, request, session, redirect, g, current_app
 from .decorators import login_required, guest_or_login_required, with_lock
 from flask_babel import Babel, gettext, ngettext, lazy_gettext
--- build/pkgs/sagenb/src/sagenb/misc/misc.py.orig	2018-08-29 08:44:38.823169061 -0600
+++ build/pkgs/sagenb/src/sagenb/misc/misc.py	2018-10-17 09:39:14.346569538 -0600
@@ -19,6 +19,7 @@ Check that github issue #195 is fixed::
 #                  http://www.gnu.org/licenses/
 #############################################################################
 
+from six import text_type, binary_type
 from pkg_resources import resource_filename
 
 def stub(f):
@@ -416,6 +417,8 @@ def encoded_str(obj, encoding='utf-8'):
     r"""
     Takes an object and returns an encoded str human-readable representation.
 
+    string to bytes
+
     EXAMPLES::
 
         sage: from sagenb.misc.misc import encoded_str
@@ -426,14 +429,16 @@ def encoded_str(obj, encoding='utf-8'):
         sage: encoded_str(123)
         '123'
     """
-    if isinstance(obj, unicode):
+    if isinstance(obj, text_type):
         return obj.encode(encoding, 'ignore')
-    return str(obj)
+    return binary_type(obj)
 
 def unicode_str(obj, encoding='utf-8'):
     r"""
     Takes an object and returns a unicode human-readable representation.
 
+    (bytes or string) to string
+
     EXAMPLES::
 
         sage: from sagenb.misc.misc import unicode_str
@@ -444,11 +449,11 @@ def unicode_str(obj, encoding='utf-8'):
         sage: unicode_str(123)
         u'123'
     """
-    if isinstance(obj, str):
+    if isinstance(obj, binary_type):
         return obj.decode(encoding, 'ignore')
-    elif isinstance(obj, unicode):
+    elif isinstance(obj, text_type):
         return obj
-    return unicode(obj)
+    return text_type(obj)
         
 
 
--- build/pkgs/sagenb/src/sagenb/misc/sphinxify.py.orig	2018-06-10 13:56:16.000000000 -0600
+++ build/pkgs/sagenb/src/sagenb/misc/sphinxify.py	2018-10-17 09:42:45.846827860 -0600
@@ -19,6 +19,7 @@ AUTHORS:
 import os
 import re
 import shutil
+import six.moves
 from tempfile import mkdtemp
 
 # We import Sphinx on demand, to reduce Sage startup time.
@@ -94,9 +95,8 @@ def sphinxify(docstring, format='html'):
         suffix = '.txt'
     output_name = base_name + suffix
 
-    filed = open(rst_name, 'w')
-    filed.write(docstring)
-    filed.close()
+    with open(rst_name, 'w') as filed:
+        filed.write(docstring)
 
     # Sphinx constructor: Sphinx(srcdir, confdir, outdir, doctreedir,
     # buildername, confoverrides, status, warning, freshenv).
@@ -119,9 +119,9 @@ def sphinxify(docstring, format='html'):
     sphinx_app.build(None, [rst_name])
     sys.path = old_sys_path
 
-    #We need to remove "_" from __builtin__ that the gettext module installs
-    import __builtin__
-    __builtin__.__dict__.pop('_', None)
+    # We need to remove "_" from __builtin__ that the gettext module installs
+    from six.moves import builtins
+    builtins.__dict__.pop('_', None)
 
     if os.path.exists(output_name):
         output = open(output_name, 'r').read()
@@ -134,8 +134,8 @@ def sphinxify(docstring, format='html'):
         # to
         #    "/doc/static/reference/media/...path.../blah.png"
         output = re.sub("""src=['"](/?\.\.)*/?media/([^"']*)['"]""",
-                          'src="/doc/static/reference/media/\\2"',
-                          output)
+                        'src="/doc/static/reference/media/\\2"',
+                        output)
         # Remove spurious \(, \), \[, \].
         output = output.replace('\\(', '').replace('\\)', '').replace('\\[', '').replace('\\]', '')
     else:
@@ -481,7 +481,7 @@ skip_picklability_check_modules = [
     #'sage.misc.nested_class_test', # for test only
     'sage.misc.latex',
     'sage.misc.explain_pickle',
-    '__builtin__',
+    'builtins',
 ]
 
 def check_nested_class_picklability(app, what, name, obj, skip, options):
@@ -532,7 +532,7 @@ def skip_member(app, what, name, obj, sk
     if 'SAGE_CHECK_NESTED' in os.environ:
         check_nested_class_picklability(app, what, name, obj, skip, options)
 
-    if getattr(obj, '__module__', None) == '__builtin__':
+    if getattr(obj, '__module__', None) == 'builtins':
         return True
 
     if (hasattr(obj, '__name__') and obj.__name__.find('.') != -1 and
--- build/pkgs/sagenb/src/sagenb/misc/support.py.orig	2018-05-22 10:01:48.000000000 -0600
+++ build/pkgs/sagenb/src/sagenb/misc/support.py	2018-10-17 09:23:38.909683823 -0600
@@ -17,7 +17,7 @@ import sys
 import pydoc
 
 from six import iteritems
-import __builtin__
+import builtins
 
 try:
     from cPickle import PicklingError
@@ -467,7 +467,7 @@ def cython_import(filename, verbose=Fals
                                             use_cache=use_cache,
                                             create_local_c_file=create_local_c_file)
     sys.path.append(build_dir)
-    return __builtin__.__import__(name)
+    return builtins.__import__(name)
 
 
 def cython_import_all(filename, globals, verbose=False, compile_message=False,
--- build/pkgs/sagenb/src/sagenb/notebook/cell.py.orig	2018-08-29 08:44:38.823169061 -0600
+++ build/pkgs/sagenb/src/sagenb/notebook/cell.py	2018-10-17 09:40:11.817824538 -0600
@@ -20,6 +20,7 @@ import shutil
 import textwrap
 import time
 from cgi import escape
+from sys import maxsize
 
 from sagenb.misc.misc import (word_wrap, strip_string_literals,
                               set_restrictive_permissions, unicode_str,
@@ -701,9 +702,8 @@ class Cell(Cell_generic):
 
         # start with a random integer so that evaluations of the cell
         # from different runs have different version numbers.
-        from sys import maxint
         from random import randint
-        self._version = randint(0,maxint)
+        self._version = randint(0, maxsize)
 
     def __repr__(self):
         """
@@ -2189,9 +2189,8 @@ class Cell(Cell_generic):
         except AttributeError:
             # start with a random integer so that evaluations of the cell
             # from different runs have different version numbers.
-            from sys import maxint
             from random import randint
-            self._version = randint(0,maxint)
+            self._version = randint(0, maxsize)
             return self._version
 
     def time(self):
--- build/pkgs/sagenb/src/sagenb/notebook/docHTMLProcessor.py.orig	2018-01-24 04:17:38.000000000 -0700
+++ build/pkgs/sagenb/src/sagenb/notebook/docHTMLProcessor.py	2018-10-17 09:51:50.480773614 -0600
@@ -7,7 +7,7 @@ file.
 
 This takes an HTML document, i.e., Sage documentation, and returns it in
 the editable format (notebook worksheet format with evaluable examples). It
-also returns a string representing the CSS link for the document.  The SGML
+also returns a string representing the CSS link for the document.  The HTML
 parser is setup to return only the body of the HTML documentation page and
 to re-format Sage examples and type-setting.
 
@@ -25,7 +25,7 @@ This module contains three classes:
 
 .. NOTE:: 
 
-    This extension of sgmllib.SGMLParser was partly inspired by Mark
+    This extension of sgmllib.HTMLParser was partly inspired by Mark
     Pilgrim's 'Dive Into Python' examples.
 
 AUTHORS:
@@ -111,14 +111,14 @@ WARNING:
 #############################################################################
 from __future__ import unicode_literals
 
-from sgmllib import SGMLParser
+from html.parser import HTMLParser
 from htmlentitydefs import entitydefs
 
 from flask import Markup
 from sagenb.misc.misc import unicode_str
 
 
-class genericHTMLProcessor(SGMLParser):
+class genericHTMLProcessor(HTMLParser):
     r"""
     This class gathers the methods that are common to both classes
     :class:`sagenb.notebook.SphinxHTMLProcessor` and
@@ -155,16 +155,16 @@ class genericHTMLProcessor(SGMLParser):
             u'<h1 class="title">Title</h1>\n\n<p>nSome text</p>\n\n\n\n'
 
         """        
-        # self.feed() is a SGMLParser method and starts everything
+        # self.feed() is a HTMLParser method and starts everything
         # off; Most of the functions here are extensions to
-        # SGMLParser, and may never actually be visibly called here.
+        # HTMLParser, and may never actually be visibly called here.
 
         # This module works with unicode literals. In case that input data is
         # ascii, exceptions may occur. So, input data must be converted to
         # unicode if it were not.
         doc_in = unicode_str(doc_in)  
-        self.feed(doc_in) #SGMLParser call
-        self.close()     #SGMLParser call
+        self.feed(doc_in) #HTMLParser call
+        self.close()     #HTMLParser call
         self.hand_off_temp_pieces('to_doc_pieces')
         return self.all_pieces.replace('\\(', '').replace('\\)', '').replace('\\[', '').replace('\\]', '')
 
@@ -390,7 +390,7 @@ class genericHTMLProcessor(SGMLParser):
                 else:
                     # first occurrence of an output string
                     # write /// denoting output
-                    if output_flag == False:
+                    if output_flag is False:
                         piece += '///'
                         if p:
                             piece += '\n' + p
@@ -400,7 +400,29 @@ class genericHTMLProcessor(SGMLParser):
                         piece += p
             piece += '\n}}}\n\n'
         return Markup(piece).unescape()
-                
+
+    def handle_starttag(self, tag, attrs):
+        """
+        introduced when replacing SGMLParser by HTMLParser
+        """
+        try:
+            method = getattr(self, 'start_' + tag)
+        except AttributeError:
+            self.unknown_starttag(tag, attrs)
+        else:
+            method(attrs)
+
+    def handle_endtag(self, tag):
+        """
+        introduced when replacing SGMLParser by HTMLParser
+        """
+        try:
+            method = getattr(self, 'end_' + tag)
+        except AttributeError:
+            self.unknown_endtag(tag)
+        else:
+            method()
+ 
     ##############################################
     ## General tag handlers
     ## These just append their HTML to self.temp_pieces.
@@ -473,6 +495,7 @@ class genericHTMLProcessor(SGMLParser):
         """
         if self.keep_data:
             self.temp_pieces.append(data)
+
     def handle_charref(self, ref):
         r"""
         INPUT:
@@ -540,6 +563,7 @@ class genericHTMLProcessor(SGMLParser):
         """
         if self.keep_data:
             self.temp_pieces.append("<!--%(data)s-->" % locals())
+
     def handle_pi(self, text):
         r"""
         Handle processing instructions
@@ -585,7 +609,7 @@ class genericHTMLProcessor(SGMLParser):
         """
         if self.keep_data:
             self.temp_pieces.append("<!%(text)s>" % locals())
-        
+
     ##############################################
     ## Specific tag handlers
     def start_body(self, attrs):
@@ -634,6 +658,7 @@ class genericHTMLProcessor(SGMLParser):
             ['bunch ', 'of ', 'tmp ', 'strings'] 
         """
         pass
+
     def end_html(self):
         r"""
         INPUT:
@@ -658,7 +683,7 @@ class SphinxHTMLProcessor(genericHTMLPro
     def reset(self):
         r"""
         Initialize necessary variables.  Called by
-        :meth:`SGMLParser.__init__`.
+        :meth:`HTMLParser.__init__`.
 
         EXAMPLES::
 
@@ -685,8 +710,8 @@ class SphinxHTMLProcessor(genericHTMLPro
 
         # counters
         self.cellcount = 0
-                
-        SGMLParser.reset(self)
+
+        HTMLParser.reset(self)
 
     def false_positive_input_output_cell(self, cell_piece):
         r"""
@@ -733,7 +758,7 @@ class SphinxHTMLProcessor(genericHTMLPro
         Once we hit the <div> tag in a highlighted block,
         hand of all of the pieces we've encountered so far
         and ignore the tag.
-        
+
         INPUT:
 
         - ``attrs`` - list of tuple
@@ -835,7 +860,7 @@ class SphinxHTMLProcessor(genericHTMLPro
             self.hand_off_temp_pieces('to_cell_pieces')
             return
         self.temp_pieces.append("</div>")
-    
+
     def start_pre(self, attrs):
         r"""
         Ignore tag <pre> when inside highligh div.
@@ -1000,6 +1025,7 @@ class SphinxHTMLProcessor(genericHTMLPro
         if self.in_highlight_div:
             return
         self.unknown_starttag('span', attrs)
+
     def end_span(self):
         r"""
         Ignore all spans that occur within highlighted blocks
@@ -1095,7 +1121,7 @@ class docutilsHTMLProcessor(genericHTMLP
     def reset(self):
         r"""
         Initialize necessary variables.  Called by
-        :meth:`SGMLParser.__init__`.
+        :meth:`HTMLParser.__init__`.
 
         EXAMPLES::
 
@@ -1125,8 +1151,8 @@ class docutilsHTMLProcessor(genericHTMLP
 
         # counters
         self.cellcount = 0
-                
-        SGMLParser.reset(self)
+
+        HTMLParser.reset(self)
 
     def false_positive_input_output_cell(self, cell_piece):
         r"""
@@ -1162,7 +1188,7 @@ class docutilsHTMLProcessor(genericHTMLP
         piece = piece.replace('}','}&nbsp;')
         piece += '\n</pre>'
         return piece
-    
+
     #############################################
     ## Specific tag handlers
     ##
--- build/pkgs/sagenb/src/sagenb/notebook/notebook.py.orig	2018-05-22 10:16:28.000000000 -0600
+++ build/pkgs/sagenb/src/sagenb/notebook/notebook.py	2018-10-17 09:41:05.937122985 -0600
@@ -1268,7 +1268,7 @@ class Notebook(object):
             W.set_not_computing()
 
     def quit(self):
-        for W in self.__worksheets.values():
+        for W in list(self.__worksheets.values()):
             W.quit()
 
     def update_worksheet_processes(self):
--- build/pkgs/sagetex/src/extractsagecode.py.orig	2015-08-26 17:28:42.000000000 -0600
+++ build/pkgs/sagetex/src/extractsagecode.py	2018-10-16 15:51:25.115052207 -0600
@@ -45,8 +45,8 @@ See the SageTeX documentation for more d
 
 try:
   opts, args = getopt.getopt(sys.argv[1:], 'ho', ['help', 'overwrite'])
-except getopt.GetoptError, err:
-  print str(err)
+except getopt.GetoptError as err:
+  print(str(err))
   usage()
   sys.exit(2)
 
--- build/pkgs/sagetex/src/makestatic.py.orig	2015-08-26 17:28:42.000000000 -0600
+++ build/pkgs/sagetex/src/makestatic.py	2018-10-16 15:52:13.282441276 -0600
@@ -45,8 +45,8 @@ See the SageTeX documentation for more d
 
 try:
   opts, args = getopt.getopt(sys.argv[1:], 'ho', ['help', 'overwrite'])
-except getopt.GetoptError, err:
-  print str(err)
+except getopt.GetoptError as err:
+  print(str(err))
   usage()
   sys.exit(2)
 
--- build/pkgs/sagetex/src/remote-sagetex.py.orig	2015-08-26 17:28:42.000000000 -0600
+++ build/pkgs/sagetex/src/remote-sagetex.py	2018-10-16 15:53:14.073670222 -0600
@@ -24,12 +24,11 @@
 ## You should have received a copy of the GNU General Public License along
 ## with this program.  If not, see <http://www.gnu.org/licenses/>.
 ## 
-from __future__ import print_function
 import json
 import sys
 import time
 import re
-import urllib
+import urllib.request, urllib.parse, urllib.error
 import hashlib
 import os
 import os.path
@@ -156,7 +155,7 @@ class RemoteSage:
                                    '\n*(?P<output>.*)', re.DOTALL)
         self._404 = re.compile('404 Not Found')
         self._session = self._get_url('login',
-                                    urllib.urlencode({'username': user,
+                                    urllib.parse.urlencode({'username': user,
                                     'password':
                                     password}))['session']
         self._codewrap = """try:
@@ -176,10 +175,10 @@ except:
             _p_.save(filename=plotfilename, **kwargs)""")
 
     def _encode(self, d):
-        return 'session={0}&'.format(self._session) + urllib.urlencode(d)
+        return 'session={0}&'.format(self._session) + urllib.parse.urlencode(d)
 
     def _get_url(self, action, u):
-        with closing(urllib.urlopen(self._srv + '/simple/' + action +
+        with closing(urllib.request.urlopen(self._srv + '/simple/' + action +
                                     '?' + u)) as h:
             data = self._response.match(h.read())
             result = json.loads(data.group('header'))
@@ -187,7 +186,7 @@ except:
         return result
 
     def _get_file(self, fn, cell, ofn=None):
-        with closing(urllib.urlopen(self._srv + '/simple/' + 'file' + '?' +
+        with closing(urllib.request.urlopen(self._srv + '/simple/' + 'file' + '?' +
                      self._encode({'cell': cell, 'file': fn}))) as h:
             myfn = ofn if ofn else fn
             data = h.read()
@@ -277,13 +276,13 @@ if login_info_file:
                     password = get_val(line)
 
 if not server:
-    server = raw_input('Enter server: ')
+    server = input('Enter server: ')
 
 if not server.startswith('http'):
     server = 'https://' + server
 
 if not username:
-    username = raw_input('Enter username: ')
+    username = input('Enter username: ')
 
 if not password:
     from getpass import getpass
--- build/pkgs/sagetex/src/run-sagetex-if-necessary.py.orig	2015-08-26 17:28:42.000000000 -0600
+++ build/pkgs/sagetex/src/run-sagetex-if-necessary.py	2018-10-16 15:53:46.501258922 -0600
@@ -58,7 +58,7 @@ with open(src + '.tex') as texf:
             break
 
 if not uses_sagetex:
-    print src + ".tex doesn't seem to use SageTeX, exiting."
+    print(src + ".tex doesn't seem to use SageTeX, exiting.")
     sys.exit(0)
 
 # if something goes wrong, assume we need to run Sage
@@ -72,7 +72,7 @@ try:
             if not re.search(ignore, line):
                 h.update(line)
 except IOError:
-    print '{0}.sagetex.sage not found, I think you need to typeset {0}.tex first.'.format(src)
+    print('{0}.sagetex.sage not found, I think you need to typeset {0}.tex first.'.format(src))
     sys.exit(1)
 
 try:
@@ -80,8 +80,8 @@ try:
         for line in outf:
             m = re.match('%([0-9a-f]+)% md5sum', line)
             if m:
-                print 'computed md5:', h.hexdigest()
-                print 'sagetex.sout md5:', m.group(1)
+                print('computed md5:', h.hexdigest())
+                print('sagetex.sout md5:', m.group(1))
                 if h.hexdigest() == m.group(1):
                     run_sage = False
                     break
@@ -89,7 +89,7 @@ except IOError:
     pass
 
 if run_sage:
-    print 'Need to run Sage on {0}.'.format(src)
+    print('Need to run Sage on {0}.'.format(src))
     sys.exit(subprocess.call([path_to_sage, src + '.sagetex.sage']))
 else:
-    print 'Not necessary to run Sage on {0}.'.format(src)
+    print('Not necessary to run Sage on {0}.'.format(src))
--- build/pkgs/sagetex/src/sagetexparse.py.orig	2015-08-26 17:28:42.000000000 -0600
+++ build/pkgs/sagetex/src/sagetexparse.py	2018-10-16 15:54:08.097984998 -0600
@@ -52,7 +52,7 @@ class SoutParser():
     try:
       OneOrMore(parselabel).parseFile(fn)
     except IOError:
-      print 'Error accessing %s; exiting. Does your .sout file exist?' % fn
+      print('Error accessing %s; exiting. Does your .sout file exist?' % fn)
       sys.exit(1)
   def newlabel(self, s, l, t):
     self.label.append(t.result[1:-1])
--- build/pkgs/sagetex/src/sagetex.py.orig	2015-08-26 17:28:42.000000000 -0600
+++ build/pkgs/sagetex/src/sagetex.py	2018-10-16 15:54:27.882734058 -0600
@@ -73,10 +73,10 @@ from your current version of Sage; see
 http://www.sagemath.org/doc/installation/sagetex.html.""".format(jobname,
   version, pyversion)
       if version_check:
-        raise VersionError, errstr
+        raise VersionError(errstr)
       else:
-        print '**** WARNING! Skipping version check for .sty and .py files, and'
-        print errstr
+        print('**** WARNING! Skipping version check for .sty and .py files, and')
+        print(errstr)
     if ' ' in jobname:
       jobname = jobname.strip('"')
     self.progress('Processing Sage code for {0}.tex...'.format(jobname))
@@ -116,7 +116,7 @@ http://www.sagemath.org/doc/installation
       elif labelname == 'sagecmdline':
           pass # output message already printed
       else:
-          raise ValueError, 'inline() got a bad labelname "{0}"'.format(labelname)
+          raise ValueError('inline() got a bad labelname "{0}"'.format(labelname))
       self.souttmp.write(r'\newlabel{@' + labelname + str(counter) +
                          '}{{%\n' + s.rstrip() + '}{}{}{}{}}\n')
   def savecmd(self, s):
@@ -178,7 +178,7 @@ http://www.sagemath.org/doc/installation
                            latex(result),
                            r' \end{displaymath}']
           except SyntaxError:
-              exec preparse(splitup[i][2]) in globals, locals
+              exec(preparse(splitup[i][2]), globals, locals)
       self.inline(counter, '\n'.join(tex_strs))
   def commandline(self, counter, s, globals, locals, text_output):
       self.progress('Sage commandline {0} (line {1})'.format(counter, self.current_tex_line))
@@ -208,7 +208,7 @@ http://www.sagemath.org/doc/installation
                                   latex(result) +
                                   r'\end{displaymath}')
           except SyntaxError:
-              exec preparse(splitup[i][2]) in globals, locals
+              exec(preparse(splitup[i][2]), globals, locals)
       if 'displaymath' not in tex_strs[-1]:
           tex_strs.append(skip)
       self.inline(counter, '\n'.join(tex_strs), labelname='sagecmdline')
@@ -233,8 +233,8 @@ http://www.sagemath.org/doc/installation
           except ValueError as inst:
               if re.match('filetype .*not supported by save', str(inst)):
                   newfilename = plotfilename[:-3] + 'png'
-                  print '  saving {0} failed; saving to {1} instead.'.format(
-                                                    plotfilename, newfilename)
+                  print('  saving {0} failed; saving to {1} instead.'.format(
+                                                    plotfilename, newfilename))
                   _p_.save(filename=newfilename, **kwargs)
                   break
               else:
@@ -248,11 +248,11 @@ http://www.sagemath.org/doc/installation
       '{0}/plot-{1}.{2}'.format(self.plotdir, counter, ext), \
       '{0}/plot-{1}.eps'.format(self.plotdir, counter)])
   def goboom(self, line):
-    print('\n**** Error in Sage code on line {0} of {1}.tex! Traceback\
- follows.'.format(line, self.filename))
+    print(('\n**** Error in Sage code on line {0} of {1}.tex! Traceback\
+ follows.'.format(line, self.filename)))
     traceback.print_exc()
-    print('\n**** Running Sage on {0}.sage failed! Fix {0}.tex and try\
- again.'.format(self.filename))
+    print(('\n**** Running Sage on {0}.sage failed! Fix {0}.tex and try\
+ again.'.format(self.filename)))
     self.souttmp.close()
     os.remove(self.filename + '.sagetex.sout.tmp')
     self.scmdtmp.close()
--- src/doc/common/conf.py.orig	2018-08-03 05:10:08.000000000 -0600
+++ src/doc/common/conf.py	2018-10-17 09:25:21.876352155 -0600
@@ -504,7 +504,7 @@ skip_picklability_check_modules = [
     #'sage.misc.nested_class_test', # for test only
     'sage.misc.latex',
     'sage.misc.explain_pickle',
-    '__builtin__',
+    'builtins',
 ]
 
 def check_nested_class_picklability(app, what, name, obj, skip, options):
@@ -553,7 +553,7 @@ def skip_member(app, what, name, obj, sk
     if 'SAGE_CHECK_NESTED' in os.environ:
         check_nested_class_picklability(app, what, name, obj, skip, options)
 
-    if getattr(obj, '__module__', None) == '__builtin__':
+    if getattr(obj, '__module__', None) == 'builtins':
         return True
 
     objname = getattr(obj, "__name__", None)
--- src/sage/arith/long.pxd.orig	2018-08-03 05:10:08.000000000 -0600
+++ src/sage/arith/long.pxd	2018-10-16 11:34:30.788518682 -0600
@@ -19,7 +19,7 @@ from cpython.object cimport Py_SIZE
 from cpython.int cimport PyInt_AS_LONG
 from cpython.long cimport PyLong_AsLong
 from cpython.number cimport PyNumber_Index, PyIndex_Check
-from cpython.longintrepr cimport PyLongObject, PyLong_SHIFT, digit
+from cpython.longintrepr cimport py_long, PyLong_SHIFT, digit
 
 from sage.libs.gmp.mpz cimport mpz_fits_slong_p, mpz_get_si
 from sage.rings.integer_fake cimport is_Integer, Integer_AS_MPZ
@@ -208,7 +208,7 @@ cdef inline bint integer_check_long_py(x
         return 0
 
     # x is a Python "long" (called "int" on Python 3)
-    cdef const digit* D = (<PyLongObject*>x).ob_digit
+    cdef const digit* D = (<py_long>x).ob_digit
     cdef Py_ssize_t size = Py_SIZE(x)
 
     # We assume that PyLong_SHIFT is 15 on a 32-bit system and 30 on a
--- src/sage/combinat/finite_state_machine.py.orig	2018-08-03 05:10:08.000000000 -0600
+++ src/sage/combinat/finite_state_machine.py	2018-10-17 08:18:20.455010671 -0600
@@ -938,6 +938,7 @@ from six import itervalues
 from six.moves import zip_longest
 
 import collections
+import collections.abc
 import itertools
 
 import sage
@@ -14143,7 +14144,7 @@ def is_FSMProcessIterator(PI):
 
 
 class FSMProcessIterator(sage.structure.sage_object.SageObject,
-                         collections.Iterator):
+                         collections.abc.Iterator):
     """
     This class takes an input, feeds it into a finite state machine
     (automaton or transducer, in particular), tests whether this was
--- src/sage/cpython/dict_del_by_value.pyx.orig	2018-08-03 05:10:08.000000000 -0600
+++ src/sage/cpython/dict_del_by_value.pyx	2018-10-14 20:42:23.000000000 -0600
@@ -347,8 +347,8 @@ ELIF PY_VERSION_HEX>=0x03060000:
         cdef MyPyDictKeysObject * keys = <MyPyDictKeysObject *>(mp.ma_keys)
         cdef size_t perturb
         cdef size_t mask = <size_t> keys.dk_size-1
-        cdef PyDictKeyEntry *entries, *ep
-        entries = DK_ENTRIES(keys)
+        cdef PyDictKeyEntry *ep
+        cdef PyDictKeyEntry *entries = DK_ENTRIES(keys)
 
         if mp.ma_values != NULL:
             print ("del_dictitem_by_exact_value cannot be applied to a shared key dict")
--- src/sage/geometry/polyhedron/backend_cdd.py.orig	2018-08-03 05:10:08.000000000 -0600
+++ src/sage/geometry/polyhedron/backend_cdd.py	2018-10-16 15:47:39.662235848 -0600
@@ -49,7 +49,7 @@ class Polyhedron_cdd(Polyhedron_base):
         """
         from .cdd_file_format import cdd_Vrepresentation
         s = cdd_Vrepresentation(self._cdd_type, vertices, rays, lines)
-        self._init_from_cdd_input(s, '--reps', verbose)
+        self._init_from_cdd_input(s, b'--reps', verbose)
 
 
     def _init_from_Hrepresentation(self, ieqs, eqns, verbose=False):
@@ -78,7 +78,7 @@ class Polyhedron_cdd(Polyhedron_base):
         """
         from .cdd_file_format import cdd_Hrepresentation
         s = cdd_Hrepresentation(self._cdd_type, ieqs, eqns)
-        self._init_from_cdd_input(s, '--reps', verbose)
+        self._init_from_cdd_input(s, b'--reps', verbose)
 
 
     def _init_facet_adjacency_matrix(self, verbose=False):
@@ -103,7 +103,7 @@ class Polyhedron_cdd(Polyhedron_base):
             [1 1 0]
         """
         self._init_from_cdd_input(self.cdd_Hrepresentation(),
-                                  '--adjacency', verbose)
+                                  b'--adjacency', verbose)
 
 
     def _init_vertex_adjacency_matrix(self, verbose=False):
@@ -128,7 +128,7 @@ class Polyhedron_cdd(Polyhedron_base):
             [1 1 0]
         """
         self._init_from_cdd_input(self.cdd_Vrepresentation(),
-                                  '--adjacency', verbose)
+                                  b'--adjacency', verbose)
 
 
     def _init_from_cdd_input(self, cdd_input_string, cmdline_arg='--all', verbose=False):
--- src/sage/graphs/generators/families.py.orig	2018-08-03 05:10:08.000000000 -0600
+++ src/sage/graphs/generators/families.py	2018-10-17 09:30:21.545476230 -0600
@@ -3144,7 +3144,7 @@ def MuzychukS6Graph(n, d, Phi='fixed', S
     from sage.rings.integer_ring import ZZ
     from time import time
     import itertools
-    from __builtin__ import range # we cannot use xrange here
+    from six.moves import range # we cannot use xrange here
 
     assert d > 1,              'd must be at least 2'
     assert is_even(n * (d-1)), 'n must be even or d must be odd'
--- src/sage/libs/gap/util.pyx.orig	2018-08-03 05:10:08.000000000 -0600
+++ src/sage/libs/gap/util.pyx	2018-10-16 15:27:53.043771756 -0600
@@ -171,7 +171,7 @@ def gap_root():
         return GAP_ROOT_DIR
     print('The gap-4.5.5.spkg (or later) seems to be not installed!')
     gap_sh = open(os.path.join(SAGE_LOCAL, 'bin', 'gap')).read().splitlines()
-    gapdir = filter(lambda dir:dir.strip().startswith('GAP_DIR'), gap_sh)[0]
+    gapdir = next(filter(lambda dir:dir.strip().startswith('GAP_DIR'), gap_sh))
     gapdir = gapdir.split('"')[1]
     gapdir = gapdir.replace('$SAGE_LOCAL', SAGE_LOCAL)
     return gapdir
--- src/sage/libs/gmp/pylong.pyx.orig	2018-08-03 05:10:08.000000000 -0600
+++ src/sage/libs/gmp/pylong.pyx	2018-10-16 11:45:44.610884365 -0600
@@ -28,7 +28,7 @@ AUTHORS:
 from cpython.object cimport Py_SIZE
 from cpython.int cimport PyInt_FromLong
 from cpython.long cimport PyLong_FromLong
-from cpython.longintrepr cimport _PyLong_New, PyLongObject, digit, PyLong_SHIFT
+from cpython.longintrepr cimport py_long, _PyLong_New, digit, PyLong_SHIFT
 from .mpz cimport *
 
 cdef extern from *:
@@ -54,7 +54,7 @@ cdef mpz_get_pylong_large(mpz_srcptr z):
     cdef size_t nbits = mpz_sizeinbase(z, 2)
     cdef size_t pylong_size = (nbits + PyLong_SHIFT - 1) // PyLong_SHIFT
     L = _PyLong_New(pylong_size)
-    mpz_export((<PyLongObject*>L).ob_digit, NULL,
+    mpz_export(L.ob_digit, NULL,
             -1, sizeof(digit), 0, PyLong_nails, z)
     if mpz_sgn(z) < 0:
         # Set correct size (use a pointer to hack around Cython's
@@ -91,7 +91,7 @@ cdef int mpz_set_pylong(mpz_ptr z, L) ex
     if pylong_size < 0:
         pylong_size = -pylong_size
     mpz_import(z, pylong_size, -1, sizeof(digit), 0, PyLong_nails,
-            (<PyLongObject*>L).ob_digit)
+            (<py_long>L).ob_digit)
     if Py_SIZE(L) < 0:
         mpz_neg(z, z)
 
--- src/sage/misc/parser.pyx.orig	2018-08-03 05:10:09.000000000 -0600
+++ src/sage/misc/parser.pyx	2018-10-14 20:18:28.000000000 -0600
@@ -96,7 +96,7 @@ def token_to_str(int token):
 
 
 cdef inline bint is_alphanumeric(char c):
-    return 'a' <= c <= 'z' or 'A' <= c <= 'Z' or '0' <= c <= '9' or c == '_'
+    return c'a' <= c <= c'z' or c'A' <= c <= c'Z' or c'0' <= c <= c'9' or c == c'_'
 
 cdef inline bint is_whitespace(char c):
     return (c != 0) & (strchr(" \t\n\r", c) != NULL)
@@ -247,23 +247,23 @@ cdef class Tokenizer:
             return EOS
 
         # dipthongs
-        if s[pos+1] == '=':
-            if s[pos] == '<':
+        if s[pos+1] == c'=':
+            if s[pos] == c'<':
                 self.pos += 2
                 return LESS_EQ
-            elif s[pos] == '>':
+            elif s[pos] == c'>':
                 self.pos += 2
                 return GREATER_EQ
-            elif s[pos] == '!':
+            elif s[pos] == c'!':
                 self.pos += 2
                 return NOT_EQ
-            elif s[pos] == '=':
+            elif s[pos] == c'=':
                 self.pos += 2
-                return '='
+                return c'='
 
-        elif s[pos] == '*' and s[pos+1] == '*':
+        elif s[pos] == c'*' and s[pos+1] == c'*':
             self.pos += 2
-            return '^'
+            return c'^'
 
         # simple tokens
         if strchr("+-*/^()=<>,[]{}!", s[pos]):
@@ -272,29 +272,29 @@ cdef class Tokenizer:
             return type
 
         # numeric literals
-        if '0' <= s[pos] <= '9' or s[pos] == '.':
+        if c'0' <= s[pos] <= c'9' or s[pos] == c'.':
             type = INT
             seen_exp = False
             seen_decimal = False
             while True:
-                if '0' <= s[pos] <= '9':
+                if c'0' <= s[pos] <= c'9':
                     pass
-                elif s[pos] == '.':
+                elif s[pos] == c'.':
                     if seen_decimal or seen_exp:
                         self.pos = pos
                         return type
                     else:
                         type = FLOAT
                         seen_decimal = True
-                elif s[pos] == 'e' or s[pos] == 'E':
+                elif s[pos] == c'e' or s[pos] == c'E':
                     if seen_exp:
                         self.pos = pos
                         return type
                     else:
                         type = FLOAT
                         seen_exp = True
-                elif s[pos] == '+' or s[pos] == '-':
-                    if not (seen_exp and (s[pos-1] == 'e' or s[pos-1] == 'E')):
+                elif s[pos] == c'+' or s[pos] == c'-':
+                    if not (seen_exp and (s[pos-1] == c'e' or s[pos-1] == c'E')):
                         self.pos = pos
                         return type
                 else:
@@ -573,13 +573,13 @@ cdef class Parser:
         """
         cdef int token
         all = []
-        if tokens.next() == '(':
-            token = ','
-            while token == ',':
+        if tokens.next() == c'(':
+            token = c','
+            while token == c',':
                 all.append(self.p_list(tokens))
                 token = tokens.next()
 
-            if token == ')':
+            if token == c')':
                 from sage.matrix.constructor import matrix
                 return matrix(all)
             else:
@@ -601,8 +601,8 @@ cdef class Parser:
             [(1, 2, 3), [a + 1, b + 2, c + 3, (d + 4,)]]
         """
         all = []
-        cdef int token = ','
-        while token == ',':
+        cdef int token = c','
+        while token == c',':
             token = tokens.peek()
             if token == MATRIX:
                 tokens.next()
@@ -615,14 +615,14 @@ cdef class Parser:
                 else:
                     tokens.backtrack()
                     obj = self.p_eqn(tokens)
-            elif token == '[':
+            elif token == c'[':
                 obj = self.p_list(tokens)
-            elif token == '(':
+            elif token == c'(':
                 obj = self.p_tuple(tokens)
             elif token == EOS:
                 return all
-            elif token == ']' or token == ')':
-                tokens.token = ','
+            elif token == c']' or token == c')':
+                tokens.token = c','
                 return all
             else:
                 obj = self.p_eqn(tokens)
@@ -646,11 +646,11 @@ cdef class Parser:
             []
         """
         cdef int token = tokens.next()
-        if token != '[':
+        if token != c'[':
             self.parse_error(tokens, "Malformed list")
         all = self.p_sequence(tokens)
         token = tokens.next()
-        if token != ']':
+        if token != c']':
             self.parse_error(tokens, "Malformed list")
         return all
 
@@ -668,20 +668,20 @@ cdef class Parser:
         cdef int start = tokens.pos
         cdef int token = tokens.next()
         cdef bint real_tuple = True
-        if token != '(':
+        if token != c'(':
             self.parse_error(tokens, "Malformed tuple")
         all = self.p_sequence(tokens)
         if len(all) == 1:
             if tokens.last() != c',':
                 real_tuple = False
         token = tokens.next()
-        if token != ')':
+        if token != c')':
             self.parse_error(tokens, "Malformed tuple")
         if real_tuple:
             return tuple(all)
         else:
             token = tokens.peek()
-            if token == ',' or token == EOS:
+            if token == c',' or token == EOS:
                 return all[0]
             else:
                 # we have to reparse the entire thing as an expression
@@ -717,15 +717,15 @@ cdef class Parser:
         """
         lhs = self.p_expr(tokens)
         cdef int op = tokens.next()
-        if op == '=':
+        if op == c'=':
             return lhs == self.p_expr(tokens)
         elif op == NOT_EQ:
             return lhs != self.p_expr(tokens)
-        elif op == '<':
+        elif op == c'<':
             return lhs < self.p_expr(tokens)
         elif op == LESS_EQ:
             return lhs <= self.p_expr(tokens)
-        elif op == '>':
+        elif op == c'>':
             return lhs > self.p_expr(tokens)
         elif op == GREATER_EQ:
             return lhs >= self.p_expr(tokens)
@@ -757,9 +757,9 @@ cdef class Parser:
         cdef int op
         operand1 = self.p_term(tokens)
         op = tokens.next()
-        while op == '+' or op == '-':
+        while op == c'+' or op == c'-':
             operand2 = self.p_term(tokens)
-            if op == '+':
+            if op == c'+':
                 operand1 = operand1 + operand2
             else:
                 operand1 = operand1 - operand2
@@ -792,17 +792,17 @@ cdef class Parser:
         operand1 = self.p_factor(tokens)
         op = tokens.next()
         if op == NAME and self.implicit_multiplication:
-            op = '*'
+            op = c'*'
             tokens.backtrack()
-        while op == '*' or op == '/':
+        while op == c'*' or op == c'/':
             operand2 = self.p_factor(tokens)
-            if op == '*':
+            if op == c'*':
                 operand1 = operand1 * operand2
             else:
                 operand1 = operand1 / operand2
             op = tokens.next()
             if op == NAME and self.implicit_multiplication:
-                op = '*'
+                op = c'*'
                 tokens.backtrack()
         tokens.backtrack()
         return operand1
@@ -826,9 +826,9 @@ cdef class Parser:
             t^11
         """
         cdef int token = tokens.next()
-        if token == '+':
+        if token == c'+':
             return self.p_factor(tokens)
-        elif token == '-':
+        elif token == c'-':
             return -self.p_factor(tokens)
         else:
             tokens.backtrack()
@@ -862,13 +862,13 @@ cdef class Parser:
         """
         operand1 = self.p_atom(tokens)
         cdef int token = tokens.next()
-        if token == '^':
+        if token == c'^':
             operand2 = self.p_factor(tokens)
             return operand1 ** operand2
-        elif token == "!":
+        elif token == c'!':
             from sage.functions.all import factorial
             operand1 = factorial(operand1)
-            if tokens.peek() == '^':
+            if tokens.peek() == c'^':
                 tokens.next()
                 operand2 = self.p_factor(tokens)
                 return operand1 ** operand2
@@ -913,20 +913,20 @@ cdef class Parser:
         elif token == NAME:
             name = tokens.last_token_string()
             token = tokens.next()
-            if token == '(':
+            if token == c'(':
                 func = self.callable_constructor(name)
                 args, kwds = self.p_args(tokens)
                 token = tokens.next()
-                if token != ')':
+                if token != c')':
                     self.parse_error(tokens, "Bad function call")
                 return func(*args, **kwds)
             else:
                 tokens.backtrack()
                 return self.variable_constructor(name)
-        elif token == '(':
+        elif token == c'(':
             expr = self.p_expr(tokens)
             token = tokens.next()
-            if token != ')':
+            if token != c')':
                 self.parse_error(tokens, "Mismatched parentheses")
             return expr
         else:
@@ -948,10 +948,10 @@ cdef class Parser:
         """
         args = []
         kwds = {}
-        if tokens.peek() == ')':
+        if tokens.peek() == c')':
             return args, kwds
-        cdef int token = ','
-        while token == ',':
+        cdef int token = c','
+        while token == c',':
             arg = self.p_arg(tokens)
             if isinstance(arg, tuple):
                 name, value = arg
@@ -993,11 +993,11 @@ cdef class Parser:
 
         """
         cdef int token = tokens.next()
-        if token == NAME and tokens.peek() == '=':
+        if token == NAME and tokens.peek() == c'=':
             name = tokens.last_token_string()
             tokens.next()
             return name, self.p_expr(tokens)
-        if token == "[" :
+        if token == c'[' :
             tokens.backtrack()
             return self.p_list(tokens)
         else:
--- src/sage/plot/plot3d/plot3d.py.orig	2018-08-03 05:10:09.000000000 -0600
+++ src/sage/plot/plot3d/plot3d.py	2018-10-17 09:03:00.049705941 -0600
@@ -188,7 +188,8 @@ class _Coordinates(object):
             Arbitrary Coordinates coordinate transform (z in terms of x, y)
         """
         import inspect
-        all_vars=inspect.getargspec(self.transform).args[1:]
+        args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = inspect.getfullargspec(self.transform)
+        all_vars=args[1:]
         if set(all_vars) != set(indep_vars + [dep_var]):
             raise ValueError('variables were specified incorrectly for this coordinate system; incorrect variables were %s'%list(set(all_vars).symmetric_difference(set(indep_vars+[dep_var]))))
         self.dep_var = dep_var
--- src/sage/plot/point.py.orig	2018-08-03 05:10:09.000000000 -0600
+++ src/sage/plot/point.py	2018-10-17 09:54:36.767621593 -0600
@@ -29,7 +29,7 @@ TESTS::
 from sage.misc.decorators import options, rename_keyword
 from sage.plot.colors import to_mpl_color
 from sage.plot.primitive import GraphicPrimitive_xydata
-import collections
+import collections.abc
 
 
 # TODO: create _allowed_options for 3D point classes to
@@ -343,7 +343,7 @@ def point(points, **kwds):
         sage: point(iter([(1,2),(3,5)]))
         Graphics object consisting of 1 graphics primitive
     """
-    if isinstance(points, collections.Iterator):
+    if isinstance(points, collections.abc.Iterator):
         points = list(points)
 
     try:
--- src/sage/repl/display/fancy_repr.py.orig	2018-08-03 05:10:09.000000000 -0600
+++ src/sage/repl/display/fancy_repr.py	2018-10-17 13:37:25.606376556 -0600
@@ -15,7 +15,7 @@ Representations of objects.
 import types
 
 from IPython.lib.pretty import (
-    _safe_getattr, _baseclass_reprs,
+    _safe_getattr,
     _type_pprinters,
 )
 
@@ -264,7 +264,7 @@ class PlainPythonRepr(ObjectReprABC):
         """
         klass = _safe_getattr(obj, '__class__', None) or type(obj)
         klass_repr = _safe_getattr(klass, '__repr__', None)
-        if klass_repr in _baseclass_reprs:
+        if klass_repr is object.__repr__:
             p.text(klass_repr(obj))
         else:
             # A user-provided repr. Find newlines and replace them with p.break_()
--- src/sage/repl/ipython_kernel/interact.py.orig	2018-08-03 05:10:09.000000000 -0600
+++ src/sage/repl/ipython_kernel/interact.py	2018-10-16 15:22:52.943730034 -0600
@@ -36,7 +36,7 @@ EXAMPLES::
 from ipywidgets.widgets import SelectionSlider, ValueWidget, ToggleButtons
 from ipywidgets.widgets.interaction import interactive, signature
 from copy import copy
-from collections import Iterable, Iterator
+from collections.abc import Iterable, Iterator
 from .widgets import EvalText, SageColorPicker
 from sage.structure.element import parent
 from sage.symbolic.ring import SR
--- src/sage/rings/integer.pyx.orig	2018-08-03 05:10:09.000000000 -0600
+++ src/sage/rings/integer.pyx	2018-10-15 14:15:05.631285493 -0600
@@ -6933,7 +6933,7 @@ cdef int mpz_set_str_python(mpz_ptr z, c
     while x[0] == c' ': x += 1  # Strip spaces
 
     # Disallow a sign here
-    if x[0] == '-' or x[0] == '+':
+    if x[0] == c'-' or x[0] == c'+':
         x = ""  # Force an error below
 
     assert base >= 2
--- src/sage/rings/real_mpfi.pyx.orig	2018-08-03 05:10:09.000000000 -0600
+++ src/sage/rings/real_mpfi.pyx	2018-10-15 14:22:32.912750377 -0600
@@ -1951,12 +1951,12 @@ cdef class RealIntervalFieldElement(Ring
 
         cdef long digits
         digits = strlen(lower_s)
-        if lower_s[0] == '-':
+        if lower_s[0] == c'-':
             digits -= 1
         lower_expo -= digits
 
         digits = strlen(upper_s)
-        if upper_s[0] == '-':
+        if upper_s[0] == c'-':
             digits -= 1
         upper_expo -= digits
 
@@ -2125,7 +2125,7 @@ cdef class RealIntervalFieldElement(Ring
             raise MemoryError("Unable to allocate memory for the mantissa of an interval")
         mpz_get_str(tmp_cstr, base, lower_mpz)
         digits = strlen(tmp_cstr)
-        if tmp_cstr[0] == '-':
+        if tmp_cstr[0] == c'-':
             digits -= 1
             mant_string = bytes_to_str(tmp_cstr+1)
             sign_string = bytes_to_str(b'-')
--- src/sage_setup/docbuild/ext/multidocs.py.orig	2018-08-29 08:36:07.829487630 -0600
+++ src/sage_setup/docbuild/ext/multidocs.py	2018-10-16 15:59:34.604773328 -0600
@@ -239,7 +239,7 @@ def write_citations(app, citations):
     """
     from sage.misc.temporary_file import atomic_write
     outdir = citation_dir(app)
-    with atomic_write(os.path.join(outdir, CITE_FILENAME)) as f:
+    with atomic_write(os.path.join(outdir, CITE_FILENAME), binary=True) as f:
         cPickle.dump(citations, f)
     app.info("Saved pickle file: %s" % CITE_FILENAME)
 
--- src/sage/symbolic/expression.pyx.orig	2018-08-03 05:10:09.000000000 -0600
+++ src/sage/symbolic/expression.pyx	2018-10-15 14:25:08.769821636 -0600
@@ -12920,7 +12920,7 @@ cdef class hold_class:
             sage: SR(2)^5
             32
         """
-        g_set_state('hold', True)
+        g_set_state(b'hold', True)
 
     def __exit__(self, *args):
         """
@@ -12933,7 +12933,7 @@ cdef class hold_class:
             sage: SR(2)^5
             32
         """
-        g_set_state('hold', False)
+        g_set_state(b'hold', False)
 
     def start(self):
         """
--- src/setup.py.orig	2018-08-29 08:35:19.955079610 -0600
+++ src/setup.py	2018-10-16 08:24:24.587609650 -0600
@@ -284,6 +284,7 @@ class sage_build_cython(Command):
             cdivision=True,
             embedsignature=True,
             fast_getattr=True,
+            language_level=3,
             preliminary_late_includes_cy28=True,
             profile=self.profile,
         )
