From defc5a33757ec611b12636bd80c030c697a3f8b2 Mon Sep 17 00:00:00 2001 From: Mark Pilgrim Date: Mon, 8 Jun 2009 15:13:47 -0400 Subject: [PATCH] match dfn terms with incoming search keywords and jump to the containing section --- j/dip3.js | 80 ++++++++++- porting-code-to-python-3-with-2to3.html | 176 ++++++++++++------------ 2 files changed, 166 insertions(+), 90 deletions(-) diff --git a/j/dip3.js b/j/dip3.js index 789a221..d557310 100644 --- a/j/dip3.js +++ b/j/dip3.js @@ -1,7 +1,69 @@ +/* + The following three functions are taken from + http://code.google.com/p/javascript-search-term-highlighter/ + Copyright 2004 Dave Lemen + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +function getSearchTerms() { + var highlighterParameters = 'q as_q as_epq as_oq query search'; + var a = new Array(); + var params = getParamValues(document.referrer/*document.location.href*/, highlighterParameters); + var terms; + for (i = 0; i < params.length; i++) { + terms = parseTerms(params[i]); + for (j = 0; j < terms.length; j++) { + if (terms[j] != '') { + a.push(terms[j].toLowerCase()); + } + } + } + return a; +} + +function parseTerms(query) { + var s = query + ''; + s = s.replace(/(^|\s)(site|related|link|info|cache):[^\s]*(\s|$)/ig, ' '); + s = s.replace(/[^a-z0-9_-]/ig, ' '); // word chars only. + s = s.replace(/(^|\s)-/g, ' '); // +required -excluded ~synonyms + s = s.replace(/\b(and|not|or)\b/ig, ' '); + s = s.replace(/\b[a-z0-9]\b/ig, ' '); // one char terms + return s.split(/\s+/); +} + +function getParamValues(url, parameters) { + var params = new Array(); + var p = parameters.replace(/,/, ' ').split(/\s+/); + if (url.indexOf('?') > 0) { + var qs = url.substr(url.indexOf('?') + 1); + var qsa = qs.split('&'); + for (i = 0; i < qsa.length; i++) { + nameValue = qsa[i].split('='); + if (nameValue.length != 2) continue; + for (j = 0; j < p.length; j++) { + if (nameValue[0] == p[j]) { + params.push(unescape(nameValue[1]).toLowerCase().replace(/\+/g, ' ')); + } + } + } + } + return params; +} + /* -"Dive Into Python 3" scripts - +The rest of this script is Copyright (c) 2009, Mark Pilgrim, All rights reserved. Redistribution and use in source and binary forms, with or without modification, @@ -92,6 +154,20 @@ $(document).ready(function() { }); }); + /* match terms with incoming search keywords and jump to the containing section */ + var searchTerms = getSearchTerms(); + $("dfn").each(function() { + var dfn = $(this); + var dfnTerm = dfn.text().toLowerCase(); + if ($.inArray(dfnTerm, searchTerms) != -1) { + var section = dfn.parents("p,table,ul,ol,blockquote").prevAll("*:header").get(0); + if (section) { + window.setTimeout(function() {document.location.hash = section.id;}, 0); + return false; + } + } + }); + }); /* document.ready */ function toggleCodeBlock(id) { diff --git a/porting-code-to-python-3-with-2to3.html b/porting-code-to-python-3-with-2to3.html index 259354d..1913a48 100644 --- a/porting-code-to-python-3-with-2to3.html +++ b/porting-code-to-python-3-with-2to3.html @@ -32,7 +32,7 @@ td pre{padding:0;border:0}

Diving in

Virtually all Python 2 programs will need at least some tweaking to run properly under Python 3. To help with this transition, Python 3 comes with a utility script called 2to3, which takes your actual Python 2 source code as input and auto-converts as much as it can to Python 3. Case study: porting chardet to Python 3 describes how to run the 2to3 script, then shows some things it can’t fix automatically. This appendix documents what it can fix automatically.

print statement

-

In Python 2, print was a statement. Whatever you wanted to print simply followed the print keyword. In Python 3, print() is a function — whatever you want to print is passed to print() like any other function. +

In Python 2, print was a statement. Whatever you wanted to print simply followed the print keyword. In Python 3, print() is a function — whatever you want to print is passed to print() like any other function.
Notes Python 2 @@ -61,7 +61,7 @@ td pre{padding:0;border:0}
  • In Python 2, you could redirect the output to a pipe — like sys.stderr — by using the >>pipe_name syntax. In Python 3, the way to do this is to pass the pipe in the file keyword argument. The file argument defaults to sys.stdout (standard out), so overriding it will output to a different pipe instead.

    Unicode string literals

    -

    Python 2 had two string types: Unicode strings and non-Unicode strings. Python 3 has one string type: Unicode strings. +

    Python 2 had two string types: Unicode strings and non-Unicode strings. Python 3 has one string type: Unicode strings.
    Notes Python 2 @@ -88,7 +88,7 @@ td pre{padding:0;border:0} str(anything)

    long data type

    -

    Python 2 had separate int and long types for non-floating-point numbers. An int could not be any larger than sys.maxint, which varied by platform. Longs were defined by appending an L to the end of the number, and they could be, well, longer than ints. In Python 3, there is only one integer type, called int, which mostly behaves like the long type in Python 2. Since there are no longer two types, there is no need for special syntax to distinguish them. +

    Python 2 had separate int and long types for non-floating-point numbers. An int could not be any larger than sys.maxint, which varied by platform. Longs were defined by appending an L to the end of the number, and they could be, well, longer than ints. In Python 3, there is only one integer type, called int, which mostly behaves like the long type in Python 2. Since there are no longer two types, there is no need for special syntax to distinguish them.

    Further reading: PEP 237: Unifying Long Integers and Integers.
    Notes @@ -135,7 +135,7 @@ td pre{padding:0;border:0}
  • A more complex comparison between three values.

    has_key() dictionary method

    -

    In Python 2, dictionaries had a has_key() method to test whether the dictionary had a certain key. In Python 3, this method no longer exists. Instead, you need to use the in operator. +

    In Python 2, dictionaries had a has_key() method to test whether the dictionary had a certain key. In Python 3, this method no longer exists. Instead, you need to use the in operator.
    Notes Python 2 @@ -164,7 +164,7 @@ td pre{padding:0;border:0}
  • This form definitely needs parentheses, since the in operator takes precedence over the + operator.

    Dictionary methods that return lists

    -

    In Python 2, many dictionary methods returned lists. The most frequently used methods were keys(), items(), and values(). In Python 3, all of these methods return dynamic views. In some contexts, this is not a problem. If the method’s return value is immediately passed to another function that iterates through the entire sequence, it makes no difference whether the actual type is a list or a view. In other contexts, it matters a great deal. If you were expecting a complete list with individually addressable elements, your code will choke, because views do not support indexing. +

    In Python 2, many dictionary methods returned lists. The most frequently used methods were keys(), items(), and values(). In Python 3, all of these methods return dynamic views. In some contexts, this is not a problem. If the method’s return value is immediately passed to another function that iterates through the entire sequence, it makes no difference whether the actual type is a list or a view. In other contexts, it matters a great deal. If you were expecting a complete list with individually addressable elements, your code will choke, because views do not support indexing.
    Notes Python 2 @@ -201,18 +201,18 @@ td pre{padding:0;border:0} Python 2 Python 3
    ① -import httplib +import httplib import http.client
    ② -import Cookie +import Cookie import http.cookies
    ③ -import cookielib +import cookielib import http.cookiejar
    ④ -
    import BaseHTTPServer
    -import SimpleHTTPServer
    -import CGIHttpServer
    +
    import BaseHTTPServer
    +import SimpleHTTPServer
    +import CGIHttpServer
    import http.server

      @@ -228,25 +228,25 @@ import CGIHttpServer
  • Python 2 Python 3
    ① -import urllib +import urllib import urllib.request, urllib.parse, urllib.error
    ② -import urllib2 +import urllib2 import urllib.request, urllib.error
    ③ -import urlparse +import urlparse import urllib.parse
    ④ -import robotparser +import robotparser import urllib.robotparser
    ⑤ -
    from urllib import FancyURLopener
    +
    from urllib import FancyURLopener
     from urllib import urlencode
    from urllib.request import FancyURLopener
     from urllib.parse import urlencode
    ⑥ -
    from urllib2 import Request
    -from urllib2 import HTTPError
    +
    from urllib2 import Request
    +from urllib2 import HTTPError
    from urllib.request import Request
     from urllib.error import HTTPError
    @@ -265,19 +265,19 @@ from urllib.error import HTTPError

  • Python 2 Python 3
    -import dbm +import dbm import dbm.ndbm
    -import gdbm +import gdbm import dbm.gnu
    -import dbhash +import dbhash import dbm.bsd
    -import dumbdbm +import dumbdbm import dbm.dumb
    -
    import anydbm
    +
    import anydbm
     import whichdb
    import dbm
    @@ -288,11 +288,11 @@ import whichdb

  • Python 2 Python 3
    -import xmlrpclib +import xmlrpclib import xmlrpc.client
    -
    import DocXMLRPCServer
    -import SimpleXMLRPCServer
    +
    import DocXMLRPCServer
    +import SimpleXMLRPCServer
    import xmlrpc.server

    Other modules

    @@ -302,7 +302,7 @@ import SimpleXMLRPCServer Python 3 ①
    try:
    -    import cStringIO as StringIO
    +    import cStringIO as StringIO
     except ImportError:
         import StringIO
    import io @@ -313,25 +313,25 @@ except ImportError: import pickle import pickle ③ -import __builtin__ +import __builtin__ import builtins ④ -import copy_reg +import copy_reg import copyreg ⑤ -import Queue +import Queue import queue ⑥ -import SocketServer +import SocketServer import socketserver ⑦ -import ConfigParser +import ConfigParser import configparserimport repr import reprlib ⑨ -import commands +import commands import subprocess
      @@ -374,7 +374,7 @@ except ImportError:
    1. To import a specific class or function from another module directly into your module’s namespace, prefix the target module with a relative path, minus the trailing slash. In this case, mbcharsetprober.py is in the same directory as universaldetector.py, so the path is a single period. You can also import form the parent directory (from ..anothermodule import AnotherClass) or a subdirectory.

    next() iterator method

    -

    In Python 2, iterators had a next() method which returned the next item in the sequence. That’s still true in Python 3, but there is now also a global next() function that takes an iterator as an argument. +

    In Python 2, iterators had a next() method which returned the next item in the sequence. That’s still true in Python 3, but there is now also a global next() function that takes an iterator as an argument.
    Notes Python 2 @@ -413,7 +413,7 @@ for an_iterator in a_sequence_of_iterators:
  • This one is a bit tricky. If you have a local variable named next, then it takes precedence over the new global next() function. In this case, you need to call the iterator’s special __next__() method to get the next item in the sequence. (Alternatively, you could also refactor the code so the local variable wasn’t named next, but 2to3 will not do that for you automatically.)

    filter() global function

    -

    In Python 2, the filter() function returned a list, the result of filtering a sequence through a function that returned True or False for each item in the sequence. In Python 3, the filter() function returns an iterator, not a list. +

    In Python 2, the filter() function returned a list, the result of filtering a sequence through a function that returned True or False for each item in the sequence. In Python 3, the filter() function returns an iterator, not a list.
    Notes Python 2 @@ -442,7 +442,7 @@ for an_iterator in a_sequence_of_iterators:
  • Again, no changes are necessary, because the list comprehension will iterate through the entire sequence, and it can do that just as well if filter() returns an iterator as if it returns a list.

    map() global function

    -

    In much the same way as filter(), the map() function now returns an iterator. (In Python 2, it returned a list.) +

    In much the same way as filter(), the map() function now returns an iterator. (In Python 2, it returned a list.)
    Notes Python 2 @@ -471,7 +471,7 @@ for an_iterator in a_sequence_of_iterators:
  • Again, no changes are necessary, because the list comprehension will iterate through the entire sequence, and it can do that just as well if map() returns an iterator as if it returns a list.

    reduce() global function (3.1+)

    -

    In Python 3, the reduce() function has been removed from the global namespace and placed in the functools module. +

    In Python 3, the reduce() function has been removed from the global namespace and placed in the functools module.
    Notes Python 2 @@ -485,7 +485,7 @@ reduce(a, b, c)

    The version of 2to3 that shipped with Python 3.0 would not fix the reduce() function automatically. The fix first appeared in the 2to3 script that shipped with Python 3.1.

    apply() global function

    -

    Python 2 had a global function called apply(), which took a function f and a list [a, b, c] and returned f(a, b, c). In Python 3, the apply() function no longer exists. Instead, there is a new function calling syntax that allows you to pass a list and have Python apply the list as the function’s arguments. +

    Python 2 had a global function called apply(), which took a function f and a list [a, b, c] and returned f(a, b, c). In Python 3, the apply() function no longer exists. Instead, there is a new function calling syntax that allows you to pass a list and have Python apply the list as the function’s arguments.
    Notes Python 2 @@ -510,7 +510,7 @@ reduce(a, b, c)
  • The 2to3 script is smart enough to convert complex apply() calls, including calling functions within imported modules.

    intern() global function

    -

    In Python 2, you could call the intern() function on a string to intern it as a performance optimization. In Python 3, the intern() function has been moved to the sys module. +

    In Python 2, you could call the intern() function on a string to intern it as a performance optimization. In Python 3, the intern() function has been moved to the sys module.
    Notes Python 2 @@ -520,7 +520,7 @@ reduce(a, b, c) sys.intern(aString)

    exec statement

    -

    Just as the print statement became a function in Python 3, so too has the exec statement. The exec() function takes a string which contains arbitrary Python code and executes it as if it were just another statement or expression. +

    Just as the print statement became a function in Python 3, so too has the exec statement. The exec() function takes a string which contains arbitrary Python code and executes it as if it were just another statement or expression.
    Notes Python 2 @@ -547,14 +547,14 @@ reduce(a, b, c) Python 2 Python 3
    -execfile('a_filename') +execfile('a_filename') exec(compile(open('a_filename').read(), 'a_filename', 'exec'))

    The version of 2to3 that shipped with Python 3.0 would not fix the execfile statement automatically. The fix first appeared in the 2to3 script that shipped with Python 3.1.

    repr literals (backticks)

    -

    In Python 2, there was a special syntax of wrapping any object in backticks (like `x`) to get a representation of the object. In Python 3, this capability still exists, but you can no longer use backticks to get it. Instead, use the global repr() function. +

    In Python 2, there was a special syntax of wrapping any object in backticks (like `x`) to get a representation of the object. In Python 3, this capability still exists, but you can no longer use backticks to get it. Instead, use the global repr() function.
    Notes Python 2 @@ -571,7 +571,7 @@ reduce(a, b, c)
  • In Python 2, backticks could be nested, leading to this sort of confusing (but valid) expression. The 2to3 tool is smart enough to convert this into nested calls to repr().

    try...except statement

    -

    The syntax for catching exceptions has changed slightly between Python 2 and Python 3. +

    The syntax for catching exceptions has changed slightly between Python 2 and Python 3.
    Notes Python 2 @@ -579,7 +579,7 @@ reduce(a, b, c)
    try:
         import mymodule
    -except ImportError, e
    +except ImportError, e
         pass
    try:
         import mymodule
    @@ -610,7 +610,7 @@ except:
     
    1. Instead of a comma after the exception type, Python 3 uses a new keyword, as.
    2. The as keyword also works for catching multiple types of exceptions at once. -
    3. If you catch an exception but don’t actually care about accessing the exception object itself, the syntax is identical between Python 2 and Python 3. +
    4. If you catch an exception but don’t actually care about accessing the exception object itself, the syntax is identical between Python 2 and Python 3.
    5. Similarly, if you use a fallback to catch all exceptions, the syntax is identical.
    @@ -623,7 +623,7 @@ except:
    Python 2 Python 3
    ① -raise MyException +raise MyException unchanged
    raise MyException, 'error message' @@ -642,7 +642,7 @@ except:
  • In Python 2, you could raise an exception with no exception class, just an error message. In Python 3, this is no longer possible. 2to3 will warn you that it was unable to fix this automatically.

    throw method on generators

    -

    In Python 2, generators have a throw() method. Calling a_generator.throw() raises an exception at the point where the generator was paused, then returns the next value yielded by the generator function. In Python 3, this functionality is still available, but the syntax is slightly different. +

    In Python 2, generators have a throw() method. Calling a_generator.throw() raises an exception at the point where the generator was paused, then returns the next value yielded by the generator function. In Python 3, this functionality is still available, but the syntax is slightly different.
    Notes Python 2 @@ -663,7 +663,7 @@ except:
  • Python 2 also supported throwing an exception with only a custom error message. Python 3 does not support this, and the 2to3 script will display a warning telling you that you will need to fix this code manually.

    xrange() global function

    -

    In Python 2, there were two ways to get a range of numbers: range(), which returned a list, and xrange(), which returned an iterator. In Python 3, range() returns an iterator, and xrange() doesn’t exist. +

    In Python 2, there were two ways to get a range of numbers: range(), which returned a list, and xrange(), which returned an iterator. In Python 3, range() returns an iterator, and xrange() doesn’t exist.
    Notes Python 2 @@ -692,7 +692,7 @@ except:
  • The sum() function will also work with an iterator, so 2to3 makes no changes here either. Like dictionary methods that return views instead of lists, this applies to min(), max(), sum(), list(), tuple(), set(), sorted(), any(), and all().

    raw_input() and input() global functions

    -

    Python 2 had two global functions for asking the user for input on the command line. The first, called input(), expected the user to enter a Python expression (and returned the result). The second, called raw_input(), just returned whatever the user typed. This was wildly confusing for beginners and widely regarded as a “wart” in the language. Python 3 excises this wart by renaming raw_input() to input(), so it works the way everyone naively expects it to work. +

    Python 2 had two global functions for asking the user for input on the command line. The first, called input(), expected the user to enter a Python expression (and returned the result). The second, called raw_input(), just returned whatever the user typed. This was wildly confusing for beginners and widely regarded as a “wart” in the language. Python 3 excises this wart by renaming raw_input() to input(), so it works the way everyone naively expects it to work.
    Notes Python 2 @@ -719,25 +719,25 @@ except: Python 2 Python 3
    ① -a_function.func_name +a_function.func_name a_function.__name__
    ② -a_function.func_doc +a_function.func_doc a_function.__doc__
    ③ -a_function.func_defaults +a_function.func_defaults a_function.__defaults__
    ④ -a_function.func_dict +a_function.func_dict a_function.__dict__
    ⑤ -a_function.func_closure +a_function.func_closure a_function.__closure__
    ⑥ -a_function.func_globals +a_function.func_globals a_function.__globals__
    ⑦ -a_function.func_code +a_function.func_code a_function.__code__

      @@ -750,7 +750,7 @@ except:
    1. The __code__ attribute (previously func_code) is a code object representing the compiled function body.

    xreadlines() I/O method

    -

    In Python 2, file objects had an xreadlines() method which returned an iterator that would read the file one line at a time. This was useful in for loops, among other places. In fact, it was so useful, later versions of Python 2 added the capability to file objects themselves. +

    In Python 2, file objects had an xreadlines() method which returned an iterator that would read the file one line at a time. This was useful in for loops, among other places. In fact, it was so useful, later versions of Python 2 added the capability to file objects themselves.
    Notes Python 2 @@ -768,7 +768,7 @@ except:

    lambda functions that take a tuple instead of multiple parameters

    -

    In Python 2, you could define anonymous lambda functions which took multiple parameters by defining the function as taking a tuple with a specific number of items. In effect, Python 2 would “unpack” the tuple into named arguments, which you could then reference (by name) within the lambda function. In Python 3, you can still pass a tuple to a lambda function, but the Python interpreter will not unpack the tuple into named arguments. Instead, you will need to reference each argument by its positional index. +

    In Python 2, you could define anonymous lambda functions which took multiple parameters by defining the function as taking a tuple with a specific number of items. In effect, Python 2 would “unpack” the tuple into named arguments, which you could then reference (by name) within the lambda function. In Python 3, you can still pass a tuple to a lambda function, but the Python interpreter will not unpack the tuple into named arguments. Instead, you will need to reference each argument by its positional index.
    Notes Python 2 @@ -799,13 +799,13 @@ except: Python 2 Python 3
    -aClassInstance.aClassMethod.im_func +aClassInstance.aClassMethod.im_func aClassInstance.aClassMethod.__func__
    -aClassInstance.aClassMethod.im_self +aClassInstance.aClassMethod.im_self aClassInstance.aClassMethod.__self__
    -aClassInstance.aClassMethod.im_class +aClassInstance.aClassMethod.im_class aClassInstance.aClassMethod.__self__.__class__

    __nonzero__ special method

    @@ -816,10 +816,10 @@ except:
    Python 3
    class A:
    -    def __nonzero__(self):
    +    def __nonzero__(self):
             pass
    class A:
    -    def __bool__(self):
    +    def __bool__(self):
             pass
    class A:
    @@ -832,7 +832,7 @@ except:
     
  • However, if you have a __nonzero__() method that takes arguments, the 2to3 tool will assume that you were using it for some other purpose, and it will not make any changes.

    Octal literals

    -

    The syntax for defining base 8 (octal) numbers has changed slightly between Python 2 and Python 3. +

    The syntax for defining base 8 (octal) numbers has changed slightly between Python 2 and Python 3.
    Notes Python 2 @@ -848,18 +848,18 @@ except: Python 2 Python 3
    ① -from sys import maxint -from sys import maxsize +from sys import maxint +from sys import maxsize
    ② -a_function(sys.maxint) -a_function(sys.maxsize) +a_function(sys.maxint) +a_function(sys.maxsize)

    1. maxint becomes maxsize.
    2. Any usage of sys.maxint becomes sys.maxsize.

    callable() global function

    -

    In Python 2, you could check whether an object was callable (like a function) with the global callable() function. In Python 3, this global function has been eliminated. To check whether an object is callable, check for the existence of the __call__() special method. +

    In Python 2, you could check whether an object was callable (like a function) with the global callable() function. In Python 3, this global function has been eliminated. To check whether an object is callable, check for the existence of the __call__() special method.
    Notes Python 2 @@ -869,7 +869,7 @@ except: hasattr(anything, '__call__')

    zip() global function

    -

    In Python 2, the global zip() function took any number of sequences and returned a list of tuples. The first tuple contained the first item from each sequence; the second tuple contained the second item from each sequence; and so on. In Python 3, zip() returns an iterator instead of a list. +

    In Python 2, the global zip() function took any number of sequences and returned a list of tuples. The first tuple contained the first item from each sequence; the second tuple contained the second item from each sequence; and so on. In Python 3, zip() returns an iterator instead of a list.
    Notes Python 2 @@ -886,7 +886,7 @@ except:
  • In contexts that already iterate through all the items of a sequence (such as this call to the join() method), the iterator that zip() returns will work just fine. The 2to3 script is smart enough to detect these cases and make no change to your code.

    StandardError exception

    -

    In Python 2, StandardError was the base class for all built-in exceptions other than StopIteration, GeneratorExit, KeyboardInterrupt, and SystemExit. In Python 3, StandardError has been eliminated; use Exception instead. +

    In Python 2, StandardError was the base class for all built-in exceptions other than StopIteration, GeneratorExit, KeyboardInterrupt, and SystemExit. In Python 3, StandardError has been eliminated; use Exception instead.
    Notes Python 2 @@ -905,22 +905,22 @@ except: Python 2 Python 3
    -types.StringType +types.StringType bytes
    -types.DictType +types.DictType dict
    -types.IntType +types.IntType int
    -types.LongType +types.LongType int
    -types.ListType +types.ListType list
    -types.NoneType +types.NoneType type(None)

    @@ -940,7 +940,7 @@ except:

    The version of 2to3 that shipped with Python 3.0 would not fix these cases of isinstance() automatically. The fix first appeared in the 2to3 script that shipped with Python 3.1.

    basestring datatype

    -

    Python 2 had two string types: Unicode and non-Unicode. But there was also another type, basestring. It was an abstract type, a superclass for both the str and unicode types. It couldn’t be called or instantiated directly, but you could pass it to the global isinstance() function to check whether an object was either a Unicode or non-Unicode string. In Python 3, there is only one string type, so basestring has no reason to exist. +

    Python 2 had two string types: Unicode and non-Unicode. But there was also another type, basestring. It was an abstract type, a superclass for both the str and unicode types. It couldn’t be called or instantiated directly, but you could pass it to the global isinstance() function to check whether an object was either a Unicode or non-Unicode string. In Python 3, there is only one string type, so basestring has no reason to exist.
    Notes Python 2 @@ -956,13 +956,13 @@ except: Python 2 Python 3
    ① -itertools.izip(a, b) +itertools.izip(a, b) zip(a, b)
    ② -itertools.imap(a, b) +itertools.imap(a, b) map(a, b)
    ③ -itertools.ifilter(a, b) +itertools.ifilter(a, b) filter(a, b)
    from itertools import imap, izip, foo @@ -981,13 +981,13 @@ except: Python 2 Python 3
    -sys.exc_type +sys.exc_type sys.exc_info()[0]
    -sys.exc_value +sys.exc_value sys.exc_info()[1]
    -sys.exc_traceback +sys.exc_traceback sys.exc_info()[2]

    List comprehensions over tuples

    @@ -1007,11 +1007,11 @@ except:
  • Python 2 Python 3
    -os.getcwdu() +os.getcwdu() os.getcwd()

    Metaclasses

    -

    In Python 2, you could create metaclasses either by defining the metaclass argument in the class declaration, or by defining a special class-level __metaclass__ attribute. In Python 3, the class-level attribute has been eliminated. +

    In Python 2, you could create metaclasses either by defining the metaclass argument in the class declaration, or by defining a special class-level __metaclass__ attribute. In Python 3, the class-level attribute has been eliminated.
    Notes Python 2 @@ -1069,8 +1069,8 @@ except: After
    -x = buffer(y) -x = memoryview(y) +x = buffer(y) +x = memoryview(y)

    Whitespace around commas (explicit)

    Despite being draconian about whitespace for indenting and outdenting, Python is actually quite liberal about whitespace in other areas. Within lists, tuples, sets, and dictionaries, whitespace can appear before and after commas with no ill effects. However, the Python style guide states that commas should be preceded by zero spaces and followed by one. Although this is purely an aesthetic issue (the code works either way, in both Python 2 and Python 3), the 2to3 script can optionally fix this for you.