Import python3.9_3.9.1-4.debian.tar.xz
authorMatthias Klose <doko@debian.org>
Fri, 5 Feb 2021 13:46:56 +0000 (13:46 +0000)
committerMatthias Klose <doko@debian.org>
Fri, 5 Feb 2021 13:46:56 +0000 (13:46 +0000)
[dgit import tarball python3.9 3.9.1-4 python3.9_3.9.1-4.debian.tar.xz]

149 files changed:
2to3-3.1 [new file with mode: 0644]
FAQ.html [new file with mode: 0644]
PVER-dbg.README.Debian.in [new file with mode: 0644]
PVER-dbg.overrides.in [new file with mode: 0644]
PVER-dbg.postinst.in [new file with mode: 0644]
PVER-dbg.prerm.in [new file with mode: 0644]
PVER-doc.doc-base.PVER-api.in [new file with mode: 0644]
PVER-doc.doc-base.PVER-dist.in [new file with mode: 0644]
PVER-doc.doc-base.PVER-ext.in [new file with mode: 0644]
PVER-doc.doc-base.PVER-inst.in [new file with mode: 0644]
PVER-doc.doc-base.PVER-lib.in [new file with mode: 0644]
PVER-doc.doc-base.PVER-new.in [new file with mode: 0644]
PVER-doc.doc-base.PVER-ref.in [new file with mode: 0644]
PVER-doc.doc-base.PVER-tut.in [new file with mode: 0644]
PVER-doc.info.in [new file with mode: 0644]
PVER-doc.overrides.in [new file with mode: 0644]
PVER-examples.overrides.in [new file with mode: 0644]
PVER-minimal.README.Debian.in [new file with mode: 0644]
PVER-minimal.overrides.in [new file with mode: 0644]
PVER-minimal.postinst.in [new file with mode: 0644]
PVER-minimal.postrm.in [new file with mode: 0644]
PVER-minimal.preinst.in [new file with mode: 0644]
PVER-minimal.prerm.in [new file with mode: 0644]
PVER-venv.overrides.in [new file with mode: 0644]
PVER-venv.postinst.in [new file with mode: 0644]
PVER-venv.postrm.in [new file with mode: 0644]
PVER-venv.prerm.in [new file with mode: 0644]
PVER.desktop.in [new file with mode: 0644]
PVER.overrides.in [new file with mode: 0644]
PVER.postinst.in [new file with mode: 0644]
PVER.prerm.in [new file with mode: 0644]
README.Debian.in [new file with mode: 0644]
README.PVER.in [new file with mode: 0644]
README.Tk [new file with mode: 0644]
README.dbm [new file with mode: 0644]
README.idle-PVER.in [new file with mode: 0644]
README.maintainers.in [new file with mode: 0644]
README.python [new file with mode: 0644]
README.source [new file with mode: 0644]
README.venv [new file with mode: 0644]
changelog [new file with mode: 0644]
changelog.shared [new file with mode: 0644]
compat [new file with mode: 0644]
control [new file with mode: 0644]
control.in [new file with mode: 0644]
control.stdlib [new file with mode: 0644]
control.udeb [new file with mode: 0644]
copyright [new file with mode: 0644]
depgraph.py [new file with mode: 0644]
dh_doclink [new file with mode: 0644]
idle-PVER.1.in [new file with mode: 0644]
idle-PVER.overrides.in [new file with mode: 0644]
idle-PVER.postinst.in [new file with mode: 0644]
idle-PVER.postrm.in [new file with mode: 0644]
idle-PVER.prerm.in [new file with mode: 0644]
idle.desktop.in [new file with mode: 0644]
libPVER-dbg.overrides.in [new file with mode: 0644]
libPVER-dbg.prerm.in [new file with mode: 0644]
libPVER-dbg.symbols.i386.in [new file with mode: 0644]
libPVER-dbg.symbols.in [new file with mode: 0644]
libPVER-dev.overrides.in [new file with mode: 0644]
libPVER-minimal.overrides.in [new file with mode: 0644]
libPVER-minimal.postinst.in [new file with mode: 0644]
libPVER-minimal.postrm.in [new file with mode: 0644]
libPVER-minimal.prerm.in [new file with mode: 0644]
libPVER-stdlib.overrides.in [new file with mode: 0644]
libPVER-stdlib.prerm.in [new file with mode: 0644]
libPVER-testsuite.overrides.in [new file with mode: 0644]
libPVER-testsuite.postinst.in [new file with mode: 0644]
libPVER-testsuite.prerm.in [new file with mode: 0644]
libPVER.overrides.in [new file with mode: 0644]
libPVER.symbols.i386.in [new file with mode: 0644]
libPVER.symbols.in [new file with mode: 0644]
libpython.symbols.in [new file with mode: 0644]
locale-gen [new file with mode: 0644]
mincheck.py [new file with mode: 0644]
mkbinfmt.py [new file with mode: 0644]
multiarch.h.in [new file with mode: 0644]
openssl.cnf [new file with mode: 0644]
patches/argparse-no-shutil.diff [new file with mode: 0644]
patches/arm-alignment.diff [new file with mode: 0644]
patches/bdist-wininst-notfound.diff [new file with mode: 0644]
patches/build-math-object.diff [new file with mode: 0644]
patches/ctypes-arm.diff [new file with mode: 0644]
patches/deb-locations.diff [new file with mode: 0644]
patches/deb-setup.diff [new file with mode: 0644]
patches/disable-sem-check.diff [new file with mode: 0644]
patches/disable-some-tests.diff [new file with mode: 0644]
patches/distutils-install-layout.diff [new file with mode: 0644]
patches/distutils-link.diff [new file with mode: 0644]
patches/distutils-sysconfig.diff [new file with mode: 0644]
patches/doc-build-texinfo.diff [new file with mode: 0644]
patches/ensurepip-disabled.diff [new file with mode: 0644]
patches/ensurepip-wheels.diff [new file with mode: 0644]
patches/ext-no-libpython-link.diff [new file with mode: 0644]
patches/gdbm-import.diff [new file with mode: 0644]
patches/git-updates.diff [new file with mode: 0644]
patches/hurd_kfreebsd_thread_native_id.diff [new file with mode: 0644]
patches/langpack-gettext.diff [new file with mode: 0644]
patches/lib-argparse.diff [new file with mode: 0644]
patches/lib2to3-no-pickled-grammar.diff [new file with mode: 0644]
patches/link-opt.diff [new file with mode: 0644]
patches/link-timemodule.diff [new file with mode: 0644]
patches/local-doc-references.diff [new file with mode: 0644]
patches/locale-module.diff [new file with mode: 0644]
patches/lto-link-flags.diff [new file with mode: 0644]
patches/mangle-fstack-protector.diff [new file with mode: 0644]
patches/mpdecimal-2.5.1.diff [new file with mode: 0644]
patches/multiarch-extname.diff [new file with mode: 0644]
patches/multiarch.diff [new file with mode: 0644]
patches/profiled-build.diff [new file with mode: 0644]
patches/pydoc-use-pager.diff [new file with mode: 0644]
patches/reproducible-buildinfo.diff [new file with mode: 0644]
patches/series [new file with mode: 0644]
patches/setup-modules.diff [new file with mode: 0644]
patches/sphinx3.diff [new file with mode: 0644]
patches/sysconfig-debian-schemes.diff [new file with mode: 0644]
patches/sysconfigdata-name.diff [new file with mode: 0644]
patches/tempfile-minimal.diff [new file with mode: 0644]
patches/test-no-random-order.diff [new file with mode: 0644]
patches/tkinter-import.diff [new file with mode: 0644]
pdb.1.in [new file with mode: 0644]
pydoc.1.in [new file with mode: 0644]
pygettext.1 [new file with mode: 0644]
pyhtml2devhelp.py [new file with mode: 0644]
pylogo.xpm [new file with mode: 0644]
pymindeps.py [new file with mode: 0644]
pysetup3.1 [new file with mode: 0644]
python3-config.1 [new file with mode: 0644]
rules [new file with mode: 0755]
script.py [new file with mode: 0644]
sitecustomize.py.in [new file with mode: 0644]
source/format [new file with mode: 0644]
source/lintian-overrides [new file with mode: 0644]
tests/control [new file with mode: 0644]
tests/failing-tests [new file with mode: 0755]
tests/failing-tests-dbg [new file with mode: 0755]
tests/module-install-local [new file with mode: 0755]
tests/module-install-user [new file with mode: 0755]
tests/module-install-venv [new file with mode: 0755]
tests/module-install-virtualenv [new file with mode: 0755]
tests/packages/fibc/fibc.c [new file with mode: 0644]
tests/packages/fibc/setup.py [new file with mode: 0755]
tests/packages/fibpy/fibpy.py [new file with mode: 0644]
tests/packages/fibpy/setup.py [new file with mode: 0755]
tests/test-common.sh [new file with mode: 0644]
tests/testsuite [new file with mode: 0755]
tests/testsuite-dbg [new file with mode: 0755]
watch [new file with mode: 0644]

diff --git a/2to3-3.1 b/2to3-3.1
new file mode 100644 (file)
index 0000000..f896799
--- /dev/null
+++ b/2to3-3.1
@@ -0,0 +1,41 @@
+.\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.40.4.
+.TH 2TO3-3.3 "1" "January 2012" "2to3-3.3 3.3" "User Commands"
+.SH NAME
+2to3-3.3 \- Python2 to Python3 converter
+.SH SYNOPSIS
+.B 2to3
+[\fIoptions\fR] \fIfile|dir \fR...
+.SH OPTIONS
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+show this help message and exit
+.TP
+\fB\-d\fR, \fB\-\-doctests_only\fR
+Fix up doctests only
+.TP
+\fB\-f\fR FIX, \fB\-\-fix\fR=\fIFIX\fR
+Each FIX specifies a transformation; default: all
+.TP
+\fB\-j\fR PROCESSES, \fB\-\-processes\fR=\fIPROCESSES\fR
+Run 2to3 concurrently
+.TP
+\fB\-x\fR NOFIX, \fB\-\-nofix\fR=\fINOFIX\fR
+Prevent a transformation from being run
+.TP
+\fB\-l\fR, \fB\-\-list\-fixes\fR
+List available transformations
+.TP
+\fB\-p\fR, \fB\-\-print\-function\fR
+Modify the grammar so that print() is a function
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+More verbose logging
+.TP
+\fB\-\-no\-diffs\fR
+Don't show diffs of the refactoring
+.TP
+\fB\-w\fR, \fB\-\-write\fR
+Write back modified files
+.TP
+\fB\-n\fR, \fB\-\-nobackups\fR
+Don't write backups for modified files
diff --git a/FAQ.html b/FAQ.html
new file mode 100644 (file)
index 0000000..389b7a2
--- /dev/null
+++ b/FAQ.html
@@ -0,0 +1,8997 @@
+<HTML>
+<HEAD>
+<TITLE>The Whole Python FAQ</TITLE>
+</HEAD>
+
+<BODY BACKGROUND="http://www.python.org/pics/RedShort.gif"
+      BGCOLOR="#FFFFFF"
+      TEXT="#000000"
+      LINK="#AA0000"
+      VLINK="#906A6A">
+<H1>The Whole Python FAQ</H1>
+Last changed on Wed Feb 12 21:31:08 2003 CET
+
+<P>(Entries marked with ** were changed within the last 24 hours;
+entries marked with * were changed within the last 7 days.)
+<P>
+
+<P>
+<HR>
+<H2>1. General information and availability</H2>
+<UL>
+<LI><A HREF="#1.1">1.1. What is Python?</A>
+<LI><A HREF="#1.2">1.2. Why is it called Python?</A>
+<LI><A HREF="#1.3">1.3. How do I obtain a copy of the Python source?</A>
+<LI><A HREF="#1.4">1.4. How do I get documentation on Python?</A>
+<LI><A HREF="#1.5">1.5. Are there other ftp sites that mirror the Python distribution?</A>
+<LI><A HREF="#1.6">1.6. Is there a newsgroup or mailing list devoted to Python?</A>
+<LI><A HREF="#1.7">1.7. Is there a WWW page devoted to Python?</A>
+<LI><A HREF="#1.8">1.8. Is the Python documentation available on the WWW?</A>
+<LI><A HREF="#1.9">1.9. Are there any books on Python?</A>
+<LI><A HREF="#1.10">1.10. Are there any published articles about Python that I can reference?</A>
+<LI><A HREF="#1.11">1.11. Are there short introductory papers or talks on Python?</A>
+<LI><A HREF="#1.12">1.12. How does the Python version numbering scheme work?</A>
+<LI><A HREF="#1.13">1.13. How do I get a beta test version of Python?</A>
+<LI><A HREF="#1.14">1.14. Are there copyright restrictions on the use of Python?</A>
+<LI><A HREF="#1.15">1.15. Why was Python created in the first place?</A>
+<LI><A HREF="#1.16">1.16. Do I have to like &quot;Monty Python's Flying Circus&quot;?</A>
+<LI><A HREF="#1.17">1.17. What is Python good for?</A>
+<LI><A HREF="#1.18">1.18. Can I use the FAQ Wizard software to maintain my own FAQ?</A>
+<LI><A HREF="#1.19">1.19. Which editor has good support for editing Python source code?</A>
+<LI><A HREF="#1.20">1.20. I've never programmed before. Is there a Python tutorial?</A>
+<LI><A HREF="#1.21">1.21. Where in the world is www.python.org located?</A>
+
+</UL>
+
+<P>
+<HR>
+<H2>2. Python in the real world</H2>
+<UL>
+<LI><A HREF="#2.1">2.1. How many people are using Python?</A>
+<LI><A HREF="#2.2">2.2. Have any significant projects been done in Python?</A>
+<LI><A HREF="#2.3">2.3. Are there any commercial projects going on using Python?</A>
+<LI><A HREF="#2.4">2.4. How stable is Python?</A>
+<LI><A HREF="#2.5">2.5. What new developments are expected for Python in the future?</A>
+<LI><A HREF="#2.6">2.6. Is it reasonable to propose incompatible changes to Python?</A>
+<LI><A HREF="#2.7">2.7. What is the future of Python?</A>
+<LI><A HREF="#2.8">2.8. What was the PSA, anyway?</A>
+<LI><A HREF="#2.9">2.9. Deleted</A>
+<LI><A HREF="#2.10">2.10. Deleted</A>
+<LI><A HREF="#2.11">2.11. Is Python Y2K (Year 2000) Compliant?</A>
+<LI><A HREF="#2.12">2.12. Is Python a good language in a class for beginning programmers?</A>
+
+</UL>
+
+<P>
+<HR>
+<H2>3. Building Python and Other Known Bugs</H2>
+<UL>
+<LI><A HREF="#3.1">3.1. Is there a test set?</A>
+<LI><A HREF="#3.2">3.2. When running the test set, I get complaints about floating point operations, but when playing with floating point operations I cannot find anything wrong with them.</A>
+<LI><A HREF="#3.3">3.3. Link errors after rerunning the configure script.</A>
+<LI><A HREF="#3.4">3.4. The python interpreter complains about options passed to a script (after the script name).</A>
+<LI><A HREF="#3.5">3.5. When building on the SGI, make tries to run python to create glmodule.c, but python hasn't been built or installed yet.</A>
+<LI><A HREF="#3.6">3.6. I use VPATH but some targets are built in the source directory.</A>
+<LI><A HREF="#3.7">3.7. Trouble building or linking with the GNU readline library.</A>
+<LI><A HREF="#3.8">3.8. Trouble with socket I/O on older Linux 1.x versions.</A>
+<LI><A HREF="#3.9">3.9. Trouble with prototypes on Ultrix.</A>
+<LI><A HREF="#3.10">3.10. Other trouble building Python on platform X.</A>
+<LI><A HREF="#3.11">3.11. How to configure dynamic loading on Linux.</A>
+<LI><A HREF="#3.12">3.12. I can't get shared modules to work on Linux 2.0 (Slackware96)?</A>
+<LI><A HREF="#3.13">3.13. Trouble when making modules shared on Linux.</A>
+<LI><A HREF="#3.14">3.14. [deleted]</A>
+<LI><A HREF="#3.15">3.15. Errors when linking with a shared library containing C++ code.</A>
+<LI><A HREF="#3.16">3.16. Deleted</A>
+<LI><A HREF="#3.17">3.17. Deleted.</A>
+<LI><A HREF="#3.18">3.18. Compilation or link errors for the _tkinter module</A>
+<LI><A HREF="#3.19">3.19. I configured and built Python for Tcl/Tk but &quot;import Tkinter&quot; fails.</A>
+<LI><A HREF="#3.20">3.20. [deleted]</A>
+<LI><A HREF="#3.21">3.21. Several common system calls are missing from the posix module.</A>
+<LI><A HREF="#3.22">3.22. ImportError: No module named string, on MS Windows.</A>
+<LI><A HREF="#3.23">3.23. Core dump on SGI when using the gl module.</A>
+<LI><A HREF="#3.24">3.24. &quot;Initializer not a constant&quot; while building DLL on MS-Windows</A>
+<LI><A HREF="#3.25">3.25. Output directed to a pipe or file disappears on Linux.</A>
+<LI><A HREF="#3.26">3.26. [deleted]</A>
+<LI><A HREF="#3.27">3.27. [deleted]</A>
+<LI><A HREF="#3.28">3.28. How can I test if Tkinter is working?</A>
+<LI><A HREF="#3.29">3.29. Is there a way to get the interactive mode of the python interpreter to perform function/variable name completion?</A>
+<LI><A HREF="#3.30">3.30. Why is the Python interpreter not built as a shared library?</A>
+<LI><A HREF="#3.31">3.31. Build with GCC on Solaris 2.6 (SunOS 5.6) fails</A>
+<LI><A HREF="#3.32">3.32. Running &quot;make clean&quot; seems to leave problematic files that cause subsequent builds to fail.</A>
+<LI><A HREF="#3.33">3.33. Submitting bug reports and patches</A>
+<LI><A HREF="#3.34">3.34. I can't load shared libraries under Python 1.5.2, Solaris 7, and gcc 2.95.2</A>
+<LI><A HREF="#3.35">3.35. In the regression test, test___all__ fails for the profile module. What's wrong?</A>
+<LI><A HREF="#3.36">3.36. relocations remain against allocatable but non-writable sections</A>
+
+</UL>
+
+<P>
+<HR>
+<H2>4. Programming in Python</H2>
+<UL>
+<LI><A HREF="#4.1">4.1. Is there a source code level debugger with breakpoints, step, etc.?</A>
+<LI><A HREF="#4.2">4.2. Can I create an object class with some methods implemented in C and others in Python (e.g. through inheritance)? (Also phrased as: Can I use a built-in type as base class?)</A>
+<LI><A HREF="#4.3">4.3. Is there a curses/termcap package for Python?</A>
+<LI><A HREF="#4.4">4.4. Is there an equivalent to C's onexit() in Python?</A>
+<LI><A HREF="#4.5">4.5. [deleted]</A>
+<LI><A HREF="#4.6">4.6. How do I iterate over a sequence in reverse order?</A>
+<LI><A HREF="#4.7">4.7. My program is too slow. How do I speed it up?</A>
+<LI><A HREF="#4.8">4.8. When I have imported a module, then edit it, and import it again (into the same Python process), the changes don't seem to take place. What is going on?</A>
+<LI><A HREF="#4.9">4.9. How do I find the current module name?</A>
+<LI><A HREF="#4.10">4.10. I have a module in which I want to execute some extra code when it is run as a script. How do I find out whether I am running as a script?</A>
+<LI><A HREF="#4.11">4.11. I try to run a program from the Demo directory but it fails with ImportError: No module named ...; what gives?</A>
+<LI><A HREF="#4.12">4.12. [deleted]</A>
+<LI><A HREF="#4.13">4.13. What GUI toolkits exist for Python?</A>
+<LI><A HREF="#4.14">4.14. Are there any interfaces to database packages in Python?</A>
+<LI><A HREF="#4.15">4.15. Is it possible to write obfuscated one-liners in Python?</A>
+<LI><A HREF="#4.16">4.16. Is there an equivalent of C's &quot;?:&quot; ternary operator?</A>
+<LI><A HREF="#4.17">4.17. My class defines __del__ but it is not called when I delete the object.</A>
+<LI><A HREF="#4.18">4.18. How do I change the shell environment for programs called using os.popen() or os.system()? Changing os.environ doesn't work.</A>
+<LI><A HREF="#4.19">4.19. What is a class?</A>
+<LI><A HREF="#4.20">4.20. What is a method?</A>
+<LI><A HREF="#4.21">4.21. What is self?</A>
+<LI><A HREF="#4.22">4.22. What is an unbound method?</A>
+<LI><A HREF="#4.23">4.23. How do I call a method defined in a base class from a derived class that overrides it?</A>
+<LI><A HREF="#4.24">4.24. How do I call a method from a base class without using the name of the base class?</A>
+<LI><A HREF="#4.25">4.25. How can I organize my code to make it easier to change the base class?</A>
+<LI><A HREF="#4.26">4.26. How can I find the methods or attributes of an object?</A>
+<LI><A HREF="#4.27">4.27. I can't seem to use os.read() on a pipe created with os.popen().</A>
+<LI><A HREF="#4.28">4.28. How can I create a stand-alone binary from a Python script?</A>
+<LI><A HREF="#4.29">4.29. What WWW tools are there for Python?</A>
+<LI><A HREF="#4.30">4.30. How do I run a subprocess with pipes connected to both input and output?</A>
+<LI><A HREF="#4.31">4.31. How do I call a function if I have the arguments in a tuple?</A>
+<LI><A HREF="#4.32">4.32. How do I enable font-lock-mode for Python in Emacs?</A>
+<LI><A HREF="#4.33">4.33. Is there a scanf() or sscanf() equivalent?</A>
+<LI><A HREF="#4.34">4.34. Can I have Tk events handled while waiting for I/O?</A>
+<LI><A HREF="#4.35">4.35. How do I write a function with output parameters (call by reference)?</A>
+<LI><A HREF="#4.36">4.36. Please explain the rules for local and global variables in Python.</A>
+<LI><A HREF="#4.37">4.37. How can I have modules that mutually import each other?</A>
+<LI><A HREF="#4.38">4.38. How do I copy an object in Python?</A>
+<LI><A HREF="#4.39">4.39. How to implement persistent objects in Python? (Persistent == automatically saved to and restored from disk.)</A>
+<LI><A HREF="#4.40">4.40. I try to use __spam and I get an error about _SomeClassName__spam.</A>
+<LI><A HREF="#4.41">4.41. How do I delete a file? And other file questions.</A>
+<LI><A HREF="#4.42">4.42. How to modify urllib or httplib to support HTTP/1.1?</A>
+<LI><A HREF="#4.43">4.43. Unexplicable syntax errors in compile() or exec.</A>
+<LI><A HREF="#4.44">4.44. How do I convert a string to a number?</A>
+<LI><A HREF="#4.45">4.45. How do I convert a number to a string?</A>
+<LI><A HREF="#4.46">4.46. How do I copy a file?</A>
+<LI><A HREF="#4.47">4.47. How do I check if an object is an instance of a given class or of a subclass of it?</A>
+<LI><A HREF="#4.48">4.48. What is delegation?</A>
+<LI><A HREF="#4.49">4.49. How do I test a Python program or component.</A>
+<LI><A HREF="#4.50">4.50. My multidimensional list (array) is broken! What gives?</A>
+<LI><A HREF="#4.51">4.51. I want to do a complicated sort: can you do a Schwartzian Transform in Python?</A>
+<LI><A HREF="#4.52">4.52. How to convert between tuples and lists?</A>
+<LI><A HREF="#4.53">4.53. Files retrieved with urllib contain leading garbage that looks like email headers.</A>
+<LI><A HREF="#4.54">4.54. How do I get a list of all instances of a given class?</A>
+<LI><A HREF="#4.55">4.55. A regular expression fails with regex.error: match failure.</A>
+<LI><A HREF="#4.56">4.56. I can't get signal handlers to work.</A>
+<LI><A HREF="#4.57">4.57. I can't use a global variable in a function? Help!</A>
+<LI><A HREF="#4.58">4.58. What's a negative index? Why doesn't list.insert() use them?</A>
+<LI><A HREF="#4.59">4.59. How can I sort one list by values from another list?</A>
+<LI><A HREF="#4.60">4.60. Why doesn't dir() work on builtin types like files and lists?</A>
+<LI><A HREF="#4.61">4.61. How can I mimic CGI form submission (METHOD=POST)?</A>
+<LI><A HREF="#4.62">4.62. If my program crashes with a bsddb (or anydbm) database open, it gets corrupted. How come?</A>
+<LI><A HREF="#4.63">4.63. How do I make a Python script executable on Unix?</A>
+<LI><A HREF="#4.64">4.64. How do you remove duplicates from a list?</A>
+<LI><A HREF="#4.65">4.65. Are there any known year 2000 problems in Python?</A>
+<LI><A HREF="#4.66">4.66. I want a version of map that applies a method to a sequence of objects! Help!</A>
+<LI><A HREF="#4.67">4.67. How do I generate random numbers in Python?</A>
+<LI><A HREF="#4.68">4.68. How do I access the serial (RS232) port?</A>
+<LI><A HREF="#4.69">4.69. Images on Tk-Buttons don't work in Py15?</A>
+<LI><A HREF="#4.70">4.70. Where is the math.py (socket.py, regex.py, etc.) source file?</A>
+<LI><A HREF="#4.71">4.71. How do I send mail from a Python script?</A>
+<LI><A HREF="#4.72">4.72. How do I avoid blocking in connect() of a socket?</A>
+<LI><A HREF="#4.73">4.73. How do I specify hexadecimal and octal integers?</A>
+<LI><A HREF="#4.74">4.74. How to get a single keypress at a time?</A>
+<LI><A HREF="#4.75">4.75. How can I overload constructors (or methods) in Python?</A>
+<LI><A HREF="#4.76">4.76. How do I pass keyword arguments from one method to another?</A>
+<LI><A HREF="#4.77">4.77. What module should I use to help with generating HTML?</A>
+<LI><A HREF="#4.78">4.78. How do I create documentation from doc strings?</A>
+<LI><A HREF="#4.79">4.79. How do I read (or write) binary data?</A>
+<LI><A HREF="#4.80">4.80. I can't get key bindings to work in Tkinter</A>
+<LI><A HREF="#4.81">4.81. &quot;import crypt&quot; fails</A>
+<LI><A HREF="#4.82">4.82. Are there coding standards or a style guide for Python programs?</A>
+<LI><A HREF="#4.83">4.83. How do I freeze Tkinter applications?</A>
+<LI><A HREF="#4.84">4.84. How do I create static class data and static class methods?</A>
+<LI><A HREF="#4.85">4.85. __import__('x.y.z') returns &lt;module 'x'&gt;; how do I get z?</A>
+<LI><A HREF="#4.86">4.86. Basic thread wisdom</A>
+<LI><A HREF="#4.87">4.87. Why doesn't closing sys.stdout (stdin, stderr) really close it?</A>
+<LI><A HREF="#4.88">4.88. What kinds of global value mutation are thread-safe?</A>
+<LI><A HREF="#4.89">4.89. How do I modify a string in place?</A>
+<LI><A HREF="#4.90">4.90. How to pass on keyword/optional parameters/arguments</A>
+<LI><A HREF="#4.91">4.91. How can I get a dictionary to display its keys in a consistent order?</A>
+<LI><A HREF="#4.92">4.92. Is there a Python tutorial?</A>
+<LI><A HREF="#4.93">4.93. Deleted</A>
+<LI><A HREF="#4.94">4.94. How do I get a single keypress without blocking?</A>
+<LI><A HREF="#4.95">4.95. Is there an equivalent to Perl chomp()? (Remove trailing newline from string)</A>
+<LI><A HREF="#4.96">4.96. Why is join() a string method when I'm really joining the elements of a (list, tuple, sequence)?</A>
+<LI><A HREF="#4.97">4.97. How can my code discover the name of an object?</A>
+<LI><A HREF="#4.98">4.98. Why are floating point calculations so inaccurate?</A>
+<LI><A HREF="#4.99">4.99. I tried to open Berkeley DB file, but bsddb produces bsddb.error: (22, 'Invalid argument'). Help! How can I restore my data?</A>
+<LI><A HREF="#4.100">4.100. What are the &quot;best practices&quot; for using import in a module?</A>
+<LI><A HREF="#4.101">4.101. Is there a tool to help find bugs or perform static analysis?</A>
+<LI><A HREF="#4.102">4.102. UnicodeError: ASCII [decoding,encoding] error: ordinal not in range(128)</A>
+<LI><A HREF="#4.103">4.103. Using strings to call functions/methods</A>
+<LI><A HREF="#4.104">4.104. How fast are exceptions?</A>
+<LI><A HREF="#4.105">4.105. Sharing global variables across modules</A>
+<LI><A HREF="#4.106">4.106. Why is cPickle so slow?</A>
+<LI><A HREF="#4.107">4.107. When importing module XXX, why do I get &quot;undefined symbol: PyUnicodeUCS2_...&quot; ?</A>
+<LI><A HREF="#4.108">4.108. How do I create a .pyc file?</A>
+
+</UL>
+
+<P>
+<HR>
+<H2>5. Extending Python</H2>
+<UL>
+<LI><A HREF="#5.1">5.1. Can I create my own functions in C?</A>
+<LI><A HREF="#5.2">5.2. Can I create my own functions in C++?</A>
+<LI><A HREF="#5.3">5.3. How can I execute arbitrary Python statements from C?</A>
+<LI><A HREF="#5.4">5.4. How can I evaluate an arbitrary Python expression from C?</A>
+<LI><A HREF="#5.5">5.5. How do I extract C values from a Python object?</A>
+<LI><A HREF="#5.6">5.6. How do I use Py_BuildValue() to create a tuple of arbitrary length?</A>
+<LI><A HREF="#5.7">5.7. How do I call an object's method from C?</A>
+<LI><A HREF="#5.8">5.8. How do I catch the output from PyErr_Print() (or anything that prints to stdout/stderr)?</A>
+<LI><A HREF="#5.9">5.9. How do I access a module written in Python from C?</A>
+<LI><A HREF="#5.10">5.10. How do I interface to C++ objects from Python?</A>
+<LI><A HREF="#5.11">5.11. mSQLmodule (or other old module) won't build with Python 1.5 (or later)</A>
+<LI><A HREF="#5.12">5.12. I added a module using the Setup file and the make fails! Huh?</A>
+<LI><A HREF="#5.13">5.13. I want to compile a Python module on my Red Hat Linux system, but some files are missing.</A>
+<LI><A HREF="#5.14">5.14. What does &quot;SystemError: _PyImport_FixupExtension: module yourmodule not loaded&quot; mean?</A>
+<LI><A HREF="#5.15">5.15. How to tell &quot;incomplete input&quot; from &quot;invalid input&quot;?</A>
+<LI><A HREF="#5.16">5.16. How do I debug an extension?</A>
+<LI><A HREF="#5.17">5.17. How do I find undefined Linux g++ symbols, __builtin_new or __pure_virtural</A>
+<LI><A HREF="#5.18">5.18. How do I define and create objects corresponding to built-in/extension types</A>
+
+</UL>
+
+<P>
+<HR>
+<H2>6. Python's design</H2>
+<UL>
+<LI><A HREF="#6.1">6.1. Why isn't there a switch or case statement in Python?</A>
+<LI><A HREF="#6.2">6.2. Why does Python use indentation for grouping of statements?</A>
+<LI><A HREF="#6.3">6.3. Why are Python strings immutable?</A>
+<LI><A HREF="#6.4">6.4. Delete</A>
+<LI><A HREF="#6.5">6.5. Why does Python use methods for some functionality (e.g. list.index()) but functions for other (e.g. len(list))?</A>
+<LI><A HREF="#6.6">6.6. Why can't I derive a class from built-in types (e.g. lists or files)?</A>
+<LI><A HREF="#6.7">6.7. Why must 'self' be declared and used explicitly in method definitions and calls?</A>
+<LI><A HREF="#6.8">6.8. Can't you emulate threads in the interpreter instead of relying on an OS-specific thread implementation?</A>
+<LI><A HREF="#6.9">6.9. Why can't lambda forms contain statements?</A>
+<LI><A HREF="#6.10">6.10. [deleted]</A>
+<LI><A HREF="#6.11">6.11. [deleted]</A>
+<LI><A HREF="#6.12">6.12. Why is there no more efficient way of iterating over a dictionary than first constructing the list of keys()?</A>
+<LI><A HREF="#6.13">6.13. Can Python be compiled to machine code, C or some other language?</A>
+<LI><A HREF="#6.14">6.14. How does Python manage memory?</A>
+<LI><A HREF="#6.15">6.15. Why are there separate tuple and list data types?</A>
+<LI><A HREF="#6.16">6.16. How are lists implemented?</A>
+<LI><A HREF="#6.17">6.17. How are dictionaries implemented?</A>
+<LI><A HREF="#6.18">6.18. Why must dictionary keys be immutable?</A>
+<LI><A HREF="#6.19">6.19. How the heck do you make an array in Python?</A>
+<LI><A HREF="#6.20">6.20. Why doesn't list.sort() return the sorted list?</A>
+<LI><A HREF="#6.21">6.21. How do you specify and enforce an interface spec in Python?</A>
+<LI><A HREF="#6.22">6.22. Why do all classes have the same type? Why do instances all have the same type?</A>
+<LI><A HREF="#6.23">6.23. Why isn't all memory freed when Python exits?</A>
+<LI><A HREF="#6.24">6.24. Why no class methods or mutable class variables?</A>
+<LI><A HREF="#6.25">6.25. Why are default values sometimes shared between objects?</A>
+<LI><A HREF="#6.26">6.26. Why no goto?</A>
+<LI><A HREF="#6.27">6.27. How do you make a higher order function in Python?</A>
+<LI><A HREF="#6.28">6.28. Why do I get a SyntaxError for a 'continue' inside a 'try'?</A>
+<LI><A HREF="#6.29">6.29. Why can't raw strings (r-strings) end with a backslash?</A>
+<LI><A HREF="#6.30">6.30. Why can't I use an assignment in an expression?</A>
+<LI><A HREF="#6.31">6.31. Why doesn't Python have a &quot;with&quot; statement like some other languages?</A>
+<LI><A HREF="#6.32">6.32. Why are colons required for if/while/def/class?</A>
+<LI><A HREF="#6.33">6.33. Can't we get rid of the Global Interpreter Lock?</A>
+
+</UL>
+
+<P>
+<HR>
+<H2>7. Using Python on non-UNIX platforms</H2>
+<UL>
+<LI><A HREF="#7.1">7.1. Is there a Mac version of Python?</A>
+<LI><A HREF="#7.2">7.2. Are there DOS and Windows versions of Python?</A>
+<LI><A HREF="#7.3">7.3. Is there an OS/2 version of Python?</A>
+<LI><A HREF="#7.4">7.4. Is there a VMS version of Python?</A>
+<LI><A HREF="#7.5">7.5. What about IBM mainframes, or other non-UNIX platforms?</A>
+<LI><A HREF="#7.6">7.6. Where are the source or Makefiles for the non-UNIX versions?</A>
+<LI><A HREF="#7.7">7.7. What is the status and support for the non-UNIX versions?</A>
+<LI><A HREF="#7.8">7.8. I have a PC version but it appears to be only a binary. Where's the library?</A>
+<LI><A HREF="#7.9">7.9. Where's the documentation for the Mac or PC version?</A>
+<LI><A HREF="#7.10">7.10. How do I create a Python program file on the Mac or PC?</A>
+<LI><A HREF="#7.11">7.11. How can I use Tkinter on Windows 95/NT?</A>
+<LI><A HREF="#7.12">7.12. cgi.py (or other CGI programming) doesn't work sometimes on NT or win95!</A>
+<LI><A HREF="#7.13">7.13. Why doesn't os.popen() work in PythonWin on NT?</A>
+<LI><A HREF="#7.14">7.14. How do I use different functionality on different platforms with the same program?</A>
+<LI><A HREF="#7.15">7.15. Is there an Amiga version of Python?</A>
+<LI><A HREF="#7.16">7.16. Why doesn't os.popen()/win32pipe.popen() work on Win9x?</A>
+
+</UL>
+
+<P>
+<HR>
+<H2>8. Python on Windows</H2>
+<UL>
+<LI><A HREF="#8.1">8.1. Using Python for CGI on Microsoft Windows</A>
+<LI><A HREF="#8.2">8.2. How to check for a keypress without blocking?</A>
+<LI><A HREF="#8.3">8.3. $PYTHONPATH</A>
+<LI><A HREF="#8.4">8.4. dedent syntax errors</A>
+<LI><A HREF="#8.5">8.5. How do I emulate os.kill() in Windows?</A>
+<LI><A HREF="#8.6">8.6. Why does os.path.isdir() fail on NT shared directories?</A>
+<LI><A HREF="#8.7">8.7. PyRun_SimpleFile() crashes on Windows but not on Unix</A>
+<LI><A HREF="#8.8">8.8. Import of _tkinter fails on Windows 95/98</A>
+<LI><A HREF="#8.9">8.9. Can't extract the downloaded documentation on Windows</A>
+<LI><A HREF="#8.10">8.10. Can't get Py_RunSimpleFile() to work.</A>
+<LI><A HREF="#8.11">8.11. Where is Freeze for Windows?</A>
+<LI><A HREF="#8.12">8.12. Is a *.pyd file the same as a DLL?</A>
+<LI><A HREF="#8.13">8.13. Missing cw3215mt.dll (or missing cw3215.dll)</A>
+<LI><A HREF="#8.14">8.14. How to make python scripts executable:</A>
+<LI><A HREF="#8.15">8.15. Warning about CTL3D32 version from installer</A>
+<LI><A HREF="#8.16">8.16. How can I embed Python into a Windows application?</A>
+<LI><A HREF="#8.17">8.17. Setting up IIS 5 to use Python for CGI</A>
+<LI><A HREF="#8.18">8.18. How do I run a Python program under Windows?</A>
+
+</UL>
+
+<HR>
+<H1>1. General information and availability</H1>
+
+<HR>
+<H2><A NAME="1.1">1.1. What is Python?</A></H2>
+Python is an interpreted, interactive, object-oriented programming
+language.  It incorporates modules, exceptions, dynamic typing, very
+high level dynamic data types, and classes.  Python combines
+remarkable power with very clear syntax.  It has interfaces to many
+system calls and libraries, as well as to various window systems, and
+is extensible in C or C++.  It is also usable as an extension language
+for applications that need a programmable interface.  Finally, Python
+is portable: it runs on many brands of UNIX, on the Mac, and on PCs
+under MS-DOS, Windows, Windows NT, and OS/2.
+<P>
+To find out more, the best thing to do is to start reading the
+tutorial from the documentation set (see a few questions further
+down).
+<P>
+See also question 1.17 (what is Python good for).
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq01.001.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq01.001.htp">Log info</A>
+
+/ Last changed on Mon May 26 16:05:18 1997 by
+<A HREF="mailto:guido@cnri.reston.va.us">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="1.2">1.2. Why is it called Python?</A></H2>
+Apart from being a computer scientist, I'm also a fan of "Monty
+Python's Flying Circus" (a BBC comedy series from the seventies, in
+the -- unlikely -- case you didn't know).  It occurred to me one day
+that I needed a name that was short, unique, and slightly mysterious.
+And I happened to be reading some scripts from the series at the
+time...  So then I decided to call my language Python.
+<P>
+By now I don't care any more whether you use a Python, some other
+snake, a foot or 16-ton weight, or a wood rat as a logo for Python!
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq01.002.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq01.002.htp">Log info</A>
+
+/ Last changed on Thu Aug 24 00:50:41 2000 by
+<A HREF="mailto:guido@beopen.com">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="1.3">1.3. How do I obtain a copy of the Python source?</A></H2>
+The latest Python source distribution is always available from
+python.org, at <A HREF="http://www.python.org/download">http://www.python.org/download</A>.  The latest development sources can be obtained via anonymous CVS from SourceForge, at <A HREF="http://www.sf.net/projects/python">http://www.sf.net/projects/python</A> .
+<P>
+The source distribution is a gzipped tar file containing the complete C source, LaTeX
+documentation, Python library modules, example programs, and several
+useful pieces of freely distributable software.  This will compile and
+run out of the box on most UNIX platforms.  (See section 7 for
+non-UNIX information.)
+<P>
+Older versions of Python are also available from python.org.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq01.003.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq01.003.htp">Log info</A>
+
+/ Last changed on Tue Apr  9 17:06:16 2002 by
+<A HREF="mailto:akuchlin@mems-exchange.org">A.M. Kuchling</A>
+<P>
+
+<HR>
+<H2><A NAME="1.4">1.4. How do I get documentation on Python?</A></H2>
+All documentation is available on-line, starting at <A HREF="http://www.python.org/doc">http://www.python.org/doc</A>/. 
+<P>
+The LaTeX source for the documentation is part of the source
+distribution.  If you don't have LaTeX, the latest Python
+documentation set is available, in various formats like postscript 
+and html, by anonymous ftp - visit the above URL for links to the
+current versions.
+<P>
+PostScript for a high-level description of Python is in the file nluug-paper.ps 
+(a separate file on the ftp site).
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq01.004.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq01.004.htp">Log info</A>
+
+/ Last changed on Wed Jan 21 12:02:55 1998 by
+<A HREF="mailto:klm@python.org">Ken Manheimer</A>
+<P>
+
+<HR>
+<H2><A NAME="1.5">1.5. Are there other ftp sites that mirror the Python distribution?</A></H2>
+The following anonymous ftp sites keep mirrors of the Python
+distribution:
+<P>
+USA:
+<P>
+<PRE>
+        <A HREF="ftp://ftp.python.org/pub/python">ftp://ftp.python.org/pub/python</A>/
+        <A HREF="ftp://gatekeeper.dec.com/pub/plan/python">ftp://gatekeeper.dec.com/pub/plan/python</A>/
+        <A HREF="ftp://ftp.uu.net/languages/python">ftp://ftp.uu.net/languages/python</A>/
+        <A HREF="ftp://ftp.wustl.edu/graphics/graphics/sgi-stuff/python">ftp://ftp.wustl.edu/graphics/graphics/sgi-stuff/python</A>/
+        <A HREF="ftp://ftp.sterling.com/programming/languages/python">ftp://ftp.sterling.com/programming/languages/python</A>/
+        <A HREF="ftp://uiarchive.cso.uiuc.edu/pub/lang/python">ftp://uiarchive.cso.uiuc.edu/pub/lang/python</A>/
+        <A HREF="ftp://ftp.pht.com/mirrors/python/python">ftp://ftp.pht.com/mirrors/python/python</A>/
+       <A HREF="ftp://ftp.cdrom.com/pub/python">ftp://ftp.cdrom.com/pub/python</A>/
+</PRE>
+Europe:
+<P>
+<PRE>
+        <A HREF="ftp://ftp.cwi.nl/pub/python">ftp://ftp.cwi.nl/pub/python</A>/
+        <A HREF="ftp://ftp.funet.fi/pub/languages/python">ftp://ftp.funet.fi/pub/languages/python</A>/
+        <A HREF="ftp://ftp.sunet.se/pub/lang/python">ftp://ftp.sunet.se/pub/lang/python</A>/
+        <A HREF="ftp://unix.hensa.ac.uk/mirrors/uunet/languages/python">ftp://unix.hensa.ac.uk/mirrors/uunet/languages/python</A>/
+        <A HREF="ftp://ftp.lip6.fr/pub/python">ftp://ftp.lip6.fr/pub/python</A>/
+        <A HREF="ftp://sunsite.cnlab-switch.ch/mirror/python">ftp://sunsite.cnlab-switch.ch/mirror/python</A>/
+        <A HREF="ftp://ftp.informatik.tu-muenchen.de/pub/comp/programming/languages/python">ftp://ftp.informatik.tu-muenchen.de/pub/comp/programming/languages/python</A>/
+</PRE>
+Australia:
+<P>
+<PRE>
+        <A HREF="ftp://ftp.dstc.edu.au/pub/python">ftp://ftp.dstc.edu.au/pub/python</A>/
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq01.005.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq01.005.htp">Log info</A>
+
+/ Last changed on Wed Mar 24 09:20:49 1999 by
+<A HREF="mailto:akuchlin@cnri.reston.va.us">A.M. Kuchling</A>
+<P>
+
+<HR>
+<H2><A NAME="1.6">1.6. Is there a newsgroup or mailing list devoted to Python?</A></H2>
+There is a newsgroup, comp.lang.python,
+and a mailing list.  The newsgroup and mailing list are gatewayed into
+each other -- if you can read news it's unnecessary to subscribe to
+the mailing list.  To subscribe to the mailing list
+(<A HREF="mailto:python-list@python.org">python-list@python.org</A>) visit its Mailman webpage at
+<A HREF="http://www.python.org/mailman/listinfo/python-list">http://www.python.org/mailman/listinfo/python-list</A>
+<P>
+More info about the newsgroup and mailing list, and about other lists,
+can be found at
+<A HREF="http://www.python.org/psa/MailingLists.html">http://www.python.org/psa/MailingLists.html</A>.
+<P>
+Archives of the newsgroup are kept by Deja News and accessible
+through the "Python newsgroup search" web page,
+<A HREF="http://www.python.org/search/search_news.html">http://www.python.org/search/search_news.html</A>.
+This page also contains pointer to other archival collections.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq01.006.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq01.006.htp">Log info</A>
+
+/ Last changed on Wed Jun 23 09:29:36 1999 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="1.7">1.7. Is there a WWW page devoted to Python?</A></H2>
+Yes, <A HREF="http://www.python.org">http://www.python.org</A>/ is the official Python home page.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq01.007.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq01.007.htp">Log info</A>
+
+/ Last changed on Fri May 23 14:42:59 1997 by
+<A HREF="mailto:klm@python.org">Ken Manheimer</A>
+<P>
+
+<HR>
+<H2><A NAME="1.8">1.8. Is the Python documentation available on the WWW?</A></H2>
+Yes. Python 2.0 documentation is available from
+<A HREF="http://www.pythonlabs.com/tech/python2.0/doc">http://www.pythonlabs.com/tech/python2.0/doc</A>/ and from
+<A HREF="http://www.python.org/doc">http://www.python.org/doc</A>/.  Note that most documentation
+is available for on-line browsing as well as for downloading.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq01.008.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq01.008.htp">Log info</A>
+
+/ Last changed on Tue Jan  2 03:14:08 2001 by
+<A HREF="mailto:moshez@zadka.site.co.il">Moshe Zadka</A>
+<P>
+
+<HR>
+<H2><A NAME="1.9">1.9. Are there any books on Python?</A></H2>
+Yes, many, and more are being published.  See
+the python.org Wiki at <A HREF="http://www.python.org/cgi-bin/moinmoin/PythonBooks">http://www.python.org/cgi-bin/moinmoin/PythonBooks</A> for a list.
+<P>
+You can also search online bookstores for "Python"
+(and filter out the Monty Python references; or
+perhaps search for "Python" and "language").
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq01.009.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq01.009.htp">Log info</A>
+
+/ Last changed on Mon Aug  5 19:08:49 2002 by
+<A HREF="mailto:akuchlin@mems-exchange.org">amk</A>
+<P>
+
+<HR>
+<H2><A NAME="1.10">1.10. Are there any published articles about Python that I can reference?</A></H2>
+If you can't reference the web site, and you don't want to reference the books
+(see previous question), there are several articles on Python that you could
+reference.
+<P>
+Most publications about Python are collected on the Python web site:
+<P>
+<PRE>
+    <A HREF="http://www.python.org/doc/Publications.html">http://www.python.org/doc/Publications.html</A>
+</PRE>
+It is no longer recommended to reference this
+very old article by Python's author:
+<P>
+<PRE>
+    Guido van Rossum and Jelke de Boer, "Interactively Testing Remote
+    Servers Using the Python Programming Language", CWI Quarterly, Volume
+    4, Issue 4 (December 1991), Amsterdam, pp 283-303.
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq01.010.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq01.010.htp">Log info</A>
+
+/ Last changed on Sat Jul  4 20:52:31 1998 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="1.11">1.11. Are there short introductory papers or talks on Python?</A></H2>
+There are several - you can find links to some of them collected at
+<A HREF="http://www.python.org/doc/Hints.html#intros">http://www.python.org/doc/Hints.html#intros</A>.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq01.011.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq01.011.htp">Log info</A>
+
+/ Last changed on Fri May 23 15:04:05 1997 by
+<A HREF="mailto:klm@python.org">Ken Manheimer</A>
+<P>
+
+<HR>
+<H2><A NAME="1.12">1.12. How does the Python version numbering scheme work?</A></H2>
+Python versions are numbered A.B.C or A.B.  A is the major version
+number -- it is only incremented for really major changes in the
+language.  B is the minor version number, incremented for less
+earth-shattering changes.  C is the micro-level -- it is
+incremented for each bugfix release.  See PEP 6 for more information
+about bugfix releases.
+<P>
+Not all releases have bugfix releases.
+Note that in the past (ending with 1.5.2),
+micro releases have added significant changes;
+in fact the changeover from 0.9.9 to 1.0.0 was the first time
+that either A or B changed!
+<P>
+Alpha, beta and release candidate versions have an additional suffixes.
+The suffix for an alpha version is "aN" for some small number N, the
+suffix for a beta version is "bN" for some small number N, and the
+suffix for a release candidate version is "cN" for some small number N.
+<P>
+Note that (for instance) all versions labeled 2.0aN precede the
+versions labeled 2.0bN, which precede versions labeled 2.0cN, and
+<I>those</I> precede 2.0.
+<P>
+As a rule, no changes are made between release candidates and the final
+release unless there are show-stopper bugs.
+<P>
+You may also find version numbers with a "+" suffix, e.g. "2.2+".
+These are unreleased versions, built directly from the CVS trunk.
+<P>
+See also the documentation for sys.version, sys.hexversion, and
+sys.version_info.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq01.012.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq01.012.htp">Log info</A>
+
+/ Last changed on Mon Jan 14 06:34:17 2002 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="1.13">1.13. How do I get a beta test version of Python?</A></H2>
+All releases, including alphas, betas and release candidates, are announced on
+comp.lang.python and comp.lang.python.announce newsgroups,
+which are gatewayed into the <A HREF="mailto:python-list@python.org">python-list@python.org</A> and
+<A HREF="mailto:python-announce@python.org">python-announce@python.org</A>. In addition, all these announcements appear on
+the Python home page, at <A HREF="http://www.python.org">http://www.python.org</A>.
+<P>
+You can also access the development version of Python through CVS.  See <A HREF="http://sourceforge.net/cvs/?group_id=5470">http://sourceforge.net/cvs/?group_id=5470</A> for details.  If you're not familiar with CVS, documents like <A HREF="http://linux.oreillynet.com/pub/a/linux/2002/01/03/cvs_intro.html">http://linux.oreillynet.com/pub/a/linux/2002/01/03/cvs_intro.html</A>
+provide an introduction.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq01.013.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq01.013.htp">Log info</A>
+
+/ Last changed on Mon Jun  3 00:57:08 2002 by
+<A HREF="mailto:neal@metaslash.com">Neal Norwitz</A>
+<P>
+
+<HR>
+<H2><A NAME="1.14">1.14. Are there copyright restrictions on the use of Python?</A></H2>
+Hardly.  You can do anything you want with the source, as long as
+you leave the copyrights in, and display those copyrights in any
+documentation about Python that you produce.  Also, don't use the
+author's institute's name in publicity without prior written
+permission, and don't hold them responsible for anything (read the
+actual copyright for a precise legal wording).
+<P>
+In particular, if you honor the copyright rules, it's OK to use Python
+for commercial use, to sell copies of Python in source or binary form,
+or to sell products that enhance Python or incorporate Python (or part
+of it) in some form.  I would still like to know about all commercial
+use of Python!
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq01.014.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq01.014.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="1.15">1.15. Why was Python created in the first place?</A></H2>
+Here's a <I>very</I> brief summary of what got me started:
+<P>
+I had extensive experience with implementing an interpreted language
+in the ABC group at CWI, and from working with this group I had
+learned a lot about language design.  This is the origin of many
+Python features, including the use of indentation for statement
+grouping and the inclusion of very-high-level data types (although the
+details are all different in Python).
+<P>
+I had a number of gripes about the ABC language, but also liked many
+of its features.  It was impossible to extend the ABC language (or its
+implementation) to remedy my complaints -- in fact its lack of
+extensibility was one of its biggest problems.
+I had some experience with using Modula-2+ and talked with the
+designers of Modula-3 (and read the M3 report).  M3 is the origin of
+the syntax and semantics used for exceptions, and some other Python
+features.
+<P>
+I was working in the Amoeba distributed operating system group at
+CWI.  We needed a better way to do system administration than by
+writing either C programs or Bourne shell scripts, since Amoeba had
+its own system call interface which wasn't easily accessible from the
+Bourne shell.  My experience with error handling in Amoeba made me
+acutely aware of the importance of exceptions as a programming
+language feature.
+<P>
+It occurred to me that a scripting language with a syntax like ABC
+but with access to the Amoeba system calls would fill the need.  I
+realized that it would be foolish to write an Amoeba-specific
+language, so I decided that I needed a language that was generally
+extensible.
+<P>
+During the 1989 Christmas holidays, I had a lot of time on my hand,
+so I decided to give it a try.  During the next year, while still
+mostly working on it in my own time, Python was used in the Amoeba
+project with increasing success, and the feedback from colleagues made
+me add many early improvements.
+<P>
+In February 1991, after just over a year of development, I decided
+to post to USENET.  The rest is in the Misc/HISTORY file.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq01.015.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq01.015.htp">Log info</A>
+
+/ Last changed on Fri May 23 00:06:23 1997 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="1.16">1.16. Do I have to like &quot;Monty Python's Flying Circus&quot;?</A></H2>
+No, but it helps.  Pythonistas like the occasional reference to SPAM,
+and of course, nobody expects the Spanish Inquisition
+<P>
+The two main reasons to use Python are:
+<P>
+<PRE>
+ - Portable
+ - Easy to learn
+</PRE>
+The <I>three</I> main reasons to use Python are:
+<P>
+<PRE>
+ - Portable
+ - Easy to learn
+ - Powerful standard library
+</PRE>
+(And nice red uniforms.)
+<P>
+And remember, there is <I>no</I> rule six.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq01.016.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq01.016.htp">Log info</A>
+
+/ Last changed on Wed May 28 10:39:21 1997 by
+<A HREF="mailto:guido@cnri.reston.va.us">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="1.17">1.17. What is Python good for?</A></H2>
+Python is used in many situations where a great deal of dynamism,
+ease of use, power, and flexibility are required.  
+<P>
+In the area of basic text
+manipulation core Python (without any non-core extensions) is easier
+to use and is roughly as fast as just  about any language, and this makes Python
+good for many system administration type tasks and for CGI programming
+and other application areas that manipulate text and strings and such.
+<P>
+When augmented with
+standard extensions (such as PIL, COM, Numeric, oracledb, kjbuckets, 
+tkinter, win32api, etc.)
+or special purpose extensions (that you write, perhaps using helper tools such
+as SWIG, or using object protocols such as ILU/CORBA or COM) Python 
+becomes a very convenient "glue" or "steering"
+language that helps make heterogeneous collections of unrelated
+software packages work together.
+For example by combining Numeric with oracledb you can help your
+SQL database do statistical analysis, or even Fourier transforms.
+One of the features that makes Python excel in the "glue language" role
+is Python's simple, usable, and powerful C language runtime API.
+<P>
+Many developers also use Python extensively as a graphical user
+interface development aide.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq01.017.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq01.017.htp">Log info</A>
+
+/ Last changed on Sat May 24 10:13:11 1997 by
+<A HREF="mailto:aaron_watters@msn.com">Aaron Watters</A>
+<P>
+
+<HR>
+<H2><A NAME="1.18">1.18. Can I use the FAQ Wizard software to maintain my own FAQ?</A></H2>
+Sure.  It's in Tools/faqwiz/ of the python source tree.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq01.018.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq01.018.htp">Log info</A>
+
+/ Last changed on Fri Mar 29 06:50:32 2002 by
+<A HREF="mailto:aahz@pythoncraft.com">Aahz</A>
+<P>
+
+<HR>
+<H2><A NAME="1.19">1.19. Which editor has good support for editing Python source code?</A></H2>
+On Unix, the first choice is Emacs/XEmacs.  There's an elaborate
+mode for editing Python code, which is available from the Python
+source distribution (Misc/python-mode.el).  It's also bundled
+with XEmacs (we're still working on legal details to make it possible
+to bundle it with FSF Emacs).  And it has its own web page:
+<P>
+<PRE>
+    <A HREF="http://www.python.org/emacs/python-mode/index.html">http://www.python.org/emacs/python-mode/index.html</A>
+</PRE>
+There are many other choices, for Unix, Windows or Macintosh.
+Richard Jones compiled a table from postings on the Python newsgroup:
+<P>
+<PRE>
+    <A HREF="http://www.bofh.asn.au/~richard/editors.html">http://www.bofh.asn.au/~richard/editors.html</A>
+</PRE>
+See also FAQ question 7.10 for some more Mac and Win options.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq01.019.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq01.019.htp">Log info</A>
+
+/ Last changed on Mon Jun 15 23:21:04 1998 by
+<A HREF="mailto:guido@python.org">Gvr</A>
+<P>
+
+<HR>
+<H2><A NAME="1.20">1.20. I've never programmed before. Is there a Python tutorial?</A></H2>
+There are several, and at least one book.  
+All information for beginning Python programmers is collected here:
+<P>
+<PRE>
+    <A HREF="http://www.python.org/doc/Newbies.html">http://www.python.org/doc/Newbies.html</A>
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq01.020.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq01.020.htp">Log info</A>
+
+/ Last changed on Wed Sep  5 05:34:07 2001 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="1.21">1.21. Where in the world is www.python.org located?</A></H2>
+It's currently in Amsterdam, graciously hosted by XS4ALL:
+<P>
+<PRE>
+    <A HREF="http://www.xs4all.nl">http://www.xs4all.nl</A>
+</PRE>
+Thanks to Thomas Wouters for setting this up!!!!
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq01.021.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq01.021.htp">Log info</A>
+
+/ Last changed on Fri Aug  3 21:49:27 2001 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H1>2. Python in the real world</H1>
+
+<HR>
+<H2><A NAME="2.1">2.1. How many people are using Python?</A></H2>
+Certainly thousands, and quite probably tens of thousands of users.
+More are seeing the light each day.  The comp.lang.python newsgroup is
+very active, but overall there is no accurate estimate of the number of subscribers or Python users.
+<P>
+Jacek Artymiak has created a Python Users Counter; you can see the 
+current count by visiting
+<A HREF="http://www.wszechnica.safenet.pl/cgi-bin/checkpythonuserscounter.py">http://www.wszechnica.safenet.pl/cgi-bin/checkpythonuserscounter.py</A>
+(this will not increment the counter; use the link there if you haven't
+added yourself already). Most Python users appear not to have registered themselves.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq02.001.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq02.001.htp">Log info</A>
+
+/ Last changed on Thu Feb 21 23:29:18 2002 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="2.2">2.2. Have any significant projects been done in Python?</A></H2>
+At CWI (the former home of Python), we have written a 20,000 line
+authoring environment for transportable hypermedia presentations, a
+5,000 line multimedia teleconferencing tool, as well as many many
+smaller programs.
+<P>
+At CNRI (Python's new home), we have written two large applications:
+Grail, a fully featured web browser (see
+<A HREF="http://grail.cnri.reston.va.us">http://grail.cnri.reston.va.us</A>),
+and the Knowbot Operating Environment,
+a distributed environment for mobile code.
+<P>
+The University of Virginia uses Python to control a virtual reality
+engine.  See <A HREF="http://alice.cs.cmu.edu">http://alice.cs.cmu.edu</A>.
+<P>
+The ILU project at Xerox PARC can generate Python glue for ILU
+interfaces.  See <A HREF="ftp://ftp.parc.xerox.com/pub/ilu/ilu.html">ftp://ftp.parc.xerox.com/pub/ilu/ilu.html</A>.  ILU
+is a free CORBA compliant ORB which supplies distributed object
+connectivity to a host of platforms using a host of languages.
+<P>
+Mark Hammond and Greg Stein and others are interfacing Python to
+Microsoft's COM and ActiveX architectures.  This means, among other
+things, that Python may be used in active server pages or as a COM
+controller (for example to automatically extract from or insert information
+into Excel or MSAccess or any other COM aware application).
+Mark claims Python can even be a ActiveX scripting host (which
+means you could embed JScript inside a Python application, if you
+had a strange sense of humor).  Python/AX/COM is distributed as part
+of the PythonWin distribution.
+<P>
+The University of California, Irvine uses a student administration
+system called TELE-Vision written entirely in Python.  Contact: Ray
+Price <A HREF="mailto:rlprice@uci.edu">rlprice@uci.edu</A>.
+<P>
+The Melbourne Cricket Ground (MCG) in Australia (a 100,000+ person venue)
+has it's scoreboard system written largely in Python on MS Windows.
+Python expressions are used to create almost every scoring entry that
+appears on the board.  The move to Python/C++ away from exclusive C++
+has provided a level of functionality that would simply not have been
+viable otherwise.
+<P>
+See also the next question.
+<P>
+Note: this FAQ entry is really old.
+See <A HREF="http://www.python.org/psa/Users.html">http://www.python.org/psa/Users.html</A> for a more recent list.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq02.002.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq02.002.htp">Log info</A>
+
+/ Last changed on Wed Oct 25 13:24:15 2000 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="2.3">2.3. Are there any commercial projects going on using Python?</A></H2>
+Yes, there's lots of commercial activity using Python.  See
+<A HREF="http://www.python.org/psa/Users.html">http://www.python.org/psa/Users.html</A> for a list.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq02.003.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq02.003.htp">Log info</A>
+
+/ Last changed on Wed Oct 14 18:17:33 1998 by
+<A HREF="mailto:klm@python.org">ken</A>
+<P>
+
+<HR>
+<H2><A NAME="2.4">2.4. How stable is Python?</A></H2>
+Very stable.  New, stable releases have been coming out roughly every 3 to 12 months since 1991, and this seems likely to continue.
+<P>
+With the introduction of retrospective "bugfix" releases the stability of the language implementations can be, and is being, improved independently of the new features offered by more recent major or minor releases. Bugfix releases, indicated by a third component of the version number, only fix known problems and do not gratuitously introduce new and possibly incompatible features or modified library functionality.
+<P>
+Release 2.2 got its first bugfix on April 10, 2002. The new version
+number is now 2.2.1. The 2.1 release, at 2.1.3, can probably be
+considered the "most stable" platform because it has been bugfixed
+twice.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq02.004.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq02.004.htp">Log info</A>
+
+/ Last changed on Tue Jul 23 10:20:04 2002 by
+<A HREF="mailto:kubieziel@gmx.de">Jens Kubieziel</A>
+<P>
+
+<HR>
+<H2><A NAME="2.5">2.5. What new developments are expected for Python in the future?</A></H2>
+See <A HREF="http://www.python.org/peps">http://www.python.org/peps</A>/ for the Python Enhancement 
+Proposals (PEPs). PEPs are design
+documents 
+describing a  suggested new feature for Python, providing
+a concise technical specification and a rationale.
+<P>
+Also, follow the discussions on the python-dev mailing list.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq02.005.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq02.005.htp">Log info</A>
+
+/ Last changed on Tue Apr  9 17:09:51 2002 by
+<A HREF="mailto:akuchlin@mems-exchange.org">A.M. Kuchling</A>
+<P>
+
+<HR>
+<H2><A NAME="2.6">2.6. Is it reasonable to propose incompatible changes to Python?</A></H2>
+In general, no.  There are already millions of lines of Python code
+around the world, so any changes in the language that invalidates more
+than a very small fraction of existing programs has to be frowned
+upon.  Even if you can provide a conversion program, there still is
+the problem of updating all documentation.  Providing a gradual
+upgrade path is the only way if a feature has to be changed.
+<P>
+See <A HREF="http://www.python.org/peps/pep-0005.html">http://www.python.org/peps/pep-0005.html</A> for the proposed
+mechanism for creating backwards-incompatibilities.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq02.006.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq02.006.htp">Log info</A>
+
+/ Last changed on Mon Apr  1 22:13:47 2002 by
+<A HREF="mailto:fdrake@acm.org">Fred Drake</A>
+<P>
+
+<HR>
+<H2><A NAME="2.7">2.7. What is the future of Python?</A></H2>
+Please see <A HREF="http://www.python.org/peps">http://www.python.org/peps</A>/ for proposals of future
+activities. One of the PEPs (Python Enhancement Proposals) deals
+with the PEP process and PEP format -- see
+<A HREF="http://www.python.org/peps/pep-0001.html">http://www.python.org/peps/pep-0001.html</A> if you want to
+submit a PEP. In <A HREF="http://www.python.org/peps/pep-0042.html">http://www.python.org/peps/pep-0042.html</A> there
+is a list of wishlists the Python Development team plans to tackle.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq02.007.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq02.007.htp">Log info</A>
+
+/ Last changed on Mon Apr  1 22:15:46 2002 by
+<A HREF="mailto:fdrake@acm.org">Fred Drake</A>
+<P>
+
+<HR>
+<H2><A NAME="2.8">2.8. What was the PSA, anyway?</A></H2>
+The Python Software Activity was
+created by a number of Python aficionados who want Python to be more
+than the product and responsibility of a single individual.
+The PSA was not an independent organization, but lived
+under the umbrealla of CNRI.
+<P>
+The PSA has been superseded by the Python Software Foundation,
+an independent non-profit organization.  The PSF's home page
+is at <A HREF="http://www.python.org/psf">http://www.python.org/psf</A>/.
+<P>
+Some pages created by the PSA still live at
+<A HREF="http://www.python.org/psa">http://www.python.org/psa</A>/
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq02.008.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq02.008.htp">Log info</A>
+
+/ Last changed on Thu Jul 25 18:19:44 2002 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="2.9">2.9. Deleted</A></H2>
+<P>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq02.009.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq02.009.htp">Log info</A>
+
+/ Last changed on Tue Jan  2 02:51:30 2001 by
+<A HREF="mailto:moshez@zadka.site.co.il">Moshe Zadka</A>
+<P>
+
+<HR>
+<H2><A NAME="2.10">2.10. Deleted</A></H2>
+<P>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq02.010.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq02.010.htp">Log info</A>
+
+/ Last changed on Tue Jan  2 02:52:19 2001 by
+<A HREF="mailto:moshez@zadka.site.co.il">Moshe Zadka</A>
+<P>
+
+<HR>
+<H2><A NAME="2.11">2.11. Is Python Y2K (Year 2000) Compliant?</A></H2>
+As of January, 2001 no major problems have been reported and Y2K
+compliance seems to be a non-issue.
+<P>
+Since Python is available free of charge, there are no absolute
+guarantees.  If there <I>are</I> unforeseen problems, liability is the
+user's rather than the developers', and there is nobody you can sue for damages.
+<P>
+Python does few 
+date manipulations, and what it does is all based on the Unix
+representation for time (even on non-Unix systems) which uses seconds
+since 1970 and won't overflow until 2038.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq02.011.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq02.011.htp">Log info</A>
+
+/ Last changed on Mon Jan  8 17:19:32 2001 by
+<A HREF="mailto:sholden@holdenweb.com">Steve Holden</A>
+<P>
+
+<HR>
+<H2><A NAME="2.12">2.12. Is Python a good language in a class for beginning programmers?</A></H2>
+Yes.  This long answer attempts to address any concerns you might
+have with teaching Python as a programmer's first language.  
+(If you want to discuss Python's use in education, then 
+you may be interested in joining the edu-sig mailinglist.
+See <A HREF="http://www.python.org/sigs/edu-sig">http://www.python.org/sigs/edu-sig</A>/ )
+<P>
+It is still common to start students with a procedural
+(subset of a) statically typed language such as Pascal, C, or
+a subset of C++ or Java.  I think that students may be better
+served by learning Python as their first language.  Python has
+a very simple and consistent syntax and a large standard library.
+Most importantly, using Python in a beginning programming course
+permits students to concentrate on important programming skills,
+such as problem decomposition and data type design.
+<P>
+With Python, students can be quickly introduced to basic concepts
+such as loops and procedures.  They can even probably work with
+user-defined objects in their very first course.  They could
+implement a tree structure as nested Python lists, for example.
+They could be introduced to objects in their first course if
+desired.  For a student who has never programmed before, using
+a statically typed language seems unnatural.  It presents
+additional complexity that the student must master and slows
+the pace of the course.  The students are trying to learn to
+think like a computer, decompose problems, design consistent
+interfaces, and encapsulate data.  While learning to use a
+statically typed language is important, it is not necessarily the
+best topic to address in the students' first programming course.
+<P>
+Many other aspects of Python make it a good first language.
+Python has a large standard library (like Java) so that
+students can be assigned programming projects very early in the
+course that <I>do</I> something.  Assignments aren't restricted to the
+standard four-function calculator and check balancing programs.
+By using the standard library, students can gain the satisfaction
+of working on realistic applications as they learn the fundamentals
+of programming.  Using the standard library also teaches students
+about code reuse.
+<P>
+Python's interactive interpreter also enables students to
+test language features while they're programming.  They can keep
+a window with the interpreter running while they enter their
+programs' source in another window.  If they can't remember the
+methods for a list, they can do something like this:
+<P>
+<PRE>
+ >>> L = []
+ >>> dir(L)
+ ['append', 'count', 'extend', 'index', 'insert', 'pop', 'remove',
+ 'reverse', 'sort']
+ >>> print L.append.__doc__
+ L.append(object) -- append object to end
+ >>> L.append(1)
+ >>> L
+ [1]
+</PRE>
+With the interpreter, documentation is never far from the
+student as he's programming.
+<P>
+There are also good IDEs for Python.  Guido van Rossum's IDLE
+is a cross-platform IDE for Python that is written in Python
+using Tk.  There is also a Windows specific IDE called PythonWin.
+Emacs users will be happy to know that there is a very good Python
+mode for Emacs.  All of these programming environments provide
+syntax highlighting, auto-indenting, and access to the interactive
+interpreter while coding.  For more information about IDEs, see XXX.
+<P>
+If your department is currently using Pascal because it was
+designed to be a teaching language, then you'll be happy to
+know that Guido van Rossum designed Python to be simple to
+teach to everyone but powerful enough to implement real world
+applications.  Python makes a good language for first time
+programmers because that was one of Python's design goals.
+There are papers at <A HREF="http://www.python.org/doc/essays">http://www.python.org/doc/essays</A>/ on the Python website 
+by Python's creator explaining his objectives for the language.
+One that may interest you is titled "Computer Programming for Everybody" 
+<A HREF="http://www.python.org/doc/essays/cp4e.html">http://www.python.org/doc/essays/cp4e.html</A>
+<P>
+If you're seriously considering Python as a language for your
+school,  Guido van Rossum may even be willing to correspond with
+you about how the language would fit in your curriculum.
+See <A HREF="http://www.python.org/doc/FAQ.html#2.2">http://www.python.org/doc/FAQ.html#2.2</A> for examples of
+Python's use in the "real world."
+<P>
+While Python, its source code, and its IDEs are freely
+available, this consideration should not rule 
+out other languages.  There are other free languages (Java, 
+free C compilers), and many companies are willing to waive some
+or all of their fees for student programming tools if it
+guarantees that a whole graduating class will know how to
+use their tools.  That is, if one of the requirements for 
+the language that will be taught is that it be freely 
+available, then Python qualifies, but this requirement 
+does not preclude other languages.
+<P>
+While Python jobs may not be as prevalent as C/C++/Java jobs,
+teachers should not worry about teaching students critical job
+skills in their first course.  The skills that win students a
+job are those they learn in their senior classes and internships.
+Their first programming courses are there to lay a solid
+foundation in programming fundamentals.  The primary question
+in choosing the language for such a course should be which
+language permits the students to learn this material without
+hindering or limiting them.
+<P>
+Another argument for Python is that there are many tasks for
+which something like C++ is overkill.  That's where languages
+like Python, Perl, Tcl, and Visual Basic thrive.  It's critical
+for students to know something about these languages.   (Every
+employer for whom I've worked used at least one such language.)
+Of the languages listed above, Python probably makes the best
+language in a programming curriculum since its syntax is simple,
+consistent, and not unlike other languages (C/C++/Java) that
+are probably in the curriculum.  By starting students with
+Python, a department simultaneously lays the foundations for
+other programming courses and introduces students to the type
+of language that is often used as a "glue" language.  As an
+added bonus, Python can be used to interface with Microsoft's
+COM components (thanks to Mark Hammond).  There is also Jython, 
+a Java implementation of the Python interpreter, that can be 
+used to connect Java components.
+<P>
+If you currently start students with Pascal or C/C++ or Java,
+you may be worried they will have trouble learning a statically
+typed language after starting with Python.  I think that this
+fear most often stems from the fact that the teacher started
+with a statically typed language, and we tend to like to teach
+others in the same way we were taught.  In reality, the
+transition from Python to one of these other languages is
+quite simple.
+<P>
+To motivate a statically typed language such as C++, begin the
+course by explaining that unlike Python, their first language,
+C++ is compiled to a machine dependent executable.  Explain
+that the point is to make a very fast executable.  To permit
+the compiler to make optimizations, programmers must help it
+by specifying the "types" of variables.  By restricting each
+variable to a specific type, the compiler can reduce the
+book-keeping it has to do to permit dynamic types.  The compiler
+also has to resolve references at compile time.  Thus, the
+language gains speed by sacrificing some of Python's dynamic
+features.  Then again, the C++ compiler provides type safety
+and catches many bugs at compile time instead of run time (a
+critical consideration for many commercial applications).  C++
+is also designed for very large programs where one may want to
+guarantee that others don't touch an object's implementation.
+C++ provides very strong language features to separate an object's
+implementation from its interface.  Explain why this separation
+is a good thing.
+<P>
+The first day of a C++ course could then be a whirlwind introduction
+to what C++ requires and provides.  The point here is that after
+a semester or two of Python, students are hopefully competent
+programmers.  They know how to handle loops and write procedures.
+They've also worked with objects, thought about the benefits of
+consistent interfaces, and used the technique of subclassing to
+specialize behavior.  Thus, a whirlwind introduction to C++ could
+show them how objects and subclassing looks in C++.  The
+potentially difficult concepts of object-oriented design were
+taught without the additional obstacles presented by a language
+such as C++ or Java.  When learning one of these languages,
+the students would already understand the "road map."  They
+understand objects; they would just be learning how objects
+fit in a statically typed languages.  Language requirements
+and compiler errors that seem unnatural to beginning programmers
+make sense in this new context.  Many students will find it
+helpful to be able to write a fast prototype of their algorithms
+in Python.  Thus, they can test and debug their ideas before
+they attempt to write the code in the new language, saving the
+effort of working with C++ types for when they've discovered a
+working solution for their assignments.  When they get annoyed
+with the rigidity of types, they'll be happy to learn about
+containers and templates to regain some of the lost flexibility
+Python afforded them.  Students may also gain an appreciation
+for the fact that no language is best for every task.  They'll
+see that C++ is faster, but they'll know that they can gain
+flexibility and development speed with a Python when execution
+speed isn't critical.
+<P>
+If you have any concerns that weren't addressed here, try
+posting to the Python newsgroup.  Others there have done some
+work with using Python as an instructional tool.  Good luck.
+We'd love to hear about it if you choose Python for your course.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq02.012.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq02.012.htp">Log info</A>
+
+/ Last changed on Mon Dec  2 19:32:35 2002 by
+<A HREF="mailto:sconce@in-spec-inc.com">Bill Sconce</A>
+<P>
+
+<HR>
+<H1>3. Building Python and Other Known Bugs</H1>
+
+<HR>
+<H2><A NAME="3.1">3.1. Is there a test set?</A></H2>
+Sure.  You can run it after building with "make test", or you can
+run it manually with this command at the Python prompt:
+<P>
+<PRE>
+ import test.autotest
+</PRE>
+In Python 1.4 or earlier, use
+<P>
+<PRE>
+ import autotest
+</PRE>
+The test set doesn't test <I>all</I> features of Python,
+but it goes a long way to confirm that Python is actually working.
+<P>
+NOTE: if "make test" fails, don't just mail the output to the
+newsgroup -- this doesn't give enough information to debug the
+problem.  Instead, find out which test fails, and run that test
+manually from an interactive interpreter.  For example, if
+"make test" reports that test_spam fails, try this interactively:
+<P>
+<PRE>
+ import test.test_spam
+</PRE>
+This generally produces more verbose output which can be diagnosed
+to debug the problem.  If you find a bug in Python or the libraries, or in the tests, please report this in the Python bug tracker at SourceForge:
+<P>
+<A HREF="http://sourceforge.net/tracker/?func=add&amp;group_id=5470&amp;atid=105470">http://sourceforge.net/tracker/?func=add&amp;group_id=5470&amp;atid=105470</A>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.001.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.001.htp">Log info</A>
+
+/ Last changed on Fri Apr 27 10:29:36 2001 by
+<A HREF="mailto:fdrake@acm.org">Fred Drake</A>
+<P>
+
+<HR>
+<H2><A NAME="3.2">3.2. When running the test set, I get complaints about floating point operations, but when playing with floating point operations I cannot find anything wrong with them.</A></H2>
+The test set makes occasional unwarranted assumptions about the
+semantics of C floating point operations.  Until someone donates a
+better floating point test set, you will have to comment out the
+offending floating point tests and execute similar tests manually.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.002.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.002.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="3.3">3.3. Link errors after rerunning the configure script.</A></H2>
+It is generally necessary to run "make clean" after a configuration
+change.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.003.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.003.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="3.4">3.4. The python interpreter complains about options passed to a script (after the script name).</A></H2>
+You are probably linking with GNU getopt, e.g. through -liberty.
+Don't.  The reason for the complaint is that GNU getopt, unlike System
+V getopt and other getopt implementations, doesn't consider a
+non-option to be the end of the option list.  A quick (and compatible)
+fix for scripts is to add "--" to the interpreter, like this:
+<P>
+<PRE>
+        #! /usr/local/bin/python --
+</PRE>
+You can also use this interactively:
+<P>
+<PRE>
+        python -- script.py [options]
+</PRE>
+Note that a working getopt implementation is provided in the Python
+distribution (in Python/getopt.c) but not automatically used.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.004.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.004.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="3.5">3.5. When building on the SGI, make tries to run python to create glmodule.c, but python hasn't been built or installed yet.</A></H2>
+Comment out the line mentioning glmodule.c in Setup and build a
+python without gl first; install it or make sure it is in your $PATH,
+then edit the Setup file again to turn on the gl module, and make
+again.  You don't need to do "make clean"; you do need to run "make
+Makefile" in the Modules subdirectory (or just run "make" at the
+toplevel).
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.005.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.005.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="3.6">3.6. I use VPATH but some targets are built in the source directory.</A></H2>
+On some systems (e.g. Sun), if the target already exists in the
+source directory, it is created there instead of in the build
+directory.  This is usually because you have previously built without
+VPATH.  Try running "make clobber" in the source directory.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.006.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.006.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="3.7">3.7. Trouble building or linking with the GNU readline library.</A></H2>
+You can use the GNU readline library to improve the interactive user
+interface: this gives you line editing and command history when
+calling python interactively. Its sources are distributed with 
+Python (at least for 2.0).  Uncomment the line 
+<P>
+#readline readline.c -lreadline -ltermcap
+<P>
+in Modules/Setup.  The configuration option --with-readline 
+is no longer supported, at least in Python 2.0.  Some hints on 
+building and using the readline library:
+On SGI IRIX 5, you may have to add the following
+to rldefs.h:
+<P>
+<PRE>
+        #ifndef sigmask
+        #define sigmask(sig) (1L &lt;&lt; ((sig)-1))
+        #endif
+</PRE>
+On some systems, you will have to add #include "rldefs.h" to the
+top of several source files, and if you use the VPATH feature, you
+will have to add dependencies of the form foo.o: foo.c to the
+Makefile for several values of foo.
+The readline library requires use of the termcap library. A
+known problem with this is that it contains entry points which
+cause conflicts with the STDWIN and SGI GL libraries. The STDWIN
+conflict can be solved by adding a line saying '#define werase w_erase' to the
+stdwin.h file (in the STDWIN distribution, subdirectory H). The
+GL conflict has been solved in the Python configure script by a
+hack that forces use of the static version of the termcap library.
+Check the newsgroup gnu.bash.bug news:gnu.bash.bug for
+specific problems with the readline library (I don't read this group
+but I've been told that it is the place for readline bugs).
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.007.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.007.htp">Log info</A>
+
+/ Last changed on Sat Dec  2 18:23:48 2000 by
+<A HREF="mailto:trotts@llnl.gov">Issac Trotts</A>
+<P>
+
+<HR>
+<H2><A NAME="3.8">3.8. Trouble with socket I/O on older Linux 1.x versions.</A></H2>
+Once you've built Python, use it to run the regen script in the
+Lib/plat-linux2 directory.  Apparently the files as distributed don't match the system headers on some Linux versions.
+<P>
+Note that this FAQ entry only applies to Linux kernel versions 1.x.y;
+these are hardly around any more.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.008.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.008.htp">Log info</A>
+
+/ Last changed on Tue Jul 30 20:05:52 2002 by
+<A HREF="mailto:kubieziel@gmx.de">Jens Kubieziel</A>
+<P>
+
+<HR>
+<H2><A NAME="3.9">3.9. Trouble with prototypes on Ultrix.</A></H2>
+Ultrix cc seems broken -- use gcc, or edit config.h to #undef
+HAVE_PROTOTYPES.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.009.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.009.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="3.10">3.10. Other trouble building Python on platform X.</A></H2>
+Please submit the details to the SourceForge bug tracker:
+<P>
+<PRE>
+  <A HREF="http://sourceforge.net/tracker/?group_id=5470&amp;atid=105470">http://sourceforge.net/tracker/?group_id=5470&amp;atid=105470</A>
+</PRE>
+and we'll look
+into it.  Please provide as many details as possible.  In particular,
+if you don't tell us what type of computer and what operating system
+(and version) you are using it will be difficult for us to figure out
+what is the matter.  If you have compilation output logs,
+please use file uploads -- don't paste everything in the message box.
+<P>
+In many cases, we won't have access to the same hardware or operating system version, so <I>please</I>, if you have a SourceForge account, log in before filing your report, or if you don't have an account, include an email address at which we can reach you for further questions.  Logging in to SourceForge first will also cause SourceForge to send you updates as we act on your report.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.010.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.010.htp">Log info</A>
+
+/ Last changed on Fri Apr 27 10:53:18 2001 by
+<A HREF="mailto:fdrake@acm.org">Fred Drake</A>
+<P>
+
+<HR>
+<H2><A NAME="3.11">3.11. How to configure dynamic loading on Linux.</A></H2>
+This is now automatic as long as your Linux version uses the ELF
+object format (all recent Linuxes do).
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.011.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.011.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="3.12">3.12. I can't get shared modules to work on Linux 2.0 (Slackware96)?</A></H2>
+This is a bug in the Slackware96 release. The fix is simple: Make sure
+that there is a link from /lib/libdl.so to /lib/libdl.so.1 so that the
+following links are setup: /lib/libdl.so -&gt; /lib/libdl.so.1
+/lib/libdl.so.1 -&gt; /lib/libdl.so.1.7.14 You may have to rerun the
+configure script, after rm'ing the config.cache file, before you
+attempt to rebuild python after this fix.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.012.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.012.htp">Log info</A>
+
+/ Last changed on Wed May 21 15:45:03 1997 by
+<A HREF="mailto:guido2@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="3.13">3.13. Trouble when making modules shared on Linux.</A></H2>
+This happens when you have built Python for static linking and then
+enable
+<PRE>
+  *shared*
+</PRE>
+in the Setup file.  Shared library code must be
+compiled with "-fpic".  If a .o file for the module already exist that
+was compiled for static linking, you must remove it or do "make clean"
+in the Modules directory.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.013.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.013.htp">Log info</A>
+
+/ Last changed on Fri May 23 13:42:30 1997 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="3.14">3.14. [deleted]</A></H2>
+[ancient information on threads on linux (when thread support
+was not standard) used to be here]
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.014.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.014.htp">Log info</A>
+
+/ Last changed on Sun Jun  2 17:27:13 2002 by
+<A HREF="mailto:erno-pyfaq@erno.iki.fi">Erno Kuusela</A>
+<P>
+
+<HR>
+<H2><A NAME="3.15">3.15. Errors when linking with a shared library containing C++ code.</A></H2>
+Link the main Python binary with C++.  Change the definition of
+LINKCC in Modules/Makefile to be your C++ compiler.  You may have to
+edit config.c slightly to make it compilable with C++.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.015.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.015.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="3.16">3.16. Deleted</A></H2>
+<P>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.016.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.016.htp">Log info</A>
+
+/ Last changed on Tue Sep 11 16:02:22 2001 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="3.17">3.17. Deleted.</A></H2>
+<P>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.017.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.017.htp">Log info</A>
+
+/ Last changed on Tue Sep 11 15:54:57 2001 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="3.18">3.18. Compilation or link errors for the _tkinter module</A></H2>
+Most likely, there's a version mismatch between the Tcl/Tk header
+files (tcl.h and tk.h) and the Tcl/Tk libraries you are using e.g.
+"-ltk8.0" and "-ltcl8.0" arguments for _tkinter in the Setup file).
+It is possible to install several versions of the Tcl/Tk libraries,
+but there can only be one version of the tcl.h and tk.h header
+files.  If the library doesn't match the header, you'll get
+problems, either when linking the module, or when importing it.
+Fortunately, the version number is clearly stated in each file,
+so this is easy to find.  Reinstalling and using the latest
+version usually fixes the problem.
+<P>
+(Also note that when compiling unpatched Python 1.5.1 against
+Tcl/Tk 7.6/4.2 or older, you get an error on Tcl_Finalize.  See
+the 1.5.1 patch page at <A HREF="http://www.python.org/1.5/patches-1.5.1">http://www.python.org/1.5/patches-1.5.1</A>/.)
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.018.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.018.htp">Log info</A>
+
+/ Last changed on Thu Jun 11 00:49:14 1998 by
+<A HREF="mailto:guido@python.org">Gvr</A>
+<P>
+
+<HR>
+<H2><A NAME="3.19">3.19. I configured and built Python for Tcl/Tk but &quot;import Tkinter&quot; fails.</A></H2>
+Most likely, you forgot to enable the line in Setup that says
+"TKPATH=:$(DESTLIB)/tkinter".
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.019.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.019.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="3.20">3.20. [deleted]</A></H2>
+[ancient information on a gcc+tkinter bug on alpha was here]
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.020.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.020.htp">Log info</A>
+
+/ Last changed on Mon Jun  3 16:46:23 2002 by
+<A HREF="mailto:erno-pyfaq@erno.iki.fi">Erno Kuusela</A>
+<P>
+
+<HR>
+<H2><A NAME="3.21">3.21. Several common system calls are missing from the posix module.</A></H2>
+Most likely, <I>all</I> test compilations run by the configure script
+are failing for some reason or another.  Have a look in config.log to
+see what could be the reason.  A common reason is specifying a
+directory to the --with-readline option that doesn't contain the
+libreadline.a file.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.021.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.021.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="3.22">3.22. ImportError: No module named string, on MS Windows.</A></H2>
+Most likely, your PYTHONPATH environment variable should be set to
+something like:
+<P>
+set PYTHONPATH=c:\python;c:\python\lib;c:\python\scripts
+<P>
+(assuming Python was installed in c:\python)
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.022.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.022.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="3.23">3.23. Core dump on SGI when using the gl module.</A></H2>
+There are conflicts between entry points in the termcap and curses
+libraries and an entry point in the GL library.  There's a hack of a
+fix for the termcap library if it's needed for the GNU readline
+library, but it doesn't work when you're using curses.  Concluding,
+you can't build a Python binary containing both the curses and gl
+modules.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.023.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.023.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="3.24">3.24. &quot;Initializer not a constant&quot; while building DLL on MS-Windows</A></H2>
+Static type object initializers in extension modules may cause compiles to
+fail with an error message like "initializer not a constant".  
+Fredrik Lundh &lt;<A HREF="mailto:Fredrik.Lundh@image.combitech.se">Fredrik.Lundh@image.combitech.se</A>&gt; explains:
+<P>
+This shows up when building DLL under MSVC.  There's two ways to
+address this: either compile the module as C++, or change your code to
+something like:
+<P>
+<PRE>
+  statichere PyTypeObject bstreamtype = {
+      PyObject_HEAD_INIT(NULL) /* must be set by init function */
+      0,
+      "bstream",
+      sizeof(bstreamobject),
+</PRE>
+<PRE>
+  ...
+</PRE>
+<PRE>
+  void
+  initbstream()
+  {
+      /* Patch object type */
+      bstreamtype.ob_type = &amp;PyType_Type;
+      Py_InitModule("bstream", functions);
+      ...
+  }
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.024.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.024.htp">Log info</A>
+
+/ Last changed on Sun May 25 14:58:05 1997 by
+<A HREF="mailto:aaron_watters@msn.com">Aaron Watters</A>
+<P>
+
+<HR>
+<H2><A NAME="3.25">3.25. Output directed to a pipe or file disappears on Linux.</A></H2>
+Some people have reported that when they run their script
+interactively, it runs great, but that when they redirect it
+to a pipe or file, no output appears.
+<P>
+<PRE>
+    % python script.py
+    ...some output...
+    % python script.py >file
+    % cat file
+    % # no output
+    % python script.py | cat
+    % # no output
+    %
+</PRE>
+This was a bug in Linux kernel. It is fixed and should not appear anymore. So most Linux users are <I>not</I> affected by this.
+<P>
+If redirection doesn't work on your Linux system, check what shell you are using. Shells like (t)csh doesn't support redirection.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.025.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.025.htp">Log info</A>
+
+/ Last changed on Thu Jan 16 13:38:30 2003 by
+<A HREF="mailto:kubieziel@gmx.de">Jens Kubieziel</A>
+<P>
+
+<HR>
+<H2><A NAME="3.26">3.26. [deleted]</A></H2>
+[ancient libc/linux problem was here]
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.026.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.026.htp">Log info</A>
+
+/ Last changed on Mon Jun  3 16:48:08 2002 by
+<A HREF="mailto:erno-pyfaq@erno.iki.fi">Erno Kuusela</A>
+<P>
+
+<HR>
+<H2><A NAME="3.27">3.27. [deleted]</A></H2>
+[ancient linux + threads + tk problem was described here]
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.027.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.027.htp">Log info</A>
+
+/ Last changed on Mon Jun  3 16:49:08 2002 by
+<A HREF="mailto:erno-pyfaq@erno.iki.fi">Erno Kuusela</A>
+<P>
+
+<HR>
+<H2><A NAME="3.28">3.28. How can I test if Tkinter is working?</A></H2>
+Try the following:
+<P>
+<PRE>
+  python
+  >>> import _tkinter
+  >>> import Tkinter
+  >>> Tkinter._test()
+</PRE>
+This should pop up a window with two buttons,
+one "Click me" and one "Quit".
+<P>
+If the first statement (import _tkinter) fails, your Python
+installation probably has not been configured to support Tcl/Tk.
+On Unix, if you have installed Tcl/Tk, you have to rebuild Python
+after editing the Modules/Setup file to enable the _tkinter module
+and the TKPATH environment variable.
+<P>
+It is also possible to get complaints about Tcl/Tk version
+number mismatches or missing TCL_LIBRARY or TK_LIBRARY
+environment variables.  These have to do with Tcl/Tk installation
+problems.
+<P>
+A common problem is to have installed versions of tcl.h and tk.h
+that don't match the installed version of the Tcl/Tk libraries;
+this usually results in linker errors or (when using dynamic
+loading) complaints about missing symbols during loading
+the shared library.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.028.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.028.htp">Log info</A>
+
+/ Last changed on Thu Aug 28 17:01:46 1997 by
+<A HREF="mailto:guido@python.org">Guido van Rossum</A>
+<P>
+
+<HR>
+<H2><A NAME="3.29">3.29. Is there a way to get the interactive mode of the python interpreter to perform function/variable name completion?</A></H2>
+(From a posting by Guido van Rossum)
+<P>
+On Unix, if you have enabled the readline module (i.e. if Emacs-style
+command line editing and bash-style history works for you), you can
+add this by importing the undocumented standard library module
+"rlcompleter".  When completing a simple identifier, it
+completes keywords, built-ins and globals in __main__; when completing
+NAME.NAME..., it evaluates (!) the expression up to the last dot and
+completes its attributes.
+<P>
+This way, you can do "import string", type "string.", hit the
+completion key twice, and see the list of names defined by the
+string module.
+<P>
+Tip: to use the tab key as the completion key, call
+<P>
+<PRE>
+    readline.parse_and_bind("tab: complete")
+</PRE>
+You can put this in a ~/.pythonrc file, and set the PYTHONSTARTUP
+environment variable to ~/.pythonrc.  This will cause the completion to be enabled
+whenever you run Python interactively.  
+<P>
+Notes (see the docstring for rlcompleter.py for more information):
+<P>
+* The evaluation of the NAME.NAME... form may cause arbitrary 
+application defined code to be executed if an object with a
+__getattr__ hook is found.  Since it is the responsibility of the
+application (or the user) to enable this feature, I consider this an
+acceptable risk.  More complicated expressions (e.g. function calls or
+indexing operations) are <I>not</I> evaluated.
+<P>
+* GNU readline is also used by the built-in functions input() and
+raw_input(), and thus these also benefit/suffer from the complete
+features.  Clearly an interactive application can benefit by
+specifying its own completer function and using raw_input() for all
+its input.
+<P>
+* When stdin is not a tty device, GNU readline is never
+used, and this module (and the readline module) are silently inactive.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.029.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.029.htp">Log info</A>
+
+/ Last changed on Fri Jun 12 09:55:24 1998 by
+<A HREF="mailto:akuchlin@cnri.reston.va.us">A.M. Kuchling</A>
+<P>
+
+<HR>
+<H2><A NAME="3.30">3.30. Why is the Python interpreter not built as a shared library?</A></H2>
+(This is a Unix question; on Mac and Windows, it <I>is</I> a shared
+library.)
+<P>
+It's just a nightmare to get this to work on all different platforms.
+Shared library portability is a pain.  And yes, I know about GNU libtool
+-- but it requires me to use its conventions for filenames etc, and it 
+would require a complete and utter rewrite of all the makefile and
+config tools I'm currently using.
+<P>
+In practice, few applications embed Python -- it's much more common to
+have Python extensions, which already are shared libraries.  Also,
+serious embedders often want total control over which Python version
+and configuration they use so they wouldn't want to use a standard
+shared library anyway.  So while the motivation of saving space
+when lots of apps embed Python is nice in theory, I
+doubt that it will save much in practice.  (Hence the low priority I
+give to making a shared library.)
+<P>
+For Linux systems, the simplest method of producing libpython1.5.so seems to 
+be (originally from the Minotaur project web page,  
+<A HREF="http://www.equi4.com/minotaur/minotaur.html">http://www.equi4.com/minotaur/minotaur.html</A>): 
+<P>
+<PRE>
+  make distclean 
+  ./configure 
+  make OPT="-fpic -O2" 
+  mkdir .extract 
+  (cd .extract; ar xv ../libpython1.5.a) 
+  gcc -shared -o libpython1.5.so .extract/*.o 
+  rm -rf .extract
+</PRE>
+In Python 2.3 this will be supported by the standard build routine
+(at least on Linux) with --enable-shared.  Note however that there
+is little advantage, and it slows down Python because of the need
+for PIC code and the extra cost at startup time to find the library.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.030.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.030.htp">Log info</A>
+
+/ Last changed on Thu May 30 13:36:55 2002 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="3.31">3.31. Build with GCC on Solaris 2.6 (SunOS 5.6) fails</A></H2>
+If you have upgraded Solaris 2.5 or 2.5.1 to Solaris 2.6,
+but you have not upgraded
+your GCC installation, the compile may fail, e.g. like this:
+<P>
+<PRE>
+ In file included from /usr/include/sys/stream.h:26,
+                  from /usr/include/netinet/in.h:38,
+                  from /usr/include/netdb.h:96,
+                  from ./socketmodule.c:121:
+ /usr/include/sys/model.h:32: #error "No DATAMODEL_NATIVE specified"
+</PRE>
+Solution: rebuild GCC for Solaris 2.6. 
+You might be able to simply re-run fixincludes, but
+people have had mixed success with doing that.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.031.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.031.htp">Log info</A>
+
+/ Last changed on Wed Oct 21 11:18:46 1998 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="3.32">3.32. Running &quot;make clean&quot; seems to leave problematic files that cause subsequent builds to fail.</A></H2>
+Use "make clobber" instead.  
+<P>
+Use "make clean" to reduce the size of the source/build directory
+after you're happy with your build and installation.
+If you have already tried to build python and you'd like to start 
+over, you should use "make clobber".  It does a "make clean" and also 
+removes files such as the partially built Python library from a previous build.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.032.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.032.htp">Log info</A>
+
+/ Last changed on Thu Jun 24 20:39:26 1999 by
+<A HREF="mailto:tbryan@python.net">TAB</A>
+<P>
+
+<HR>
+<H2><A NAME="3.33">3.33. Submitting bug reports and patches</A></H2>
+To report a bug or submit a patch, please use the relevant service
+from the Python project at SourceForge.
+<P>
+Bugs: <A HREF="http://sourceforge.net/tracker/?group_id=5470&amp;atid=105470">http://sourceforge.net/tracker/?group_id=5470&amp;atid=105470</A>
+<P>
+Patches: <A HREF="http://sourceforge.net/tracker/?group_id=5470&amp;atid=305470">http://sourceforge.net/tracker/?group_id=5470&amp;atid=305470</A>
+<P>
+If you have a SourceForge account, please log in before submitting your bug report; this will make it easier for us to contact you regarding your report in the event we have follow-up questions.  It will also enable SourceForge to send you update information as we act on your bug.  If you do not have a SourceForge account, please consider leaving your name and email address as part of the report.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.033.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.033.htp">Log info</A>
+
+/ Last changed on Fri Apr 27 10:58:26 2001 by
+<A HREF="mailto:fdrake@acm.org">Fred Drake</A>
+<P>
+
+<HR>
+<H2><A NAME="3.34">3.34. I can't load shared libraries under Python 1.5.2, Solaris 7, and gcc 2.95.2</A></H2>
+When trying to load shared libraries, you may see errors like:
+ImportError: ld.so.1: python: fatal: relocation error: file /usr/local/lib/python1.5/site-packages/Perp/util/du_SweepUtilc.so:
+<PRE>
+ symbol PyExc_RuntimeError: referenced symbol not found
+</PRE>
+<P>
+There is a problem with the configure script for Python 1.5.2
+under Solaris 7 with gcc 2.95 .  configure should set the make variable
+LINKFORSHARED=-Xlinker -export-dynamic
+<P>
+<P>
+in Modules/Makefile, 
+<P>
+Manually add this line to the Modules/Makefile.
+This builds a Python executable that can load shared library extensions (xxx.so) .
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.034.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.034.htp">Log info</A>
+
+/ Last changed on Mon Feb 19 10:37:05 2001 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="3.35">3.35. In the regression test, test___all__ fails for the profile module. What's wrong?</A></H2>
+If you have been using the profile module, and have properly calibrated a copy of the module as described in the documentation for the profiler:
+<P>
+<A HREF="http://www.python.org/doc/current/lib/profile-calibration.html">http://www.python.org/doc/current/lib/profile-calibration.html</A>
+<P>
+then it is possible that the regression test "test___all__" will fail if you run the regression test manually rather than using "make test" in the Python source directory.  This will happen if you have set your PYTHONPATH environment variable to include the directory containing your calibrated profile module.  You have probably calibrated the profiler using an older version of the profile module which does not define the __all__ value, added to the module as of Python 2.1.
+<P>
+The problem can be fixed by removing the old calibrated version of the profile module and using the latest version to do a fresh calibration. In general, you will need to re-calibrate for each version of Python anyway, since the performance characteristics can change in subtle ways that impact profiling.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.035.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.035.htp">Log info</A>
+
+/ Last changed on Fri Apr 27 10:44:10 2001 by
+<A HREF="mailto:fdrake@acm.org">Fred Drake</A>
+<P>
+
+<HR>
+<H2><A NAME="3.36">3.36. relocations remain against allocatable but non-writable sections</A></H2>
+This linker error occurs on Solaris if you attempt to build an extension module which incorporates position-dependent (non-PIC) code. A common source of problems is that a static library (.a file), such as libreadline.a or libcrypto.a is linked with the extension module. The error specifically occurs when using gcc as the compiler, but /usr/ccs/bin/ld as the linker.
+<P>
+The following solutions and work-arounds are known:
+<P>
+1. Rebuild the libraries (libreadline, libcrypto) with -fPIC (-KPIC if using the system compiler). This is recommended; all object files in a shared library should be position-independent.
+<P>
+2. Statically link the extension module and its libraries into the Python interpreter, by editing Modules/Setup.
+<P>
+3. Use GNU ld instead of /usr/ccs/bin/ld; GNU ld will accept non-PIC code in shared libraries (and mark the section writable)
+<P>
+4. Pass -mimpure-text to GCC when linking the module. This will force gcc to not pass -z text to ld; in turn, ld will make all text sections writable.
+<P>
+Options 3 and 4 are not recommended, since the ability to share code across processes is lost.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq03.036.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq03.036.htp">Log info</A>
+
+/ Last changed on Tue Jan 29 12:05:11 2002 by
+<A HREF="mailto:loewis@informatik.hu-berlin.de">Martin v. Löwis</A>
+<P>
+
+<HR>
+<H1>4. Programming in Python</H1>
+
+<HR>
+<H2><A NAME="4.1">4.1. Is there a source code level debugger with breakpoints, step, etc.?</A></H2>
+Yes.  
+<P>
+Module pdb is a rudimentary but adequate console-mode debugger for Python. It is part of the standard Python library, and is documented in the Library Reference Manual. (You can also write your own debugger by using the code for pdb as an example.)
+<P>
+The IDLE interactive development environment, which is part of the standard Python distribution (normally available in Tools/idle), includes a graphical debugger.  There is documentation for the IDLE debugger at <A HREF="http://www.python.org/idle/doc/idle2.html#Debugger">http://www.python.org/idle/doc/idle2.html#Debugger</A>
+<P>
+Pythonwin is a Python IDE that includes a GUI debugger based on bdb.  The Pythonwin debugger colors breakpoints and has quite a few cool features (including debugging non-Pythonwin programs).  A reference can be found at <A HREF="http://www.python.org/ftp/python/pythonwin/pwindex.html">http://www.python.org/ftp/python/pythonwin/pwindex.html</A>
+More recent versions of PythonWin are available as a part of the ActivePython distribution (see   <A HREF="http://www.activestate.com/Products/ActivePython/index.html">http://www.activestate.com/Products/ActivePython/index.html</A>).
+<P>
+Pydb is a version of the standard Python debugger pdb, modified for use with DDD (Data Display Debugger), a popular graphical debugger front end.  Pydb can be found at  <A HREF="http://packages.debian.org/unstable/devel/pydb.html">http://packages.debian.org/unstable/devel/pydb.html</A>
+and DDD can be found at <A HREF="http://www.gnu.org/software/ddd">http://www.gnu.org/software/ddd</A>/
+<P>
+There are a number of commmercial Python IDEs that include graphical debuggers.  They include:
+<P>
+<PRE>
+ * Wing IDE (<A HREF="http://wingide.com">http://wingide.com</A>/) 
+ * Komodo IDE (<A HREF="http://www.activestate.com/Products/Komodo">http://www.activestate.com/Products/Komodo</A>/)
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.001.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.001.htp">Log info</A>
+
+/ Last changed on Tue Jan 28 01:43:41 2003 by
+<A HREF="mailto:steve@ferg.org">Stephen Ferg</A>
+<P>
+
+<HR>
+<H2><A NAME="4.2">4.2. Can I create an object class with some methods implemented in C and others in Python (e.g. through inheritance)? (Also phrased as: Can I use a built-in type as base class?)</A></H2>
+In Python 2.2, you can inherit from builtin classes such as int, list, dict, etc.
+<P>
+In previous versions of Python, you can easily create a Python class which serves as a wrapper around a built-in object, e.g. (for dictionaries):
+<P>
+<PRE>
+        # A user-defined class behaving almost identical
+        # to a built-in dictionary.
+        class UserDict:
+                def __init__(self): self.data = {}
+                def __repr__(self): return repr(self.data)
+                def __cmp__(self, dict):
+                        if type(dict) == type(self.data):
+                                return cmp(self.data, dict)
+                        else:
+                                return cmp(self.data, dict.data)
+                def __len__(self): return len(self.data)
+                def __getitem__(self, key): return self.data[key]
+                def __setitem__(self, key, item): self.data[key] = item
+                def __delitem__(self, key): del self.data[key]
+                def keys(self): return self.data.keys()
+                def items(self): return self.data.items()
+                def values(self): return self.data.values()
+                def has_key(self, key): return self.data.has_key(key)
+</PRE>
+A2. See Jim Fulton's ExtensionClass for an example of a mechanism
+which allows you to have superclasses which you can inherit from in
+Python -- that way you can have some methods from a C superclass (call
+it a mixin) and some methods from either a Python superclass or your
+subclass.  ExtensionClass is distributed as a part of Zope (see
+<A HREF="http://www.zope.org">http://www.zope.org</A>), but will be phased out with Zope 3, since
+Zope 3 uses Python 2.2 or later which supports direct inheritance
+from built-in types.  Here's a link to the original paper about
+ExtensionClass:
+<A HREF="http://debian.acm.ndsu.nodak.edu/doc/python-extclass/ExtensionClass.html">http://debian.acm.ndsu.nodak.edu/doc/python-extclass/ExtensionClass.html</A>
+<P>
+A3. The Boost Python Library (BPL, <A HREF="http://www.boost.org/libs/python/doc/index.html">http://www.boost.org/libs/python/doc/index.html</A>)
+provides a way of doing this from C++ (i.e. you can inherit from an
+extension class written in C++ using the BPL).
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.002.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.002.htp">Log info</A>
+
+/ Last changed on Tue May 28 21:09:52 2002 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="4.3">4.3. Is there a curses/termcap package for Python?</A></H2>
+The standard Python source distribution comes with a curses module in
+the Modules/ subdirectory, though it's not compiled by default (note
+that this is not available in the Windows distribution -- there is
+no curses module for Windows).
+<P>
+In Python versions before 2.0 the module only supported plain curses; 
+you couldn't use ncurses features like colors with it (though it would 
+link with ncurses).
+<P>
+In Python 2.0, the curses module has been greatly extended, starting 
+from Oliver Andrich's enhanced version, to provide many additional 
+functions from ncurses and SYSV curses, such as colour, alternative
+character set support, pads, and mouse support. This means the
+module is no longer compatible with operating systems that only
+have BSD curses, but there don't seem to be any currently
+maintained OSes that fall into this category.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.003.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.003.htp">Log info</A>
+
+/ Last changed on Sun Jun 23 20:24:06 2002 by
+<A HREF="mailto:tim.one@comcast.net">Tim Peters</A>
+<P>
+
+<HR>
+<H2><A NAME="4.4">4.4. Is there an equivalent to C's onexit() in Python?</A></H2>
+For Python 2.0: The new atexit module provides a register function that
+is similar to C's onexit. See the Library Reference for details. For
+2.0 you should <I>not</I> assign to sys.exitfunc!
+<P>
+For Python 1.5.2: You need to import sys and assign a function to 
+sys.exitfunc, it will be called when your program exits, is 
+killed by an unhandled exception, or (on UNIX) receives a 
+SIGHUP or SIGTERM signal.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.004.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.004.htp">Log info</A>
+
+/ Last changed on Thu Dec 28 12:14:55 2000 by
+<A HREF="mailto:pbjorn@uswest.net">Bjorn Pettersen</A>
+<P>
+
+<HR>
+<H2><A NAME="4.5">4.5. [deleted]</A></H2>
+[python used to lack nested scopes, it was explained here]
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.005.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.005.htp">Log info</A>
+
+/ Last changed on Thu Mar 21 05:18:22 2002 by
+<A HREF="mailto:erno-pyfaq@erno.iki.fi">Erno Kuusela</A>
+<P>
+
+<HR>
+<H2><A NAME="4.6">4.6. How do I iterate over a sequence in reverse order?</A></H2>
+If it is a list, the fastest solution is\r
+<P>
+<PRE>
+        list.reverse()\r
+        try:\r
+                for x in list:\r
+                        "do something with x"\r
+        finally:\r
+                list.reverse()\r
+</PRE>
+This has the disadvantage that while you are in the loop, the list\r
+is temporarily reversed.  If you don't like this, you can make a copy.\r
+This appears expensive but is actually faster than other solutions:\r
+<P>
+<PRE>
+        rev = list[:]\r
+        rev.reverse()\r
+        for x in rev:\r
+                &lt;do something with x&gt;\r
+</PRE>
+If it's not a list, a more general but slower solution is:\r
+<P>
+<PRE>
+        for i in range(len(sequence)-1, -1, -1):\r
+                x = sequence[i]\r
+                &lt;do something with x&gt;\r
+</PRE>
+A more elegant solution, is to define a class which acts as a sequence\r
+and yields the elements in reverse order (solution due to Steve\r
+Majewski):\r
+<P>
+<PRE>
+        class Rev:\r
+                def __init__(self, seq):\r
+                        self.forw = seq\r
+                def __len__(self):\r
+                        return len(self.forw)\r
+                def __getitem__(self, i):\r
+                        return self.forw[-(i + 1)]\r
+</PRE>
+You can now simply write:\r
+<P>
+<PRE>
+        for x in Rev(list):\r
+                &lt;do something with x&gt;\r
+</PRE>
+Unfortunately, this solution is slowest of all, due to the method\r
+call overhead...
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.006.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.006.htp">Log info</A>
+
+/ Last changed on Sun May 25 21:10:50 1997 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="4.7">4.7. My program is too slow. How do I speed it up?</A></H2>
+That's a tough one, in general.  There are many tricks to speed up
+Python code; I would consider rewriting parts in C only as a last
+resort.  One thing to notice is that function and (especially) method
+calls are rather expensive; if you have designed a purely OO interface
+with lots of tiny functions that don't do much more than get or set an
+instance variable or call another method, you may consider using a
+more direct way, e.g. directly accessing instance variables.  Also see
+the standard module "profile" (described in the Library Reference
+manual) which makes it possible to find out where
+your program is spending most of its time (if you have some patience
+-- the profiling itself can slow your program down by an order of
+magnitude).
+<P>
+Remember that many standard optimization heuristics you
+may know from other programming experience may well apply
+to Python.  For example it may be faster to send output to output
+devices using larger writes rather than smaller ones in order to
+avoid the overhead of kernel system calls.  Thus CGI scripts
+that write all output in "one shot" may be notably faster than
+those that write lots of small pieces of output.
+<P>
+Also, be sure to use "aggregate" operations where appropriate.
+For example the "slicing" feature allows programs to chop up
+lists and other sequence objects in a single tick of the interpreter
+mainloop using highly optimized C implementations.  Thus to 
+get the same effect as
+<P>
+<PRE>
+  L2 = []
+  for i in range[3]:
+       L2.append(L1[i])
+</PRE>
+it is much shorter and far faster to use
+<P>
+<PRE>
+  L2 = list(L1[:3]) # "list" is redundant if L1 is a list.
+</PRE>
+Note that the map() function, particularly used with
+builtin methods or builtin functions can be a convenient
+accelerator.  For example to pair the elements of two
+lists together:
+<P>
+<PRE>
+  >>> map(None, [1,2,3], [4,5,6])
+  [(1, 4), (2, 5), (3, 6)]
+</PRE>
+or to compute a number of sines:
+<P>
+<PRE>
+  >>> map( math.sin, (1,2,3,4))
+  [0.841470984808, 0.909297426826, 0.14112000806,   -0.756802495308]
+</PRE>
+The map operation completes very quickly in such cases.
+<P>
+Other examples of aggregate operations include the join and split
+methods of string objects.  For example if s1..s7 are large (10K+) strings then
+"".join([s1,s2,s3,s4,s5,s6,s7]) may be far faster than
+the more obvious s1+s2+s3+s4+s5+s6+s7, since the "summation"
+will compute many subexpressions, whereas join does all
+copying in one pass.  For manipulating strings also consider the 
+regular expression libraries and the "substitution" operations
+String % tuple and String % dictionary.  Also be sure to use
+the list.sort builtin method to do sorting, and see FAQ's 4.51
+and 4.59 for examples of moderately advanced usage -- list.sort beats
+other techniques for sorting in all but the most extreme
+circumstances.
+<P>
+There are many other aggregate operations
+available in the standard libraries and in contributed libraries
+and extensions.
+<P>
+Another common trick is to "push loops into functions or methods."
+For example suppose you have a program that runs slowly and you
+use the profiler (profile.run) to determine that a Python function ff
+is being called lots of times.  If you notice that ff 
+<P>
+<PRE>
+   def ff(x):
+       ...do something with x computing result...
+       return result
+</PRE>
+tends to be called in loops like (A)
+<P>
+<PRE>
+   list = map(ff, oldlist)
+</PRE>
+or (B)
+<P>
+<PRE>
+   for x in sequence:
+       value = ff(x)
+       ...do something with value...
+</PRE>
+then you can often eliminate function call overhead by rewriting
+ff to
+<P>
+<PRE>
+   def ffseq(seq):
+       resultseq = []
+       for x in seq:
+           ...do something with x computing result...
+           resultseq.append(result)
+       return resultseq
+</PRE>
+and rewrite (A) to
+<P>
+<PRE>
+    list = ffseq(oldlist)
+</PRE>
+and (B) to
+<P>
+<PRE>
+    for value in ffseq(sequence):
+        ...do something with value...
+</PRE>
+Other single calls ff(x) translate to ffseq([x])[0] with little
+penalty.  Of course this technique is not always appropriate
+and there are other variants, which you can figure out.
+<P>
+You can gain some performance by explicitly storing the results of
+a function or method lookup into a local variable.  A loop like
+<P>
+<PRE>
+    for key in token:
+        dict[key] = dict.get(key, 0) + 1
+</PRE>
+resolves dict.get every iteration.  If the method isn't going to
+change, a faster implementation is
+<P>
+<PRE>
+    dict_get = dict.get  # look up the method once
+    for key in token:
+        dict[key] = dict_get(key, 0) + 1
+</PRE>
+Default arguments can be used to determine values once, at
+compile time instead of at run time.  This can only be done for
+functions or objects which will not be changed during program
+execution, such as replacing
+<P>
+<PRE>
+    def degree_sin(deg):
+        return math.sin(deg * math.pi / 180.0)
+</PRE>
+with
+<P>
+<PRE>
+    def degree_sin(deg, factor = math.pi/180.0, sin = math.sin):
+        return sin(deg * factor)
+</PRE>
+Because this trick uses default arguments for terms which should
+not be changed, it should only be used when you are not concerned
+with presenting a possibly confusing API to your users.
+<P>
+<P>
+For an anecdote related to optimization, see
+<P>
+<PRE>
+       <A HREF="http://www.python.org/doc/essays/list2str.html">http://www.python.org/doc/essays/list2str.html</A>
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.007.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.007.htp">Log info</A>
+
+/ Last changed on Mon Jun  3 01:03:54 2002 by
+<A HREF="mailto:neal@metaslash.com">Neal Norwitz</A>
+<P>
+
+<HR>
+<H2><A NAME="4.8">4.8. When I have imported a module, then edit it, and import it again (into the same Python process), the changes don't seem to take place. What is going on?</A></H2>
+For reasons of efficiency as well as consistency, Python only reads
+the module file on the first time a module is imported.  (Otherwise a
+program consisting of many modules, each of which imports the same
+basic module, would read the basic module over and over again.)  To
+force rereading of a changed module, do this:
+<P>
+<PRE>
+        import modname
+        reload(modname)
+</PRE>
+Warning: this technique is not 100% fool-proof.  In particular,
+modules containing statements like
+<P>
+<PRE>
+        from modname import some_objects
+</PRE>
+will continue to work with the old version of the imported objects.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.008.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.008.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="4.9">4.9. How do I find the current module name?</A></H2>
+A module can find out its own module name by looking at the
+(predefined) global variable __name__.  If this has the value
+'__main__' you are running as a script.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.009.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.009.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="4.10">4.10. I have a module in which I want to execute some extra code when it is run as a script. How do I find out whether I am running as a script?</A></H2>
+See the previous question.  E.g. if you put the following on the
+last line of your module, main() is called only when your module is
+running as a script:
+<P>
+<PRE>
+        if __name__ == '__main__': main()
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.010.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.010.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="4.11">4.11. I try to run a program from the Demo directory but it fails with ImportError: No module named ...; what gives?</A></H2>
+This is probably an optional module (written in C!) which hasn't
+been configured on your system.  This especially happens with modules
+like "Tkinter", "stdwin", "gl", "Xt" or "Xm".  For Tkinter, STDWIN and
+many other modules, see Modules/Setup.in for info on how to add these
+modules to your Python, if it is possible at all.  Sometimes you will
+have to ftp and build another package first (e.g. Tcl and Tk for Tkinter).
+Sometimes the module only works on specific platforms (e.g. gl only works
+on SGI machines).
+<P>
+NOTE: if the complaint is about "Tkinter" (upper case T) and you have
+already configured module "tkinter" (lower case t), the solution is
+<I>not</I> to rename tkinter to Tkinter or vice versa.  There is probably
+something wrong with your module search path.  Check out the value of
+sys.path.
+<P>
+For X-related modules (Xt and Xm) you will have to do more work: they
+are currently not part of the standard Python distribution.  You will
+have to ftp the Extensions tar file, i.e.
+<A HREF="ftp://ftp.python.org/pub/python/src/X-extension.tar.gz">ftp://ftp.python.org/pub/python/src/X-extension.tar.gz</A> and follow
+the instructions there.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.011.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.011.htp">Log info</A>
+
+/ Last changed on Wed Feb 12 21:31:08 2003 by
+<A HREF="mailto:kubieziel@gmx.de">Jens Kubieziel</A>
+<P>
+
+<HR>
+<H2><A NAME="4.12">4.12. [deleted]</A></H2>
+[stdwin (long dead windowing library) entry deleted]
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.012.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.012.htp">Log info</A>
+
+/ Last changed on Thu Mar 21 08:30:13 2002 by
+<A HREF="mailto:erno-pyfaq@erno.iki.fi">Erno Kuusela</A>
+<P>
+
+<HR>
+<H2><A NAME="4.13">4.13. What GUI toolkits exist for Python?</A></H2>
+Depending on what platform(s) you are aiming at, there are several.
+<P>
+Currently supported solutions:
+<P>
+Cross-platform:
+<P>
+Tk:
+<P>
+There's a neat object-oriented interface to the Tcl/Tk widget set,
+called Tkinter.  It is part of the standard Python distribution and
+well-supported -- all you need to do is build and install Tcl/Tk and
+enable the _tkinter module and the TKPATH definition in Modules/Setup
+when building Python.  This is probably the easiest to install and
+use, and the most complete widget set.  It is also very likely that in
+the future the standard Python GUI API will be based on or at least
+look very much like the Tkinter interface.  For more info about Tk,
+including pointers to the source, see the Tcl/Tk home page at
+<A HREF="http://www.scriptics.com">http://www.scriptics.com</A>.  Tcl/Tk is now fully
+portable to the Mac and Windows platforms (NT and 95 only); you need
+Python 1.4beta3 or later and Tk 4.1patch1 or later.
+<P>
+wxWindows:
+<P>
+There's an interface to wxWindows called wxPython.  wxWindows is a 
+portable GUI class library written in C++.  It supports GTK, Motif, 
+MS-Windows and Mac as targets.  Ports to other platforms are being 
+contemplated or have already had some work done on them.  wxWindows 
+preserves the look and feel of the underlying graphics toolkit, and 
+there is quite a rich widget set and collection of GDI classes.  
+See the wxWindows page at <A HREF="http://www.wxwindows.org">http://www.wxwindows.org</A>/ for more details.  
+wxPython is a python extension module that wraps many of the wxWindows 
+C++ classes, and is quickly gaining popularity amongst Python 
+developers.  You can get wxPython as part of the source or CVS 
+distribution of wxWindows, or directly from its home page at 
+<A HREF="http://alldunn.com/wxPython">http://alldunn.com/wxPython</A>/.
+<P>
+Gtk+:
+<P>
+PyGtk bindings for the Gtk+ Toolkit by James Henstridge exist; see <A HREF="ftp://ftp.daa.com.au/pub/james/python">ftp://ftp.daa.com.au/pub/james/python</A>/.  Note that there are two incompatible bindings.  If you are using Gtk+ 1.2.x you should get the 0.6.x PyGtk bindings from
+<P>
+<PRE>
+    <A HREF="ftp://ftp.gtk.org/pub/python/v1.2">ftp://ftp.gtk.org/pub/python/v1.2</A>
+</PRE>
+If you plan to use Gtk+ 2.0 with Python (highly recommended if you are just starting with Gtk), get the most recent distribution from
+<P>
+<PRE>
+    <A HREF="ftp://ftp.gtk.org/pub/python/v2.0">ftp://ftp.gtk.org/pub/python/v2.0</A>
+</PRE>
+If you are adventurous, you can also check out the source from the Gnome CVS repository.  Set your CVS directory to :pserver:<A HREF="mailto:anonymous@anoncvs.gnome.org">anonymous@anoncvs.gnome.org</A>:/cvs/gnome and check the gnome-python module out from the repository.
+<P>
+Other:
+<P>
+There are also bindings available for the Qt toolkit (PyQt), and for KDE (PyKDE); see <A HREF="http://www.thekompany.com/projects/pykde">http://www.thekompany.com/projects/pykde</A>/.
+<P>
+For OpenGL bindings, see <A HREF="http://starship.python.net/~da/PyOpenGL">http://starship.python.net/~da/PyOpenGL</A>.
+<P>
+Platform specific:
+<P>
+The Mac port has a rich and ever-growing set of modules that support
+the native Mac toolbox calls.  See the documentation that comes with
+the Mac port.  See <A HREF="ftp://ftp.python.org/pub/python/mac">ftp://ftp.python.org/pub/python/mac</A>.  Support
+by Jack Jansen <A HREF="mailto:jack@cwi.nl">jack@cwi.nl</A>.
+<P>
+Pythonwin by Mark Hammond (<A HREF="mailto:MHammond@skippinet.com.au">MHammond@skippinet.com.au</A>)
+includes an interface to the Microsoft Foundation
+Classes and a Python programming environment using it that's written
+mostly in Python.  See <A HREF="http://www.python.org/windows">http://www.python.org/windows</A>/.
+<P>
+There's an object-oriented GUI based on the Microsoft Foundation
+Classes model called WPY, supported by Jim Ahlstrom <A HREF="mailto:jim@interet.com">jim@interet.com</A>.
+Programs written in WPY run unchanged and with native look and feel on
+Windows NT/95, Windows 3.1 (using win32s), and on Unix (using Tk).
+Source and binaries for Windows and Linux are available in
+<A HREF="ftp://ftp.python.org/pub/python/wpy">ftp://ftp.python.org/pub/python/wpy</A>/.
+<P>
+Obsolete or minority solutions:
+<P>
+There's an interface to X11, including the Athena and Motif widget
+sets (and a few individual widgets, like Mosaic's HTML widget and
+SGI's GL widget) available from
+<A HREF="ftp://ftp.python.org/pub/python/src/X-extension.tar.gz">ftp://ftp.python.org/pub/python/src/X-extension.tar.gz</A>.
+Support by Sjoerd Mullender <A HREF="mailto:sjoerd@cwi.nl">sjoerd@cwi.nl</A>.
+<P>
+On top of the X11 interface there's the vpApp
+toolkit by Per Spilling, now also maintained by Sjoerd Mullender
+<A HREF="mailto:sjoerd@cwi.nl">sjoerd@cwi.nl</A>.  See <A HREF="ftp://ftp.cwi.nl/pub/sjoerd/vpApp.tar.gz">ftp://ftp.cwi.nl/pub/sjoerd/vpApp.tar.gz</A>.
+<P>
+For SGI IRIX only, there are unsupported interfaces to the complete
+GL (Graphics Library -- low level but very good 3D capabilities) as
+well as to FORMS (a buttons-and-sliders-etc package built on top of GL
+by Mark Overmars -- ftp'able from
+<A HREF="ftp://ftp.cs.ruu.nl/pub/SGI/FORMS">ftp://ftp.cs.ruu.nl/pub/SGI/FORMS</A>/).  This is probably also
+becoming obsolete, as OpenGL takes over (see above).
+<P>
+There's an interface to STDWIN, a platform-independent low-level
+windowing interface for Mac and X11.  This is totally unsupported and
+rapidly becoming obsolete.  The STDWIN sources are at
+<A HREF="ftp://ftp.cwi.nl/pub/stdwin">ftp://ftp.cwi.nl/pub/stdwin</A>/.
+<P>
+There is an interface to WAFE, a Tcl interface to the X11
+Motif and Athena widget sets.  WAFE is at
+<A HREF="http://www.wu-wien.ac.at/wafe/wafe.html">http://www.wu-wien.ac.at/wafe/wafe.html</A>.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.013.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.013.htp">Log info</A>
+
+/ Last changed on Mon May 13 21:40:39 2002 by
+<A HREF="mailto:skip@pobox.com">Skip Montanaro</A>
+<P>
+
+<HR>
+<H2><A NAME="4.14">4.14. Are there any interfaces to database packages in Python?</A></H2>
+Yes!  See the Database Topic Guide at 
+<A HREF="http://www.python.org/topics/database">http://www.python.org/topics/database</A>/ for details.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.014.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.014.htp">Log info</A>
+
+/ Last changed on Tue Jan  4 20:12:19 2000 by
+<A HREF="mailto:bwarsaw@python.org">Barney Warplug</A>
+<P>
+
+<HR>
+<H2><A NAME="4.15">4.15. Is it possible to write obfuscated one-liners in Python?</A></H2>
+Yes.  See the following three examples, due to Ulf Bartelt:
+<P>
+<PRE>
+        # Primes &lt; 1000
+        print filter(None,map(lambda y:y*reduce(lambda x,y:x*y!=0,
+        map(lambda x,y=y:y%x,range(2,int(pow(y,0.5)+1))),1),range(2,1000)))
+</PRE>
+<PRE>
+        # First 10 Fibonacci numbers
+        print map(lambda x,f=lambda x,f:(x&lt;=1) or (f(x-1,f)+f(x-2,f)): f(x,f),
+        range(10))
+</PRE>
+<PRE>
+        # Mandelbrot set
+        print (lambda Ru,Ro,Iu,Io,IM,Sx,Sy:reduce(lambda x,y:x+y,map(lambda y,
+        Iu=Iu,Io=Io,Ru=Ru,Ro=Ro,Sy=Sy,L=lambda yc,Iu=Iu,Io=Io,Ru=Ru,Ro=Ro,i=IM,
+        Sx=Sx,Sy=Sy:reduce(lambda x,y:x+y,map(lambda x,xc=Ru,yc=yc,Ru=Ru,Ro=Ro,
+        i=i,Sx=Sx,F=lambda xc,yc,x,y,k,f=lambda xc,yc,x,y,k,f:(k&lt;=0)or (x*x+y*y
+        >=4.0) or 1+f(xc,yc,x*x-y*y+xc,2.0*x*y+yc,k-1,f):f(xc,yc,x,y,k,f):chr(
+        64+F(Ru+x*(Ro-Ru)/Sx,yc,0,0,i)),range(Sx))):L(Iu+y*(Io-Iu)/Sy),range(Sy
+        ))))(-2.1, 0.7, -1.2, 1.2, 30, 80, 24)
+        #    \___ ___/  \___ ___/  |   |   |__ lines on screen
+        #        V          V      |   |______ columns on screen
+        #        |          |      |__________ maximum of "iterations"
+        #        |          |_________________ range on y axis
+        #        |____________________________ range on x axis
+</PRE>
+Don't try this at home, kids!
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.015.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.015.htp">Log info</A>
+
+/ Last changed on Wed May 21 15:48:33 1997 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="4.16">4.16. Is there an equivalent of C's &quot;?:&quot; ternary operator?</A></H2>
+Not directly.  In many cases you can mimic a?b:c with "a and b or
+c", but there's a flaw: if b is zero (or empty, or None -- anything
+that tests false) then c will be selected instead.  In many cases you
+can prove by looking at the code that this can't happen (e.g. because
+b is a constant or has a type that can never be false), but in general
+this can be a problem.
+<P>
+Tim Peters (who wishes it was Steve Majewski) suggested the following
+solution: (a and [b] or [c])[0].  Because [b] is a singleton list it
+is never false, so the wrong path is never taken; then applying [0] to
+the whole thing gets the b or c that you really wanted.  Ugly, but it
+gets you there in the rare cases where it is really inconvenient to
+rewrite your code using 'if'.
+<P>
+As a last resort it is possible to implement the "?:" operator as a function:
+<P>
+<PRE>
+    def q(cond,on_true,on_false):
+        from inspect import isfunction
+</PRE>
+<PRE>
+        if cond:
+            if not isfunction(on_true): return on_true
+            else: return apply(on_true)
+        else:
+            if not isfunction(on_false): return on_false 
+            else: return apply(on_false)
+</PRE>
+In most cases you'll pass b and c directly: q(a,b,c).  To avoid evaluating b
+or c when they shouldn't be, encapsulate them
+within a lambda function, e.g.: q(a,lambda: b, lambda: c).
+<P>
+<P>
+<P>
+It has been asked <I>why</I> Python has no if-then-else expression,
+since most language have one; it is a frequently requested feature.
+<P>
+There are several possible answers: just as many languages do
+just fine without one; it can easily lead to less readable code;
+no sufficiently "Pythonic" syntax has been discovered; a search
+of the standard library found remarkably few places where using an
+if-then-else expression would make the code more understandable.
+<P>
+Nevertheless, in an effort to decide once and for all whether
+an if-then-else expression should be added to the language,
+PEP 308 (<A HREF="http://www.python.org/peps/pep-0308.html">http://www.python.org/peps/pep-0308.html</A>) has been
+put forward, proposing a specific syntax.  The community can
+now vote on this issue.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.016.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.016.htp">Log info</A>
+
+/ Last changed on Fri Feb  7 19:41:13 2003 by
+<A HREF="mailto:goodger@python.org">David Goodger</A>
+<P>
+
+<HR>
+<H2><A NAME="4.17">4.17. My class defines __del__ but it is not called when I delete the object.</A></H2>
+There are several possible reasons for this.
+<P>
+The del statement does not necessarily call __del__ -- it simply
+decrements the object's reference count, and if this reaches zero
+__del__ is called.
+<P>
+If your data structures contain circular links (e.g. a tree where
+each child has a parent pointer and each parent has a list of
+children) the reference counts will never go back to zero.  You'll
+have to define an explicit close() method which removes those
+pointers.  Please don't ever call __del__ directly -- __del__ should
+call close() and close() should make sure that it can be called more
+than once for the same object.
+<P>
+If the object has ever been a local variable (or argument, which is
+really the same thing) to a function that caught an expression in an
+except clause, chances are that a reference to the object still exists
+in that function's stack frame as contained in the stack trace.
+Normally, deleting (better: assigning None to) sys.exc_traceback will
+take care of this.  If a stack was printed for an unhandled
+exception in an interactive interpreter, delete sys.last_traceback
+instead.
+<P>
+There is code that deletes all objects when the interpreter exits,
+but it is not called if your Python has been configured to support
+threads (because other threads may still be active).  You can define
+your own cleanup function using sys.exitfunc (see question 4.4).
+<P>
+Finally, if your __del__ method raises an exception, a warning message is printed to sys.stderr.
+<P>
+<P>
+Starting with Python 2.0, a garbage collector periodically reclaims the space used by most cycles with no external references. (See the "gc" module documentation for details.) There <I>are</I>, however, pathological cases where it can be expected to fail. Moreover, the garbage collector runs some time after the last reference to your data structure vanishes, so your __del__ method may be called at an inconvenient and random time. This is inconvenient if you're trying to reproduce a problem. Worse, the order in which object's __del__ methods are executed is arbitrary.
+<P>
+Another way to avoid cyclical references is to use the "weakref" module, which allows you to point to objects without incrementing their reference count. Tree data structures, for instance, should use weak references for their parent  and sibling pointers (if they need them!).
+<P>
+Question 6.14 is intended to explain the new garbage collection algorithm.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.017.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.017.htp">Log info</A>
+
+/ Last changed on Mon Jun 10 15:27:28 2002 by
+<A HREF="mailto:smurf@noris.de">Matthias Urlichs</A>
+<P>
+
+<HR>
+<H2><A NAME="4.18">4.18. How do I change the shell environment for programs called using os.popen() or os.system()? Changing os.environ doesn't work.</A></H2>
+You must be using either a version of python before 1.4, or on a
+(rare) system that doesn't have the putenv() library function.
+<P>
+Before Python 1.4, modifying the environment passed to subshells was
+left out of the interpreter because there seemed to be no
+well-established portable way to do it (in particular, some systems,
+have putenv(), others have setenv(), and some have none at all).  As
+of Python 1.4, almost all Unix systems <I>do</I> have putenv(), and so does
+the Win32 API, and thus the os module was modified so that changes to
+os.environ are trapped and the corresponding putenv() call is made.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.018.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.018.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="4.19">4.19. What is a class?</A></H2>
+A class is the particular object type created by executing
+a class statement.  Class objects are used as templates, to create
+instance objects, which embody both the data structure
+(attributes) and program routines (methods) specific to a datatype.
+<P>
+A class can be based on one or more other classes, called its base
+class(es). It then inherits the attributes and methods of its base classes. This allows an object model to be successively refined
+by inheritance.
+<P>
+The term "classic class" is used to refer to the original
+class implementation in Python. One problem with classic
+classes is their inability to use the built-in data types
+(such as list and dictionary) as base classes. Starting
+with Python 2.2 an attempt is in progress to unify user-defined
+classes and built-in types. It is now possible to declare classes
+that inherit from built-in types.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.019.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.019.htp">Log info</A>
+
+/ Last changed on Mon May 27 01:31:21 2002 by
+<A HREF="mailto:sholden@holdenweb.com">Steve Holden</A>
+<P>
+
+<HR>
+<H2><A NAME="4.20">4.20. What is a method?</A></H2>
+A method is a function that you normally call as
+x.name(arguments...) for some object x.  The term is used for methods
+of classes and class instances as well as for methods of built-in
+objects.  (The latter have a completely different implementation and
+only share the way their calls look in Python code.)  Methods of
+classes (and class instances) are defined as functions inside the
+class definition.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.020.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.020.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="4.21">4.21. What is self?</A></H2>
+Self is merely a conventional name for the first argument of a
+method -- i.e. a function defined inside a class definition.  A method
+defined as meth(self, a, b, c) should be called as x.meth(a, b, c) for
+some instance x of the class in which the definition occurs;
+the called method will think it is called as meth(x, a, b, c).
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.021.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.021.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="4.22">4.22. What is an unbound method?</A></H2>
+An unbound method is a method defined in a class that is not yet
+bound to an instance.  You get an unbound method if you ask for a
+class attribute that happens to be a function. You get a bound method
+if you ask for an instance attribute.  A bound method knows which
+instance it belongs to and calling it supplies the instance automatically;
+an unbound method only knows which class it wants for its first
+argument (a derived class is also OK).  Calling an unbound method
+doesn't "magically" derive the first argument from the context -- you
+have to provide it explicitly.
+<P>
+Trivia note regarding bound methods:  each reference to a bound
+method of a particular object creates a bound method object.  If you
+have two such references (a = inst.meth; b = inst.meth), they will
+compare equal (a == b) but are not the same (a is not b).
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.022.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.022.htp">Log info</A>
+
+/ Last changed on Wed May  6 18:07:25 1998 by
+<A HREF="mailto:clarence@avtel.com">Clarence Gardner</A>
+<P>
+
+<HR>
+<H2><A NAME="4.23">4.23. How do I call a method defined in a base class from a derived class that overrides it?</A></H2>
+If your class definition starts with "class Derived(Base): ..."
+then you can call method meth defined in Base (or one of Base's base
+classes) as Base.meth(self, arguments...).  Here, Base.meth is an
+unbound method (see previous question).
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.023.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.023.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="4.24">4.24. How do I call a method from a base class without using the name of the base class?</A></H2>
+DON'T DO THIS.  REALLY.  I MEAN IT.  It appears that you could call
+self.__class__.__bases__[0].meth(self, arguments...) but this fails when
+a doubly-derived method is derived from your class: for its instances,
+self.__class__.__bases__[0] is your class, not its base class -- so
+(assuming you are doing this from within Derived.meth) you would start
+a recursive call.
+<P>
+Often when you want to do this you are forgetting that classes
+are first class in Python.  You can "point to" the class you want
+to delegate an operation to either at the instance or at the
+subclass level.  For example if you want to use a "glorp"
+operation of a superclass you can point to the right superclass
+to use.
+<P>
+<PRE>
+  class subclass(superclass1, superclass2, superclass3):
+      delegate_glorp = superclass2
+      ...
+      def glorp(self, arg1, arg2):
+            ... subclass specific stuff ...
+            self.delegate_glorp.glorp(self, arg1, arg2)
+       ...
+</PRE>
+<PRE>
+  class subsubclass(subclass):
+       delegate_glorp = superclass3
+       ...
+</PRE>
+Note, however that setting delegate_glorp to subclass in
+subsubclass would cause an infinite recursion on subclass.delegate_glorp.  Careful!  Maybe you are getting too fancy for your own good.  Consider simplifying the design (?).
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.024.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.024.htp">Log info</A>
+
+/ Last changed on Mon Jul 28 13:58:22 1997 by
+<A HREF="mailto:aaron_watters@msn.com">aaron watters</A>
+<P>
+
+<HR>
+<H2><A NAME="4.25">4.25. How can I organize my code to make it easier to change the base class?</A></H2>
+You could define an alias for the base class, assign the real base
+class to it before your class definition, and use the alias throughout
+your class.  Then all you have to change is the value assigned to the
+alias.  Incidentally, this trick is also handy if you want to decide
+dynamically (e.g. depending on availability of resources) which base
+class to use.  Example:
+<P>
+<PRE>
+        BaseAlias = &lt;real base class&gt;
+        class Derived(BaseAlias):
+                def meth(self):
+                        BaseAlias.meth(self)
+                        ...
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.025.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.025.htp">Log info</A>
+
+/ Last changed on Wed May 21 15:49:57 1997 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="4.26">4.26. How can I find the methods or attributes of an object?</A></H2>
+This depends on the object type.
+<P>
+For an instance x of a user-defined class, instance attributes are
+found in the dictionary x.__dict__, and methods and attributes defined
+by its class are found in x.__class__.__bases__[i].__dict__ (for i in
+range(len(x.__class__.__bases__))).  You'll have to walk the tree of
+base classes to find <I>all</I> class methods and attributes.
+<P>
+Many, but not all built-in types define a list of their method names
+in x.__methods__, and if they have data attributes, their names may be
+found in x.__members__.  However this is only a convention.
+<P>
+For more information, read the source of the standard (but
+undocumented) module newdir.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.026.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.026.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="4.27">4.27. I can't seem to use os.read() on a pipe created with os.popen().</A></H2>
+os.read() is a low-level function which takes a file descriptor (a
+small integer).  os.popen() creates a high-level file object -- the
+same type used for sys.std{in,out,err} and returned by the builtin
+open() function.  Thus, to read n bytes from a pipe p created with
+os.popen(), you need to use p.read(n).
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.027.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.027.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="4.28">4.28. How can I create a stand-alone binary from a Python script?</A></H2>
+Even though there are Python compilers being developed,
+you probably don't need a <I>real</I> compiler, if all you want
+is a stand-alone program. There are three solutions to that. 
+<P>
+One is to use the freeze tool, which is included in the Python
+source tree as Tools/freeze. It converts Python byte
+code to C arrays.  Using a C compiler, you can embed all
+your modules into a new program, which is then linked
+with the standard Python modules. 
+<P>
+It works by scanning your source recursively for import statements
+(in both forms) and looking for the modules in the standard Python path
+as well as in the source directory (for built-in modules).  It then
+1 the modules written in Python to C code (array initializers
+that can be turned into code objects using the marshal module) and
+creates a custom-made config file that only contains those built-in
+modules which are actually used in the program.  It then compiles the
+generated C code and links it with the rest of the Python interpreter
+to form a self-contained binary which acts exactly like your script.
+<P>
+(Hint: the freeze program only works if your script's filename ends in
+".py".)
+<P>
+There are several utilities which may be helpful.  The first is Gordon McMillan's installer at
+<P>
+<PRE>
+    <A HREF="http://www.mcmillan-inc.com/install1.html">http://www.mcmillan-inc.com/install1.html</A>
+</PRE>
+which works on Windows, Linux and at least some forms of Unix.
+<P>
+Another is Thomas Heller's py2exe (Windows only) at
+<P>
+<PRE>
+    <A HREF="http://starship.python.net/crew/theller/py2exe">http://starship.python.net/crew/theller/py2exe</A>/
+</PRE>
+A third is Christian Tismer's SQFREEZE
+(<A HREF="http://starship.python.net/crew/pirx">http://starship.python.net/crew/pirx</A>/) which appends the byte code
+to a specially-prepared Python interpreter, which
+will find the byte code in executable. 
+<P>
+A fourth is Fredrik Lundh's Squeeze
+(<A HREF="http://www.pythonware.com/products/python/squeeze">http://www.pythonware.com/products/python/squeeze</A>/).
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.028.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.028.htp">Log info</A>
+
+/ Last changed on Wed Jun 19 14:01:30 2002 by
+<A HREF="mailto:gmcm@hypernet.com">Gordon McMillan</A>
+<P>
+
+<HR>
+<H2><A NAME="4.29">4.29. What WWW tools are there for Python?</A></H2>
+See the chapters titled "Internet Protocols and Support" and
+"Internet Data Handling" in the Library Reference
+Manual. Python is full of good things which will help you build server-side and client-side web systems.
+<P>
+A summary of available frameworks is maintained by Paul Boddie at
+<P>
+<PRE>
+    <A HREF="http://thor.prohosting.com/~pboddie/Python/web_modules.html">http://thor.prohosting.com/~pboddie/Python/web_modules.html</A>
+</PRE>
+Cameron Laird maintains a useful set of pages about Python web technologies at
+<P>
+<PRE>
+   <A HREF="http://starbase.neosoft.com/~claird/comp.lang.python/web_python.html">http://starbase.neosoft.com/~claird/comp.lang.python/web_python.html</A>/
+</PRE>
+There was a web browser written in Python, called Grail --
+see <A HREF="http://sourceforge.net/project/grail">http://sourceforge.net/project/grail</A>/. This project has been terminated; <A HREF="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/grail/grail/README">http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/grail/grail/README</A> gives more details.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.029.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.029.htp">Log info</A>
+
+/ Last changed on Mon Nov 11 22:48:25 2002 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="4.30">4.30. How do I run a subprocess with pipes connected to both input and output?</A></H2>
+Use the standard popen2 module.  For example:
+<P>
+<PRE>
+       import popen2
+       fromchild, tochild = popen2.popen2("command")
+       tochild.write("input\n")
+       tochild.flush()
+       output = fromchild.readline()
+</PRE>
+Warning: in general, it is unwise to
+do this, because you can easily cause a deadlock where your
+process is blocked waiting for output from the child, while the child
+is blocked waiting for input from you.  This can be caused
+because the parent expects the child to output more text than it does,
+or it can be caused by data being stuck in stdio buffers due to lack
+of flushing.  The Python parent can of course explicitly flush the data
+it sends to the child before it reads any output, but if the child is
+a naive C program it can easily have been written to never explicitly
+flush its output, even if it is interactive, since flushing is
+normally automatic.
+<P>
+Note that a deadlock is also possible if you use popen3 to read
+stdout and stderr. If one of the two is too large for the internal
+buffer (increasing the buffersize does not help) and you read()
+the other one first, there is a deadlock, too.
+<P>
+Note on a bug in popen2: unless your program calls wait()
+or waitpid(), finished child processes are never removed,
+and eventually calls to popen2 will fail because of a limit on
+the number of child processes.  Calling os.waitpid with the
+os.WNOHANG option can prevent this; a good place to insert such
+a call would be before calling popen2 again.
+<P>
+Another way to produce a deadlock: Call a wait() and there is
+still more output from the program than what fits into the 
+internal buffers.
+<P>
+In many cases, all you really need is to run some data through a
+command and get the result back.  Unless the data is infinite in size,
+the easiest (and often the most efficient!) way to do this is to write
+it to a temporary file and run the command with that temporary file as
+input.  The standard module tempfile exports a function mktemp() which
+generates unique temporary file names.
+<P>
+<PRE>
+ import tempfile
+ import os
+ class Popen3:
+    """
+    This is a deadlock-save version of popen, that returns
+    an object with errorlevel, out (a string) and err (a string).
+    (capturestderr may not work under windows.)
+    Example: print Popen3('grep spam','\n\nhere spam\n\n').out
+    """
+    def __init__(self,command,input=None,capturestderr=None):
+        outfile=tempfile.mktemp()
+        command="( %s ) > %s" % (command,outfile)
+        if input:
+            infile=tempfile.mktemp()
+            open(infile,"w").write(input)
+            command=command+" &lt;"+infile
+        if capturestderr:
+            errfile=tempfile.mktemp()
+            command=command+" 2>"+errfile
+        self.errorlevel=os.system(command) >> 8
+        self.out=open(outfile,"r").read()
+        os.remove(outfile)
+        if input:
+            os.remove(infile)
+        if capturestderr:
+            self.err=open(errfile,"r").read()
+            os.remove(errfile)
+</PRE>
+Note that many interactive programs (e.g. vi) don't work well with
+pipes substituted for standard input and output.  You will have to use
+pseudo ttys ("ptys") instead of pipes.  There is some undocumented
+code to use these in the library module pty.py -- I'm afraid you're on
+your own here.
+<P>
+A different answer is a Python interface to Don Libes' "expect"
+library.  A Python extension that interfaces to expect is called "expy"
+and available from
+<A HREF="http://expectpy.sourceforge.net">http://expectpy.sourceforge.net</A>/.
+<P>
+A pure Python solution that works like expect is pexpect of Noah Spurrier.
+A beta version is available from
+<A HREF="http://pexpect.sourceforge.net">http://pexpect.sourceforge.net</A>/
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.030.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.030.htp">Log info</A>
+
+/ Last changed on Tue Sep  3 16:31:31 2002 by
+<A HREF="mailto:polzin@gmx.de">Tobias Polzin</A>
+<P>
+
+<HR>
+<H2><A NAME="4.31">4.31. How do I call a function if I have the arguments in a tuple?</A></H2>
+Use the built-in function apply().  For instance,
+<P>
+<PRE>
+    func(1, 2, 3)
+</PRE>
+is equivalent to
+<P>
+<PRE>
+    args = (1, 2, 3)
+    apply(func, args)
+</PRE>
+Note that func(args) is not the same -- it calls func() with exactly
+one argument, the tuple args, instead of three arguments, the integers
+1, 2 and 3.
+<P>
+In Python 2.0, you can also use extended call syntax:
+<P>
+f(*args) is equivalent to apply(f, args)
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.031.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.031.htp">Log info</A>
+
+/ Last changed on Tue Jan  2 03:42:50 2001 by
+<A HREF="mailto:moshez@zadka.site.co.il">Moshe Zadka</A>
+<P>
+
+<HR>
+<H2><A NAME="4.32">4.32. How do I enable font-lock-mode for Python in Emacs?</A></H2>
+If you are using XEmacs 19.14 or later, any XEmacs 20, FSF Emacs 19.34
+or any Emacs 20, font-lock should work automatically for you if you
+are using the latest python-mode.el.
+<P>
+If you are using an older version of XEmacs or Emacs you will need 
+to put this in your .emacs file:
+<P>
+<PRE>
+        (defun my-python-mode-hook ()
+          (setq font-lock-keywords python-font-lock-keywords)
+          (font-lock-mode 1))
+        (add-hook 'python-mode-hook 'my-python-mode-hook)
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.032.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.032.htp">Log info</A>
+
+/ Last changed on Mon Apr  6 16:18:46 1998 by
+<A HREF="mailto:bwarsaw@python.org">Barry Warsaw</A>
+<P>
+
+<HR>
+<H2><A NAME="4.33">4.33. Is there a scanf() or sscanf() equivalent?</A></H2>
+Not as such.
+<P>
+For simple input parsing, the easiest approach is usually to split
+the line into whitespace-delimited words using string.split(), and to
+convert decimal strings to numeric values using int(),
+long() or float().  (Python's int() is 32-bit and its
+long() is arbitrary precision.)  string.split supports an optional
+"sep" parameter which is useful if the line uses something other
+than whitespace as a delimiter.
+<P>
+For more complicated input parsing, regular expressions (see module re)
+are better suited and more powerful than C's sscanf().
+<P>
+There's a contributed module that emulates sscanf(), by Steve Clift;
+see contrib/Misc/sscanfmodule.c of the ftp site:
+<P>
+<PRE>
+    <A HREF="http://www.python.org/ftp/python/contrib-09-Dec-1999/Misc">http://www.python.org/ftp/python/contrib-09-Dec-1999/Misc</A>/
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.033.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.033.htp">Log info</A>
+
+/ Last changed on Mon Jun  3 01:07:51 2002 by
+<A HREF="mailto:neal@metaslash.com">Neal Norwitz</A>
+<P>
+
+<HR>
+<H2><A NAME="4.34">4.34. Can I have Tk events handled while waiting for I/O?</A></H2>
+Yes, and you don't even need threads!  But you'll have to
+restructure your I/O code a bit.  Tk has the equivalent of Xt's
+XtAddInput() call, which allows you to register a callback function
+which will be called from the Tk mainloop when I/O is possible on a
+file descriptor.  Here's what you need:
+<P>
+<PRE>
+        from Tkinter import tkinter
+        tkinter.createfilehandler(file, mask, callback)
+</PRE>
+The file may be a Python file or socket object (actually, anything
+with a fileno() method), or an integer file descriptor.  The mask is
+one of the constants tkinter.READABLE or tkinter.WRITABLE.  The
+callback is called as follows:
+<P>
+<PRE>
+        callback(file, mask)
+</PRE>
+You must unregister the callback when you're done, using
+<P>
+<PRE>
+        tkinter.deletefilehandler(file)
+</PRE>
+Note: since you don't know *how many bytes* are available for reading,
+you can't use the Python file object's read or readline methods, since
+these will insist on reading a predefined number of bytes.  For
+sockets, the recv() or recvfrom() methods will work fine; for other
+files, use os.read(file.fileno(), maxbytecount).
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.034.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.034.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="4.35">4.35. How do I write a function with output parameters (call by reference)?</A></H2>
+[Mark Lutz] The thing to remember is that arguments are passed by
+assignment in Python.  Since assignment just creates references to
+objects, there's no alias between an argument name in the caller and
+callee, and so no call-by-reference per se.  But you can simulate it
+in a number of ways:
+<P>
+1) By using global variables; but you probably shouldn't :-)
+<P>
+2) By passing a mutable (changeable in-place) object:
+<P>
+<PRE>
+      def func1(a):
+          a[0] = 'new-value'     # 'a' references a mutable list
+          a[1] = a[1] + 1        # changes a shared object
+</PRE>
+<PRE>
+      args = ['old-value', 99]
+      func1(args)
+      print args[0], args[1]     # output: new-value 100
+</PRE>
+3) By returning a tuple, holding the final values of arguments:
+<P>
+<PRE>
+      def func2(a, b):
+          a = 'new-value'        # a and b are local names
+          b = b + 1              # assigned to new objects
+          return a, b            # return new values
+</PRE>
+<PRE>
+      x, y = 'old-value', 99
+      x, y = func2(x, y)
+      print x, y                 # output: new-value 100
+</PRE>
+4) And other ideas that fall-out from Python's object model. For instance, it might be clearer to pass in a mutable dictionary:
+<P>
+<PRE>
+      def func3(args):
+          args['a'] = 'new-value'     # args is a mutable dictionary
+          args['b'] = args['b'] + 1   # change it in-place
+</PRE>
+<PRE>
+      args = {'a':' old-value', 'b': 99}
+      func3(args)
+      print args['a'], args['b']
+</PRE>
+5) Or bundle-up values in a class instance:
+<P>
+<PRE>
+      class callByRef:
+          def __init__(self, **args):
+              for (key, value) in args.items():
+                  setattr(self, key, value)
+</PRE>
+<PRE>
+      def func4(args):
+          args.a = 'new-value'        # args is a mutable callByRef
+          args.b = args.b + 1         # change object in-place
+</PRE>
+<PRE>
+      args = callByRef(a='old-value', b=99)
+      func4(args)
+      print args.a, args.b
+</PRE>
+<PRE>
+   But there's probably no good reason to get this complicated :-).
+</PRE>
+[Python's author favors solution 3 in most cases.]
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.035.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.035.htp">Log info</A>
+
+/ Last changed on Sun Jun  8 23:49:46 1997 by
+<A HREF="mailto:david_ascher@brown.edu">David Ascher</A>
+<P>
+
+<HR>
+<H2><A NAME="4.36">4.36. Please explain the rules for local and global variables in Python.</A></H2>
+[Ken Manheimer] In Python, procedure variables are implicitly
+global, unless they are assigned anywhere within the block.
+In that case
+they are implicitly local, and you need to explicitly declare them as
+'global'.
+<P>
+Though a bit surprising at first, a moment's consideration explains
+this.  On one hand, requirement of 'global' for assigned vars provides
+a bar against unintended side-effects.  On the other hand, if global
+were required for all global references, you'd be using global all the
+time.  Eg, you'd have to declare as global every reference to a
+builtin function, or to a component of an imported module.  This
+clutter would defeat the usefulness of the 'global' declaration for
+identifying side-effects.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.036.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.036.htp">Log info</A>
+
+/ Last changed on Fri Aug 28 09:53:27 1998 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="4.37">4.37. How can I have modules that mutually import each other?</A></H2>
+Suppose you have the following modules:
+<P>
+foo.py:
+<P>
+<PRE>
+       from bar import bar_var
+       foo_var=1
+</PRE>
+bar.py:
+<P>
+<PRE>
+       from foo import foo_var
+       bar_var=2
+</PRE>
+The problem is that the above is processed by the interpreter thus:
+<P>
+<PRE>
+       main imports foo
+       Empty globals for foo are created
+       foo is compiled and starts executing
+       foo imports bar
+       Empty globals for bar are created
+       bar is compiled and starts executing
+       bar imports foo (which is a no-op since there already is a module named foo)
+       bar.foo_var = foo.foo_var
+       ...
+</PRE>
+The last step fails, because Python isn't done with interpreting foo yet and the global symbol dict for foo is still empty.
+<P>
+The same thing happens when you use "import foo", and then try to access "foo.one" in global code.
+<P>
+<P>
+There are (at least) three possible workarounds for this problem. 
+<P>
+Guido van Rossum recommends to avoid all uses of "from &lt;module&gt; import ..." (so everything from an imported module is referenced as &lt;module&gt;.&lt;name&gt;) and to place all code inside functions. Initializations of global variables and class variables should use constants or built-in functions only.
+<P>
+<P>
+Jim Roskind suggests the following order in each module:
+<P>
+<PRE>
+ exports (globals, functions, and classes that don't need imported base classes)
+ import statements
+ active code (including globals that are initialized from imported values).
+</PRE>
+Python's author doesn't like this approach much because the imports
+appear in a strange place, but has to admit that it works.
+<P>
+<P>
+<P>
+Matthias Urlichs recommends to restructure your code so that the recursive import is not necessary in the first place.
+<P>
+<P>
+These solutions are not mutually exclusive.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.037.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.037.htp">Log info</A>
+
+/ Last changed on Mon Jun  3 06:52:51 2002 by
+<A HREF="mailto:smurf@noris.de">Matthias Urlichs</A>
+<P>
+
+<HR>
+<H2><A NAME="4.38">4.38. How do I copy an object in Python?</A></H2>
+Try copy.copy() or copy.deepcopy() for the general case. Not all objects can be copied, but most can.
+<P>
+Dictionaries have a copy method. Sequences can be copied by slicing:
+<PRE>
+ new_l = l[:]
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.038.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.038.htp">Log info</A>
+
+/ Last changed on Thu Mar 21 05:40:26 2002 by
+<A HREF="mailto:erno-pyfaq@erno.iki.fi">Erno Kuusela</A>
+<P>
+
+<HR>
+<H2><A NAME="4.39">4.39. How to implement persistent objects in Python? (Persistent == automatically saved to and restored from disk.)</A></H2>
+The library module "pickle" now solves this in a very general way
+(though you still can't store things like open files, sockets or
+windows), and the library module "shelve" uses pickle and (g)dbm to
+create persistent mappings containing arbitrary Python objects.
+For possibly better performance also look for the latest version
+of the relatively recent cPickle module.
+<P>
+A more awkward way of doing things is to use pickle's little sister,
+marshal.  The marshal module provides very fast ways to store
+noncircular basic Python types to files and strings, and back again.
+Although marshal does not do fancy things like store instances or
+handle shared references properly, it does run extremely fast.  For
+example loading a half megabyte of data may take less than a
+third of a second (on some machines).  This often beats doing
+something more complex and general such as using gdbm with
+pickle/shelve.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.039.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.039.htp">Log info</A>
+
+/ Last changed on Sun Jun  8 22:59:00 1997 by
+<A HREF="mailto:david_ascher@brown.edu">David Ascher</A>
+<P>
+
+<HR>
+<H2><A NAME="4.40">4.40. I try to use __spam and I get an error about _SomeClassName__spam.</A></H2>
+Variables with double leading underscore are "mangled" to provide a
+simple but effective way to define class private variables.  See the
+chapter "New in Release 1.4" in the Python Tutorial.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.040.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.040.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="4.41">4.41. How do I delete a file? And other file questions.</A></H2>
+Use os.remove(filename) or os.unlink(filename); for documentation,
+see the posix section of the library manual.  They are the same,
+unlink() is simply the Unix name for this function.  In earlier
+versions of Python, only os.unlink() was available.
+<P>
+To remove a directory, use os.rmdir(); use os.mkdir() to create one.
+<P>
+To rename a file, use os.rename().
+<P>
+To truncate a file, open it using f = open(filename, "r+"), and use
+f.truncate(offset); offset defaults to the current seek position.
+(The "r+" mode opens the file for reading and writing.)
+There's also os.ftruncate(fd, offset) for files opened with os.open()
+-- for advanced Unix hacks only.
+<P>
+The shutil module also contains a number of functions to work on files
+including copyfile, copytree, and rmtree amongst others.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.041.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.041.htp">Log info</A>
+
+/ Last changed on Thu Dec 28 12:30:01 2000 by
+<A HREF="mailto:pbjorn@uswest.net">Bjorn Pettersen</A>
+<P>
+
+<HR>
+<H2><A NAME="4.42">4.42. How to modify urllib or httplib to support HTTP/1.1?</A></H2>
+Recent versions of Python (2.0 and onwards) support HTTP/1.1 natively.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.042.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.042.htp">Log info</A>
+
+/ Last changed on Tue Jan  2 02:56:56 2001 by
+<A HREF="mailto:moshez@zadka.site.co.il">Moshe Zadka</A>
+<P>
+
+<HR>
+<H2><A NAME="4.43">4.43. Unexplicable syntax errors in compile() or exec.</A></H2>
+When a statement suite (as opposed to an expression) is compiled by
+compile(), exec or execfile(), it <I>must</I> end in a newline.  In some
+cases, when the source ends in an indented block it appears that at
+least two newlines are required.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.043.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.043.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="4.44">4.44. How do I convert a string to a number?</A></H2>
+For integers, use the built-in int() function, e.g. int('144') == 144.  Similarly, long() converts from string to long integer, e.g. long('144') == 144L; and float() to floating-point, e.g. float('144') == 144.0.
+<P>
+Note that these are restricted to decimal interpretation, so 
+that int('0144') == 144 and int('0x144') raises ValueError. For Python
+2.0 int takes the base to convert from as a second optional argument, so
+int('0x144', 16) == 324.
+<P>
+For greater flexibility, or before Python 1.5, import the module 
+string and use the string.atoi() function for integers, 
+string.atol() for long integers, or string.atof() for 
+floating-point.  E.g., 
+string.atoi('100', 16) == string.atoi('0x100', 0) == 256.  
+See the library reference manual section for the string module for 
+more details.
+<P>
+While you could use the built-in function eval() instead of
+any of those, this is not recommended, because someone could pass you
+a Python expression that might have unwanted side effects (like
+reformatting your disk). It also has the effect of interpreting numbers
+as Python expressions, so that e.g. eval('09') gives a syntax error
+since Python regards numbers starting with '0' as octal (base 8).
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.044.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.044.htp">Log info</A>
+
+/ Last changed on Thu Dec 28 12:37:34 2000 by
+<A HREF="mailto:pbjorn@uswest.net">Bjorn Pettersen</A>
+<P>
+
+<HR>
+<H2><A NAME="4.45">4.45. How do I convert a number to a string?</A></H2>
+To convert, e.g., the number 144 to the string '144', use the
+built-in function repr() or the backquote notation (these are
+equivalent).  If you want a hexadecimal or octal representation, use
+the built-in functions hex() or oct(), respectively.  For fancy
+formatting, use the % operator on strings, just like C printf formats,
+e.g. "%04d" % 144 yields '0144' and "%.3f" % (1/3.0) yields '0.333'.
+See the library reference manual for details.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.045.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.045.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="4.46">4.46. How do I copy a file?</A></H2>
+There's the shutil module which contains a copyfile()
+function that implements a copy loop;
+it isn't good enough for the Macintosh, though:
+it doesn't copy the resource fork and Finder info.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.046.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.046.htp">Log info</A>
+
+/ Last changed on Tue Jan  2 02:59:40 2001 by
+<A HREF="mailto:moshez@zadka.site.co.il">Moshe Zadka</A>
+<P>
+
+<HR>
+<H2><A NAME="4.47">4.47. How do I check if an object is an instance of a given class or of a subclass of it?</A></H2>
+If you are developing the classes from scratch it might be better to
+program in a more proper object-oriented style -- instead of doing a different
+thing based on class membership, why not use a method and define the
+method differently in different classes?
+<P>
+However, there are some legitimate situations
+where you need to test for class membership.
+<P>
+In Python 1.5, you can use the built-in function isinstance(obj, cls).
+<P>
+The following approaches can be used with earlier Python versions:
+<P>
+An unobvious method is to raise the object
+as an exception and to try to catch the exception with the class you're
+testing for:
+<P>
+<PRE>
+       def is_instance_of(the_instance, the_class):
+           try:
+               raise the_instance
+           except the_class:
+               return 1
+           except:
+               return 0
+</PRE>
+This technique can be used to distinguish "subclassness"
+from a collection of classes as well
+<P>
+<PRE>
+                try:
+                              raise the_instance
+                except Audible:
+                              the_instance.play(largo)
+                except Visual:
+                              the_instance.display(gaudy)
+                except Olfactory:
+                              sniff(the_instance)
+                except:
+                              raise ValueError, "dunno what to do with this!"
+</PRE>
+This uses the fact that exception catching tests for class or subclass
+membership.
+<P>
+A different approach is to test for the presence of a class attribute that
+is presumably unique for the given class.  For instance:
+<P>
+<PRE>
+       class MyClass:
+           ThisIsMyClass = 1
+           ...
+</PRE>
+<PRE>
+       def is_a_MyClass(the_instance):
+           return hasattr(the_instance, 'ThisIsMyClass')
+</PRE>
+This version is easier to inline, and probably faster (inlined it
+is definitely faster).  The disadvantage is that someone else could cheat:
+<P>
+<PRE>
+       class IntruderClass:
+           ThisIsMyClass = 1    # Masquerade as MyClass
+           ...
+</PRE>
+but this may be seen as a feature (anyway, there are plenty of other ways
+to cheat in Python).  Another disadvantage is that the class must be
+prepared for the membership test.  If you do not "control the
+source code" for the class it may not be advisable to modify the
+class to support testability.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.047.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.047.htp">Log info</A>
+
+/ Last changed on Fri Jan  2 15:16:04 1998 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="4.48">4.48. What is delegation?</A></H2>
+Delegation refers to an object oriented technique Python programmers
+may implement with particular ease.  Consider the following:
+<P>
+<PRE>
+  from string import upper
+</PRE>
+<PRE>
+  class UpperOut:
+        def __init__(self, outfile):
+              self.__outfile = outfile
+        def write(self, str):
+              self.__outfile.write( upper(str) )
+        def __getattr__(self, name):
+              return getattr(self.__outfile, name)
+</PRE>
+Here the UpperOut class redefines the write method
+to convert the argument string to upper case before
+calling the underlying self.__outfile.write method, but
+all other methods are delegated to the underlying 
+self.__outfile object.  The delegation is accomplished
+via the "magic" __getattr__ method.  Please see the
+language reference for more information on the use
+of this method.
+<P>
+Note that for more general cases delegation can
+get trickier. Particularly when attributes must be set
+as well as gotten the class must define a __settattr__
+method too, and it must do so carefully.
+<P>
+The basic implementation of __setattr__ is roughly
+equivalent to the following:
+<P>
+<PRE>
+   class X:
+        ...
+        def __setattr__(self, name, value):
+             self.__dict__[name] = value
+        ...
+</PRE>
+Most __setattr__ implementations must modify
+self.__dict__ to store local state for self without
+causing an infinite recursion.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.048.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.048.htp">Log info</A>
+
+/ Last changed on Wed Aug 13 07:11:24 1997 by
+<A HREF="mailto:aaron_watters@msn.com">aaron watters</A>
+<P>
+
+<HR>
+<H2><A NAME="4.49">4.49. How do I test a Python program or component.</A></H2>
+We presume for the purposes of this question you are interested
+in standalone testing, rather than testing your components inside
+a testing framework. The best-known testing framework for Python
+is the PyUnit module, maintained at
+<P>
+<PRE>
+    <A HREF="http://pyunit.sourceforge.net">http://pyunit.sourceforge.net</A>/
+</PRE>
+For standalone testing, it helps to write the program so that
+it may be easily tested by using good modular design.
+In particular your program
+should have almost all functionality encapsulated in either functions
+or class methods -- and this sometimes has the surprising and
+delightful effect of making the program run faster (because
+local variable accesses are faster than global accesses).
+Furthermore the program should avoid depending on mutating
+global variables, since this makes testing much more difficult to do.
+<P>
+The "global main logic" of your program may be as simple
+as
+<P>
+<PRE>
+  if __name__=="__main__":
+       main_logic()
+</PRE>
+at the bottom of the main module of your program.
+<P>
+Once your program is organized as a tractable collection
+of functions and class behaviours you should write test
+functions that exercise the behaviours.  A test suite 
+can be associated with each module which automates
+a sequence of tests.  This sounds like a lot of work, but
+since Python is so terse and flexible it's surprisingly easy.
+You can make coding much more pleasant and fun by
+writing your test functions in parallel with the "production
+code", since this makes it easy to find bugs and even
+design flaws earlier.
+<P>
+"Support modules" that are not intended to be the main
+module of a program may include a "test script interpretation"
+which invokes a self test of the module.
+<P>
+<PRE>
+   if __name__ == "__main__":
+      self_test()
+</PRE>
+Even programs that interact with complex external
+interfaces may be tested when the external interfaces are
+unavailable by using "fake" interfaces implemented in
+Python.  For an example of a "fake" interface, the following
+class defines (part of) a "fake" file interface:
+<P>
+<PRE>
+ import string
+ testdata = "just a random sequence of characters"
+</PRE>
+<PRE>
+ class FakeInputFile:
+   data = testdata
+   position = 0
+   closed = 0
+</PRE>
+<PRE>
+   def read(self, n=None):
+       self.testclosed()
+       p = self.position
+       if n is None:
+          result= self.data[p:]
+       else:
+          result= self.data[p: p+n]
+       self.position = p + len(result)
+       return result
+</PRE>
+<PRE>
+   def seek(self, n, m=0):
+       self.testclosed()
+       last = len(self.data)
+       p = self.position
+       if m==0: 
+          final=n
+       elif m==1:
+          final=n+p
+       elif m==2:
+          final=len(self.data)+n
+       else:
+          raise ValueError, "bad m"
+       if final&lt;0:
+          raise IOError, "negative seek"
+       self.position = final
+</PRE>
+<PRE>
+   def isatty(self):
+       return 0
+</PRE>
+<PRE>
+   def tell(self):
+       return self.position
+</PRE>
+<PRE>
+   def close(self):
+       self.closed = 1
+</PRE>
+<PRE>
+   def testclosed(self):
+       if self.closed:
+          raise IOError, "file closed"
+</PRE>
+Try f=FakeInputFile() and test out its operations.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.049.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.049.htp">Log info</A>
+
+/ Last changed on Mon Jun  3 01:12:10 2002 by
+<A HREF="mailto:neal@metaslash.com">Neal Norwitz</A>
+<P>
+
+<HR>
+<H2><A NAME="4.50">4.50. My multidimensional list (array) is broken! What gives?</A></H2>
+You probably tried to make a multidimensional array like this.
+<P>
+<PRE>
+   A = [[None] * 2] * 3
+</PRE>
+This makes a list containing 3 references to the same list of length
+two.  Changes to one row will show in all rows, which is probably not
+what you want.  The following works much better:
+<P>
+<PRE>
+   A = [None]*3
+   for i in range(3):
+        A[i] = [None] * 2
+</PRE>
+This generates a list containing 3 different lists of length two.
+<P>
+If you feel weird, you can also do it in the following way:
+<P>
+<PRE>
+   w, h = 2, 3
+   A = map(lambda i,w=w: [None] * w, range(h))
+</PRE>
+For Python 2.0 the above can be spelled using a list comprehension:
+<P>
+<PRE>
+   w,h = 2,3
+   A = [ [None]*w for i in range(h) ]
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.050.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.050.htp">Log info</A>
+
+/ Last changed on Thu Dec 28 12:18:35 2000 by
+<A HREF="mailto:pbjorn@uswest.net">Bjorn Pettersen</A>
+<P>
+
+<HR>
+<H2><A NAME="4.51">4.51. I want to do a complicated sort: can you do a Schwartzian Transform in Python?</A></H2>
+Yes, and in Python you only have to write it once:
+<P>
+<PRE>
+ def st(List, Metric):
+     def pairing(element, M = Metric):
+           return (M(element), element)
+     paired = map(pairing, List)
+     paired.sort()
+     return map(stripit, paired)
+</PRE>
+<PRE>
+ def stripit(pair):
+     return pair[1]
+</PRE>
+This technique, attributed to Randal Schwartz, sorts the elements
+of a list by a metric which maps each element to its "sort value".
+For example, if L is a list of string then
+<P>
+<PRE>
+   import string
+   Usorted = st(L, string.upper)
+</PRE>
+<PRE>
+   def intfield(s):
+         return string.atoi( string.strip(s[10:15] ) )
+</PRE>
+<PRE>
+   Isorted = st(L, intfield)
+</PRE>
+Usorted gives the elements of L sorted as if they were upper
+case, and Isorted gives the elements of L sorted by the integer
+values that appear in the string slices starting at position 10
+and ending at position 15. In Python 2.0 this can be done more
+naturally with list comprehensions:
+<P>
+<PRE>
+  tmp1 = [ (x.upper(), x) for x in L ] # Schwartzian transform
+  tmp1.sort()
+  Usorted = [ x[1] for x in tmp1 ]
+</PRE>
+<PRE>
+  tmp2 = [ (int(s[10:15]), s) for s in L ] # Schwartzian transform
+  tmp2.sort()
+  Isorted = [ x[1] for x in tmp2 ]
+</PRE>
+<P>
+Note that Isorted may also be computed by
+<P>
+<PRE>
+   def Icmp(s1, s2):
+         return cmp( intfield(s1), intfield(s2) )
+</PRE>
+<PRE>
+   Isorted = L[:]
+   Isorted.sort(Icmp)
+</PRE>
+but since this method computes intfield many times for each
+element of L, it is slower than the Schwartzian Transform.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.051.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.051.htp">Log info</A>
+
+/ Last changed on Sat Jun  1 19:18:46 2002 by
+<A HREF="mailto:neal@metaslash.com">Neal Norwitz</A>
+<P>
+
+<HR>
+<H2><A NAME="4.52">4.52. How to convert between tuples and lists?</A></H2>
+The function tuple(seq) converts any sequence into a tuple with
+the same items in the same order.
+For example, tuple([1, 2, 3]) yields (1, 2, 3) and tuple('abc')
+yields ('a', 'b', 'c').  If the argument is
+a tuple, it does not make a copy but returns the same object, so
+it is cheap to call tuple() when you aren't sure that an object
+is already a tuple.
+<P>
+The function list(seq) converts any sequence into a list with
+the same items in the same order.
+For example, list((1, 2, 3)) yields [1, 2, 3] and list('abc')
+yields ['a', 'b', 'c'].  If the argument is a list,
+it makes a copy just like seq[:] would.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.052.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.052.htp">Log info</A>
+
+/ Last changed on Sun Jun 14 14:18:53 1998 by
+<A HREF="mailto:tim_one@email.msn.com">Tim Peters</A>
+<P>
+
+<HR>
+<H2><A NAME="4.53">4.53. Files retrieved with urllib contain leading garbage that looks like email headers.</A></H2>
+<I>Extremely</I> old  versions of Python supplied libraries which
+did not support HTTP/1.1; the vanilla httplib in Python 1.4
+only recognized HTTP/1.0.  In Python 2.0 full HTTP/1.1 support is included.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.053.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.053.htp">Log info</A>
+
+/ Last changed on Mon Jan  8 17:26:18 2001 by
+<A HREF="mailto:sholden@holdenweb.com">Steve Holden</A>
+<P>
+
+<HR>
+<H2><A NAME="4.54">4.54. How do I get a list of all instances of a given class?</A></H2>
+Python does not keep track of all instances of a class (or of a
+built-in type).
+<P>
+You can program the class's constructor to keep track of all
+instances, but unless you're very clever, this has the disadvantage
+that the instances never get deleted,because your list of all
+instances keeps a reference to them.
+<P>
+(The trick is to regularly inspect the reference counts of the
+instances you've retained, and if the reference count is below a
+certain level, remove it from the list.  Determining that level is
+tricky -- it's definitely larger than 1.)
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.054.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.054.htp">Log info</A>
+
+/ Last changed on Tue May 27 23:52:16 1997 by
+<A HREF="mailto:guido@cnri.reston.va.us">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="4.55">4.55. A regular expression fails with regex.error: match failure.</A></H2>
+This is usually caused by too much backtracking; the regular
+expression engine has a fixed size stack which holds at most 4000
+backtrack points.  Every character matched by e.g. ".*" accounts for a
+backtrack point, so even a simple search like
+<P>
+<PRE>
+  regex.match('.*x',"x"*5000)
+</PRE>
+will fail.
+<P>
+This is fixed in the re module introduced with 
+Python 1.5; consult the Library Reference section on re for more information.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.055.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.055.htp">Log info</A>
+
+/ Last changed on Thu Jul 30 12:35:49 1998 by
+<A HREF="mailto:akuchlin@cnri.reston.va.us">A.M. Kuchling</A>
+<P>
+
+<HR>
+<H2><A NAME="4.56">4.56. I can't get signal handlers to work.</A></H2>
+The most common problem is that the signal handler is declared
+with the wrong argument list.  It is called as
+<P>
+<PRE>
+       handler(signum, frame)
+</PRE>
+so it should be declared with two arguments:
+<P>
+<PRE>
+       def handler(signum, frame):
+               ...
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.056.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.056.htp">Log info</A>
+
+/ Last changed on Wed May 28 09:29:08 1997 by
+<A HREF="mailto:guido@cnri.reston.va.us">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="4.57">4.57. I can't use a global variable in a function? Help!</A></H2>
+Did you do something like this?
+<P>
+<PRE>
+   x = 1 # make a global
+</PRE>
+<PRE>
+   def f():
+         print x # try to print the global
+         ...
+         for j in range(100):
+              if q>3:
+                 x=4
+</PRE>
+Any variable assigned in a function is local to that function.
+unless it is specifically declared global. Since a value is bound
+to x as the last statement of the function body, the compiler
+assumes that x is local. Consequently the "print x"
+attempts to print an uninitialized local variable and will
+trigger a NameError.
+<P>
+In such cases the solution is to insert an explicit global
+declaration at the start of the function, making it
+<P>
+<P>
+<PRE>
+   def f():
+         global x
+         print x # try to print the global
+         ...
+         for j in range(100):
+              if q>3:
+                 x=4
+</PRE>
+<P>
+In this case, all references to x are interpreted as references
+to the x from the module namespace.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.057.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.057.htp">Log info</A>
+
+/ Last changed on Mon Feb 12 15:52:12 2001 by
+<A HREF="mailto:sholden@holdenweb.com">Steve Holden</A>
+<P>
+
+<HR>
+<H2><A NAME="4.58">4.58. What's a negative index? Why doesn't list.insert() use them?</A></H2>
+Python sequences are indexed with positive numbers and
+negative numbers.  For positive numbers 0 is the first index
+1 is the second index and so forth.  For negative indices -1
+is the last index and -2 is the pentultimate (next to last) index
+and so forth.  Think of seq[-n] as the same as seq[len(seq)-n].
+<P>
+Using negative indices can be very convenient.  For example
+if the string Line ends in a newline then Line[:-1] is all of Line except
+the newline.
+<P>
+Sadly the list builtin method L.insert does not observe negative
+indices.  This feature could be considered a mistake but since
+existing programs depend on this feature it may stay around 
+forever.  L.insert for negative indices inserts at the start of the
+list.  To get "proper" negative index behaviour use L[n:n] = [x]
+in place of the insert method.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.058.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.058.htp">Log info</A>
+
+/ Last changed on Wed Aug 13 07:03:18 1997 by
+<A HREF="mailto:aaron_watters@msn.com">aaron watters</A>
+<P>
+
+<HR>
+<H2><A NAME="4.59">4.59. How can I sort one list by values from another list?</A></H2>
+You can sort lists of  tuples.
+<P>
+<PRE>
+  >>> list1 = ["what", "I'm", "sorting", "by"]
+  >>> list2 = ["something", "else", "to", "sort"]
+  >>> pairs = map(None, list1, list2)
+  >>> pairs
+  [('what', 'something'), ("I'm", 'else'), ('sorting', 'to'), ('by', 'sort')]
+  >>> pairs.sort()
+  >>> pairs
+  [("I'm", 'else'), ('by', 'sort'), ('sorting', 'to'), ('what', 'something')]
+  >>> result = pairs[:]
+  >>> for i in xrange(len(result)): result[i] = result[i][1]
+  ...
+  >>> result
+  ['else', 'sort', 'to', 'something']
+</PRE>
+And if you didn't understand the question, please see the
+example above ;c).  Note that "I'm" sorts before "by" because
+uppercase "I" comes before lowercase "b" in the ascii order.
+Also see 4.51.
+<P>
+In Python 2.0 this can be done like:
+<P>
+<PRE>
+ >>> list1 = ["what", "I'm", "sorting", "by"]
+ >>> list2 = ["something", "else", "to", "sort"]
+ >>> pairs = zip(list1, list2)
+ >>> pairs
+ [('what', 'something'), ("I'm", 'else'), ('sorting', 'to'), ('by', 'sort')]
+ >>> pairs.sort()
+ >>> result = [ x[1] for x in pairs ]
+ >>> result
+ ['else', 'sort', 'to', 'something']
+</PRE>
+[Followup]
+<P>
+Someone asked, why not this for the last steps:
+<P>
+<PRE>
+  result = []
+  for p in pairs: result.append(p[1])
+</PRE>
+This is much more legible.  However, a quick test shows that
+it is almost twice as slow for long lists.  Why?  First of all,
+the append() operation has to reallocate memory, and while it
+uses some tricks to avoid doing that each time, it still has
+to do it occasionally, and apparently that costs quite a bit.
+Second, the expression "result.append" requires an extra
+attribute lookup.  The attribute lookup could be done away
+with by rewriting as follows:
+<P>
+<PRE>
+  result = []
+  append = result.append
+  for p in pairs: append(p[1])
+</PRE>
+which gains back some speed, but is still considerably slower
+than the original solution, and hardly less convoluted.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.059.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.059.htp">Log info</A>
+
+/ Last changed on Thu Dec 28 12:56:35 2000 by
+<A HREF="mailto:pbjorn@uswest.net">Bjorn Pettersen</A>
+<P>
+
+<HR>
+<H2><A NAME="4.60">4.60. Why doesn't dir() work on builtin types like files and lists?</A></H2>
+It does starting with Python 1.5.
+<P>
+Using 1.4, you can find out which methods a given object supports
+by looking at its __methods__ attribute:
+<P>
+<PRE>
+    >>> List = []
+    >>> List.__methods__
+    ['append', 'count', 'index', 'insert', 'remove', 'reverse', 'sort']
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.060.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.060.htp">Log info</A>
+
+/ Last changed on Thu Sep 16 14:56:42 1999 by
+<A HREF="mailto:skip@mojam.com">Skip Montanaro</A>
+<P>
+
+<HR>
+<H2><A NAME="4.61">4.61. How can I mimic CGI form submission (METHOD=POST)?</A></H2>
+I would like to retrieve web pages that are the result of POSTing a
+form. Is there existing code that would let me do this easily?
+<P>
+Yes. Here's a simple example that uses httplib.  
+<P>
+<PRE>
+    #!/usr/local/bin/python
+</PRE>
+<PRE>
+    import httplib, sys, time
+</PRE>
+<PRE>
+    ### build the query string
+    qs = "First=Josephine&amp;MI=Q&amp;Last=Public"
+</PRE>
+<PRE>
+    ### connect and send the server a path
+    httpobj = httplib.HTTP('www.some-server.out-there', 80)
+    httpobj.putrequest('POST', '/cgi-bin/some-cgi-script')
+    ### now generate the rest of the HTTP headers...
+    httpobj.putheader('Accept', '*/*')
+    httpobj.putheader('Connection', 'Keep-Alive')
+    httpobj.putheader('Content-type', 'application/x-www-form-urlencoded')
+    httpobj.putheader('Content-length', '%d' % len(qs))
+    httpobj.endheaders()
+    httpobj.send(qs)
+    ### find out what the server said in response...
+    reply, msg, hdrs = httpobj.getreply()
+    if reply != 200:
+       sys.stdout.write(httpobj.getfile().read())
+</PRE>
+Note that in general for "url encoded posts" (the default) query strings must be "quoted" to, for example, change equals signs and spaces to an encoded form when they occur in name or value.  Use urllib.quote to perform this quoting.  For example to send name="Guy Steele, Jr.":
+<P>
+<PRE>
+   >>> from urllib import quote
+   >>> x = quote("Guy Steele, Jr.")
+   >>> x
+   'Guy%20Steele,%20Jr.'
+   >>> query_string = "name="+x
+   >>> query_string
+   'name=Guy%20Steele,%20Jr.'
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.061.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.061.htp">Log info</A>
+
+/ Last changed on Mon Jun 21 03:47:07 1999 by
+<A HREF="mailto:tbryan@python.net">TAB</A>
+<P>
+
+<HR>
+<H2><A NAME="4.62">4.62. If my program crashes with a bsddb (or anydbm) database open, it gets corrupted. How come?</A></H2>
+Databases opened for write access with the bsddb module (and often by
+the anydbm module, since it will preferentially use bsddb) must
+explicitly be closed using the close method of the database.  The
+underlying libdb package caches database contents which need to be
+converted to on-disk form and written, unlike regular open files which
+already have the on-disk bits in the kernel's write buffer, where they
+can just be dumped by the kernel with the program exits.
+<P>
+If you have initialized a new bsddb database but not written anything to
+it before the program crashes, you will often wind up with a zero-length
+file and encounter an exception the next time the file is opened.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.062.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.062.htp">Log info</A>
+
+/ Last changed on Mon Jun  3 01:15:01 2002 by
+<A HREF="mailto:neal@metaslash.com">Neal Norwitz</A>
+<P>
+
+<HR>
+<H2><A NAME="4.63">4.63. How do I make a Python script executable on Unix?</A></H2>
+You need to do two things: the script file's mode must be executable
+(include the 'x' bit), and the first line must begin with #!
+followed by the pathname for the Python interpreter.
+<P>
+The first is done by executing 'chmod +x scriptfile' or perhaps
+'chmod 755 scriptfile'.
+<P>
+The second can be done in a number of way.  The most straightforward
+way is to write
+<P>
+<PRE>
+  #!/usr/local/bin/python
+</PRE>
+as the very first line of your file - or whatever the pathname is
+where the python interpreter is installed on your platform.
+<P>
+If you would like the script to be independent of where the python
+interpreter lives, you can use the "env" program.  On almost all
+platforms, the following will work, assuming the python interpreter
+is in a directory on the user's $PATH:
+<P>
+<PRE>
+  #! /usr/bin/env python
+</PRE>
+Note -- *don't* do this for CGI scripts.  The $PATH variable for
+CGI scripts is often very minimal, so you need to use the actual
+absolute pathname of the interpreter.
+<P>
+Occasionally, a user's environment is so full that the /usr/bin/env
+program fails; or there's no env program at all.
+In that case, you can try the following hack (due to Alex Rezinsky):
+<P>
+<PRE>
+  #! /bin/sh
+  """:"
+  exec python $0 ${1+"$@"}
+  """
+</PRE>
+The disadvantage is that this defines the script's __doc__ string.
+However, you can fix that by adding
+<P>
+<PRE>
+  __doc__ = """...Whatever..."""
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.063.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.063.htp">Log info</A>
+
+/ Last changed on Mon Jan 15 09:19:16 2001 by
+<A HREF="mailto:neal@metaslash.com">Neal Norwitz</A>
+<P>
+
+<HR>
+<H2><A NAME="4.64">4.64. How do you remove duplicates from a list?</A></H2>
+See the Python Cookbook for a long discussion of many cool ways:
+<P>
+<PRE>
+    <A HREF="http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52560">http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52560</A>
+</PRE>
+Generally, if you don't mind reordering the List
+<P>
+<PRE>
+   if List:
+      List.sort()
+      last = List[-1]
+      for i in range(len(List)-2, -1, -1):
+          if last==List[i]: del List[i]
+          else: last=List[i]
+</PRE>
+If all elements of the list may be used as
+dictionary keys (ie, they are all hashable)
+this is often faster
+<P>
+<PRE>
+   d = {}
+   for x in List: d[x]=x
+   List = d.values()
+</PRE>
+Also, for extremely large lists you might
+consider more optimal alternatives to the first one.
+The second one is pretty good whenever it can
+be used.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.064.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.064.htp">Log info</A>
+
+/ Last changed on Fri May 24 21:56:33 2002 by
+<A HREF="mailto:tim.one@comcast.net">Tim Peters</A>
+<P>
+
+<HR>
+<H2><A NAME="4.65">4.65. Are there any known year 2000 problems in Python?</A></H2>
+I am not aware of year 2000 deficiencies in Python 1.5.  Python does
+very few date calculations and for what it does, it relies on the C
+library functions.  Python generally represent times either as seconds
+since 1970 or as a tuple (year, month, day, ...) where the year is
+expressed with four digits, which makes Y2K bugs unlikely.  So as long
+as your C library is okay, Python should be okay.  Of course, I cannot
+vouch for <I>your</I> Python code!
+<P>
+Given the nature of freely available software, I have to add that this statement is not
+legally binding.  The Python copyright notice contains the following
+disclaimer:
+<P>
+<PRE>
+  STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
+  REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
+  MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
+  CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
+  DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+  PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+  TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+  PERFORMANCE OF THIS SOFTWARE.
+</PRE>
+The good news is that <I>if</I> you encounter a problem, you have full
+source available to track it down and fix it!
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.065.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.065.htp">Log info</A>
+
+/ Last changed on Fri Apr 10 14:59:31 1998 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="4.66">4.66. I want a version of map that applies a method to a sequence of objects! Help!</A></H2>
+Get fancy!
+<P>
+<PRE>
+  def method_map(objects, method, arguments):
+       """method_map([a,b], "flog", (1,2)) gives [a.flog(1,2), b.flog(1,2)]"""
+       nobjects = len(objects)
+       methods = map(getattr, objects, [method]*nobjects)
+       return map(apply, methods, [arguments]*nobjects)
+</PRE>
+It's generally a good idea to get to know the mysteries of map and apply
+and getattr and the other dynamic features of Python.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.066.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.066.htp">Log info</A>
+
+/ Last changed on Mon Jan  5 14:21:14 1998 by
+<A HREF="mailto:aaron_watters@msn.com">Aaron Watters</A>
+<P>
+
+<HR>
+<H2><A NAME="4.67">4.67. How do I generate random numbers in Python?</A></H2>
+The standard library module "random" implements a random number
+generator.  Usage is simple:
+<P>
+<PRE>
+    import random
+</PRE>
+<PRE>
+    random.random()
+</PRE>
+This returns a random floating point number in the range [0, 1).
+<P>
+There are also many other specialized generators in this module, such
+as
+<P>
+<PRE>
+    randrange(a, b) chooses an integer in the range [a, b)
+    uniform(a, b) chooses a floating point number in the range [a, b)
+    normalvariate(mean, sdev) sample from normal (Gaussian) distribution
+</PRE>
+Some higher-level functions operate on sequences directly, such as
+<P>
+<PRE>
+    choice(S) chooses random element from a given sequence
+    shuffle(L) shuffles a list in-place, i.e. permutes it randomly
+</PRE>
+There's also a class, Random, which you can instantiate
+to create independent multiple random number generators.
+<P>
+All this is documented in the library reference manual.  Note that
+the module "whrandom" is obsolete.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.067.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.067.htp">Log info</A>
+
+/ Last changed on Mon Jun  3 01:16:51 2002 by
+<A HREF="mailto:neal@metaslash.com">Neal Norwitz</A>
+<P>
+
+<HR>
+<H2><A NAME="4.68">4.68. How do I access the serial (RS232) port?</A></H2>
+There's a Windows serial communication module (for communication
+over RS 232 serial ports) at
+<P>
+<PRE>
+  <A HREF="ftp://ftp.python.org/pub/python/contrib/sio-151.zip">ftp://ftp.python.org/pub/python/contrib/sio-151.zip</A>
+  <A HREF="http://www.python.org/ftp/python/contrib/sio-151.zip">http://www.python.org/ftp/python/contrib/sio-151.zip</A>
+</PRE>
+For DOS, try Hans Nowak's Python-DX, which supports this, at:
+<P>
+<PRE>
+  <A HREF="http://www.cuci.nl/~hnowak">http://www.cuci.nl/~hnowak</A>/
+</PRE>
+For Unix, see a usenet post by Mitch Chapman:
+<P>
+<PRE>
+  <A HREF="http://groups.google.com/groups?selm=34A04430.CF9@ohioee.com">http://groups.google.com/groups?selm=34A04430.CF9@ohioee.com</A>
+</PRE>
+For Win32, POSIX(Linux, BSD, *), Jython, Chris':
+<P>
+<PRE>
+  <A HREF="http://pyserial.sourceforge.net">http://pyserial.sourceforge.net</A>
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.068.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.068.htp">Log info</A>
+
+/ Last changed on Tue Jul  2 21:11:07 2002 by
+<A HREF="mailto:cliechti@gmx.net">Chris Liechti</A>
+<P>
+
+<HR>
+<H2><A NAME="4.69">4.69. Images on Tk-Buttons don't work in Py15?</A></H2>
+They <I>do</I> work, but you must keep your own <I>reference</I> to the image 
+object now. More verbosely, you must make sure that, say, a global 
+variable or a class attribute refers to the object.
+<P>
+Quoting Fredrik Lundh from the mailinglist:
+<P>
+<PRE>
+  Well, the Tk button widget keeps a reference to the internal
+  photoimage object, but Tkinter does not.  So when the last
+  Python reference goes away, Tkinter tells Tk to release the
+  photoimage.  But since the image is in use by a widget, Tk
+  doesn't destroy it.  Not completely.  It just blanks the image,
+  making it completely transparent...
+</PRE>
+<PRE>
+  And yes, there was a bug in the keyword argument handling
+  in 1.4 that kept an extra reference around in some cases.  And
+  when Guido fixed that bug in 1.5, he broke quite a few Tkinter
+  programs...
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.069.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.069.htp">Log info</A>
+
+/ Last changed on Tue Feb  3 11:31:03 1998 by
+<A HREF="mailto:cjr@euronet.nl">Case Roole</A>
+<P>
+
+<HR>
+<H2><A NAME="4.70">4.70. Where is the math.py (socket.py, regex.py, etc.) source file?</A></H2>
+If you can't find a source file for a module it may be a builtin
+or dynamically loaded module implemented in C, C++ or other
+compiled language.  In this case you may not have the source
+file or it may be something like mathmodule.c, somewhere in
+a C source directory (not on the Python Path).
+<P>
+Fredrik Lundh (<A HREF="mailto:fredrik@pythonware.com">fredrik@pythonware.com</A>) explains (on the python-list):
+<P>
+There are (at least) three kinds of modules in Python:
+1) modules written in Python (.py);
+2) modules written in C and dynamically loaded (.dll, .pyd, .so, .sl, etc);
+3) modules written in C and linked with the interpreter; to get a list
+of these, type:
+<P>
+<PRE>
+    import sys
+    print sys.builtin_module_names
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.070.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.070.htp">Log info</A>
+
+/ Last changed on Tue Feb  3 13:55:33 1998 by
+<A HREF="mailto:aaron_watters@msn.com">Aaron Watters</A>
+<P>
+
+<HR>
+<H2><A NAME="4.71">4.71. How do I send mail from a Python script?</A></H2>
+The standard library module smtplib does this.
+Here's a very simple interactive mail
+sender that uses it.  This method will work on any host that
+supports an SMTP listener.
+<P>
+<PRE>
+    import sys, smtplib
+</PRE>
+<PRE>
+    fromaddr = raw_input("From: ")
+    toaddrs  = raw_input("To: ").split(',')
+    print "Enter message, end with ^D:"
+    msg = ''
+    while 1:
+        line = sys.stdin.readline()
+        if not line:
+            break
+        msg = msg + line
+</PRE>
+<PRE>
+    # The actual mail send
+    server = smtplib.SMTP('localhost')
+    server.sendmail(fromaddr, toaddrs, msg)
+    server.quit()
+</PRE>
+If the local host doesn't have an SMTP listener, you need to find one. The simple method is to ask the user. Alternately, you can use the DNS system to find the mail gateway(s) responsible for the source address.
+<P>
+A Unix-only alternative uses sendmail.  The location of the
+sendmail program varies between systems; sometimes it is
+/usr/lib/sendmail, sometime /usr/sbin/sendmail.  The sendmail manual
+page will help you out.  Here's some sample code:
+<P>
+<PRE>
+  SENDMAIL = "/usr/sbin/sendmail" # sendmail location
+  import os
+  p = os.popen("%s -t -i" % SENDMAIL, "w")
+  p.write("To: <A HREF="mailto:cary@ratatosk.org">cary@ratatosk.org</A>\n")
+  p.write("Subject: test\n")
+  p.write("\n") # blank line separating headers from body
+  p.write("Some text\n")
+  p.write("some more text\n")
+  sts = p.close()
+  if sts != 0:
+      print "Sendmail exit status", sts
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.071.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.071.htp">Log info</A>
+
+/ Last changed on Mon Jun  3 07:05:12 2002 by
+<A HREF="mailto:smurf@noris.de">Matthias Urlichs</A>
+<P>
+
+<HR>
+<H2><A NAME="4.72">4.72. How do I avoid blocking in connect() of a socket?</A></H2>
+The select module is widely known to help with asynchronous
+I/O on sockets once they are connected.  However, it is less
+than common knowledge how to avoid blocking on the initial
+connect() call.  Jeremy Hylton has the following advice (slightly
+edited):
+<P>
+To prevent the TCP connect from blocking, you can set the socket to 
+non-blocking mode.  Then when you do the connect(), you will either 
+connect immediately (unlikely) or get an exception that contains the 
+errno.  errno.EINPROGRESS indicates that the connection is in 
+progress, but hasn't finished yet.  Different OSes will return 
+different errnos, so you're going to have to check.  I can tell you 
+that different versions of Solaris return different errno values. 
+<P>
+In Python 1.5 and later, you can use connect_ex() to avoid
+creating an exception.  It will just return the errno value. 
+<P>
+To poll, you can call connect_ex() again later -- 0 or errno.EISCONN 
+indicate that you're connected -- or you can pass this socket to 
+select (checking to see if it is writeable).
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.072.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.072.htp">Log info</A>
+
+/ Last changed on Tue Feb 24 21:30:45 1998 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="4.73">4.73. How do I specify hexadecimal and octal integers?</A></H2>
+To specify an octal digit, precede the octal value with a zero.  For example,
+to set the variable "a" to the octal value "10" (8 in decimal), type:
+<P>
+<PRE>
+    >>> a = 010
+</PRE>
+To verify that this works, you can type "a" and hit enter while in the
+interpreter, which will cause Python to spit out the current value of "a"
+in decimal:
+<P>
+<PRE>
+    >>> a
+    8
+</PRE>
+Hexadecimal is just as easy.  Simply precede the hexadecimal number with a
+zero, and then a lower or uppercase "x".  Hexadecimal digits can be specified
+in lower or uppercase.  For example, in the Python interpreter:
+<P>
+<PRE>
+    >>> a = 0xa5
+    >>> a
+    165
+    >>> b = 0XB2
+    >>> b
+    178
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.073.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.073.htp">Log info</A>
+
+/ Last changed on Tue Mar  3 12:53:16 1998 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="4.74">4.74. How to get a single keypress at a time?</A></H2>
+For Windows, see question 8.2.  Here is an answer for Unix (see also 4.94).
+<P>
+There are several solutions; some involve using curses, which is a
+pretty big thing to learn.  Here's a solution without curses, due
+to Andrew Kuchling (adapted from code to do a PGP-style
+randomness pool):
+<P>
+<PRE>
+        import termios, sys, os
+        fd = sys.stdin.fileno()
+        old = termios.tcgetattr(fd)
+        new = termios.tcgetattr(fd)
+        new[3] = new[3] &amp; ~termios.ICANON &amp; ~termios.ECHO
+        new[6][termios.VMIN] = 1
+        new[6][termios.VTIME] = 0
+        termios.tcsetattr(fd, termios.TCSANOW, new)
+        s = ''    # We'll save the characters typed and add them to the pool.
+        try:
+            while 1:
+                c = os.read(fd, 1)
+                print "Got character", `c`
+                s = s+c
+        finally:
+            termios.tcsetattr(fd, termios.TCSAFLUSH, old)
+</PRE>
+You need the termios module for any of this to work, and I've only
+tried it on Linux, though it should work elsewhere.  It turns off
+stdin's echoing and disables canonical mode, and then reads a
+character at a time from stdin, noting the time after each keystroke.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.074.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.074.htp">Log info</A>
+
+/ Last changed on Thu Oct 24 00:36:56 2002 by
+<A HREF="mailto:cliechti@gmx.net">chris</A>
+<P>
+
+<HR>
+<H2><A NAME="4.75">4.75. How can I overload constructors (or methods) in Python?</A></H2>
+(This actually applies to all methods, but somehow the question
+usually comes up first in the context of constructors.)
+<P>
+Where in C++ you'd write
+<P>
+<PRE>
+    class C {
+        C() { cout &lt;&lt; "No arguments\n"; }
+        C(int i) { cout &lt;&lt; "Argument is " &lt;&lt; i &lt;&lt; "\n"; }
+    }
+</PRE>
+in Python you have to write a single constructor that catches all
+cases using default arguments.  For example:
+<P>
+<PRE>
+    class C:
+        def __init__(self, i=None):
+            if i is None:
+                print "No arguments"
+            else:
+                print "Argument is", i
+</PRE>
+This is not entirely equivalent, but close enough in practice.
+<P>
+You could also try a variable-length argument list, e.g.
+<P>
+<PRE>
+        def __init__(self, *args):
+            ....
+</PRE>
+The same approach works for all method definitions.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.075.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.075.htp">Log info</A>
+
+/ Last changed on Mon Apr 20 11:55:55 1998 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="4.76">4.76. How do I pass keyword arguments from one method to another?</A></H2>
+Use apply.  For example:
+<P>
+<PRE>
+    class Account:
+        def __init__(self, **kw):
+            self.accountType = kw.get('accountType')
+            self.balance = kw.get('balance')
+</PRE>
+<PRE>
+    class CheckingAccount(Account):
+        def __init__(self, **kw):
+            kw['accountType'] = 'checking'
+            apply(Account.__init__, (self,), kw)
+</PRE>
+<PRE>
+    myAccount = CheckingAccount(balance=100.00)
+</PRE>
+In Python 2.0 you can call it directly using the new ** syntax:
+<P>
+<PRE>
+    class CheckingAccount(Account):
+        def __init__(self, **kw):
+            kw['accountType'] = 'checking'
+            Account.__init__(self, **kw)
+</PRE>
+or more generally:
+<P>
+<PRE>
+ >>> def f(x, *y, **z):
+ ...  print x,y,z
+ ...
+ >>> Y = [1,2,3]
+ >>> Z = {'foo':3,'bar':None}
+ >>> f('hello', *Y, **Z)
+ hello (1, 2, 3) {'foo': 3, 'bar': None}
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.076.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.076.htp">Log info</A>
+
+/ Last changed on Thu Dec 28 13:04:01 2000 by
+<A HREF="mailto:pbjorn@uswest.net">Bjorn Pettersen</A>
+<P>
+
+<HR>
+<H2><A NAME="4.77">4.77. What module should I use to help with generating HTML?</A></H2>
+Check out HTMLgen written by Robin Friedrich. It's a class library
+of objects corresponding to all the HTML 3.2 markup tags. It's used
+when you are writing in Python and wish to synthesize HTML pages for
+generating a web or for CGI forms, etc. 
+<P>
+It can be found in the FTP contrib area on python.org or on the 
+Starship. Use the search engines there to locate the latest version.
+<P>
+It might also be useful to consider DocumentTemplate, which offers clear 
+separation between Python code and HTML code.  DocumentTemplate is part 
+of the Bobo objects publishing system (http:/www.digicool.com/releases) 
+but can be used independantly of course!
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.077.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.077.htp">Log info</A>
+
+/ Last changed on Fri Aug 28 09:54:58 1998 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="4.78">4.78. How do I create documentation from doc strings?</A></H2>
+Use gendoc, by Daniel Larson.  See
+<P>
+<A HREF="http://starship.python.net/crew/danilo">http://starship.python.net/crew/danilo</A>/
+<P>
+It can create HTML from the doc strings in your Python source code.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.078.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.078.htp">Log info</A>
+
+/ Last changed on Mon Oct  7 17:15:51 2002 by
+<A HREF="mailto:phil@dspfactory.com">Phil Rittenhouse</A>
+<P>
+
+<HR>
+<H2><A NAME="4.79">4.79. How do I read (or write) binary data?</A></H2>
+For complex data formats, it's best to use
+use the struct module.  It's documented in the library reference.
+It allows you to take a string read from a file containing binary
+data (usually numbers) and convert it to Python objects; and vice
+versa.
+<P>
+For example, the following code reads two 2-byte integers
+and one 4-byte integer in big-endian format from a file:
+<P>
+<PRE>
+  import struct
+</PRE>
+<PRE>
+  f = open(filename, "rb")  # Open in binary mode for portability
+  s = f.read(8)
+  x, y, z = struct.unpack(">hhl", s)
+</PRE>
+The '>' in the format string forces bin-endian data; the letter
+'h' reads one "short integer" (2 bytes), and 'l' reads one
+"long integer" (4 bytes) from the string.
+<P>
+For data that is more regular (e.g. a homogeneous list of ints or
+floats), you can also use the array module, also documented
+in the library reference.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.079.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.079.htp">Log info</A>
+
+/ Last changed on Wed Oct  7 09:16:45 1998 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="4.80">4.80. I can't get key bindings to work in Tkinter</A></H2>
+An oft-heard complaint is that event handlers bound to events
+with the bind() method don't get handled even when the appropriate
+key is pressed.
+<P>
+The most common cause is that the widget to which the binding applies
+doesn't have "keyboard focus".  Check out the Tk documentation
+for the focus command.  Usually a widget is given the keyboard
+focus by clicking in it (but not for labels; see the taketocus
+option).
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.080.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.080.htp">Log info</A>
+
+/ Last changed on Fri Jun 12 09:37:33 1998 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="4.81">4.81. &quot;import crypt&quot; fails</A></H2>
+[Unix]
+<P>
+Starting with Python 1.5, the crypt module is disabled by default.
+In order to enable it, you must go into the Python source tree and
+edit the file Modules/Setup to enable it (remove a '#' sign in
+front of the line starting with '#crypt').  Then rebuild.
+You may also have to add the string '-lcrypt' to that same line.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.081.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.081.htp">Log info</A>
+
+/ Last changed on Wed Aug  5 08:57:09 1998 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="4.82">4.82. Are there coding standards or a style guide for Python programs?</A></H2>
+Yes, Guido has written the "Python Style Guide".  See
+<A HREF="http://www.python.org/doc/essays/styleguide.html">http://www.python.org/doc/essays/styleguide.html</A>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.082.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.082.htp">Log info</A>
+
+/ Last changed on Tue Sep 29 09:50:27 1998 by
+<A HREF="mailto:vanandel@ucar.edu">Joseph VanAndel</A>
+<P>
+
+<HR>
+<H2><A NAME="4.83">4.83. How do I freeze Tkinter applications?</A></H2>
+Freeze is a tool to create stand-alone applications (see 4.28).
+<P>
+When freezing Tkinter applications, the applications will not be
+truly stand-alone, as the application will still need the tcl and
+tk libraries.
+<P>
+One solution is to ship the application with the tcl and tk libraries,
+and point to them at run-time using the TCL_LIBRARY and TK_LIBRARY
+environment variables.
+<P>
+To get truly stand-alone applications, the Tcl scripts that form
+the library have to be integrated into the application as well. One
+tool supporting that is SAM (stand-alone modules), which is part
+of the Tix distribution (<A HREF="http://tix.mne.com">http://tix.mne.com</A>). Build Tix with SAM 
+enabled, perform the appropriate call to Tclsam_init etc inside 
+Python's Modules/tkappinit.c, and link with libtclsam
+and libtksam (you might include the Tix libraries as well).
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.083.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.083.htp">Log info</A>
+
+/ Last changed on Wed Jan 20 17:35:01 1999 by
+<A HREF="mailto:loewis@informatik.hu-berlin.de">Martin v. Löwis</A>
+<P>
+
+<HR>
+<H2><A NAME="4.84">4.84. How do I create static class data and static class methods?</A></H2>
+[Tim Peters, <A HREF="mailto:tim_one@email.msn.com">tim_one@email.msn.com</A>]
+<P>
+Static data (in the sense of C++ or Java) is easy; static methods (again in the sense of C++ or Java) are not supported directly.
+<P>
+STATIC DATA
+<P>
+For example,
+<P>
+<PRE>
+    class C:
+        count = 0   # number of times C.__init__ called
+</PRE>
+<PRE>
+        def __init__(self):
+            C.count = C.count + 1
+</PRE>
+<PRE>
+        def getcount(self):
+            return C.count  # or return self.count
+</PRE>
+c.count also refers to C.count for any c such that isinstance(c, C) holds, unless overridden by c itself or by some class on the base-class search path from c.__class__ back to C.
+<P>
+Caution:  within a method of C,
+<P>
+<PRE>
+    self.count = 42
+</PRE>
+creates a new and unrelated instance vrbl named "count" in self's own dict.  So rebinding of a class-static data name needs the
+<P>
+<PRE>
+    C.count = 314
+</PRE>
+form whether inside a method or not.
+<P>
+<P>
+STATIC METHODS
+<P>
+Static methods (as opposed to static data) are unnatural in Python, because
+<P>
+<PRE>
+    C.getcount
+</PRE>
+returns an unbound method object, which can't be invoked without supplying an instance of C as the first argument.
+<P>
+The intended way to get the effect of a static method is via a module-level function:
+<P>
+<PRE>
+    def getcount():
+        return C.count
+</PRE>
+If your code is structured so as to define one class (or tightly related class hierarchy) per module, this supplies the desired encapsulation.
+<P>
+Several tortured schemes for faking static methods can be found by searching DejaNews.  Most people feel such cures are worse than the disease.  Perhaps the least obnoxious is due to Pekka Pessi (mailto:<A HREF="mailto:ppessi@hut.fi">ppessi@hut.fi</A>):
+<P>
+<PRE>
+    # helper class to disguise function objects
+    class _static:
+        def __init__(self, f):
+            self.__call__ = f
+</PRE>
+<PRE>
+    class C:
+        count = 0
+</PRE>
+<PRE>
+        def __init__(self):
+            C.count = C.count + 1
+</PRE>
+<PRE>
+        def getcount():
+            return C.count
+        getcount = _static(getcount)
+</PRE>
+<PRE>
+        def sum(x, y):
+            return x + y
+        sum = _static(sum)
+</PRE>
+<PRE>
+    C(); C()
+    c = C()
+    print C.getcount()  # prints 3
+    print c.getcount()  # prints 3
+    print C.sum(27, 15) # prints 42
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.084.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.084.htp">Log info</A>
+
+/ Last changed on Thu Jan 21 21:35:38 1999 by
+<A HREF="mailto:tim_one@email.msn.com">Tim Peters</A>
+<P>
+
+<HR>
+<H2><A NAME="4.85">4.85. __import__('x.y.z') returns &lt;module 'x'&gt;; how do I get z?</A></H2>
+Try
+<P>
+<PRE>
+   __import__('x.y.z').y.z
+</PRE>
+For more realistic situations, you may have to do something like
+<P>
+<PRE>
+   m = __import__(s)
+   for i in string.split(s, ".")[1:]:
+       m = getattr(m, i)
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.085.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.085.htp">Log info</A>
+
+/ Last changed on Thu Jan 28 11:01:43 1999 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="4.86">4.86. Basic thread wisdom</A></H2>
+Please note that there is no way to take advantage of
+multiprocessor hardware using the Python thread model. The interpreter
+uses a global interpreter lock (GIL),
+which does not allow multiple threads to be concurrently active.
+<P>
+If you write a simple test program like this:
+<P>
+<PRE>
+  import thread
+  def run(name, n):
+      for i in range(n): print name, i
+  for i in range(10):
+      thread.start_new(run, (i, 100))
+</PRE>
+none of the threads seem to run!  The reason is that as soon as
+the main thread exits, all threads are killed.
+<P>
+A simple fix is to add a sleep to the end of the program,
+sufficiently long for all threads to finish:
+<P>
+<PRE>
+  import thread, time
+  def run(name, n):
+      for i in range(n): print name, i
+  for i in range(10):
+      thread.start_new(run, (i, 100))
+  time.sleep(10) # &lt;----------------------------!
+</PRE>
+But now (on many platforms) the threads don't run in parallel,
+but appear to run sequentially, one at a time!  The reason is
+that the OS thread scheduler doesn't start a new thread until
+the previous thread is blocked.
+<P>
+A simple fix is to add a tiny sleep to the start of the run
+function:
+<P>
+<PRE>
+  import thread, time
+  def run(name, n):
+      time.sleep(0.001) # &lt;---------------------!
+      for i in range(n): print name, i
+  for i in range(10):
+      thread.start_new(run, (i, 100))
+  time.sleep(10)
+</PRE>
+Some more hints:
+<P>
+Instead of using a time.sleep() call at the end, it's
+better to use some kind of semaphore mechanism.  One idea is to
+use a the Queue module to create a queue object, let each thread
+append a token to the queue when it finishes, and let the main
+thread read as many tokens from the queue as there are threads.
+<P>
+Use the threading module instead of the thread module.  It's part
+of Python since version 1.5.1.  It takes care of all these details,
+and has many other nice features too!
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.086.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.086.htp">Log info</A>
+
+/ Last changed on Fri Feb  7 16:21:55 2003 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="4.87">4.87. Why doesn't closing sys.stdout (stdin, stderr) really close it?</A></H2>
+Python file objects are a high-level layer of abstraction on top of C streams, which in turn are a medium-level layer of abstraction on top of (among other things) low-level C file descriptors.
+<P>
+For most file objects f you create in Python via the builtin "open" function, f.close() marks the Python file object as being closed from Python's point of view, and also arranges to close the underlying C stream.  This happens automatically too, in f's destructor, when f becomes garbage.
+<P>
+But stdin, stdout and stderr are treated specially by Python, because of the special status also given to them by C:  doing
+<P>
+<PRE>
+    sys.stdout.close() # ditto for stdin and stderr
+</PRE>
+marks the Python-level file object as being closed, but does <I>not</I> close the associated C stream (provided sys.stdout is still bound to its default value, which is the stream C also calls "stdout").
+<P>
+To close the underlying C stream for one of these three, you should first be sure that's what you really want to do (e.g., you may confuse the heck out of extension modules trying to do I/O).  If it is, use os.close:
+<P>
+<PRE>
+    os.close(0)   # close C's stdin stream
+    os.close(1)   # close C's stdout stream
+    os.close(2)   # close C's stderr stream
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.087.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.087.htp">Log info</A>
+
+/ Last changed on Sat Apr 17 02:22:35 1999 by
+<A HREF="mailto:tim_one@email.msn.com">Tim Peters</A>
+<P>
+
+<HR>
+<H2><A NAME="4.88">4.88. What kinds of global value mutation are thread-safe?</A></H2>
+[adapted from c.l.py responses by Gordon McMillan &amp; GvR]
+<P>
+A global interpreter lock (GIL) is used internally to ensure that only one thread runs in the Python VM at a time.  In general, Python offers to switch among threads only between bytecode instructions (how frequently it offers to switch can be set via sys.setcheckinterval).  Each bytecode instruction-- and all the C implementation code reached from it --is therefore atomic.
+<P>
+In theory, this means an exact accounting requires an exact understanding of the PVM bytecode implementation.  In practice, it means that operations on shared vrbls of builtin data types (ints, lists, dicts, etc) that "look atomic" really are.
+<P>
+For example, these are atomic (L, L1, L2 are lists, D, D1, D2 are dicts, x, y
+are objects, i, j are ints):
+<P>
+<PRE>
+    L.append(x)
+    L1.extend(L2)
+    x = L[i]
+    x = L.pop()
+    L1[i:j] = L2
+    L.sort()
+    x = y
+    x.field = y
+    D[x] = y
+    D1.update(D2)
+    D.keys()
+</PRE>
+These aren't:
+<P>
+<PRE>
+    i = i+1
+    L.append(L[-1])
+    L[i] = L[j]
+    D[x] = D[x] + 1
+</PRE>
+Note: operations that replace other objects may invoke those other objects' __del__ method when their reference count reaches zero, and that can affect things.  This is especially true for the mass updates to dictionaries and lists.  When in doubt, use a mutex!
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.088.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.088.htp">Log info</A>
+
+/ Last changed on Fri Feb  7 16:21:03 2003 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="4.89">4.89. How do I modify a string in place?</A></H2>
+Strings are immutable (see question 6.2) so you cannot modify a string
+directly.  If you need an object with this ability, try converting the
+string to a list or take a look at the array module.
+<P>
+<PRE>
+    >>> s = "Hello, world"
+    >>> a = list(s)
+    >>> print a
+    ['H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd']
+    >>> a[7:] = list("there!")
+    >>> import string
+    >>> print string.join(a, '')
+    'Hello, there!'
+</PRE>
+<PRE>
+    >>> import array
+    >>> a = array.array('c', s)
+    >>> print a
+    array('c', 'Hello, world')
+    >>> a[0] = 'y' ; print a
+    array('c', 'yello world')
+    >>> a.tostring()
+    'yello, world'
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.089.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.089.htp">Log info</A>
+
+/ Last changed on Tue May 18 01:22:47 1999 by
+<A HREF="mailto:dalke@bioreason.com">Andrew Dalke</A>
+<P>
+
+<HR>
+<H2><A NAME="4.90">4.90. How to pass on keyword/optional parameters/arguments</A></H2>
+Q: How can I pass on optional or keyword parameters from one function to another?
+<P>
+<PRE>
+       def f1(a, *b, **c):
+               ...
+</PRE>
+A: In Python 2.0 and above:
+<P>
+<PRE>
+       def f2(x, *y, **z):
+               ...
+               z['width']='14.3c'
+               ...
+               f1(x, *y, **z)
+</PRE>
+<PRE>
+   Note: y can be any sequence (e.g., list or tuple) and z must be a dict.
+</PRE>
+<P>
+A: For versions prior to 2.0, use 'apply', like:
+<P>
+<PRE>
+       def f2(x, *y, **z):
+               ...
+               z['width']='14.3c'
+               ...
+               apply(f1, (x,)+y, z)
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.090.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.090.htp">Log info</A>
+
+/ Last changed on Mon Jun  3 07:20:56 2002 by
+<A HREF="mailto:smurf@noris.de">Matthias Urlichs</A>
+<P>
+
+<HR>
+<H2><A NAME="4.91">4.91. How can I get a dictionary to display its keys in a consistent order?</A></H2>
+In general, dictionaries store their keys in an unpredictable order,
+so the display order of a dictionary's elements will be similarly
+unpredictable.
+(See 
+<a href="http://www.python.org/doc/FAQ.html#6.12">Question 6.12</a>
+to understand why this is so.)
+<P>
+This can be frustrating if you want to save a printable version to a 
+file, make some changes and then compare it with some other printed
+dictionary.  If you have such needs you can subclass UserDict.UserDict
+to create a SortedDict class that prints itself in a predictable order.
+Here's one simpleminded implementation of such a class:
+<P>
+<PRE>
+  import UserDict, string
+</PRE>
+<PRE>
+  class SortedDict(UserDict.UserDict):
+    def __repr__(self):
+      result = []
+      append = result.append
+      keys = self.data.keys()
+      keys.sort()
+      for k in keys:
+        append("%s: %s" % (`k`, `self.data[k]`))
+      return "{%s}" % string.join(result, ", ")
+</PRE>
+<PRE>
+    ___str__ = __repr__
+</PRE>
+<P>
+This will work for many common situations you might encounter, though
+it's far from a perfect solution. (It won't have any effect on the
+pprint module and does not transparently handle values that are or
+contain dictionaries.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.091.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.091.htp">Log info</A>
+
+/ Last changed on Thu Sep 16 17:31:06 1999 by
+<A HREF="mailto:skip@mojam.com">Skip Montanaro</A>
+<P>
+
+<HR>
+<H2><A NAME="4.92">4.92. Is there a Python tutorial?</A></H2>
+Yes.  See question 1.20 at 
+<A HREF="http://www.python.org/doc/FAQ.html#1.20">http://www.python.org/doc/FAQ.html#1.20</A>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.092.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.092.htp">Log info</A>
+
+/ Last changed on Sat Dec  4 16:04:00 1999 by
+<A HREF="mailto:tbryan@python.net">TAB</A>
+<P>
+
+<HR>
+<H2><A NAME="4.93">4.93. Deleted</A></H2>
+See 4.28
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.093.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.093.htp">Log info</A>
+
+/ Last changed on Tue May 28 20:40:37 2002 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="4.94">4.94. How do I get a single keypress without blocking?</A></H2>
+There are several solutions; some involve using curses, which is a
+pretty big thing to learn.  Here's a solution without curses. (see also 4.74, for Windows, see question 8.2)
+<P>
+<PRE>
+  import termios, fcntl, sys, os
+  fd = sys.stdin.fileno()
+</PRE>
+<PRE>
+  oldterm = termios.tcgetattr(fd)
+  newattr = termios.tcgetattr(fd)
+  newattr[3] = newattr[3] &amp; ~termios.ICANON &amp; ~termios.ECHO
+  termios.tcsetattr(fd, termios.TCSANOW, newattr)
+</PRE>
+<PRE>
+  oldflags = fcntl.fcntl(fd, fcntl.F_GETFL)
+  fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK)
+</PRE>
+<PRE>
+  try:
+      while 1:
+          try:
+              c = sys.stdin.read(1)
+              print "Got character", `c`
+          except IOError: pass
+  finally:
+      termios.tcsetattr(fd, termios.TCSAFLUSH, oldterm)
+      fcntl.fcntl(fd, fcntl.F_SETFL, oldflags)
+</PRE>
+<P>
+You need the termios and the fcntl module for any of this to work, 
+and I've only tried it on Linux, though it should work elsewhere. 
+<P>
+In this code, characters are read and printed one at a time.
+<P>
+termios.tcsetattr() turns off stdin's echoing and disables canonical
+mode.  fcntl.fnctl() is used to obtain stdin's file descriptor flags
+and modify them for non-blocking mode.  Since reading stdin when it is
+empty results in an IOError, this error is caught and ignored.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.094.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.094.htp">Log info</A>
+
+/ Last changed on Thu Oct 24 00:39:06 2002 by
+<A HREF="mailto:cliechti@gmx.net">chris</A>
+<P>
+
+<HR>
+<H2><A NAME="4.95">4.95. Is there an equivalent to Perl chomp()? (Remove trailing newline from string)</A></H2>
+There are two partial substitutes. If you want to remove all trailing
+whitespace, use the method string.rstrip(). Otherwise, if there is only
+one line in the string, use string.splitlines()[0].
+<P>
+<PRE>
+ -----------------------------------------------------------------------
+</PRE>
+<PRE>
+ rstrip() is too greedy, it strips all trailing white spaces.
+ splitlines() takes ControlM as line boundary.
+ Consider these strings as input:
+   "python python    \r\n"
+   "python\rpython\r\n"
+   "python python   \r\r\r\n"
+ The results from rstrip()/splitlines() are perhaps not what we want.
+</PRE>
+<PRE>
+ It seems re can perform this task.
+</PRE>
+<P>
+<PRE>
+ #!/usr/bin/python 
+ # requires python2                                                             
+</PRE>
+<PRE>
+ import re, os, StringIO
+</PRE>
+<PRE>
+ lines=StringIO.StringIO(
+   "The Python Programming Language\r\n"
+   "The Python Programming Language \r \r \r\r\n"
+   "The\rProgramming\rLanguage\r\n"
+   "The\rProgramming\rLanguage\r\r\r\r\n"
+   "The\r\rProgramming\r\rLanguage\r\r\r\r\n"
+ )
+</PRE>
+<PRE>
+ ln=re.compile("(?:[\r]?\n|\r)$") # dos:\r\n, unix:\n, mac:\r, others: unknown
+ # os.linesep does not work if someone ftps(in binary mode) a dos/mac text file
+ # to your unix box
+ #ln=re.compile(os.linesep + "$")
+</PRE>
+<PRE>
+ while 1:
+   s=lines.readline()
+   if not s: break
+   print "1.(%s)" % `s.rstrip()`
+   print "2.(%s)" % `ln.sub( "", s, 1)`
+   print "3.(%s)" % `s.splitlines()[0]`
+   print "4.(%s)" % `s.splitlines()`
+   print
+</PRE>
+<PRE>
+ lines.close()
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.095.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.095.htp">Log info</A>
+
+/ Last changed on Wed Aug  8 09:51:34 2001 by
+<A HREF="mailto:serpent@ms5.hinet.net">Crystal</A>
+<P>
+
+<HR>
+<H2><A NAME="4.96">4.96. Why is join() a string method when I'm really joining the elements of a (list, tuple, sequence)?</A></H2>
+Strings became much more like other standard types starting in release 1.6, when methods were added which give the same functionality that has always been available using the functions of the string module.  These new methods have been widely accepted, but the one which appears to make (some) programmers feel uncomfortable is:
+<P>
+<PRE>
+    ", ".join(['1', '2', '4', '8', '16'])
+</PRE>
+which gives the result
+<P>
+<PRE>
+    "1, 2, 4, 8, 16"
+</PRE>
+There are two usual arguments against this usage.
+<P>
+The first runs along the lines of: "It looks really ugly using a method of a string literal (string constant)", to which the answer is that it might, but a string literal is just a fixed value. If the methods are to be allowed on names bound to strings there is no logical reason to make them unavailable on literals. Get over it!
+<P>
+The second objection is typically cast as: "I am really telling a sequence to join its members together with a string constant". Sadly, you aren't. For some reason there seems to be much less difficulty with having split() as a string method, since in that case it is easy to see that
+<P>
+<PRE>
+    "1, 2, 4, 8, 16".split(", ")
+</PRE>
+is an instruction to a string literal to return the substrings delimited by the given separator (or, by default, arbitrary runs of white space). In this case a Unicode string returns a list of Unicode strings, an ASCII string returns a list of ASCII strings, and everyone is happy.
+<P>
+join() is a string method because in using it you are telling the separator string to iterate over an arbitrary sequence, forming string representations of each of the elements, and inserting itself between the elements' representations.  This method can be used with any argument which obeys the rules for sequence objects, inluding any new classes you might define yourself.
+<P>
+Because this is a string method it can work for Unicode strings as well as plain ASCII strings. If join() were a method of the sequence types then the sequence types would have to decide which type of string to return depending on the type of the separator.
+<P>
+If none of these arguments persuade you, then for the moment you can continue to use the join() function from the string module, which allows you to write
+<P>
+<PRE>
+    string.join(['1', '2', '4', '8', '16'], ", ")
+</PRE>
+You will just have to try and forget that the string module actually uses the syntax you are compaining about to implement the syntax you prefer!
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.096.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.096.htp">Log info</A>
+
+/ Last changed on Fri Aug  2 15:51:58 2002 by
+<A HREF="mailto:sholden@holdenweb.com">Steve Holden</A>
+<P>
+
+<HR>
+<H2><A NAME="4.97">4.97. How can my code discover the name of an object?</A></H2>
+Generally speaking, it can't, because objects don't really have names. The assignment statement does not store the assigned value in the name but a reference to it. Essentially, assignment creates a binding of a name to a value. The same is true of <I>def</I> and <I>class</I> statements, but in that case the value is a callable. Consider the following code:
+<P>
+<PRE>
+    class A:
+        pass
+</PRE>
+<PRE>
+    B = A
+</PRE>
+<PRE>
+    a = B()
+    b = a
+    print b
+    &lt;__main__.A instance at 016D07CC&gt;
+    print a
+    &lt;__main__.A instance at 016D07CC&gt;
+</PRE>
+<P>
+Arguably the class has a name: even though it is bound to two names and invoked through the name B the created instance is still reported as an instance of class A. However, it is impossible to say whether the instance's name is a or b, since both names are bound to the same value.
+<P>
+Generally speaking it should not be necessary for your code to "know the names" of particular values. Unless you are deliberately writing introspective programs, this is usually an indication that a change of approach might be beneficial.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.097.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.097.htp">Log info</A>
+
+/ Last changed on Thu Mar  8 03:53:39 2001 by
+<A HREF="mailto:sholden@holdenweb.com">Steve Holden</A>
+<P>
+
+<HR>
+<H2><A NAME="4.98">4.98. Why are floating point calculations so inaccurate?</A></H2>
+The development version of the Python Tutorial now contains an Appendix with more info:
+<PRE>
+    <A HREF="http://www.python.org/doc/current/tut/node14.html">http://www.python.org/doc/current/tut/node14.html</A>
+</PRE>
+People are often very surprised by results like this:
+<P>
+<PRE>
+ >>> 1.2-1.0
+ 0.199999999999999996
+</PRE>
+And think it is a bug in Python. It's not. It's a problem caused by
+the internal representation of a floating point number. A floating point
+number is stored as a fixed number of binary digits.
+<P>
+In decimal math, there are many numbers that can't be represented
+with a fixed number of decimal digits, i.e.
+1/3 = 0.3333333333.......
+<P>
+In the binary case, 1/2 = 0.1, 1/4 = 0.01, 1/8 = 0.001, etc. There are 
+a lot of numbers that can't be represented. The digits are cut off at
+some point.
+<P>
+Since Python 1.6, a floating point's repr() function prints as many
+digits are necessary to make eval(repr(f)) == f true for any float f.
+The str() function prints the more sensible number that was probably
+intended:
+<P>
+<PRE>
+ >>> 0.2
+ 0.20000000000000001
+ >>> print 0.2
+ 0.2
+</PRE>
+Again, this has nothing to do with Python, but with the way the
+underlying C platform handles floating points, and ultimately with
+the inaccuracy you'll always have when writing down numbers of fixed
+number of digit strings.
+<P>
+One of the consequences of this is that it is dangerous to compare 
+the result of some computation to a float with == ! 
+Tiny inaccuracies may mean that == fails.
+<P>
+Instead try something like this:
+<P>
+<PRE>
+ epsilon = 0.0000000000001 # Tiny allowed error
+ expected_result = 0.4
+</PRE>
+<PRE>
+ if expected_result-epsilon &lt;= computation() &lt;= expected_result+epsilon:
+    ...
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.098.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.098.htp">Log info</A>
+
+/ Last changed on Mon Apr  1 22:18:47 2002 by
+<A HREF="mailto:fdrake@acm.org">Fred Drake</A>
+<P>
+
+<HR>
+<H2><A NAME="4.99">4.99. I tried to open Berkeley DB file, but bsddb produces bsddb.error: (22, 'Invalid argument'). Help! How can I restore my data?</A></H2>
+Don't panic! Your data are probably intact. The most frequent cause
+for the error is that you tried to open an earlier Berkeley DB file
+with a later version of the Berkeley DB library.
+<P>
+Many Linux systems now have all three versions of Berkeley DB
+available.  If you are migrating from version 1 to a newer version use
+db_dump185 to dump a plain text version of the database.
+If you are migrating from version 2 to version 3 use db2_dump to create
+a plain text version of the database.  In either case, use db_load to
+create a new native database for the latest version installed on your
+computer.  If you have version 3 of Berkeley DB installed, you should
+be able to use db2_load to create a native version 2 database.
+<P>
+You should probably move away from Berkeley DB version 1 files because
+the hash file code contains known bugs that can corrupt your data.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.099.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.099.htp">Log info</A>
+
+/ Last changed on Wed Aug 29 16:04:29 2001 by
+<A HREF="mailto:skip@pobox.com">Skip Montanaro</A>
+<P>
+
+<HR>
+<H2><A NAME="4.100">4.100. What are the &quot;best practices&quot; for using import in a module?</A></H2>
+First, the standard modules are great.  Use them!  The standard Python library is large and varied.  Using modules can save you time and effort and will reduce maintainenance cost of your code.  (Other programs are dedicated to supporting and fixing bugs in the standard Python modules.  Coworkers may also be familiar with themodules that you use, reducing the amount of time it takes them to understand your code.)
+<P>
+The rest of this answer is largely a matter of personal preference, but here's what some newsgroup posters said (thanks to all who responded)
+<P>
+In general, don't use 
+<PRE>
+ from modulename import *
+</PRE>
+Doing so clutters the importer's namespace.  Some avoid this idiom even with the few modules that were designed to be imported in this manner.  (Modules designed in this manner include Tkinter, thread, and wxPython.)
+<P>
+Import modules at the top of a file, one module per line.  Doing so makes it clear what other modules your code requires and avoids questions of whether the module name is in scope.  Using one import per line makes it easy to add and delete module imports.
+<P>
+Move imports into a local scope (such as at the top of a function definition) if there are a lot of imports, and you're trying to avoid the cost (lots of initialization time) of many imports.  This technique is especially helpful if many of the imports are unnecessary depending on how the program executes.  You may also want to move imports into a function if the modules are only ever used in that function.  Note that loading a module the first time may be expensive (because of the one time initialization of the module) but that loading a module multiple times is virtually free (a couple of dictionary lookups).  Even if the module name has gone out of scope, the module is probably available in sys.modules.  Thus, there isn't really anything wrong with putting no imports at the module level (if they aren't needed) and putting all of the imports at the function level.  
+<P>
+It is sometimes necessary to move imports to a function or class to avoid problems with circular imports.  Gordon says:
+<PRE>
+ Circular imports are fine where both modules use the "import &lt;module&gt;"
+ form of import. They fail when the 2nd module wants to grab a name
+ out of the first ("from module import name") and the import is at
+ the top level. That's because names in the 1st are not yet available,
+ (the first module is busy importing the 2nd).  
+</PRE>
+In this case, if the 2nd module is only used in one function, then the  import can easily be moved into that function.  By the time the import is called, the first module will have finished initializing, and the second module can do its import.
+<P>
+It may also be necessary to move imports out of the top level of code 
+if some of the modules are platform-specific.  In that case, it may not even be possible to import all of the modules at the top of the file.  In this case, importing the correct modules in the corresponding platform-specific code is a good option.   
+<P>
+If only instances of a specific class uses a module, then it is reasonable to import the module in the class's __init__ method and then assign the module to an instance variable so that the module is always available (via that instance variable) during the life of the object.  Note that to delay an import until the class is instantiated, the import must be inside a method.  Putting the import inside the class but outside of any method still causes the import to occur when the module is initialized.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.100.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.100.htp">Log info</A>
+
+/ Last changed on Sat Aug  4 04:44:47 2001 by
+<A HREF="mailto:tbryan@python.net">TAB</A>
+<P>
+
+<HR>
+<H2><A NAME="4.101">4.101. Is there a tool to help find bugs or perform static analysis?</A></H2>
+Yes.  PyChecker is a static analysis tool for finding bugs 
+in Python source code as well as warning about code complexity 
+and style.
+<P>
+You can get PyChecker from:  <A HREF="http://pychecker.sf.net">http://pychecker.sf.net</A>.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.101.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.101.htp">Log info</A>
+
+/ Last changed on Fri Aug 10 15:42:11 2001 by
+<A HREF="mailto:neal@metaslash.com">Neal</A>
+<P>
+
+<HR>
+<H2><A NAME="4.102">4.102. UnicodeError: ASCII [decoding,encoding] error: ordinal not in range(128)</A></H2>
+This error indicates that your Python installation can handle
+only 7-bit ASCII strings.  There are a couple ways to fix or
+workaround the problem.
+<P>
+If your programs must handle data in arbitary character set encodings, the environment the application runs in will generally identify the encoding of the data it is handing you.  You need to convert the input to Unicode data using that encoding.  For instance, a program that handles email or web input will typically find character set encoding information in Content-Type headers.  This can then be used to properly convert input data to Unicode. Assuming the string referred to by "value" is encoded as UTF-8:
+<P>
+<PRE>
+    value = unicode(value, "utf-8")
+</PRE>
+will return a Unicode object.  If the data is not correctly encoded as UTF-8, the above call will raise a UnicodeError.
+<P>
+If you only want strings coverted to Unicode which have non-ASCII data, you can try converting them first assuming an ASCII encoding, and then generate Unicode objects if that fails:
+<P>
+<PRE>
+    try:
+        x = unicode(value, "ascii")
+    except UnicodeError:
+        value = unicode(value, "utf-8")
+    else:
+        # value was valid ASCII data
+        pass
+</PRE>
+<P>
+If you normally use a character set encoding other than US-ASCII and only need to handle data in that encoding, the simplest way to fix the problem may be simply to set the encoding in sitecustomize.py. The following code is just a modified version of the encoding setup code from site.py with the relevant lines uncommented.
+<P>
+<PRE>
+    # Set the string encoding used by the Unicode implementation.
+    # The default is 'ascii'
+    encoding = "ascii" # &lt;= CHANGE THIS if you wish
+</PRE>
+<PRE>
+    # Enable to support locale aware default string encodings.
+    import locale
+    loc = locale.getdefaultlocale()
+    if loc[1]:
+        encoding = loc[1]
+    if encoding != "ascii":
+        import sys
+        sys.setdefaultencoding(encoding)
+</PRE>
+<P>
+Also note that on Windows, there is an encoding known as "mbcs", which uses an encoding specific to your current locale.  In many cases, and particularly when working with COM, this may be an appropriate default encoding to use.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.102.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.102.htp">Log info</A>
+
+/ Last changed on Sat Apr 13 04:45:41 2002 by
+<A HREF="mailto:skip@pobox.com">Skip Montanaro</A>
+<P>
+
+<HR>
+<H2><A NAME="4.103">4.103. Using strings to call functions/methods</A></H2>
+There are various techniques:
+<P>
+* Use a dictionary pre-loaded with strings and functions.  The primary
+advantage of this technique is that the strings do not need to match the
+names of the functions.  This is also the primary technique used to
+emulate a case construct:
+<P>
+<PRE>
+    def a():
+        pass
+</PRE>
+<PRE>
+    def b():
+        pass
+</PRE>
+<PRE>
+    dispatch = {'go': a, 'stop': b}  # Note lack of parens for funcs
+</PRE>
+<PRE>
+    dispatch[get_input()]()  # Note trailing parens to call function
+</PRE>
+* Use the built-in function getattr():
+<P>
+<PRE>
+    import foo
+    getattr(foo, 'bar')()
+</PRE>
+Note that getattr() works on any object, including classes, class
+instances, modules, and so on.
+<P>
+This is used in several places in the standard library, like
+this:
+<P>
+<PRE>
+    class Foo:
+        def do_foo(self):
+            ...
+</PRE>
+<PRE>
+        def do_bar(self):
+            ...
+</PRE>
+<PRE>
+     f = getattr(foo_instance, 'do_' + opname)
+     f()
+</PRE>
+<P>
+* Use locals() or eval() to resolve the function name:
+<P>
+def myFunc():
+<PRE>
+    print "hello"
+</PRE>
+fname = "myFunc"
+<P>
+f = locals()[fname]
+f()
+<P>
+f = eval(fname)
+f()
+<P>
+Note: Using eval() can be dangerous. If you don't have absolute control
+over the contents of the string, all sorts of things could happen...
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.103.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.103.htp">Log info</A>
+
+/ Last changed on Thu Mar 21 08:14:58 2002 by
+<A HREF="mailto:erno-pyfaq@erno.iki.fi">Erno Kuusela</A>
+<P>
+
+<HR>
+<H2><A NAME="4.104">4.104. How fast are exceptions?</A></H2>
+A try/except block is extremely efficient.  Actually executing an
+exception is expensive.  In older versions of Python (prior to 2.0), it
+was common to code this idiom:
+<P>
+<PRE>
+    try:
+        value = dict[key]
+    except KeyError:
+        dict[key] = getvalue(key)
+        value = dict[key]
+</PRE>
+This idiom only made sense when you expected the dict to have the key
+95% of the time or more; other times, you coded it like this:
+<P>
+<PRE>
+    if dict.has_key(key):
+        value = dict[key]
+    else:
+        dict[key] = getvalue(key)
+        value = dict[key]
+</PRE>
+In Python 2.0 and higher, of course, you can code this as
+<P>
+<PRE>
+    value = dict.setdefault(key, getvalue(key))
+</PRE>
+However this evaluates getvalue(key) always, regardless of whether it's needed or not.  So if it's slow or has a side effect you should use one of the above variants.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.104.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.104.htp">Log info</A>
+
+/ Last changed on Mon Dec  9 10:12:30 2002 by
+<A HREF="mailto:yeti@physics.muni.cz">Yeti</A>
+<P>
+
+<HR>
+<H2><A NAME="4.105">4.105. Sharing global variables across modules</A></H2>
+The canonical way to share information across modules within a single
+program is to create a special module (often called config or cfg).
+Just import the config module in all modules of your application; the
+module then becomes available as a global name.  Because there is only
+one instance of each module, any changes made to the module object get
+reflected everywhere.  For example:
+<P>
+config.py:
+<P>
+<PRE>
+    pass
+</PRE>
+mod.py:
+<P>
+<PRE>
+    import config
+    config.x = 1
+</PRE>
+main.py:
+<P>
+<PRE>
+    import config
+    import mod
+    print config.x
+</PRE>
+Note that using a module is also the basis for implementing the
+Singleton design pattern, for the same reason.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.105.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.105.htp">Log info</A>
+
+/ Last changed on Tue Apr 23 23:07:19 2002 by
+<A HREF="mailto:aahz@pythoncraft.com">Aahz</A>
+<P>
+
+<HR>
+<H2><A NAME="4.106">4.106. Why is cPickle so slow?</A></H2>
+Use the binary option.  We'd like to make that the default, but it would
+break backward compatibility:
+<P>
+<PRE>
+    largeString = 'z' * (100 * 1024)
+    myPickle = cPickle.dumps(largeString, 1)
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.106.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.106.htp">Log info</A>
+
+/ Last changed on Thu Aug 22 19:54:25 2002 by
+<A HREF="mailto:aahz@pythoncraft.com">Aahz</A>
+<P>
+
+<HR>
+<H2><A NAME="4.107">4.107. When importing module XXX, why do I get &quot;undefined symbol: PyUnicodeUCS2_...&quot; ?</A></H2>
+You are using a version of Python that uses a 4-byte representation for
+Unicode characters, but the extension module you are importing (possibly
+indirectly) was compiled using a Python that uses a 2-byte representation
+for Unicode characters (the default).
+<P>
+If instead the name of the undefined symbol starts with PyUnicodeUCS4_,
+the problem is the same by the relationship is reversed:  Python was
+built using 2-byte Unicode characters, and the extension module was
+compiled using a Python with 4-byte Unicode characters.
+<P>
+This can easily occur when using pre-built extension packages.  RedHat
+Linux 7.x, in particular, provides a "python2" binary that is compiled
+with 4-byte Unicode.  This only causes the link failure if the extension
+uses any of the PyUnicode_*() functions.  It is also a problem if if an
+extension uses any of the Unicode-related format specifiers for
+Py_BuildValue (or similar) or parameter-specifications for
+PyArg_ParseTuple().
+<P>
+You can check the size of the Unicode character a Python interpreter is
+using by checking the value of sys.maxunicode:
+<P>
+<PRE>
+  >>> import sys
+  >>> if sys.maxunicode > 65535:
+  ...     print 'UCS4 build'
+  ... else:
+  ...     print 'UCS2 build'
+</PRE>
+The only way to solve this problem is to use extension modules compiled
+with a Python binary built using the same size for Unicode characters.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.107.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.107.htp">Log info</A>
+
+/ Last changed on Tue Aug 27 15:00:17 2002 by
+<A HREF="mailto:fdrake@acm.org">Fred Drake</A>
+<P>
+
+<HR>
+<H2><A NAME="4.108">4.108. How do I create a .pyc file?</A></H2>
+QUESTION:
+<P>
+I have a module and I wish to generate a .pyc file.  
+How do I do it? Everything I read says that generation of a .pyc file is 
+"automatic", but I'm not getting anywhere.  
+<P>
+<P>
+ANSWER: 
+<P>
+When a module is imported for the first time (or when the source is more
+recent than the current compiled file) a .pyc file containing the compiled code should be created in the
+same directory as the .py file.
+<P>
+One reason that a .pyc file may not be created is permissions problems with the directory. This can happen, for example, if you develop as one user but run as another, such as if you are testing with a web server.
+<P>
+However, in most cases, that's not the problem.
+<P>
+Creation of a .pyc file is "automatic" if you are importing a module and Python has the
+ability (permissions, free space, etc...) to write the compiled module
+back to the directory. But note that running Python on a top level script is not considered an
+import and so no .pyc will be created automatically.  For example, if you have a top-level module abc.py that imports another module xyz.py, when you run abc, xyz.pyc will be created since xyz is imported, but no abc.pyc file will be created since abc isn't imported.
+<P>
+If you need to create abc.pyc -- that is, to create a .pyc file for a
+module that is not imported -- you can.  (Look up
+the py_compile and compileall modules in the Library Reference.) 
+<P>
+You can manually compile any module using the "py_compile" module.  One
+way is to use the compile() function in that module interactively:
+<P>
+<PRE>
+    >>> import py_compile
+    >>> py_compile.compile('abc.py')
+</PRE>
+This will write the .pyc to the same location as abc.py (or you
+can override that with the optional parameter cfile).
+<P>
+You can also automatically compile all files in a directory or
+directories using the "compileall" module, which can also be run
+straight from the command line.
+<P>
+You can do it from the shell (or DOS) prompt by entering:
+<PRE>
+       python compile.py abc.py
+</PRE>
+or 
+<PRE>
+       python compile.py *
+</PRE>
+Or you can write a script to do it on a list of filenames that you enter.
+<P>
+<PRE>
+     import sys
+     from py_compile import compile
+</PRE>
+<PRE>
+     if len(sys.argv) &lt;= 1:
+        sys.exit(1)
+</PRE>
+<PRE>
+     for file in sys.argv[1:]:
+        compile(file)
+</PRE>
+ACKNOWLEDGMENTS:
+<P>
+Steve Holden, David Bolen, Rich Somerfield,  Oleg Broytmann, Steve Ferg
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq04.108.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq04.108.htp">Log info</A>
+
+/ Last changed on Wed Feb 12 15:58:25 2003 by
+<A HREF="mailto:steve@ferg.org">Stephen Ferg</A>
+<P>
+
+<HR>
+<H1>5. Extending Python</H1>
+
+<HR>
+<H2><A NAME="5.1">5.1. Can I create my own functions in C?</A></H2>
+Yes, you can create built-in modules containing functions,
+variables, exceptions and even new types in C.  This is explained in
+the document "Extending and Embedding the Python Interpreter" (<A HREF="http://www.python.org/doc/current/ext/ext.html">http://www.python.org/doc/current/ext/ext.html</A>).  Also read the chapter
+on dynamic loading.
+<P>
+There's more information on this in each of the Python books:
+Programming Python, Internet Programming with Python, and Das Python-Buch
+(in German).
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq05.001.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq05.001.htp">Log info</A>
+
+/ Last changed on Mon Dec 10 05:18:57 2001 by
+<A HREF="mailto:fdrake@acm.org">Fred L. Drake, Jr.</A>
+<P>
+
+<HR>
+<H2><A NAME="5.2">5.2. Can I create my own functions in C++?</A></H2>
+Yes, using the C-compatibility features found in C++.  Basically
+you place extern "C" { ... } around the Python include files and put
+extern "C" before each function that is going to be called by the
+Python interpreter.  Global or static C++ objects with constructors
+are probably not a good idea.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq05.002.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq05.002.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="5.3">5.3. How can I execute arbitrary Python statements from C?</A></H2>
+The highest-level function to do this is PyRun_SimpleString() which takes
+a single string argument which is executed in the context of module
+__main__ and returns 0 for success and -1 when an exception occurred
+(including SyntaxError).  If you want more control, use PyRun_String();
+see the source for PyRun_SimpleString() in Python/pythonrun.c.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq05.003.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq05.003.htp">Log info</A>
+
+/ Last changed on Fri May 23 20:08:14 1997 by
+<A HREF="mailto:billtut@microsoft.com">Bill Tutt</A>
+<P>
+
+<HR>
+<H2><A NAME="5.4">5.4. How can I evaluate an arbitrary Python expression from C?</A></H2>
+Call the function PyRun_String() from the previous question with the
+start symbol eval_input (Py_eval_input starting with 1.5a1); it 
+parses an expression, evaluates it and returns its value.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq05.004.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq05.004.htp">Log info</A>
+
+/ Last changed on Wed May 21 22:23:18 1997 by
+<A HREF="mailto:david_ascher@brown.edu">David Ascher</A>
+<P>
+
+<HR>
+<H2><A NAME="5.5">5.5. How do I extract C values from a Python object?</A></H2>
+That depends on the object's type.  If it's a tuple,
+PyTupleSize(o) returns its length and PyTuple_GetItem(o, i)
+returns its i'th item; similar for lists with PyListSize(o)
+and PyList_GetItem(o, i).  For strings, PyString_Size(o) returns
+its length and PyString_AsString(o) a pointer to its value
+(note that Python strings may contain null bytes so strlen()
+is not safe).  To test which type an object is, first make sure
+it isn't NULL, and then use PyString_Check(o), PyTuple_Check(o),
+PyList_Check(o), etc.
+<P>
+There is also a high-level API to Python objects which is
+provided by the so-called 'abstract' interface -- read
+Include/abstract.h for further details.  It allows for example 
+interfacing with any kind of Python sequence (e.g. lists and tuples)
+using calls like PySequence_Length(), PySequence_GetItem(), etc.)
+as well as many other useful protocols.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq05.005.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq05.005.htp">Log info</A>
+
+/ Last changed on Wed May 21 22:34:20 1997 by
+<A HREF="mailto:david_ascher@brown.edu">David Ascher</A>
+<P>
+
+<HR>
+<H2><A NAME="5.6">5.6. How do I use Py_BuildValue() to create a tuple of arbitrary length?</A></H2>
+You can't.  Use t = PyTuple_New(n) instead, and fill it with
+objects using PyTuple_SetItem(t, i, o) -- note that this "eats" a
+reference count of o.  Similar for lists with PyList_New(n) and
+PyList_SetItem(l, i, o).  Note that you <I>must</I> set all the tuple items to
+some value before you pass the tuple to Python code --
+PyTuple_New(n) initializes them to NULL, which isn't a valid Python
+value.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq05.006.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq05.006.htp">Log info</A>
+
+/ Last changed on Thu Jul 31 18:15:29 1997 by
+<A HREF="mailto:guido@python.org">Guido van Rossum</A>
+<P>
+
+<HR>
+<H2><A NAME="5.7">5.7. How do I call an object's method from C?</A></H2>
+The PyObject_CallMethod() function can be used to call an arbitrary
+method of an object.  The parameters are the object, the name of the
+method to call, a format string like that used with Py_BuildValue(), and the argument values:
+<P>
+<PRE>
+    PyObject *
+    PyObject_CallMethod(PyObject *object, char *method_name,
+                        char *arg_format, ...);
+</PRE>
+This works for any object that has methods -- whether built-in or
+user-defined.  You are responsible for eventually DECREF'ing the
+return value.
+<P>
+To call, e.g., a file object's "seek" method with arguments 10, 0
+(assuming the file object pointer is "f"):
+<P>
+<PRE>
+        res = PyObject_CallMethod(f, "seek", "(ii)", 10, 0);
+        if (res == NULL) {
+                ... an exception occurred ...
+        }
+        else {
+                Py_DECREF(res);
+        }
+</PRE>
+Note that since PyObject_CallObject() <I>always</I> wants a tuple for the
+argument list, to call a function without arguments, pass "()" for the
+format, and to call a function with one argument, surround the argument
+in parentheses, e.g. "(i)".
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq05.007.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq05.007.htp">Log info</A>
+
+/ Last changed on Thu Jun  6 16:15:46 2002 by
+<A HREF="mailto:neal@metaslash.com">Neal Norwitz</A>
+<P>
+
+<HR>
+<H2><A NAME="5.8">5.8. How do I catch the output from PyErr_Print() (or anything that prints to stdout/stderr)?</A></H2>
+(Due to Mark Hammond):
+<P>
+In Python code, define an object that supports the "write()" method.
+Redirect sys.stdout and sys.stderr to this object.
+Call print_error, or just allow the standard traceback mechanism to
+work. Then, the output will go wherever your write() method sends it.
+<P>
+The easiest way to do this is to use the StringIO class in the standard
+library.
+<P>
+Sample code and use for catching stdout:
+<PRE>
+       >>> class StdoutCatcher:
+       ...  def __init__(self):
+       ...   self.data = ''
+       ...  def write(self, stuff):
+       ...   self.data = self.data + stuff
+       ...  
+       >>> import sys
+       >>> sys.stdout = StdoutCatcher()
+       >>> print 'foo'
+       >>> print 'hello world!'
+       >>> sys.stderr.write(sys.stdout.data)
+       foo
+       hello world!
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq05.008.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq05.008.htp">Log info</A>
+
+/ Last changed on Wed Dec 16 18:34:25 1998 by
+<A HREF="mailto:richard@bofh.asn.au">Richard Jones</A>
+<P>
+
+<HR>
+<H2><A NAME="5.9">5.9. How do I access a module written in Python from C?</A></H2>
+You can get a pointer to the module object as follows:
+<P>
+<PRE>
+        module = PyImport_ImportModule("&lt;modulename&gt;");
+</PRE>
+If the module hasn't been imported yet (i.e. it is not yet present in
+sys.modules), this initializes the module; otherwise it simply returns
+the value of sys.modules["&lt;modulename&gt;"].  Note that it doesn't enter
+the module into any namespace -- it only ensures it has been
+initialized and is stored in sys.modules.
+<P>
+You can then access the module's attributes (i.e. any name defined in
+the module) as follows:
+<P>
+<PRE>
+        attr = PyObject_GetAttrString(module, "&lt;attrname&gt;");
+</PRE>
+Calling PyObject_SetAttrString(), to assign to variables in the module, also works.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq05.009.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq05.009.htp">Log info</A>
+
+/ Last changed on Wed May 21 22:56:40 1997 by
+<A HREF="mailto:david_ascher@brown.edu">david ascher</A>
+<P>
+
+<HR>
+<H2><A NAME="5.10">5.10. How do I interface to C++ objects from Python?</A></H2>
+Depending on your requirements, there are many approaches.  To do
+this manually, begin by reading the "Extending and Embedding" document
+(Doc/ext.tex, see also <A HREF="http://www.python.org/doc">http://www.python.org/doc</A>/).  Realize
+that for the Python run-time system, there isn't a whole lot of
+difference between C and C++ -- so the strategy to build a new Python
+type around a C structure (pointer) type will also work for C++
+objects.
+<P>
+A useful automated approach (which also works for C) is SWIG:
+<A HREF="http://www.swig.org">http://www.swig.org</A>/.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq05.010.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq05.010.htp">Log info</A>
+
+/ Last changed on Fri Oct 15 05:14:01 1999 by
+<A HREF="mailto:sjoerd.mullender@oratrix.nl">Sjoerd Mullender</A>
+<P>
+
+<HR>
+<H2><A NAME="5.11">5.11. mSQLmodule (or other old module) won't build with Python 1.5 (or later)</A></H2>
+Since python-1.4 "Python.h" will have the file includes needed in an 
+extension module.
+Backward compatibility is dropped after version 1.4 and therefore 
+mSQLmodule.c will not build as "allobjects.h" cannot be found. 
+The following change in mSQLmodule.c is harmless when building it with
+1.4 and necessary when doing so for later python versions:
+<P>
+Remove lines:
+<P>
+<PRE>
+       #include "allobjects.h"
+       #include "modsupport.h"
+</PRE>
+And insert instead:
+<P>
+<PRE>
+       #include "Python.h"
+</PRE>
+You may also need to add
+<P>
+<PRE>
+                #include "rename2.h"
+</PRE>
+if the module uses "old names".
+<P>
+This may happen with other ancient python modules as well,
+and the same fix applies.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq05.011.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq05.011.htp">Log info</A>
+
+/ Last changed on Sun Dec 21 02:03:35 1997 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="5.12">5.12. I added a module using the Setup file and the make fails! Huh?</A></H2>
+Setup must end in a newline, if there is no newline there it gets
+very sad.  Aside from this possibility, maybe you have other
+non-Python-specific linkage problems.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq05.012.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq05.012.htp">Log info</A>
+
+/ Last changed on Tue Jun 24 15:54:01 1997 by
+<A HREF="mailto:aaron_watters@msn.com">aaron watters</A>
+<P>
+
+<HR>
+<H2><A NAME="5.13">5.13. I want to compile a Python module on my Red Hat Linux system, but some files are missing.</A></H2>
+Red Hat's RPM for Python doesn't include the 
+/usr/lib/python1.x/config/ directory, which contains various files required 
+for compiling Python extensions.
+Install the python-devel RPM to get the necessary files.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq05.013.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq05.013.htp">Log info</A>
+
+/ Last changed on Tue Jan 26 13:44:04 1999 by
+<A HREF="mailto:akuchling@acm.org">A.M. Kuchling</A>
+<P>
+
+<HR>
+<H2><A NAME="5.14">5.14. What does &quot;SystemError: _PyImport_FixupExtension: module yourmodule not loaded&quot; mean?</A></H2>
+This means that you have created an extension module named "yourmodule", but your module init function does not initialize with that name.
+<P>
+Every module init function will have a line similar to:
+<P>
+<PRE>
+  module = Py_InitModule("yourmodule", yourmodule_functions);
+</PRE>
+If the string passed to this function is not the same name as your extenion module, the SystemError will be raised.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq05.014.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq05.014.htp">Log info</A>
+
+/ Last changed on Thu Mar 25 07:16:08 1999 by
+<A HREF="mailto:mhammond@skippinet.com.au">Mark Hammond</A>
+<P>
+
+<HR>
+<H2><A NAME="5.15">5.15. How to tell &quot;incomplete input&quot; from &quot;invalid input&quot;?</A></H2>
+Sometimes you want to emulate the Python interactive interpreter's
+behavior, where it gives you a continuation prompt when the input
+is incomplete (e.g. you typed the start of an "if" statement
+or you didn't close your parentheses or triple string quotes),
+but it gives you a syntax error message immediately when the input
+is invalid.
+<P>
+In Python you can use the codeop module, which approximates the
+parser's behavior sufficiently.  IDLE uses this, for example.
+<P>
+The easiest way to do it in C is to call PyRun_InteractiveLoop()
+(in a separate thread maybe) and let the Python interpreter handle
+the input for you. You can also set the PyOS_ReadlineFunctionPointer
+to point at your custom input function. See Modules/readline.c and
+Parser/myreadline.c for more hints.
+<P>
+However sometimes you have to run the embedded Python interpreter
+in the same thread as your rest application and you can't allow the
+PyRun_InteractiveLoop() to stop while waiting for user input.
+The one solution then is to call PyParser_ParseString()
+and test for e.error equal to E_EOF (then the input is incomplete).
+Sample code fragment, untested, inspired by code from  Alex Farber:
+<P>
+<PRE>
+  #include &lt;Python.h&gt;
+  #include &lt;node.h&gt;
+  #include &lt;errcode.h&gt;
+  #include &lt;grammar.h&gt;
+  #include &lt;parsetok.h&gt;
+  #include &lt;compile.h&gt;
+</PRE>
+<PRE>
+  int testcomplete(char *code)
+    /* code should end in \n */
+    /* return -1 for error, 0 for incomplete, 1 for complete */
+  {
+    node *n;
+    perrdetail e;
+</PRE>
+<PRE>
+    n = PyParser_ParseString(code, &amp;_PyParser_Grammar,
+                             Py_file_input, &amp;e);
+    if (n == NULL) {
+      if (e.error == E_EOF) 
+        return 0;
+      return -1;
+    }
+</PRE>
+<PRE>
+    PyNode_Free(n);
+    return 1;
+  }
+</PRE>
+Another solution is trying to compile the received string with 
+Py_CompileString(). If it compiles fine - try to execute the returned 
+code object by calling PyEval_EvalCode(). Otherwise save the input for 
+later. If the compilation fails, find out if it's an error or just 
+more input is required - by extracting the message string from the 
+exception tuple and comparing it to the "unexpected EOF while parsing".
+Here is a complete example using the GNU readline library (you may
+want to ignore SIGINT while calling readline()):
+<P>
+<PRE>
+  #include &lt;stdio.h&gt;
+  #include &lt;readline.h&gt;
+</PRE>
+<PRE>
+  #include &lt;Python.h&gt;
+  #include &lt;object.h&gt;
+  #include &lt;compile.h&gt;
+  #include &lt;eval.h&gt;
+</PRE>
+<PRE>
+  int main (int argc, char* argv[])
+  {
+    int i, j, done = 0;                          /* lengths of line, code */
+    char ps1[] = ">>> ";
+    char ps2[] = "... ";
+    char *prompt = ps1;
+    char *msg, *line, *code = NULL;
+    PyObject *src, *glb, *loc;
+    PyObject *exc, *val, *trb, *obj, *dum;
+</PRE>
+<PRE>
+    Py_Initialize ();
+    loc = PyDict_New ();
+    glb = PyDict_New ();
+    PyDict_SetItemString (glb, "__builtins__", PyEval_GetBuiltins ());
+</PRE>
+<PRE>
+    while (!done)
+    {
+      line = readline (prompt);
+</PRE>
+<PRE>
+      if (NULL == line)                          /* CTRL-D pressed */
+      {
+        done = 1;
+      }
+      else
+      {
+        i = strlen (line);
+</PRE>
+<PRE>
+        if (i > 0)
+          add_history (line);                    /* save non-empty lines */
+</PRE>
+<PRE>
+        if (NULL == code)                        /* nothing in code yet */
+          j = 0;
+        else
+          j = strlen (code);
+</PRE>
+<PRE>
+        code = realloc (code, i + j + 2);
+        if (NULL == code)                        /* out of memory */
+          exit (1);
+</PRE>
+<PRE>
+        if (0 == j)                              /* code was empty, so */
+          code[0] = '\0';                        /* keep strncat happy */
+</PRE>
+<PRE>
+        strncat (code, line, i);                 /* append line to code */
+        code[i + j] = '\n';                      /* append '\n' to code */
+        code[i + j + 1] = '\0';
+</PRE>
+<PRE>
+        src = Py_CompileString (code, "&lt;stdin&gt;", Py_single_input);       
+</PRE>
+<PRE>
+        if (NULL != src)                         /* compiled just fine - */
+        {
+          if (ps1  == prompt ||                  /* "&gt;&gt;&gt; " or */
+              '\n' == code[i + j - 1])           /* "... " and double '\n' */
+          {                                               /* so execute it */
+            dum = PyEval_EvalCode ((PyCodeObject *)src, glb, loc);
+            Py_XDECREF (dum);
+            Py_XDECREF (src);
+            free (code);
+            code = NULL;
+            if (PyErr_Occurred ())
+              PyErr_Print ();
+            prompt = ps1;
+          }
+        }                                        /* syntax error or E_EOF? */
+        else if (PyErr_ExceptionMatches (PyExc_SyntaxError))           
+        {
+          PyErr_Fetch (&amp;exc, &amp;val, &amp;trb);        /* clears exception! */
+</PRE>
+<PRE>
+          if (PyArg_ParseTuple (val, "sO", &amp;msg, &amp;obj) &amp;&amp;
+              !strcmp (msg, "unexpected EOF while parsing")) /* E_EOF */
+          {
+            Py_XDECREF (exc);
+            Py_XDECREF (val);
+            Py_XDECREF (trb);
+            prompt = ps2;
+          }
+          else                                   /* some other syntax error */
+          {
+            PyErr_Restore (exc, val, trb);
+            PyErr_Print ();
+            free (code);
+            code = NULL;
+            prompt = ps1;
+          }
+        }
+        else                                     /* some non-syntax error */
+        {
+          PyErr_Print ();
+          free (code);
+          code = NULL;
+          prompt = ps1;
+        }
+</PRE>
+<PRE>
+        free (line);
+      }
+    }
+</PRE>
+<PRE>
+    Py_XDECREF(glb);
+    Py_XDECREF(loc);
+    Py_Finalize();
+    exit(0);
+  }
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq05.015.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq05.015.htp">Log info</A>
+
+/ Last changed on Wed Mar 15 09:47:24 2000 by
+<A HREF="mailto:farber@cpan.org">Alex Farber</A>
+<P>
+
+<HR>
+<H2><A NAME="5.16">5.16. How do I debug an extension?</A></H2>
+When using gdb with dynamically loaded extensions, you can't set a 
+breakpoint in your extension until your extension is loaded.
+<P>
+In your .gdbinit file (or interactively), add the command
+<P>
+br _PyImport_LoadDynamicModule
+<P>
+<P>
+$ gdb /local/bin/python
+<P>
+gdb) run myscript.py
+<P>
+gdb) continue # repeat until your extension is loaded
+<P>
+gdb) finish   # so that your extension is loaded
+<P>
+gdb) br myfunction.c:50
+<P>
+gdb) continue
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq05.016.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq05.016.htp">Log info</A>
+
+/ Last changed on Fri Oct 20 11:10:32 2000 by
+<A HREF="mailto:vanandel@ucar.edu">Joe VanAndel</A>
+<P>
+
+<HR>
+<H2><A NAME="5.17">5.17. How do I find undefined Linux g++ symbols, __builtin_new or __pure_virtural</A></H2>
+To dynamically load g++ extension modules, you must recompile python, relink python using g++ (change LINKCC in the python Modules Makefile), and link your extension module using g++ (e.g., "g++ -shared -o mymodule.so mymodule.o").
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq05.017.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq05.017.htp">Log info</A>
+
+/ Last changed on Sun Jan 14 18:03:51 2001 by
+<A HREF="mailto:dbo@angryduck.com">douglas orr</A>
+<P>
+
+<HR>
+<H2><A NAME="5.18">5.18. How do I define and create objects corresponding to built-in/extension types</A></H2>
+Usually you would like to be able to inherit from a Python type when
+you ask this question. The bottom line for Python 2.2 is: types and classes are miscible. You build instances by calling classes, and you can build subclasses to your heart's desire.
+<P>
+You need to be careful when instantiating immutable types like integers or strings. See <A HREF="http://www.amk.ca/python/2.2">http://www.amk.ca/python/2.2</A>/, section 2, for details.
+<P>
+Prior to version 2.2, Python (like Java) insisted that there are first-class and second-class objects (the former are types, the latter classes), and never the twain shall meet.
+<P>
+The library has, however, done a good job of providing class wrappers for the more commonly desired objects (see UserDict, UserList and UserString for examples), and more are always welcome if you happen to be in the mood to write code. These wrappers still exist in Python 2.2.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq05.018.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq05.018.htp">Log info</A>
+
+/ Last changed on Mon Jun 10 15:14:07 2002 by
+<A HREF="mailto:smurf@noris.de">Matthias Urlichs</A>
+<P>
+
+<HR>
+<H1>6. Python's design</H1>
+
+<HR>
+<H2><A NAME="6.1">6.1. Why isn't there a switch or case statement in Python?</A></H2>
+You can do this easily enough with a sequence of
+if... elif... elif... else.  There have been some proposals for switch
+statement syntax, but there is no consensus (yet) on whether and how
+to do range tests.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.001.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.001.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="6.2">6.2. Why does Python use indentation for grouping of statements?</A></H2>
+Basically I believe that using indentation for grouping is
+extremely elegant and contributes a lot to the clarity of the average
+Python program.  Most people learn to love this feature after a while.
+Some arguments for it:
+<P>
+Since there are no begin/end brackets there cannot be a disagreement
+between grouping perceived by the parser and the human reader.  I
+remember long ago seeing a C fragment like this:
+<P>
+<PRE>
+        if (x &lt;= y)
+                x++;
+                y--;
+        z++;
+</PRE>
+and staring a long time at it wondering why y was being decremented
+even for x > y...  (And I wasn't a C newbie then either.)
+<P>
+Since there are no begin/end brackets, Python is much less prone to
+coding-style conflicts.  In C there are loads of different ways to
+place the braces (including the choice whether to place braces around
+single statements in certain cases, for consistency).  If you're used
+to reading (and writing) code that uses one style, you will feel at
+least slightly uneasy when reading (or being required to write)
+another style.
+Many coding styles place begin/end brackets on a line by themself.
+This makes programs considerably longer and wastes valuable screen
+space, making it harder to get a good overview over a program.
+Ideally, a function should fit on one basic tty screen (say, 20
+lines).  20 lines of Python are worth a LOT more than 20 lines of C.
+This is not solely due to the lack of begin/end brackets (the lack of
+declarations also helps, and the powerful operations of course), but
+it certainly helps!
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.002.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.002.htp">Log info</A>
+
+/ Last changed on Wed May 21 16:00:15 1997 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="6.3">6.3. Why are Python strings immutable?</A></H2>
+There are two advantages.  One is performance: knowing that a
+string is immutable makes it easy to lay it out at construction time
+-- fixed and unchanging storage requirements.  (This is also one of
+the reasons for the distinction between tuples and lists.)  The
+other is that strings in Python are considered as "elemental" as
+numbers.  No amount of activity will change the value 8 to anything
+else, and in Python, no amount of activity will change the string
+"eight" to anything else.  (Adapted from Jim Roskind)
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.003.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.003.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="6.4">6.4. Delete</A></H2>
+<P>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.004.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.004.htp">Log info</A>
+
+/ Last changed on Tue Jan  2 03:05:25 2001 by
+<A HREF="mailto:moshez@zadka.site.co.il">Moshe Zadka</A>
+<P>
+
+<HR>
+<H2><A NAME="6.5">6.5. Why does Python use methods for some functionality (e.g. list.index()) but functions for other (e.g. len(list))?</A></H2>
+The major reason is history. Functions were used for those
+operations that were generic for a group of types and which
+were intended to work even for objects that didn't have
+methods at all (e.g. numbers before type/class unification
+began, or tuples).
+<P>
+It is also convenient to have a function that can readily be applied
+to an amorphous collection of objects when you use the functional features of Python (map(), apply() et al).
+<P>
+In fact, implementing len(), max(), min() as a built-in function is
+actually less code than implementing them as methods for each type.
+One can quibble about individual cases but it's a part of Python,
+and it's too late to change such things fundamentally now. The
+functions have to remain to avoid massive code breakage.
+<P>
+Note that for string operations Python has moved from external functions
+(the string module) to methods.  However, len() is still a function.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.005.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.005.htp">Log info</A>
+
+/ Last changed on Thu May 30 14:08:58 2002 by
+<A HREF="mailto:sholden@holdenweb.com">Steve Holden</A>
+<P>
+
+<HR>
+<H2><A NAME="6.6">6.6. Why can't I derive a class from built-in types (e.g. lists or files)?</A></H2>
+As of Python 2.2, you can derive from built-in types.  For previous versions, the answer is:
+<P>
+This is caused by the relatively late addition of (user-defined)
+classes to the language -- the implementation framework doesn't easily
+allow it.  See the answer to question 4.2 for a work-around.  This
+<I>may</I> be fixed in the (distant) future.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.006.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.006.htp">Log info</A>
+
+/ Last changed on Thu May 23 02:53:22 2002 by
+<A HREF="mailto:neal@metaslash.com">Neal Norwitz</A>
+<P>
+
+<HR>
+<H2><A NAME="6.7">6.7. Why must 'self' be declared and used explicitly in method definitions and calls?</A></H2>
+So, is your current programming language C++ or Java? :-)
+When classes were added to Python, this was (again) the simplest way of
+implementing methods without too many changes to the interpreter.  The
+idea was borrowed from Modula-3.  It turns out to be very useful, for
+a variety of reasons.
+<P>
+First, it makes it more obvious that you are using a method or
+instance attribute instead of a local variable.  Reading "self.x" or
+"self.meth()" makes it absolutely clear that an instance variable or
+method is used even if you don't know the class definition by heart.
+In C++, you can sort of tell by the lack of a local variable
+declaration (assuming globals are rare or easily recognizable) -- but
+in Python, there are no local variable declarations, so you'd have to
+look up the class definition to be sure.
+<P>
+Second, it means that no special syntax is necessary if you want to
+explicitly reference or call the method from a particular class.  In
+C++, if you want to use a method from base class that is overridden in
+a derived class, you have to use the :: operator -- in Python you can
+write baseclass.methodname(self, &lt;argument list&gt;).  This is
+particularly useful for __init__() methods, and in general in cases
+where a derived class method wants to extend the base class method of
+the same name and thus has to call the base class method somehow.
+<P>
+Lastly, for instance variables, it solves a syntactic problem with
+assignment: since local variables in Python are (by definition!) those
+variables to which a value assigned in a function body (and that
+aren't explicitly declared global), there has to be some way to tell
+the interpreter that an assignment was meant to assign to an instance
+variable instead of to a local variable, and it should preferably be
+syntactic (for efficiency reasons).  C++ does this through
+declarations, but Python doesn't have declarations and it would be a
+pity having to introduce them just for this purpose.  Using the
+explicit "self.var" solves this nicely.  Similarly, for using instance
+variables, having to write "self.var" means that references to
+unqualified names inside a method don't have to search the instance's
+directories.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.007.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.007.htp">Log info</A>
+
+/ Last changed on Fri Jan 12 08:01:50 2001 by
+<A HREF="mailto:sholden@holdenweb.com">Steve Holden</A>
+<P>
+
+<HR>
+<H2><A NAME="6.8">6.8. Can't you emulate threads in the interpreter instead of relying on an OS-specific thread implementation?</A></H2>
+Answer 1: Unfortunately, the interpreter pushes at least one C stack
+frame for each Python stack frame.  Also, extensions can call back into
+Python at almost random moments.  Therefore a complete threads
+implementation requires thread support for C.
+<P>
+Answer 2: Fortunately, there is Stackless Python, which has a completely redesigned interpreter loop that avoids the C stack. It's still experimental but looks very promising. Although it is binary compatible with standard Python, it's still unclear whether Stackless will make it into the core -- maybe it's just too revolutionary. Stackless Python currently lives here: <A HREF="http://www.stackless.com">http://www.stackless.com</A>. A microthread implementation that uses it can be found here: <A HREF="http://world.std.com/~wware/uthread.html">http://world.std.com/~wware/uthread.html</A>.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.008.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.008.htp">Log info</A>
+
+/ Last changed on Sat Apr 15 08:18:16 2000 by
+<A HREF="mailto:just@letterror.com">Just van Rossum</A>
+<P>
+
+<HR>
+<H2><A NAME="6.9">6.9. Why can't lambda forms contain statements?</A></H2>
+Python lambda forms cannot contain statements because Python's
+syntactic framework can't handle statements nested inside expressions.
+<P>
+However, in Python, this is not a serious problem.  Unlike lambda
+forms in other languages, where they add functionality, Python lambdas
+are only a shorthand notation if you're too lazy to define a function.
+<P>
+Functions are already first class objects in Python, and can be
+declared in a local scope.  Therefore the only advantage of using a
+lambda form instead of a locally-defined function is that you don't need to invent a name for the function -- but that's just a local variable to which the function object (which is exactly the same type of object that a lambda form yields) is assigned!
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.009.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.009.htp">Log info</A>
+
+/ Last changed on Sun Jun 14 14:15:17 1998 by
+<A HREF="mailto:tim_one@email.msn.com">Tim Peters</A>
+<P>
+
+<HR>
+<H2><A NAME="6.10">6.10. [deleted]</A></H2>
+[lambda vs non-nested scopes used to be here]
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.010.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.010.htp">Log info</A>
+
+/ Last changed on Thu Mar 21 05:20:56 2002 by
+<A HREF="mailto:erno-pyfaq@erno.iki.fi">Erno Kuusela</A>
+<P>
+
+<HR>
+<H2><A NAME="6.11">6.11. [deleted]</A></H2>
+[recursive functions vs non-nested scopes used to be here]
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.011.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.011.htp">Log info</A>
+
+/ Last changed on Thu Mar 21 05:22:04 2002 by
+<A HREF="mailto:erno-pyfaq@erno.iki.fi">Erno Kuusela</A>
+<P>
+
+<HR>
+<H2><A NAME="6.12">6.12. Why is there no more efficient way of iterating over a dictionary than first constructing the list of keys()?</A></H2>
+As of Python 2.2, you can now iterate over a dictionary directly,
+using the new implied dictionary iterator:
+<P>
+<PRE>
+    for k in d: ...
+</PRE>
+There are also methods returning iterators over the values and items:
+<P>
+<PRE>
+    for k in d.iterkeys(): # same as above
+    for v in d.itervalues(): # iterate over values
+    for k, v in d.iteritems(): # iterate over items
+</PRE>
+All these require that you do not modify the dictionary during the loop.
+<P>
+For previous Python versions, the following defense should do:
+<P>
+Have you tried it?  I bet it's fast enough for your purposes!  In
+most cases such a list takes only a few percent of the space occupied
+by the dictionary.  Apart from the fixed header,
+the list needs only 4 bytes (the size of a pointer) per
+key.  A dictionary uses 12 bytes per key plus between 30 and 70
+percent hash table overhead, plus the space for the keys and values.
+By necessity, all keys are distinct objects, and a string object (the most
+common key type) costs at least 20 bytes plus the length of the
+string.  Add to that the values contained in the dictionary, and you
+see that 4 bytes more per item really isn't that much more memory...
+<P>
+A call to dict.keys() makes one fast scan over the dictionary
+(internally, the iteration function does exist) copying the pointers
+to the key objects into a pre-allocated list object of the right size.
+The iteration time isn't lost (since you'll have to iterate anyway --
+unless in the majority of cases your loop terminates very prematurely
+(which I doubt since you're getting the keys in random order).
+<P>
+I don't expose the dictionary iteration operation to Python
+programmers because the dictionary shouldn't be modified during the
+entire iteration -- if it is, there's a small chance that the
+dictionary is reorganized because the hash table becomes too full, and
+then the iteration may miss some items and see others twice.  Exactly
+because this only occurs rarely, it would lead to hidden bugs in
+programs: it's easy never to have it happen during test runs if you
+only insert or delete a few items per iteration -- but your users will 
+surely hit upon it sooner or later.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.012.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.012.htp">Log info</A>
+
+/ Last changed on Fri May 24 21:24:08 2002 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="6.13">6.13. Can Python be compiled to machine code, C or some other language?</A></H2>
+Not easily.  Python's high level data types, dynamic typing of
+objects and run-time invocation of the interpreter (using eval() or
+exec) together mean that a "compiled" Python program would probably
+consist mostly of calls into the Python run-time system, even for
+seemingly simple operations like "x+1".
+<P>
+Several projects described in the Python newsgroup or at past
+Python conferences have shown that this approach is feasible,
+although the speedups reached so far are only modest (e.g. 2x).
+JPython uses the same strategy for compiling to Java bytecode.
+(Jim Hugunin has demonstrated that in combination with whole-program
+analysis, speedups of 1000x are feasible for small demo programs.
+See the website for the 1997 Python conference.)
+<P>
+Internally, Python source code is always translated into a "virtual
+machine code" or "byte code" representation before it is interpreted
+(by the "Python virtual machine" or "bytecode interpreter").  In order
+to avoid the overhead of parsing and translating modules that rarely
+change over and over again, this byte code is written on a file whose
+name ends in ".pyc" whenever a module is parsed (from a file whose
+name ends in ".py").  When the corresponding .py file is changed, it
+is parsed and translated again and the .pyc file is rewritten.
+<P>
+There is no performance difference once the .pyc file has been loaded
+(the bytecode read from the .pyc file is exactly the same as the bytecode
+created by direct translation).  The only difference is that loading
+code from a .pyc file is faster than parsing and translating a .py
+file, so the presence of precompiled .pyc files will generally improve
+start-up time of Python scripts.  If desired, the Lib/compileall.py
+module/script can be used to force creation of valid .pyc files for a
+given set of modules.
+<P>
+Note that the main script executed by Python, even if its filename
+ends in .py, is not compiled to a .pyc file.  It is compiled to
+bytecode, but the bytecode is not saved to a file.
+<P>
+If you are looking for a way to translate Python programs in order to
+distribute them in binary form, without the need to distribute the
+interpreter and library as well, have a look at the freeze.py script
+in the Tools/freeze directory.  This creates a single binary file
+incorporating your program, the Python interpreter, and those parts of
+the Python library that are needed by your program.  Of course, the
+resulting binary will only run on the same type of platform as that
+used to create it.
+<P>
+Newsflash: there are now several programs that do this, to some extent.
+Look for Psyco, Pyrex, PyInline, Py2Cmod, and Weave.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.013.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.013.htp">Log info</A>
+
+/ Last changed on Fri May 24 21:26:19 2002 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="6.14">6.14. How does Python manage memory?</A></H2>
+The details of Python memory management depend on the implementation.
+The standard Python implementation (the C implementation) uses reference
+counting and another mechanism to collect reference cycles.
+<P>
+Jython relies on the Java runtime; so it uses
+the JVM's garbage collector.  This difference can cause some subtle
+porting problems if your Python code depends on the behavior of
+the reference counting implementation.
+<P>
+The reference cycle collector was added in CPython 2.0. It
+periodically executes a cycle detection algorithm which looks for inaccessible cycles and deletes the objects involved. A new gc module provides functions to perform a garbage collection, obtain debugging statistics, and tuning the collector's parameters. 
+<P>
+The detection of cycles can be disabled when Python is compiled, if you can't afford even a tiny speed penalty or suspect that the cycle collection is buggy, by specifying the "--without-cycle-gc" switch when running the configure script. 
+<P>
+Sometimes objects get stuck in "tracebacks" temporarily and hence are not deallocated when you might expect.  Clear the tracebacks via
+<P>
+<PRE>
+       import sys
+       sys.exc_traceback = sys.last_traceback = None
+</PRE>
+Tracebacks are used for reporting errors and implementing debuggers and related things.  They contain a portion of the program state extracted during the handling of an exception (usually the most recent exception).
+<P>
+In the absence of circularities and modulo tracebacks, Python programs need not explicitly manage memory.
+<P>
+Why python doesn't use a more traditional garbage collection
+scheme? For one thing, unless this were
+added to C as a standard feature, it's a portability pain in the ass.
+And yes, I know about the Xerox library.  It has bits of assembler
+code for <I>most</I> <I>common</I> platforms.  Not for all.  And although it is
+mostly transparent, it isn't completely transparent (when I once
+linked Python with it, it dumped core).
+<P>
+Traditional GC also becomes a problem when Python gets embedded into
+other applications.  While in a stand-alone Python it may be fine to
+replace the standard malloc() and free() with versions provided by the
+GC library, an application embedding Python may want to have its <I>own</I>
+substitute for malloc() and free(), and may not want Python's.  Right
+now, Python works with anything that implements malloc() and free()
+properly.
+<P>
+In Jython, the following code (which is 
+fine in C Python) will probably run out of file descriptors long before
+it runs out of memory:
+<P>
+<PRE>
+        for file in &lt;very long list of files&gt;:
+                f = open(file)
+                c = f.read(1)
+</PRE>
+Using the current reference counting and destructor scheme, each new
+assignment to f closes the previous file.  Using GC, this is not
+guaranteed.  Sure, you can think of ways to fix this.  But it's not
+off-the-shelf technology.  If you want to write code that will
+work with any Python implementation, you should explicitly close
+the file; this will work regardless of GC:
+<P>
+<PRE>
+       for file in &lt;very long list of files&gt;:
+                f = open(file)
+                c = f.read(1)
+                f.close()
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.014.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.014.htp">Log info</A>
+
+/ Last changed on Thu Mar 21 05:35:38 2002 by
+<A HREF="mailto:erno-pyfaq@erno.iki.fi">Erno Kuusela</A>
+<P>
+
+<HR>
+<H2><A NAME="6.15">6.15. Why are there separate tuple and list data types?</A></H2>
+This is done so that tuples can be immutable while lists are mutable.
+<P>
+Immutable tuples are useful in situations where you need to pass a few
+items to a function and don't want the function to modify the tuple;
+for example,
+<P>
+<PRE>
+       point1 = (120, 140)
+       point2 = (200, 300)
+       record(point1, point2)
+       draw(point1, point2)
+</PRE>
+You don't want to have to think about what would happen if record()
+changed the coordinates -- it can't, because the tuples are immutable.
+<P>
+On the other hand, when creating large lists dynamically, it is
+absolutely crucial that they are mutable -- adding elements to a tuple
+one by one requires using the concatenation operator, which makes it
+quadratic in time.
+<P>
+As a general guideline, use tuples like you would use structs in C or
+records in Pascal, use lists like (variable length) arrays.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.015.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.015.htp">Log info</A>
+
+/ Last changed on Fri May 23 15:26:03 1997 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="6.16">6.16. How are lists implemented?</A></H2>
+Despite what a Lisper might think, Python's lists are really
+variable-length arrays.  The implementation uses a contiguous
+array of references to other objects, and keeps a pointer
+to this array (as well as its length) in a list head structure.
+<P>
+This makes indexing a list (a[i]) an operation whose cost is
+independent of the size of the list or the value of the index.
+<P>
+When items are appended or inserted, the array of references is resized.
+Some cleverness is applied to improve the performance of appending
+items repeatedly; when the array must be grown, some extra space
+is allocated so the next few times don't require an actual resize.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.016.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.016.htp">Log info</A>
+
+/ Last changed on Fri May 23 15:32:24 1997 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="6.17">6.17. How are dictionaries implemented?</A></H2>
+Python's dictionaries are implemented as resizable hash tables.
+<P>
+Compared to B-trees, this gives better performance for lookup
+(the most common operation by far) under most circumstances,
+and the implementation is simpler.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.017.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.017.htp">Log info</A>
+
+/ Last changed on Fri May 23 23:51:14 1997 by
+<A HREF="mailto:Vladimir.Marangozov@inrialpes.fr">Vladimir Marangozov</A>
+<P>
+
+<HR>
+<H2><A NAME="6.18">6.18. Why must dictionary keys be immutable?</A></H2>
+The hash table implementation of dictionaries uses a hash value
+calculated from the key value to find the key.  If the key were
+a mutable object, its value could change, and thus its hash could
+change.  But since whoever changes the key object can't tell that
+is incorporated in a dictionary, it can't move the entry around in
+the dictionary.  Then, when you try to look up the same object
+in the dictionary, it won't be found, since its hash value is different;
+and if you try to look up the old value, it won't be found either,
+since the value of the object found in that hash bin differs.
+<P>
+If you think you need to have a dictionary indexed with a list,
+try to use a tuple instead.  The function tuple(l) creates a tuple
+with the same entries as the list l.
+<P>
+Some unacceptable solutions that have been proposed:
+<P>
+- Hash lists by their address (object ID).  This doesn't work because
+if you construct a new list with the same value it won't be found;
+e.g.,
+<P>
+<PRE>
+  d = {[1,2]: '12'}
+  print d[[1,2]]
+</PRE>
+will raise a KeyError exception because the id of the [1,2] used
+in the second line differs from that in the first line.
+In other words, dictionary keys should be compared using '==', not using 'is'.
+<P>
+- Make a copy when using a list as a key.  This doesn't work because
+the list (being a mutable object) could contain a reference to itself,
+and then the copying code would run into an infinite loop.
+<P>
+- Allow lists as keys but tell the user not to modify them.  This would
+allow a class of hard-to-track bugs in programs that I'd rather not see;
+it invalidates an important invariant of dictionaries (every value in
+d.keys() is usable as a key of the dictionary).
+<P>
+- Mark lists as read-only once they are used as a dictionary key.
+The problem is that it's not just the top-level object that could change
+its value; you could use a tuple containing a list as a key.  Entering
+anything as a key into a dictionary would require marking all objects
+reachable from there as read-only -- and again, self-referential objects
+could cause an infinite loop again (and again and again).
+<P>
+There is a trick to get around this if you need to, but
+use it at your own risk:  You
+can wrap a mutable structure inside a class instance which
+has both a __cmp__ and a __hash__ method.  
+<P>
+<PRE>
+   class listwrapper:
+        def __init__(self, the_list):
+              self.the_list = the_list
+        def __cmp__(self, other):
+              return self.the_list == other.the_list
+        def __hash__(self):
+              l = self.the_list
+              result = 98767 - len(l)*555
+              for i in range(len(l)):
+                   try:
+                        result = result + (hash(l[i]) % 9999999) * 1001 + i
+                   except:
+                        result = (result % 7777777) + i * 333
+              return result
+</PRE>
+Note that the hash computation is complicated by the
+possibility that some members of the list may be unhashable
+and also by the possibility of arithmetic overflow.
+<P>
+You must make
+sure that the hash value for all such wrapper objects that reside in a
+dictionary (or other hash based structure), remain fixed while
+the object is in the dictionary (or other structure).
+<P>
+Furthermore it must always be the case that if
+o1 == o2 (ie o1.__cmp__(o2)==0) then hash(o1)==hash(o2)
+(ie, o1.__hash__() == o2.__hash__()), regardless of whether
+the object is in a dictionary or not.
+If you fail to meet these restrictions dictionaries and other
+hash based structures may misbehave!
+<P>
+In the case of listwrapper above whenever the wrapper
+object is in a dictionary the wrapped list must not change
+to avoid anomalies.  Don't do this unless you are prepared
+to think hard about the requirements and the consequences
+of not meeting them correctly.  You've been warned!
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.018.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.018.htp">Log info</A>
+
+/ Last changed on Thu Jul 10 10:08:40 1997 by
+<A HREF="mailto:aaron_watters@msn.com">aaron watters</A>
+<P>
+
+<HR>
+<H2><A NAME="6.19">6.19. How the heck do you make an array in Python?</A></H2>
+["this", 1, "is", "an", "array"]
+<P>
+Lists are arrays in the C or Pascal sense of the word (see question
+6.16).  The array module also provides methods for creating arrays
+of fixed types with compact representations (but they are slower to
+index than lists).  Also note that the Numerics extensions and others
+define array-like structures with various characteristics as well.
+<P>
+To get Lisp-like lists, emulate cons cells
+<P>
+<PRE>
+    lisp_list = ("like",  ("this",  ("example", None) ) )
+</PRE>
+using tuples (or lists, if you want mutability).  Here the analogue
+of lisp car is lisp_list[0] and the analogue of cdr is lisp_list[1].
+Only do this if you're sure you really need to (it's usually a lot
+slower than using Python lists).
+<P>
+Think of Python lists as mutable heterogeneous arrays of
+Python objects (say that 10 times fast :) ).
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.019.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.019.htp">Log info</A>
+
+/ Last changed on Wed Aug 13 07:08:27 1997 by
+<A HREF="mailto:aaron_watters@msn.com">aaron watters</A>
+<P>
+
+<HR>
+<H2><A NAME="6.20">6.20. Why doesn't list.sort() return the sorted list?</A></H2>
+In situations where performance matters, making a copy of the list
+just to sort it would be wasteful.  Therefore, list.sort() sorts
+the list in place.  In order to remind you of that fact, it does
+not return the sorted list.  This way, you won't be fooled into
+accidentally overwriting a list when you need a sorted copy but also
+need to keep the unsorted version around.
+<P>
+As a result, here's the idiom to iterate over the keys of a dictionary
+in sorted order:
+<P>
+<PRE>
+       keys = dict.keys()
+       keys.sort()
+       for key in keys:
+               ...do whatever with dict[key]...
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.020.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.020.htp">Log info</A>
+
+/ Last changed on Thu Dec  2 17:01:52 1999 by
+<A HREF="mailto:fdrake@acm.org">Fred L. Drake, Jr.</A>
+<P>
+
+<HR>
+<H2><A NAME="6.21">6.21. How do you specify and enforce an interface spec in Python?</A></H2>
+An interfaces specification for a module as provided
+by languages such as C++ and java describes the prototypes
+for the methods and functions of the module.  Many feel
+that compile time enforcement of interface specifications
+help aid in the construction of large programs.  Python
+does not support interface specifications directly, but many
+of their advantages can be obtained by an appropriate
+test discipline for components, which can often be very
+easily accomplished in Python.  There is also a tool, PyChecker,
+which can be used to find problems due to subclassing.
+<P>
+A good test suite for a module can at
+once provide a regression test and serve as a module interface
+specification (even better since it also gives example usage).  Look to
+many of the standard libraries which often have a "script
+interpretation" which provides a simple "self test."  Even
+modules which use complex external interfaces can often
+be tested in isolation using trivial "stub" emulations of the
+external interface.
+<P>
+An appropriate testing discipline (if enforced) can help
+build large complex applications in Python as well as having interface
+specifications would do (or better).  Of course Python allows you 
+to get sloppy and not do it.  Also you might want to design
+your code with an eye to make it easily tested.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.021.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.021.htp">Log info</A>
+
+/ Last changed on Thu May 23 03:05:29 2002 by
+<A HREF="mailto:neal@metaslash.com">Neal Norwitz</A>
+<P>
+
+<HR>
+<H2><A NAME="6.22">6.22. Why do all classes have the same type? Why do instances all have the same type?</A></H2>
+The Pythonic use of the word "type" is quite different from
+common usage in much of the rest of the programming language
+world.  A "type" in Python is a description for an object's operations
+as implemented in C.  All classes have the same operations
+implemented in C which sometimes "call back" to differing program
+fragments implemented in Python, and hence all classes have the
+same type.  Similarly at the C level all class instances have the
+same C implementation, and hence all instances have the same
+type.
+<P>
+Remember that in Python usage "type" refers to a C implementation
+of an object.  To distinguish among instances of different classes
+use Instance.__class__, and also look to 4.47.  Sorry for the
+terminological confusion, but at this point in Python's development
+nothing can be done!
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.022.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.022.htp">Log info</A>
+
+/ Last changed on Tue Jul  1 12:35:47 1997 by
+<A HREF="mailto:aaron_watters@msn.com">aaron watters</A>
+<P>
+
+<HR>
+<H2><A NAME="6.23">6.23. Why isn't all memory freed when Python exits?</A></H2>
+Objects referenced from Python module global name spaces are
+not always deallocated when Python exits.
+<P>
+This may happen if there are circular references (see question
+4.17).  There are also certain bits of memory that are allocated
+by the C library that are impossible to free (e.g. a tool
+like Purify will complain about these).
+<P>
+But in general, Python 1.5 and beyond
+(in contrast with earlier versions) is quite agressive about
+cleaning up memory on exit.
+<P>
+If you want to force Python to delete certain things on deallocation
+use the sys.exitfunc hook to force those deletions.  For example
+if you are debugging an extension module using a memory analysis
+tool and you wish to make Python deallocate almost everything
+you might use an exitfunc like this one:
+<P>
+<PRE>
+  import sys
+</PRE>
+<PRE>
+  def my_exitfunc():
+       print "cleaning up"
+       import sys
+       # do order dependant deletions here
+       ...
+       # now delete everything else in arbitrary order
+       for x in sys.modules.values():
+            d = x.__dict__
+            for name in d.keys():
+                 del d[name]
+</PRE>
+<PRE>
+  sys.exitfunc = my_exitfunc
+</PRE>
+Other exitfuncs can be less drastic, of course.
+<P>
+(In fact, this one just does what Python now already does itself;
+but the example of using sys.exitfunc to force cleanups is still
+useful.)
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.023.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.023.htp">Log info</A>
+
+/ Last changed on Tue Sep 29 09:46:26 1998 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="6.24">6.24. Why no class methods or mutable class variables?</A></H2>
+The notation
+<P>
+<PRE>
+    instance.attribute(arg1, arg2)
+</PRE>
+usually translates to the equivalent of
+<P>
+<PRE>
+    Class.attribute(instance, arg1, arg2)
+</PRE>
+where Class is a (super)class of instance.  Similarly
+<P>
+<PRE>
+    instance.attribute = value
+</PRE>
+sets an attribute of an instance (overriding any attribute of a class
+that instance inherits).  
+<P>
+Sometimes programmers want to have
+different behaviours -- they want a method which does not bind
+to the instance and a class attribute which changes in place.
+Python does not preclude these behaviours, but you have to
+adopt a convention to implement them.  One way to accomplish
+this is to use "list wrappers" and global functions.
+<P>
+<PRE>
+   def C_hello():
+         print "hello"
+</PRE>
+<PRE>
+   class C:
+        hello = [C_hello]
+        counter = [0]
+</PRE>
+<PRE>
+    I = C()
+</PRE>
+Here I.hello[0]() acts very much like a "class method" and
+I.counter[0] = 2 alters C.counter (and doesn't override it).
+If you don't understand why you'd ever want to do this, that's
+because you are pure of mind, and you probably never will
+want to do it!  This is dangerous trickery, not recommended
+when avoidable.  (Inspired by Tim Peter's discussion.)
+<P>
+In Python 2.2, you can do this using the new built-in operations
+classmethod and staticmethod.
+See <A HREF="http://www.python.org/2.2/descrintro.html#staticmethods">http://www.python.org/2.2/descrintro.html#staticmethods</A>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.024.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.024.htp">Log info</A>
+
+/ Last changed on Tue Sep 11 15:59:37 2001 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="6.25">6.25. Why are default values sometimes shared between objects?</A></H2>
+It is often expected that a function CALL creates new objects for default
+values. This is not what happens. Default values are created when the
+function is DEFINED, that is, there is only one such object that all 
+functions refer to. If that object is changed, subsequent calls to the 
+function will refer to this changed object. By definition, immutable objects
+(like numbers, strings, tuples, None) are safe from change. Changes to mutable 
+objects (like dictionaries, lists, class instances) is what causes the
+confusion.
+<P>
+Because of this feature it is good programming practice not to use mutable
+objects as default values, but to introduce them in the function.
+Don't write:
+<P>
+<PRE>
+       def foo(dict={}):  # XXX shared reference to one dict for all calls
+           ...
+</PRE>
+but:
+<PRE>
+       def foo(dict=None):
+               if dict is None:
+                       dict = {} # create a new dict for local namespace
+</PRE>
+See page 182 of "Internet Programming with Python" for one discussion
+of this feature. Or see the top of page 144 or bottom of page 277 in 
+"Programming Python" for another discussion.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.025.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.025.htp">Log info</A>
+
+/ Last changed on Sat Aug 16 07:03:35 1997 by
+<A HREF="mailto:cjr@bound.xs4all.nl">Case Roole</A>
+<P>
+
+<HR>
+<H2><A NAME="6.26">6.26. Why no goto?</A></H2>
+Actually, you can use exceptions to provide a "structured goto"
+that even works across function calls.  Many feel that exceptions
+can conveniently emulate all reasonable uses of the "go" or "goto"
+constructs of C, Fortran, and other languages.  For example:
+<P>
+<PRE>
+   class label: pass # declare a label
+   try:
+        ...
+        if (condition): raise label() # goto label
+        ...
+   except label: # where to goto
+        pass
+   ...
+</PRE>
+This doesn't allow you to jump into the middle of a loop, but
+that's usually considered an abuse of goto anyway.  Use sparingly.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.026.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.026.htp">Log info</A>
+
+/ Last changed on Wed Sep 10 07:16:44 1997 by
+<A HREF="mailto:aaron_watters@msn.com">aaron watters</A>
+<P>
+
+<HR>
+<H2><A NAME="6.27">6.27. How do you make a higher order function in Python?</A></H2>
+You have two choices: you can use default arguments and override
+them or you can use "callable objects."  For example suppose you
+wanted to define linear(a,b) which returns a function f where f(x)
+computes the value a*x+b.  Using default arguments:
+<P>
+<PRE>
+     def linear(a,b):
+         def result(x, a=a, b=b):
+             return a*x + b
+         return result
+</PRE>
+Or using callable objects:
+<P>
+<PRE>
+     class linear:
+        def __init__(self, a, b):
+            self.a, self.b = a,b
+        def __call__(self, x):
+            return self.a * x + self.b
+</PRE>
+In both cases:
+<P>
+<PRE>
+     taxes = linear(0.3,2)
+</PRE>
+gives a callable object where taxes(10e6) == 0.3 * 10e6 + 2.
+<P>
+The defaults strategy has the disadvantage that the default arguments
+could be accidentally or maliciously overridden.  The callable objects
+approach has the disadvantage that it is a bit slower and a bit
+longer.  Note however that a collection of callables can share
+their signature via inheritance.  EG
+<P>
+<PRE>
+      class exponential(linear):
+         # __init__ inherited
+         def __call__(self, x):
+             return self.a * (x ** self.b)
+</PRE>
+On comp.lang.python, <A HREF="mailto:zenin@bawdycaste.org">zenin@bawdycaste.org</A> points out that
+an object can encapsulate state for several methods in order
+to emulate the "closure" concept from functional programming
+languages, for example:
+<P>
+<PRE>
+    class counter:
+        value = 0
+        def set(self, x): self.value = x
+        def up(self): self.value=self.value+1
+        def down(self): self.value=self.value-1
+</PRE>
+<PRE>
+    count = counter()
+    inc, dec, reset = count.up, count.down, count.set
+</PRE>
+Here inc, dec and reset act like "functions which share the
+same closure containing the variable count.value" (if you
+like that way of thinking).
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.027.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.027.htp">Log info</A>
+
+/ Last changed on Fri Sep 25 08:38:35 1998 by
+<A HREF="mailto:arw@pythonpros.com">Aaron Watters</A>
+<P>
+
+<HR>
+<H2><A NAME="6.28">6.28. Why do I get a SyntaxError for a 'continue' inside a 'try'?</A></H2>
+This is an implementation limitation,
+caused by the extremely simple-minded
+way Python generates bytecode.  The try block pushes something on the
+"block stack" which the continue would have to pop off again.  The
+current code generator doesn't have the data structures around so that 
+'continue' can generate the right code.
+<P>
+Note that JPython doesn't have this restriction!
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.028.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.028.htp">Log info</A>
+
+/ Last changed on Fri May 22 15:01:07 1998 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="6.29">6.29. Why can't raw strings (r-strings) end with a backslash?</A></H2>
+More precisely, they can't end with an odd number of backslashes:
+the unpaired backslash at the end escapes the closing quote character,
+leaving an unterminated string.
+<P>
+Raw strings were designed to ease creating input for processors (chiefly
+regular expression engines) that want to do their own backslash escape processing. Such processors consider an unmatched trailing backslash to be an error anyway, so raw strings disallow that.  In return, they allow you to pass on the string quote character by escaping it with a backslash.  These rules work well when r-strings are used for their intended purpose.
+<P>
+If you're trying to build Windows pathnames, note that all Windows system calls accept forward slashes too:
+<P>
+<PRE>
+    f = open("/mydir/file.txt") # works fine!
+</PRE>
+If you're trying to build a pathname for a DOS command, try e.g. one of
+<P>
+<PRE>
+    dir = r"\this\is\my\dos\dir" "\\"
+    dir = r"\this\is\my\dos\dir\ "[:-1]
+    dir = "\\this\\is\\my\\dos\\dir\\"
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.029.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.029.htp">Log info</A>
+
+/ Last changed on Mon Jul 13 20:50:20 1998 by
+<A HREF="mailto:tim_one@email.msn.com">Tim Peters</A>
+<P>
+
+<HR>
+<H2><A NAME="6.30">6.30. Why can't I use an assignment in an expression?</A></H2>
+Many people used to C or Perl complain that they want to be able to
+use e.g. this C idiom:
+<P>
+<PRE>
+    while (line = readline(f)) {
+        ...do something with line...
+    }
+</PRE>
+where in Python you're forced to write this:
+<P>
+<PRE>
+    while 1:
+        line = f.readline()
+        if not line:
+            break
+        ...do something with line...
+</PRE>
+This issue comes up in the Python newsgroup with alarming frequency
+-- search Deja News for past messages about assignment expression.
+The reason for not allowing assignment in Python expressions
+is a common, hard-to-find bug in those other languages,
+caused by this construct:
+<P>
+<PRE>
+    if (x = 0) {
+        ...error handling...
+    }
+    else {
+        ...code that only works for nonzero x...
+    }
+</PRE>
+Many alternatives have been proposed.  Most are hacks that save some
+typing but use arbitrary or cryptic syntax or keywords,
+and fail the simple criterion that I use for language change proposals:
+it should intuitively suggest the proper meaning to a human reader
+who has not yet been introduced with the construct.
+<P>
+The earliest time something can be done about this will be with
+Python 2.0 -- if it is decided that it is worth fixing.
+An interesting phenomenon is that most experienced Python programmers
+recognize the "while 1" idiom and don't seem to be missing the
+assignment in expression construct much; it's only the newcomers
+who express a strong desire to add this to the language.
+<P>
+One fairly elegant solution would be to introduce a new operator
+for assignment in expressions spelled ":=" -- this avoids the "="
+instead of "==" problem.  It would have the same precedence
+as comparison operators but the parser would flag combination with
+other comparisons (without disambiguating parentheses) as an error.
+<P>
+Finally -- there's an alternative way of spelling this that seems
+attractive but is generally less robust than the "while 1" solution:
+<P>
+<PRE>
+    line = f.readline()
+    while line:
+        ...do something with line...
+        line = f.readline()
+</PRE>
+The problem with this is that if you change your mind about exactly
+how you get the next line (e.g. you want to change it into
+sys.stdin.readline()) you have to remember to change two places
+in your program -- the second one hidden at the bottom of the loop.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.030.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.030.htp">Log info</A>
+
+/ Last changed on Tue May 18 00:57:41 1999 by
+<A HREF="mailto:dalke@bioreason.com">Andrew Dalke</A>
+<P>
+
+<HR>
+<H2><A NAME="6.31">6.31. Why doesn't Python have a &quot;with&quot; statement like some other languages?</A></H2>
+Basically, because such a construct would be terribly ambiguous. Thanks to Carlos Ribeiro for the following remarks:
+<P>
+Some languages, such as Object Pascal, Delphi, and C++, use static types. So it is possible to know, in an unambiguous way, what member is being assigned in a "with" clause. This is the main point - the compiler <I>always</I>  knows the scope of every variable at compile time.
+<P>
+Python uses dynamic types. It is impossible to know in advance which 
+attribute will be referenced at runtime. Member attributes may be added or removed from objects on the fly. This would make it impossible to know, from a simple reading, what attribute is being referenced - a local one, a global one, or a member attribute.
+<P>
+For instance, take the following snippet (it is incomplete btw, just to 
+give you the idea):
+<P>
+<PRE>
+   def with_is_broken(a):
+      with a:
+         print x
+</PRE>
+The snippet assumes that "a" must have a member attribute called "x". 
+However, there is nothing in Python that guarantees that. What should 
+happen if "a" is, let us say, an integer? And if I have a global variable named "x", will it end up being used inside the with block? As you see, the dynamic nature of Python makes such choices much harder.
+<P>
+The primary benefit of "with" and similar language features (reduction of code volume) can, however, easily be achieved in Python by assignment. Instead of:
+<P>
+<PRE>
+    function(args).dict[index][index].a = 21
+    function(args).dict[index][index].b = 42
+    function(args).dict[index][index].c = 63
+</PRE>
+would become:
+<P>
+<PRE>
+    ref = function(args).dict[index][index]
+    ref.a = 21
+    ref.b = 42
+    ref.c = 63
+</PRE>
+This also has the happy side-effect of increasing execution speed, since name bindings are resolved at run-time in Python, and the second method only needs to perform the resolution once. If the referenced object does not have a, b and c attributes, of course, the end result is still a run-time exception.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.031.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.031.htp">Log info</A>
+
+/ Last changed on Fri Jan 11 14:32:58 2002 by
+<A HREF="mailto:sholden@holdenweb.com">Steve Holden</A>
+<P>
+
+<HR>
+<H2><A NAME="6.32">6.32. Why are colons required for if/while/def/class?</A></H2>
+The colon is required primarily to enhance readability (one of the
+results of the experimental ABC language).  Consider this:
+<P>
+<PRE>
+    if a==b
+        print a
+</PRE>
+versus
+<P>
+<PRE>
+    if a==b:
+        print a
+</PRE>
+Notice how the second one is slightly easier to read.  Notice further how
+a colon sets off the example in the second line of this FAQ answer; it's
+a standard usage in English.  Finally, the colon makes it easier for
+editors with syntax highlighting.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.032.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.032.htp">Log info</A>
+
+/ Last changed on Mon Jun  3 07:22:57 2002 by
+<A HREF="mailto:smurf@noris.de">Matthias Urlichs</A>
+<P>
+
+<HR>
+<H2><A NAME="6.33">6.33. Can't we get rid of the Global Interpreter Lock?</A></H2>
+The Global Interpreter Lock (GIL) is often seen as a hindrance to
+Python's deployment on high-end multiprocessor server machines,
+because a multi-threaded Python program effectively only uses
+one CPU, due to the insistence that (almost) all Python code
+can only run while the GIL is held.
+<P>
+Back in the days of Python 1.5, Greg Stein actually implemented
+a comprehensive patch set ("free threading")
+that removed the GIL, replacing it with
+fine-grained locking.  Unfortunately, even on Windows (where locks
+are very efficient) this ran ordinary Python code about twice as
+slow as the interpreter using the GIL.  On Linux the performance
+loss was even worse (pthread locks aren't as efficient).
+<P>
+Since then, the idea of getting rid of the GIL has occasionally
+come up but nobody has found a way to deal with the expected slowdown;
+Greg's free threading patch set has not been kept up-to-date for
+later Python versions.
+<P>
+This doesn't mean that you can't make good use of Python on
+multi-CPU machines!  You just have to be creative with dividing
+the work up between multiple <I>processes</I> rather than multiple
+<I>threads</I>.
+<P>
+<P>
+It has been suggested that the GIL should be a per-interpreter-state
+lock rather than truly global; interpreters then wouldn't be able
+to share objects.  Unfortunately, this isn't likely to happen either.
+<P>
+It would be a tremendous amount of work, because many object
+implementations currently have global state.  E.g. small ints and
+small strings are cached; these caches would have to be moved to the
+interpreter state.  Other object types have their own free list; these
+free lists would have to be moved to the interpreter state.  And so
+on.
+<P>
+And I doubt that it can even be done in finite time, because the same
+problem exists for 3rd party extensions.  It is likely that 3rd party
+extensions are being written at a faster rate than you can convert
+them to store all their global state in the interpreter state.
+<P>
+And finally, once you have multiple interpreters not sharing any
+state, what have you gained over running each interpreter
+in a separate process?
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq06.033.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq06.033.htp">Log info</A>
+
+/ Last changed on Fri Feb  7 16:34:01 2003 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H1>7. Using Python on non-UNIX platforms</H1>
+
+<HR>
+<H2><A NAME="7.1">7.1. Is there a Mac version of Python?</A></H2>
+Yes, it is maintained by Jack Jansen.  See Jack's MacPython Page:
+<P>
+<PRE>
+  <A HREF="http://www.cwi.nl/~jack/macpython.html">http://www.cwi.nl/~jack/macpython.html</A>
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq07.001.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq07.001.htp">Log info</A>
+
+/ Last changed on Fri May  4 09:33:42 2001 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="7.2">7.2. Are there DOS and Windows versions of Python?</A></H2>
+Yes.  The core windows binaries are available from <A HREF="http://www.python.org/windows">http://www.python.org/windows</A>/. There is a plethora of Windows extensions available, including a large number of not-always-compatible GUI toolkits.  The core binaries include the standard Tkinter GUI extension.
+<P>
+Most windows extensions can be found (or referenced) at <A HREF="http://www.python.org/windows">http://www.python.org/windows</A>/ 
+<P>
+Windows 3.1/DOS support seems to have dropped off recently.  You may need to settle for an old version of Python one these platforms.  One such port is WPY
+<P>
+WPY: Ports to DOS, Windows 3.1(1), Windows 95, Windows NT and OS/2.
+Also contains a GUI package that offers portability between Windows 
+(not DOS) and Unix, and native look and feel on both.
+<A HREF="ftp://ftp.python.org/pub/python/wpy">ftp://ftp.python.org/pub/python/wpy</A>/.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq07.002.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq07.002.htp">Log info</A>
+
+/ Last changed on Tue Jun  2 20:21:57 1998 by
+<A HREF="mailto:MHammond@skippinet.com.au">Mark Hammond</A>
+<P>
+
+<HR>
+<H2><A NAME="7.3">7.3. Is there an OS/2 version of Python?</A></H2>
+Yes, see <A HREF="http://www.python.org/download/download_os2.html">http://www.python.org/download/download_os2.html</A>.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq07.003.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq07.003.htp">Log info</A>
+
+/ Last changed on Tue Sep  7 11:33:16 1999 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="7.4">7.4. Is there a VMS version of Python?</A></H2>
+Jean-François Piéronne has ported 2.1.3 to OpenVMS.  It can be found at
+&lt;<A HREF="http://vmspython.dyndns.org">http://vmspython.dyndns.org</A>/&gt;.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq07.004.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq07.004.htp">Log info</A>
+
+/ Last changed on Thu Sep 19 15:40:38 2002 by
+<A HREF="mailto:skip@pobox.com">Skip Montanaro</A>
+<P>
+
+<HR>
+<H2><A NAME="7.5">7.5. What about IBM mainframes, or other non-UNIX platforms?</A></H2>
+I haven't heard about these, except I remember hearing about an
+OS/9 port and a port to Vxworks (both operating systems for embedded
+systems).  If you're interested in any of this, go directly to the
+newsgroup and ask there, you may find exactly what you need.  For
+example, a port to MPE/iX 5.0 on HP3000 computers was just announced,
+see <A HREF="http://www.allegro.com/software">http://www.allegro.com/software</A>/.
+<P>
+On the IBM mainframe side, for Z/OS there's a port of python 1.4 that goes with their open-unix package, formely OpenEdition MVS, (<A HREF="http://www-1.ibm.com/servers/eserver/zseries/zos/unix/python.html">http://www-1.ibm.com/servers/eserver/zseries/zos/unix/python.html</A>). On a side note, there's also a java vm ported - so, in theory, jython could run too.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq07.005.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq07.005.htp">Log info</A>
+
+/ Last changed on Mon Nov 18 03:18:39 2002 by
+<A HREF="mailto:bjessen@uol.com.br">Bruno Jessen</A>
+<P>
+
+<HR>
+<H2><A NAME="7.6">7.6. Where are the source or Makefiles for the non-UNIX versions?</A></H2>
+The standard sources can (almost) be used.  Additional sources can
+be found in the platform-specific subdirectories of the distribution.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq07.006.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq07.006.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="7.7">7.7. What is the status and support for the non-UNIX versions?</A></H2>
+I don't have access to most of these platforms, so in general I am
+dependent on material submitted by volunteers.  However I strive to
+integrate all changes needed to get it to compile on a particular
+platform back into the standard sources, so porting of the next
+version to the various non-UNIX platforms should be easy.
+(Note that Linux is classified as a UNIX platform here. :-)
+<P>
+Some specific platforms:
+<P>
+Windows: all versions (95, 98, ME, NT, 2000, XP) are supported,
+all python.org releases come with a Windows installer.
+<P>
+MacOS: Jack Jansen does an admirable job of keeping the Mac version
+up to date (both MacOS X and older versions);
+see <A HREF="http://www.cwi.nl/~jack/macpython.html">http://www.cwi.nl/~jack/macpython.html</A>
+<P>
+For all supported platforms, see <A HREF="http://www.python.org/download">http://www.python.org/download</A>/
+(follow the link to "Other platforms" for less common platforms)
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq07.007.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq07.007.htp">Log info</A>
+
+/ Last changed on Fri May 24 21:34:24 2002 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="7.8">7.8. I have a PC version but it appears to be only a binary. Where's the library?</A></H2>
+If you are running any version of Windows, then you have the wrong distribution.  The FAQ lists current Windows versions.  Notably, Pythonwin and wpy provide fully functional installations.
+<P>
+But if you are sure you have the only distribution with a hope of working on
+your system, then...
+<P>
+You still need to copy the files from the distribution directory
+"python/Lib" to your system.  If you don't have the full distribution,
+you can get the file lib&lt;version&gt;.tar.gz from most ftp sites carrying
+Python; this is a subset of the distribution containing just those
+files, e.g.  <A HREF="ftp://ftp.python.org/pub/python/src/lib1.4.tar.gz">ftp://ftp.python.org/pub/python/src/lib1.4.tar.gz</A>.
+<P>
+Once you have installed the library, you need to point sys.path to it.
+Assuming the library is in C:\misc\python\lib, the following commands
+will point your Python interpreter to it (note the doubled backslashes
+-- you can also use single forward slashes instead):
+<P>
+<PRE>
+        >>> import sys
+        >>> sys.path.insert(0, 'C:\\misc\\python\\lib')
+        >>>
+</PRE>
+For a more permanent effect, set the environment variable PYTHONPATH,
+as follows (talking to a DOS prompt):
+<P>
+<PRE>
+        C> SET PYTHONPATH=C:\misc\python\lib
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq07.008.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq07.008.htp">Log info</A>
+
+/ Last changed on Fri May 23 16:28:27 1997 by
+<A HREF="mailto:klm@python.org">Ken Manheimer</A>
+<P>
+
+<HR>
+<H2><A NAME="7.9">7.9. Where's the documentation for the Mac or PC version?</A></H2>
+The documentation for the Unix version also applies to the Mac and
+PC versions.  Where applicable, differences are indicated in the text.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq07.009.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq07.009.htp">Log info</A>
+<P>
+
+<HR>
+<H2><A NAME="7.10">7.10. How do I create a Python program file on the Mac or PC?</A></H2>
+Use an external editor.  On the Mac, BBEdit seems to be a popular
+no-frills text editor.  I work like this: start the interpreter; edit
+a module file using BBedit; import and test it in the interpreter;
+edit again in BBedit; then use the built-in function reload() to
+re-read the imported module; etc. In the 1.4 distribution 
+you will find a BBEdit extension that makes life a little easier: 
+it can tell the interpreter to execute the current window. 
+See :Mac:Tools:BBPy:README. 
+<P>
+Regarding the same question for the PC, Kurt Wm. Hemr writes: "While
+anyone with a pulse could certainly figure out how to do the same on
+MS-Windows, I would recommend the NotGNU Emacs clone for MS-Windows.
+Not only can you easily resave and "reload()" from Python after making
+changes, but since WinNot auto-copies to the clipboard any text you
+select, you can simply select the entire procedure (function) which
+you changed in WinNot, switch to QWPython, and shift-ins to reenter
+the changed program unit."
+<P>
+If you're using Windows95 or Windows NT, you should also know about
+PythonWin, which provides a GUI framework, with an mouse-driven
+editor, an object browser, and a GUI-based debugger.  See
+<PRE>
+       <A HREF="http://www.python.org/ftp/python/pythonwin">http://www.python.org/ftp/python/pythonwin</A>/
+</PRE>
+for details.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq07.010.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq07.010.htp">Log info</A>
+
+/ Last changed on Sun May 25 10:04:25 1997 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="7.11">7.11. How can I use Tkinter on Windows 95/NT?</A></H2>
+Starting from Python 1.5, it's very easy -- just download and install
+Python and Tcl/Tk and you're in business.  See 
+<P>
+<PRE>
+  <A HREF="http://www.python.org/download/download_windows.html">http://www.python.org/download/download_windows.html</A>
+</PRE>
+One warning: don't attempt to use Tkinter from PythonWin
+(Mark Hammond's IDE).  Use it from the command line interface
+(python.exe) or the windowless interpreter (pythonw.exe).
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq07.011.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq07.011.htp">Log info</A>
+
+/ Last changed on Fri Jun 12 09:32:48 1998 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="7.12">7.12. cgi.py (or other CGI programming) doesn't work sometimes on NT or win95!</A></H2>
+Be sure you have the latest python.exe, that you are using
+python.exe rather than a GUI version of python and that you
+have configured the server to execute
+<P>
+<PRE>
+     "...\python.exe -u ..."
+</PRE>
+for the cgi execution.  The -u (unbuffered) option on NT and
+win95 prevents the interpreter from altering newlines in the
+standard input and output.  Without it post/multipart requests
+will seem to have the wrong length and binary (eg, GIF)
+responses may get garbled (resulting in, eg, a "broken image").
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq07.012.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq07.012.htp">Log info</A>
+
+/ Last changed on Wed Jul 30 10:48:02 1997 by
+<A HREF="mailto:aaron_watters@msn.com">aaron watters</A>
+<P>
+
+<HR>
+<H2><A NAME="7.13">7.13. Why doesn't os.popen() work in PythonWin on NT?</A></H2>
+The reason that os.popen() doesn't work from within PythonWin is due to a bug in Microsoft's C Runtime Library (CRT). The CRT assumes you  have a Win32 console attached to the process.
+<P>
+You should use the win32pipe module's popen() instead which doesn't depend on having an attached Win32 console.
+<P>
+Example:
+<PRE>
+ import win32pipe
+ f = win32pipe.popen('dir /c c:\\')
+ print f.readlines()
+ f.close()
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq07.013.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq07.013.htp">Log info</A>
+
+/ Last changed on Thu Jul 31 15:34:09 1997 by
+<A HREF="mailto:billtut@microsoft.com">Bill Tutt</A>
+<P>
+
+<HR>
+<H2><A NAME="7.14">7.14. How do I use different functionality on different platforms with the same program?</A></H2>
+Remember that Python is extremely dynamic and that you
+can use this dynamism to configure a program at run-time to
+use available functionality on different platforms.  For example
+you can test the sys.platform and import different modules based
+on its value.
+<P>
+<PRE>
+   import sys
+   if sys.platform == "win32":
+      import win32pipe
+      popen = win32pipe.popen
+   else:
+      import os
+      popen = os.popen
+</PRE>
+(See FAQ 7.13 for an explanation of why you might want to
+do something like this.)  Also you can try to import a module
+and use a fallback if the import fails:
+<P>
+<PRE>
+    try:
+         import really_fast_implementation
+         choice = really_fast_implementation
+    except ImportError:
+         import slower_implementation
+         choice = slower_implementation
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq07.014.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq07.014.htp">Log info</A>
+
+/ Last changed on Wed Aug 13 07:39:06 1997 by
+<A HREF="mailto:aaron_watters@msn.com">aaron watters</A>
+<P>
+
+<HR>
+<H2><A NAME="7.15">7.15. Is there an Amiga version of Python?</A></H2>
+Yes. See the AmigaPython homepage at <A HREF="http://www.bigfoot.com/~irmen/python.html">http://www.bigfoot.com/~irmen/python.html</A>.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq07.015.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq07.015.htp">Log info</A>
+
+/ Last changed on Mon Dec 14 06:53:32 1998 by
+<A HREF="mailto:irmen@bigfoot.com">Irmen de Jong</A>
+<P>
+
+<HR>
+<H2><A NAME="7.16">7.16. Why doesn't os.popen()/win32pipe.popen() work on Win9x?</A></H2>
+There is a bug in Win9x that prevents os.popen/win32pipe.popen* from working. The good news is there is a way to work around this problem.
+The Microsoft Knowledge Base article that you need to lookup is: Q150956. You will find links to the knowledge base at:
+<A HREF="http://www.microsoft.com/kb">http://www.microsoft.com/kb</A>.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq07.016.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq07.016.htp">Log info</A>
+
+/ Last changed on Fri Jun 25 10:45:38 1999 by
+<A HREF="mailto:billtut@microsoft.com">Bill Tutt</A>
+<P>
+
+<HR>
+<H1>8. Python on Windows</H1>
+
+<HR>
+<H2><A NAME="8.1">8.1. Using Python for CGI on Microsoft Windows</A></H2>
+** Setting up the Microsoft IIS Server/Peer Server
+<P>
+On the Microsoft IIS 
+server or on the Win95 MS Personal Web Server
+you set up python in the same way that you 
+would set up any other scripting engine. 
+<P>
+Run regedt32 and go to: 
+<P>
+HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W3SVC\Parameters\ScriptMap 
+<P>
+and enter the following line (making any specific changes that your system may need) 
+<P>
+.py :REG_SZ: c:\&lt;path to python&gt;\python.exe -u %s %s 
+<P>
+This line will allow you to call your script with a simple reference like:
+http://yourserver/scripts/yourscript.py 
+provided "scripts" is an "executable" directory for your server (which
+it usually is by default).
+The "-u" flag specifies unbuffered and binary mode for stdin - needed when working with binary data
+<P>
+In addition, it is recommended by people who would know that using ".py" may 
+not be a good idea for the file extensions when used in this context
+(you might want to reserve *.py for support modules and use *.cgi or *.cgp
+for "main program" scripts).
+However, that issue is beyond this Windows FAQ entry.
+<P>
+<P>
+** Apache configuration
+<P>
+In the Apache configuration file httpd.conf, add the following line at 
+the end of the file:
+<P>
+ScriptInterpreterSource Registry
+<P>
+Then, give your Python CGI-scripts the extension .py and put them in the cgi-bin directory.
+<P>
+<P>
+** Netscape Servers:
+Information on this topic exists at:
+<A HREF="http://home.netscape.com/comprod/server_central/support/fasttrack_man/programs.htm#1010870">http://home.netscape.com/comprod/server_central/support/fasttrack_man/programs.htm#1010870</A>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq08.001.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq08.001.htp">Log info</A>
+
+/ Last changed on Wed Mar 27 12:25:54 2002 by
+<A HREF="mailto:gerhard@bigfoot.de">Gerhard Häring</A>
+<P>
+
+<HR>
+<H2><A NAME="8.2">8.2. How to check for a keypress without blocking?</A></H2>
+Use the msvcrt module.  This is a standard Windows-specific extensions
+in Python 1.5 and beyond.  It defines a function kbhit() which checks
+whether a keyboard hit is present; also getch() which gets one
+character without echo.  Plus a few other goodies.
+<P>
+(Search for "keypress" to find an answer for Unix as well.)
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq08.002.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq08.002.htp">Log info</A>
+
+/ Last changed on Mon Mar 30 16:21:46 1998 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="8.3">8.3. $PYTHONPATH</A></H2>
+In MS-DOS derived environments, a unix variable such as $PYTHONPATH is 
+set as PYTHONPATH, without the dollar sign.  PYTHONPATH is useful for
+specifying the location of library files.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq08.003.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq08.003.htp">Log info</A>
+
+/ Last changed on Thu Jun 11 00:41:26 1998 by
+<A HREF="mailto:guido@python.org">Gvr</A>
+<P>
+
+<HR>
+<H2><A NAME="8.4">8.4. dedent syntax errors</A></H2>
+The FAQ does not recommend using tabs, and Guido's Python Style Guide recommends 4 spaces for distributed Python code; this is also the Emacs python-mode default; see
+<P>
+<PRE>
+    <A HREF="http://www.python.org/doc/essays/styleguide.html">http://www.python.org/doc/essays/styleguide.html</A>
+</PRE>
+Under any editor mixing tabs and spaces is a bad idea.  MSVC is no different in this respect, and is easily configured to use spaces:  Take Tools -> Options -> Tabs, and for file type "Default" set "Tab size" and "Indent size" to 4, and select the "Insert spaces" radio button.
+<P>
+If you suspect mixed tabs and spaces are causing problems in leading whitespace, run Python with the -t switch or, run Tools/Scripts/tabnanny.py to check a directory tree in batch mode.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq08.004.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq08.004.htp">Log info</A>
+
+/ Last changed on Mon Feb 12 15:04:14 2001 by
+<A HREF="mailto:sholden@holdenweb.com">Steve Holden</A>
+<P>
+
+<HR>
+<H2><A NAME="8.5">8.5. How do I emulate os.kill() in Windows?</A></H2>
+Use win32api:
+<P>
+<PRE>
+    def kill(pid):
+        """kill function for Win32"""
+        import win32api
+        handle = win32api.OpenProcess(1, 0, pid)
+        return (0 != win32api.TerminateProcess(handle, 0))
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq08.005.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq08.005.htp">Log info</A>
+
+/ Last changed on Sat Aug  8 18:55:06 1998 by
+<A HREF="mailto:jeffbauer@bigfoot.com">Jeff Bauer</A>
+<P>
+
+<HR>
+<H2><A NAME="8.6">8.6. Why does os.path.isdir() fail on NT shared directories?</A></H2>
+The solution appears to be always append the "\\" on 
+the end of shared drives.
+<P>
+<PRE>
+  >>> import os
+  >>> os.path.isdir( '\\\\rorschach\\public')
+  0
+  >>> os.path.isdir( '\\\\rorschach\\public\\')
+  1
+</PRE>
+[Blake Winton responds:]
+I've had the same problem doing "Start >> Run" and then a
+directory on a shared drive.  If I use "\\rorschach\public", 
+it will fail, but if I use "\\rorschach\public\", it will 
+work.  For that matter, os.stat() does the same thing (well, 
+it gives an error for "\\\\rorschach\\public", but you get 
+the idea)...
+<P>
+I've got a theory about why this happens, but it's only 
+a theory.  NT knows the difference between shared directories, 
+and regular directories.  "\\rorschach\public" isn't a 
+directory, it's _really_ an IPC abstraction.  This is sort 
+of lended credence to by the fact that when you're mapping 
+a network drive, you can't map "\\rorschach\public\utils", 
+but only "\\rorschach\public".
+<P>
+[Clarification by <A HREF="mailto:funkster@midwinter.com">funkster@midwinter.com</A>]
+It's not actually a Python 
+question, as Python is working just fine; it's clearing up something 
+a bit muddled about Windows networked drives.
+<P>
+It helps to think of share points as being like drive letters.
+Example:
+<PRE>
+        k: is not a directory
+        k:\ is a directory
+        k:\media is a directory
+        k:\media\ is not a directory
+</PRE>
+The same rules apply if you substitute "k:" with "\\conky\foo":
+<PRE>
+        \\conky\foo  is not a directory
+        \\conky\foo\ is a directory
+        \\conky\foo\media is a directory
+        \\conky\foo\media\ is not a directory
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq08.006.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq08.006.htp">Log info</A>
+
+/ Last changed on Sun Jan 31 08:44:48 1999 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="8.7">8.7. PyRun_SimpleFile() crashes on Windows but not on Unix</A></H2>
+I've seen a number of reports of PyRun_SimpleFile() failing
+in a Windows port of an application embedding Python that worked
+fine on Unix.  PyRun_SimpleString() works fine on both platforms.
+<P>
+I think this happens because the application was compiled with a 
+different set of compiler flags than Python15.DLL.  It seems that some 
+compiler flags affect the standard I/O library in such a way that 
+using different flags makes calls fail.  You need to set it for 
+the non-debug multi-threaded DLL (/MD on the command line, or can be set via MSVC under Project Settings-&gt;C++/Code Generation then the "Use rum-time library" dropdown.)
+<P>
+Also note that you can not mix-and-match Debug and Release versions.  If you wish to use the Debug Multithreaded DLL, then your module _must_ have an "_d" appended to the base name.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq08.007.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq08.007.htp">Log info</A>
+
+/ Last changed on Wed Nov 17 17:37:07 1999 by
+<A HREF="mailto:mhammond@skippinet.com.au">Mark Hammond</A>
+<P>
+
+<HR>
+<H2><A NAME="8.8">8.8. Import of _tkinter fails on Windows 95/98</A></H2>
+Sometimes, the import of _tkinter fails on Windows 95 or 98,
+complaining with a message like the following:
+<P>
+<PRE>
+  ImportError: DLL load failed: One of the library files needed
+  to run this application cannot be found.
+</PRE>
+It could be that you haven't installed Tcl/Tk, but if you did
+install Tcl/Tk, and the Wish application works correctly,
+the problem may be that its installer didn't
+manage to edit the autoexec.bat file correctly.  It tries to add a
+statement that changes the PATH environment variable to include
+the Tcl/Tk 'bin' subdirectory, but sometimes this edit doesn't
+quite work.  Opening it with notepad usually reveals what the
+problem is.
+<P>
+(One additional hint, noted by David Szafranski: you can't use
+long filenames here; e.g. use C:\PROGRA~1\Tcl\bin instead of
+C:\Program Files\Tcl\bin.)
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq08.008.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq08.008.htp">Log info</A>
+
+/ Last changed on Wed Dec  2 22:32:41 1998 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="8.9">8.9. Can't extract the downloaded documentation on Windows</A></H2>
+Sometimes, when you download the documentation package to a Windows
+machine using a web browser, the file extension of the saved file
+ends up being .EXE.  This is a mistake; the extension should be .TGZ.
+<P>
+Simply rename the downloaded file to have the .TGZ extension, and
+WinZip will be able to handle it.  (If your copy of WinZip doesn't,
+get a newer one from <A HREF="http://www.winzip.com">http://www.winzip.com</A>.)
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq08.009.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq08.009.htp">Log info</A>
+
+/ Last changed on Sat Nov 21 13:41:35 1998 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="8.10">8.10. Can't get Py_RunSimpleFile() to work.</A></H2>
+This is very sensitive to the compiler vendor, version and (perhaps)
+even options.  If the FILE* structure in your embedding program isn't
+the same as is assumed by the Python interpreter it won't work.
+<P>
+The Python 1.5.* DLLs (python15.dll) are all compiled
+with MS VC++ 5.0 and with multithreading-DLL options (/MD, I think).
+<P>
+If you can't change compilers or flags, try using Py_RunSimpleString().
+A trick to get it to run an arbitrary file is to construct a call to
+execfile() with the name of your file as argument.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq08.010.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq08.010.htp">Log info</A>
+
+/ Last changed on Wed Jan 13 10:58:14 1999 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="8.11">8.11. Where is Freeze for Windows?</A></H2>
+("Freeze" is a program that allows you to ship a Python program
+as a single stand-alone executable file.  It is <I>not</I> a compiler,
+your programs don't run any faster, but they are more easily
+distributable (to platforms with the same OS and CPU).  Read the
+README file of the freeze program for more disclaimers.)
+<P>
+You can use freeze on Windows, but you must download the source
+tree (see <A HREF="http://www.python.org/download/download_source.html">http://www.python.org/download/download_source.html</A>).
+This is recommended for Python 1.5.2 (and betas thereof) only;
+older versions don't quite work.
+<P>
+You need the Microsoft VC++ 5.0 compiler (maybe it works with
+6.0 too).  You probably need to build Python -- the project files
+are all in the PCbuild directory.
+<P>
+The freeze program is in the Tools\freeze subdirectory of the source
+tree.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq08.011.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq08.011.htp">Log info</A>
+
+/ Last changed on Wed Feb 17 18:47:24 1999 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="8.12">8.12. Is a *.pyd file the same as a DLL?</A></H2>
+Yes, .pyd files are dll's.  But there are a few differences.  If you
+have a DLL named foo.pyd, then it must have a function initfoo().  You
+can then write Python "import foo", and Python will search for foo.pyd
+(as well as foo.py, foo.pyc) and if it finds it, will attempt to call
+initfoo() to initialize it.  You do not link your .exe with foo.lib,
+as that would cause Windows to require the DLL to be present.
+<P>
+Note that the search path for foo.pyd is PYTHONPATH, not the same as
+the path that Windows uses to search for foo.dll.  Also, foo.pyd need
+not be present to run your program, whereas if you linked your program
+with a dll, the dll is required.  Of course, foo.pyd is required if
+you want to say "import foo".  In a dll, linkage is declared in the
+source code with __declspec(dllexport).  In a .pyd, linkage is defined
+in a list of available functions.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq08.012.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq08.012.htp">Log info</A>
+
+/ Last changed on Tue Nov 23 02:40:08 1999 by
+<A HREF="mailto:jquinn+psa@cs.oberlin.edu">Jameson Quinn</A>
+<P>
+
+<HR>
+<H2><A NAME="8.13">8.13. Missing cw3215mt.dll (or missing cw3215.dll)</A></H2>
+Sometimes, when using Tkinter on Windows, you get an error that
+cw3215mt.dll or cw3215.dll is missing.
+<P>
+Cause: you have an old Tcl/Tk DLL built with cygwin in your path
+(probably C:\Windows).  You must use the Tcl/Tk DLLs from the
+standard Tcl/Tk installation (Python 1.5.2 comes with one).
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq08.013.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq08.013.htp">Log info</A>
+
+/ Last changed on Fri Jun 11 00:54:13 1999 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="8.14">8.14. How to make python scripts executable:</A></H2>
+[Blake Coverett]
+<P>
+Win2K:
+<P>
+The standard installer already associates the .py extension with a file type
+(Python.File) and gives that file type an open command that runs the
+interpreter (D:\Program Files\Python\python.exe "%1" %*).  This is enough to
+make scripts executable from the command prompt as 'foo.py'.  If you'd
+rather be able to execute the script by simple typing 'foo' with no
+extension you need to add .py to the PATHEXT environment variable.
+<P>
+WinNT:
+<P>
+The steps taken by the installed as described above allow you do run a
+script with 'foo.py', but a long time bug in the NT command processor
+prevents you from redirecting the input or output of any script executed in
+this way.  This is often important.
+<P>
+An appropriate incantation for making a Python script executable under WinNT
+is to give the file an extension of .cmd and add the following as the first
+line:
+<P>
+<PRE>
+    @setlocal enableextensions &amp; python -x %~f0 %* &amp; goto :EOF
+</PRE>
+Win9x:
+<P>
+[Due to Bruce Eckel]
+<P>
+<PRE>
+  @echo off
+  rem = """
+  rem run python on this bat file. Needs the full path where
+  rem you keep your python files. The -x causes python to skip
+  rem the first line of the file:
+  python -x c:\aaa\Python\\"%0".bat %1 %2 %3 %4 %5 %6 %7 %8 %9
+  goto endofpython
+  rem """
+</PRE>
+<PRE>
+  # The python program goes here:
+</PRE>
+<PRE>
+  print "hello, Python"
+</PRE>
+<PRE>
+  # For the end of the batch file:
+  rem = """
+  :endofpython
+  rem """
+</PRE>
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq08.014.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq08.014.htp">Log info</A>
+
+/ Last changed on Tue Nov 30 10:25:17 1999 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="8.15">8.15. Warning about CTL3D32 version from installer</A></H2>
+The Python installer issues a warning like this:
+<P>
+<PRE>
+  This version uses CTL3D32.DLL whitch is not the correct version.
+  This version is used for windows NT applications only.
+</PRE>
+[Tim Peters]
+This is a Microsoft DLL, and a notorious
+source of problems.  The msg means what it says:  you have the wrong version
+of this DLL for your operating system.  The Python installation did not
+cause this -- something else you installed previous to this overwrote the
+DLL that came with your OS (probably older shareware of some sort, but
+there's no way to tell now).  If you search for "CTL3D32" using any search
+engine (AltaVista, for example), you'll find hundreds and hundreds of web
+pages complaining about the same problem with all sorts of installation
+programs.  They'll point you to ways to get the correct version reinstalled
+on your system (since Python doesn't cause this, we can't fix it).
+<P>
+David A Burton has written a little program to fix this.  Go to
+<A HREF="http://www.burtonsys.com/download.html">http://www.burtonsys.com/download.html</A> and click on "ctl3dfix.zip"
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq08.015.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq08.015.htp">Log info</A>
+
+/ Last changed on Thu Oct 26 15:42:00 2000 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<H2><A NAME="8.16">8.16. How can I embed Python into a Windows application?</A></H2>
+Edward K. Ream &lt;<A HREF="mailto:edream@tds.net">edream@tds.net</A>&gt; writes
+<P>
+When '##' appears in a file name below, it is an abbreviated version number.  For example, for Python 2.1.1, ## will be replaced by 21.
+<P>
+Embedding the Python interpreter in a Windows app can be summarized as
+follows:
+<P>
+1. Do _not_ build Python into your .exe file directly.  On Windows,
+Python must be a DLL to handle importing modules that are themselves
+DLL's.  (This is the first key undocumented fact.) Instead, link to
+python##.dll; it is typically installed in c:\Windows\System.  
+<P>
+You can link to Python statically or dynamically.  Linking statically
+means linking against python##.lib The drawback is that your app won't
+run if python##.dll does not exist on your system.
+<P>
+General note: python##.lib is the so-called "import lib" corresponding
+to python.dll.  It merely defines symbols for the linker.
+<P>
+Borland note: convert python##.lib to OMF format using Coff2Omf.exe
+first.
+<P>
+Linking dynamically greatly simplifies link options; everything happens
+at run time.  Your code must load python##.dll using the Windows
+LoadLibraryEx() routine.  The code must also use access routines and
+data in python##.dll (that is, Python's C API's) using pointers
+obtained by the Windows GetProcAddress() routine.  Macros can make
+using these pointers transparent to any C code that calls routines in
+Python's C API.
+<P>
+2. If you use SWIG, it is easy to create a Python "extension module"
+that will make the app's data and methods available to Python.  SWIG
+will handle just about all the grungy details for you.  The result is C
+code that you link _into your .exe file_ (!)  You do _not_ have to
+create a DLL file, and this also simplifies linking.
+<P>
+3.  SWIG will create an init function (a C function) whose name depends
+on the name of the extension module.  For example, if the name of the
+module is leo, the init function will be called initleo().  If you use
+SWIG shadow classes, as you should, the init function will be called
+initleoc().  This initializes a mostly hidden helper class used by the
+shadow class.
+<P>
+The reason you can link the C code in step 2 into your .exe file is that
+calling the initialization function is equivalent to importing the
+module into Python! (This is the second key undocumented fact.)
+<P>
+4. In short, you can use the following code to initialize the Python
+interpreter with your extension module.
+<P>
+<PRE>
+    #include "python.h"
+    ...
+    Py_Initialize();  // Initialize Python.
+    initmyAppc();  // Initialize (import) the helper class. 
+    PyRun_SimpleString("import myApp") ;  // Import the shadow class.
+</PRE>
+5. There are two problems with Python's C API which will become apparent
+if you use a compiler other than MSVC, the compiler used to build
+python##.dll.
+<P>
+Problem 1: The so-called "Very High Level" functions that take FILE *
+arguments will not work in a multi-compiler environment; each compiler's
+notion of a struct FILE will be different.  From an implementation
+standpoint these are very _low_ level functions.
+<P>
+Problem 2: SWIG generates the following code when generating wrappers to
+void functions:
+<P>
+<PRE>
+    Py_INCREF(Py_None);
+    _resultobj = Py_None;
+    return _resultobj;
+</PRE>
+Alas, Py_None is a macro that expands to a reference to a complex data
+structure called _Py_NoneStruct inside python##.dll.  Again, this code
+will fail in a mult-compiler environment.  Replace such code by:
+<P>
+<PRE>
+    return Py_BuildValue("");
+</PRE>
+It may be possible to use SWIG's %typemap command to make the change
+automatically, though I have not been able to get this to work (I'm a
+complete SWIG newbie).
+<P>
+6. Using a Python shell script to put up a Python interpreter window
+from inside your Windows app is not a good idea; the resulting window
+will be independent of your app's windowing system.  Rather, you (or the
+wxPythonWindow class) should create a "native" interpreter window.  It
+is easy to connect that window to the Python interpreter.  You can
+redirect Python's i/o to _any_ object that supports read and write, so
+all you need is a Python object (defined in your extension module) that
+contains read() and write() methods.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq08.016.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq08.016.htp">Log info</A>
+
+/ Last changed on Thu Jan 31 16:29:34 2002 by
+<A HREF="mailto:vkryukov@ufg.com">Victor Kryukov</A>
+<P>
+
+<HR>
+<H2><A NAME="8.17">8.17. Setting up IIS 5 to use Python for CGI</A></H2>
+In order to set up Internet Information Services 5 to use Python for CGI processing, please see the following links:
+<P>
+<A HREF="http://www.e-coli.net/pyiis_server.html">http://www.e-coli.net/pyiis_server.html</A> (for Win2k Server)
+<A HREF="http://www.e-coli.net/pyiis.html">http://www.e-coli.net/pyiis.html</A> (for Win2k pro)
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq08.017.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq08.017.htp">Log info</A>
+
+/ Last changed on Fri Mar 22 22:05:51 2002 by
+<A HREF="mailto:dsavitsk@e-coli.net">douglas savitsky</A>
+<P>
+
+<HR>
+<H2><A NAME="8.18">8.18. How do I run a Python program under Windows?</A></H2>
+This is not necessarily quite the straightforward question it appears
+to be. If you are already familiar with running programs from the
+Windows command line then everything will seem really easy and
+obvious. If your computer experience is limited then you might need a
+little more guidance. Also there are differences between Windows 95,
+98, NT, ME, 2000 and XP which can add to the confusion. You might
+think of this as "why I pay software support charges" if you have a
+helpful and friendly administrator to help you set things up without
+having to understand all this yourself. If so, then great! Show them
+this page and it should be a done deal.
+<P>
+Unless you use some sort of integrated development environment (such
+as PythonWin or IDLE, to name only two in a growing family) then you
+will end up <I>typing</I> Windows commands into what is variously referred
+to as a "DOS window" or "Command prompt window". Usually you can
+create such a window from your Start menu (under Windows 2000 I use
+"Start | Programs | Accessories | Command Prompt").  You should be
+able to recognize when you have started such a window because you will
+see a Windows "command prompt", which usually looks like this:
+<P>
+<PRE>
+    C:\>
+</PRE>
+The letter may be different, and there might be other things after it,
+so you might just as easily see something like:
+<P>
+<PRE>
+    D:\Steve\Projects\Python>
+</PRE>
+depending on how your computer has been set up and what else you have
+recently done with it. Once you have started such a window, you are
+well on the way to running Python programs.
+<P>
+You need to realize that your Python scripts have to be processed by
+another program, usually called the "Python interpreter". The
+interpreter reads your script, "compiles" it into "Python bytecodes"
+(which are instructions for an imaginary computer known as the "Python
+Virtual Machine") and then executes the bytecodes to run your
+program. So, how do you arrange for the interpreter to handle your
+Python?
+<P>
+First, you need to make sure that your command window recognises the
+word "python" as an instruction to start the interpreter. If you have
+opened a command window, you should try entering the command:
+<P>
+<PRE>
+    python
+</PRE>
+and hitting return. If you then see something like:
+<P>
+<PRE>
+    Python 2.2 (#28, Dec 21 2001, 12:21:22) [MSC 32 bit (Intel)] on win32
+    Type "help", "copyright", "credits" or "license" for more information.
+    >>>
+</PRE>
+then this part of the job has been correctly managed during Python's
+installation process, and you have started the interpreter in
+"interactive mode". That means you can enter Python statements or
+expressions interactively and have them executed or evaluated while
+you wait. This is one of Python's strongest features, but it takes a
+little getting used to. Check it by entering a few expressions of your
+choice and seeing the results...
+<P>
+<PRE>
+    >>> print "Hello"
+    Hello
+    >>> "Hello" * 3
+    HelloHelloHello
+</PRE>
+When you want to end your interactive Python session, enter a
+terminator (hold the Ctrl key down while you enter a Z, then hit the
+"Enter" key) to get back to your Windows command prompt.  You may also
+find that you have a Start-menu entry such as "Start | Programs |
+Python 2.2 | Python (command line)" that results in you seeing the
+">>>" prompt in a new window. If so, the window will disappear after
+you enter the terminator -- Windows runs a single "python" command in
+the window, which terminates when you terminate the interpreter.
+<P>
+If the "python" command, instead of displaying the interpreter prompt ">>>", gives you a message like
+<P>
+<PRE>
+    'python' is not recognized as an internal or external command,
+    operable program or batch file.
+</PRE>
+or
+<P>
+<PRE>
+    Bad command or filename
+</PRE>
+then you need to make sure that your computer knows where to find the
+Python interpreter. To do this you will have to modify a setting
+called the PATH, which is a just list of directories where Windows
+will look for programs. Rather than just enter the right command every
+time you create a command window, you should arrange for Python's
+installation directory to be added to the PATH of every command window
+as it starts. If you installed Python fairly recently then the command
+<P>
+<PRE>
+    dir C:\py*
+</PRE>
+will probably tell you where it is installed. Alternatively, perhaps
+you made a note. Otherwise you will be reduced to a search of your
+whole disk ... break out the Windows explorer and use "Tools | Find"
+or hit the "Search" button and look for "python.exe". Suppose you
+discover that Python is installed in the C:\Python22 directory (the
+default at the time of writing) then you should make sure that
+entering the command
+<P>
+<PRE>
+    c:\Python22\python
+</PRE>
+starts up the interpreter as above (and don't forget you'll need a
+"CTRL-Z" and an "Enter" to get out of it). Once you have verified the
+directory, you need to add it to the start-up routines your computer
+goes through.  For older versions of Windows the easiest way to do
+this is to edit the C:\AUTOEXEC.BAT file. You would want to add a line
+like the following to AUTOEXEC.BAT:
+<P>
+<PRE>
+    PATH C:\Python22;%PATH%
+</PRE>
+For Windows NT, 2000 and (I assume) XP, you will need to add a string
+such as
+<P>
+<PRE>
+    ;C:\Python22
+</PRE>
+to the current setting for the PATH environment variable, which you
+will find in the properties window of "My Computer" under the
+"Advanced" tab. Note that if you have sufficient privilege you might
+get a choice of installing the settings either for the Current User or
+for System. The latter is preferred if you want everybody to be able
+to run Python on the machine.
+<P>
+If you aren't confident doing any of these manipulations yourself, ask
+for help!  At this stage you may or may not want to reboot your system
+to make absolutely sure the new setting has "taken" (don't you love
+the way Windows gives you these freqeuent coffee breaks). You probably
+won't need to for Windows NT, XP or 2000. You can also avoid it in
+earlier versions by editing the file C:\WINDOWS\COMMAND\CMDINIT.BAT
+instead of AUTOEXEC.BAT.
+<P>
+You should now be able to start a new command window, enter
+<P>
+<PRE>
+    python
+</PRE>
+at the "C:>" (or whatever) prompt, and see the ">>>" prompt that
+indicates the Python interpreter is reading interactive commands.
+<P>
+Let's suppose you have a program called "pytest.py" in directory
+"C:\Steve\Projects\Python". A session to run that program might look
+like this:
+<P>
+<PRE>
+    C:\> cd \Steve\Projects\Python
+    C:\Steve\Projects\Python> python pytest.py
+</PRE>
+Because you added a file name to the command to start the interpreter,
+when it starts up it reads the Python script in the named file,
+compiles it, executes it, and terminates (so you see another "C:\>"
+prompt).  You might also have entered
+<P>
+<PRE>
+    C:\> python \Steve\Projects\Python\pytest.py
+</PRE>
+if you hadn't wanted to change your current directory.
+<P>
+Under NT, 2000 and XP you may well find that the installation process
+has also arranged that the command
+<P>
+<PRE>
+    pytest.py
+</PRE>
+(or, if the file isn't in the current directory)
+<P>
+<PRE>
+    C:\Steve\Projects\Python\pytest.py
+</PRE>
+will automatically recognize the ".py" extension and run the Python
+interpreter on the named file. Using this feature is fine, but <I>some</I>
+versions of Windows have bugs which mean that this form isn't exactly
+equivalent to using the interpreter explicitly, so be careful. Easier
+to remember, for now, that
+<P>
+<PRE>
+    python C:\Steve\Projects\Python\pytest.py
+</PRE>
+works pretty close to the same, and redirection will work (more)
+reliably.
+<P>
+The important things to remember are:
+<P>
+1. Start Python from the Start Menu, or make sure the PATH is set
+correctly so Windows can find the Python interpreter.
+<P>
+<PRE>
+    python
+</PRE>
+should give you a '>>>" prompt from the Python interpreter. Don't
+forget the CTRL-Z and ENTER to terminate the interpreter (and, if you
+started the window from the Start Menu, make the window disappear).
+<P>
+2. Once this works, you run programs with commands:
+<P>
+<PRE>
+    python {program-file}
+</PRE>
+3. When you know the commands to use you can build Windows shortcuts
+to run the Python interpreter on any of your scripts, naming
+particular working directories, and adding them to your menus, but
+that's another lessFAQ. Take a look at
+<P>
+<PRE>
+    python --help
+</PRE>
+if your needs are complex.
+<P>
+4. Interactive mode (where you see the ">>>" prompt) is best used
+<I>not</I> for running programs, which are better executed as in steps 2
+and 3, but for checking that individual statements and expressions do
+what you think they will, and for developing code by experiment.
+<P>
+
+<A HREF="faqw.py?req=edit&amp;file=faq08.018.htp">Edit this entry</A> /
+<A HREF="faqw.py?req=log&amp;file=faq08.018.htp">Log info</A>
+
+/ Last changed on Tue Aug 20 16:19:53 2002 by
+<A HREF="mailto:guido@python.org">GvR</A>
+<P>
+
+<HR>
+<A HREF="http://www.python.org">Python home</A> /
+<A HREF="faqw.py?req=home">Python FAQ Wizard 1.0.3</A> /
+Feedback to <A HREF="mailto:guido@python.org">GvR</A>
+<P><A HREF="http://www.python.org/"><IMG
+SRC="http://www.python.org/pics/PythonPowered.gif" 
+ALIGN=top WIDTH=110 HEIGHT=44 ALT="Python Powered" BORDER=0></A><BR>
+</BODY>
+</HTML>
diff --git a/PVER-dbg.README.Debian.in b/PVER-dbg.README.Debian.in
new file mode 100644 (file)
index 0000000..b30149b
--- /dev/null
@@ -0,0 +1,52 @@
+Contents of the @PVER@-dbg package
+-------------------------------------
+
+For debugging python and extension modules, you may want to add the contents
+of /usr/share/doc/@PVER@/gdbinit (found in the @PVER@-dev package) to your
+~/.gdbinit file.
+
+@PVER@-dbg contains two sets of packages:
+
+ - debugging symbols for the standard @PVER@ build. When this package
+   is installed, gdb will automatically load up the debugging symbols
+   from it when debugging @PVER@ or one of the included extension
+   modules.
+
+ - a separate @PVER@-dbg binary, configured --with-pydebug, enabling the
+   additional debugging code to help debug memory management problems.
+
+For the latter, all extension modules have to be recompiled to
+correctly load with an pydebug enabled build.
+
+
+Debian and Ubuntu specific changes to the debug interpreter
+-----------------------------------------------------------
+The python2.4 and python2.5 packages in Ubuntu feisty are modified to
+first look for extension modules under a different name.
+
+  normal build: foo.so
+  debug build:  foo_d.so foo.so
+
+This naming schema allows installation of the extension modules into
+the same path (The naming is directly taken from the Windows builds
+which already uses this naming scheme).
+
+See https://wiki.ubuntu.com/PyDbgBuilds for more information.
+
+
+Using the python-dbg builds
+---------------------------
+
+ * Call the python-dbg or the pythonX.Y-dbg binaries instead of the
+   python or pythonX.Y binaries.
+
+ * Properties of the debug build are described in
+   /usr/share/doc/@PVER@/SpecialBuilds.txt.gz.
+   The debug interpreter is built with Py_DEBUG defined.
+
+ * From SpecialBuilds.txt: This is what is generally meant by "a debug
+   build" of Python.  Py_DEBUG implies LLTRACE, Py_REF_DEBUG,
+   Py_TRACE_REFS, and PYMALLOC_DEBUG (if WITH_PYMALLOC is enabled).
+   In addition, C assert()s are enabled (via the C way: by not defining
+   NDEBUG), and some routines do additional sanity checks inside
+   "#ifdef Py_DEBUG" blocks.
diff --git a/PVER-dbg.overrides.in b/PVER-dbg.overrides.in
new file mode 100644 (file)
index 0000000..22e76f1
--- /dev/null
@@ -0,0 +1,7 @@
+# just the gdb debug file
+@PVER@-dbg binary: python-script-but-no-python-dep
+
+# pointless lintian ...
+@PVER@-dbg binary: hardening-no-fortify-functions
+
+@PVER@-dbg binary: command-with-path-in-maintainer-script
diff --git a/PVER-dbg.postinst.in b/PVER-dbg.postinst.in
new file mode 100644 (file)
index 0000000..8f0208e
--- /dev/null
@@ -0,0 +1,19 @@
+#! /bin/sh
+
+set -e
+
+if [ "$1" = configure ]; then
+    files=$(dpkg -L lib@PVER@-dbg@HOST_QUAL@ | sed -n '/^\/usr\/lib\/@PVER@\/.*\.py$/p')
+    if [ -n "$files" ]; then
+       /usr/bin/@PVER@ -E -S /usr/lib/@PVER@/py_compile.py $files
+       if grep -sq '^byte-compile[^#]*optimize' /etc/python/debian_config; then
+           /usr/bin/@PVER@ -E -S -O /usr/lib/@PVER@/py_compile.py $files
+       fi
+    else
+       echo >&2 "@PVER@-dbg: can't get files for byte-compilation"
+    fi
+fi
+
+#DEBHELPER#
+
+exit 0
diff --git a/PVER-dbg.prerm.in b/PVER-dbg.prerm.in
new file mode 100644 (file)
index 0000000..3d92951
--- /dev/null
@@ -0,0 +1,35 @@
+#! /bin/sh
+
+set -e
+
+remove_bytecode()
+{
+    pkg=$1
+    max=$(LANG=C LC_ALL=C xargs --show-limits < /dev/null 2>&1 | awk '/Maximum length/ {print int($NF / 4)}')
+    dpkg -L $pkg \
+       | awk -F/ 'BEGIN {OFS="/"} /\.py$/ {$NF=sprintf("__pycache__/%s.*.py[co]", substr($NF,1,length($NF)-3)); print}' \
+       | xargs --max-chars=$max echo \
+       | while read files; do rm -f $files; done
+    if [ -d /usr/bin/__pycache__ ]; then
+       rmdir --ignore-fail-on-non-empty /usr/bin/__pycache__
+    fi
+}
+
+case "$1" in
+    remove)
+       remove_bytecode lib@PVER@-dbg@HOST_QUAL@
+        ;;
+    upgrade)
+       remove_bytecode lib@PVER@-dbg@HOST_QUAL@
+        ;;
+    deconfigure)
+        ;;
+    failed-upgrade)
+        ;;
+    *)
+        echo "prerm called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+#DEBHELPER#
diff --git a/PVER-doc.doc-base.PVER-api.in b/PVER-doc.doc-base.PVER-api.in
new file mode 100644 (file)
index 0000000..e4fdd43
--- /dev/null
@@ -0,0 +1,13 @@
+Document: @PVER@-api
+Title: Python/C API Reference Manual (v@VER@)
+Author: Guido van Rossum
+Abstract: This manual documents the API used by C (or C++) programmers who
+ want to write extension modules or embed Python.  It is a
+ companion to *Extending and Embedding the Python Interpreter*,
+ which describes the general principles of extension writing but
+ does not document the API functions in detail.
+Section: Programming/Python
+
+Format: HTML
+Index: /usr/share/doc/@PVER@/html/c-api/index.html
+Files: /usr/share/doc/@PVER@/html/c-api/*.html
diff --git a/PVER-doc.doc-base.PVER-dist.in b/PVER-doc.doc-base.PVER-dist.in
new file mode 100644 (file)
index 0000000..37c9dee
--- /dev/null
@@ -0,0 +1,13 @@
+Document: @PVER@-dist
+Title: Distributing Python Modules (v@VER@)
+Author: Greg Ward
+Abstract: This document describes the Python Distribution Utilities
+ (``Distutils'') from the module developer's point-of-view, describing
+ how to use the Distutils to make Python modules and extensions easily
+ available to a wider audience with very little overhead for
+ build/release/install mechanics.
+Section: Programming/Python
+
+Format: HTML
+Index: /usr/share/doc/@PVER@/html/distutils/index.html
+Files: /usr/share/doc/@PVER@/html/distutils/*.html
diff --git a/PVER-doc.doc-base.PVER-ext.in b/PVER-doc.doc-base.PVER-ext.in
new file mode 100644 (file)
index 0000000..ce7d2b5
--- /dev/null
@@ -0,0 +1,16 @@
+Document: @PVER@-ext
+Title: Extending and Embedding the Python Interpreter (v@VER@)
+Author: Guido van Rossum
+Abstract: This document describes how to write modules in C or C++ to extend
+ the Python interpreter with new modules.  Those modules can define
+ new functions but also new object types and their methods.  The
+ document also describes how to embed the Python interpreter in
+ another application, for use as an extension language.  Finally,
+ it shows how to compile and link extension modules so that they
+ can be loaded dynamically (at run time) into the interpreter, if
+ the underlying operating system supports this feature.
+Section: Programming/Python
+
+Format: HTML
+Index: /usr/share/doc/@PVER@/html/extending/index.html
+Files: /usr/share/doc/@PVER@/html/extending/*.html
diff --git a/PVER-doc.doc-base.PVER-inst.in b/PVER-doc.doc-base.PVER-inst.in
new file mode 100644 (file)
index 0000000..f3d56f2
--- /dev/null
@@ -0,0 +1,12 @@
+Document: @PVER@-inst
+Title: Installing Python Modules (v@VER@)
+Author: Greg Ward
+Abstract: This document describes the Python Distribution Utilities
+ (``Distutils'') from the end-user's point-of-view, describing how to
+ extend the capabilities of a standard Python installation by building
+ and installing third-party Python modules and extensions.
+Section: Programming/Python
+
+Format: HTML
+Index: /usr/share/doc/@PVER@/html/install/index.html
+Files: /usr/share/doc/@PVER@/html/install/*.html
diff --git a/PVER-doc.doc-base.PVER-lib.in b/PVER-doc.doc-base.PVER-lib.in
new file mode 100644 (file)
index 0000000..1bd47ac
--- /dev/null
@@ -0,0 +1,15 @@
+Document: @PVER@-lib
+Title: Python Library Reference (v@VER@)
+Author: Guido van Rossum
+Abstract: This library reference manual documents Python's standard library,
+ as well as many optional library modules (which may or may not be
+ available, depending on whether the underlying platform supports
+ them and on the configuration choices made at compile time).  It
+ also documents the standard types of the language and its built-in
+ functions and exceptions, many of which are not or incompletely
+ documented in the Reference Manual.
+Section: Programming/Python
+
+Format: HTML
+Index: /usr/share/doc/@PVER@/html/library/index.html
+Files: /usr/share/doc/@PVER@/html/library/*.html
diff --git a/PVER-doc.doc-base.PVER-new.in b/PVER-doc.doc-base.PVER-new.in
new file mode 100644 (file)
index 0000000..f613395
--- /dev/null
@@ -0,0 +1,10 @@
+Document: @PVER@-new
+Title: What's new in Python @VER@
+Author: A.M. Kuchling
+Abstract: This documents lists new features and changes worth mentioning
+ in Python @VER@.
+Section: Programming/Python
+
+Format: HTML
+Index: /usr/share/doc/@PVER@/html/whatsnew/@VER@.html
+Files: /usr/share/doc/@PVER@/html/whatsnew/@VER@.html
diff --git a/PVER-doc.doc-base.PVER-ref.in b/PVER-doc.doc-base.PVER-ref.in
new file mode 100644 (file)
index 0000000..4a48a65
--- /dev/null
@@ -0,0 +1,18 @@
+Document: @PVER@-ref
+Title: Python Reference Manual (v@VER@)
+Author: Guido van Rossum
+Abstract: This reference manual describes the syntax and "core semantics" of
+ the language.  It is terse, but attempts to be exact and complete.
+ The semantics of non-essential built-in object types and of the
+ built-in functions and modules are described in the *Python
+ Library Reference*.  For an informal introduction to the language,
+ see the *Python Tutorial*.  For C or C++ programmers, two
+ additional manuals exist: *Extending and Embedding the Python
+ Interpreter* describes the high-level picture of how to write a
+ Python extension module, and the *Python/C API Reference Manual*
+ describes the interfaces available to C/C++ programmers in detail.
+Section: Programming/Python
+
+Format: HTML
+Index: /usr/share/doc/@PVER@/html/reference/index.html
+Files: /usr/share/doc/@PVER@/html/reference/*.html
diff --git a/PVER-doc.doc-base.PVER-tut.in b/PVER-doc.doc-base.PVER-tut.in
new file mode 100644 (file)
index 0000000..8021e2d
--- /dev/null
@@ -0,0 +1,13 @@
+Document: @PVER@-tut
+Title: Python Tutorial (v@VER@)
+Author: Guido van Rossum, Fred L. Drake, Jr., editor
+Abstract: This tutorial introduces the reader informally to the basic
+ concepts and features of the Python language and system.  It helps
+ to have a Python interpreter handy for hands-on experience, but
+ all examples are self-contained, so the tutorial can be read
+ off-line as well.
+Section: Programming/Python
+
+Format: HTML
+Index: /usr/share/doc/@PVER@/html/tutorial/index.html
+Files: /usr/share/doc/@PVER@/html/tutorial/*.html
diff --git a/PVER-doc.info.in b/PVER-doc.info.in
new file mode 100644 (file)
index 0000000..7476490
--- /dev/null
@@ -0,0 +1 @@
+Doc/build/texinfo/@PVER@.info
diff --git a/PVER-doc.overrides.in b/PVER-doc.overrides.in
new file mode 100644 (file)
index 0000000..9aafae4
--- /dev/null
@@ -0,0 +1,2 @@
+# this is referenced by the html docs
+@PVER@-doc binary: extra-license-file
diff --git a/PVER-examples.overrides.in b/PVER-examples.overrides.in
new file mode 100644 (file)
index 0000000..4239e36
--- /dev/null
@@ -0,0 +1,3 @@
+# don't care about permissions of the example files
+@PVER@-examples binary: executable-not-elf-or-script
+@PVER@-examples binary: package-contains-vcs-control-file
diff --git a/PVER-minimal.README.Debian.in b/PVER-minimal.README.Debian.in
new file mode 100644 (file)
index 0000000..470d221
--- /dev/null
@@ -0,0 +1,189 @@
+Contents of the @PVER@-minimal package
+-----------------------------------------
+
+@PVER@-minimal consists of a minimum set of modules which may be needed
+for python scripts used during the boot process.  If other packages
+are needed in these scripts, don't work around the missing module, but
+file a bug report against this package. The modules in this package
+are:
+
+  __builtin__          builtin
+  __future__           module
+  _abc                 extension
+  _ast                 extension
+  _bisect              extension
+  _blake2              extension
+  _bootlocale          module
+  _bytesio             builtin
+  _codecs              builtin
+  _collections         extension
+  _collections_abc     module
+  _compat_pickle       module
+  _csv                 extension
+  _datetime            extension
+  _elementtree         extension
+  _fileio              builtin
+  _functools           extension
+  _hashlib             extensionx
+  _heapq               extension
+  _imp                 builtin
+  _io                  builtin
+  _locale              extension
+  _md5                 extension
+  _opcode              extension
+  _operator            extension
+  _pickle              extension
+  _posixsubprocess     extension
+  _py_abc              module
+  _random              extension
+  _sha1                        extension
+  _sha3                        extension
+  _sha256              extension
+  _sha512              extension
+  _signal              builtin
+  _sitebuiltins                module
+  _socket              extension
+  _sre                 builtin
+  _ssl                 extensionx
+  _stat                        extension
+  _stringio            extension
+  _struct              extension
+  _string              builtin
+  _stringio            builtin
+  _strptime            module
+  _symtable            builtin
+  _thread              builtin
+  _threading_local     module
+  _tracemalloc         extension
+  _types               builtin
+  _weakref             builtin
+  _weakrefset          module
+  _warnings            builtin
+  configparser         module
+  abc                  module
+  argparse             module
+  array                        extension
+  ast                  module
+  atexit               extension
+  base64               module
+  binascii             extension
+  bisect               module
+  builtins             builtin
+  calendar             module
+  cmath                        extension
+  codecs               module
+  collections          package
+  compileall           module
+  contextlib           module
+  copy                 module
+  copyreg              module
+  csv                  module
+  datetime             module
+  dis                  module
+  email                        package
+  encodings            package
+  enum                 module
+  errno                        builtin
+  exceptions           builtin
+  fcntl                        extension
+  filecmp              module
+  fnmatch              module
+  functools            module
+  gc                   builtin
+  genericpath          module
+  getopt               module
+  glob                 module
+  grp                  extension
+  hashlib              module
+  heapq                        module
+  imp                  module
+  importlib            package
+  inspect              module
+  io                   module
+  ipaddress            module
+  itertools            extension
+  keyword              module
+  linecache            module
+  locale               module
+  logging              package
+  marshal              builtin
+  math                 extension
+  opcode               module
+  operator             module
+  optparse             module
+  os                   module
+  pathlib              module
+  pickle               module
+  pkgutil              module
+  platform             module
+  posix                        builtin
+  posixpath            module
+  pwd                  builtin
+  pyexpat              extension
+  py_compile           module
+  quopri               module
+  random               module
+  re                   module
+  reprlib              module
+  runpy                        module
+  select               extension
+  selectors            module
+  signal               module
+  socket               module
+  spwd                 extension
+  sre_compile          module
+  sre_constants                module
+  sre_parse            module
+  ssl                  module
+  stat                 module
+  string               module
+  struct               module
+  subprocess           module
+  sys                  builtin
+  sysconfig            module
+  syslog               extension
+  tempfile             module
+  textwrap             module
+  threading            module
+  time                 extension
+  token                        module
+  tokenize             module
+  traceback            module
+  tracemalloc          module
+  types                        module
+  typing               module
+  unicodedata          extension
+  urllib               package
+  uu                   module
+  warnings             module
+  weakref              module
+  zipfile              module
+  zipimport            module
+  zlib                 extension
+
+Included are as well the codecs and stringprep modules, and the encodings
+modules for all encodings except the multibyte encodings and the bz2 codec.
+
+The following modules are excluded, their import is guarded from the
+importing module:
+
+  Used in       Excluded
+  ------------  ------------------------------------
+  io           _dummy_thread
+  os           nt ntpath os2 os2emxpath mac macpath
+               riscos riscospath riscosenviron
+  optparse     gettext
+  pickle       doctest
+  subprocess   threading_dummy
+
+This list was derived by looking at the modules in the perl-base package,
+then adding python specific "core modules".
+
+TODO's
+------
+
+- time.strptime cannot be used. The required _strptime module is not
+  included in the -minimal package yet. _strptime, locale, _locale and
+  calendar have to be added.
+
+- modules used very often in the testsuite: copy, cPickle, operator.
diff --git a/PVER-minimal.overrides.in b/PVER-minimal.overrides.in
new file mode 100644 (file)
index 0000000..f63083b
--- /dev/null
@@ -0,0 +1 @@
+@PVER@-minimal binary: command-with-path-in-maintainer-script
diff --git a/PVER-minimal.postinst.in b/PVER-minimal.postinst.in
new file mode 100644 (file)
index 0000000..6cc4a1a
--- /dev/null
@@ -0,0 +1,87 @@
+#! /bin/sh
+
+set -e
+
+if [ ! -f /etc/@PVER@/sitecustomize.py ]; then
+    cat <<-EOF
+       # Empty sitecustomize.py to avoid a dangling symlink
+EOF
+fi
+
+case "$1" in
+    configure)
+        # Create empty directories in /usr/local
+        if [ -e /etc/staff-group-for-usr-local ]; then
+            perm=2775; group=staff
+        else
+            perm=775; group=root
+        fi
+        if [ ! -e /usr/local/lib/@PVER@ ]; then
+            mkdir -p /usr/local/lib/@PVER@ 2> /dev/null || true
+            chmod $perm /usr/local/lib/@PVER@ 2> /dev/null || true
+            chown root:$group /usr/local/lib/@PVER@ 2> /dev/null || true
+        fi
+       localsite=/usr/local/lib/@PVER@/dist-packages
+        if [ ! -e $localsite ]; then
+            mkdir -p $localsite 2> /dev/null || true
+            chmod $perm $localsite 2> /dev/null || true
+            chown root:$group $localsite 2> /dev/null || true
+        fi
+
+       if which update-binfmts >/dev/null; then
+           update-binfmts --import @PVER@
+       fi
+
+    ;;
+esac
+
+if [ "$1" = configure ]; then
+
+    # only available before removal of the packaging package
+    rm -f /etc/@PVER@/sysconfig.cfg
+
+    if ls -L /usr/lib/@PVER@/sitecustomize.py >/dev/null 2>&1; then
+       filt='cat'
+    else
+       filt='fgrep -v sitecustomize.py'
+    fi
+    files=$(dpkg -L lib@PVER@-minimal@HOST_QUAL@ \
+               | sed -n '/^\/usr\/lib\/@PVER@\/.*\.py$/p' | $filt)
+    if [ -n "$files" ]; then
+       /usr/bin/@PVER@ -E -S /usr/lib/@PVER@/py_compile.py $files
+       if grep -sq '^byte-compile[^#]*optimize' /etc/python/debian_config; then
+           /usr/bin/@PVER@ -E -S -O /usr/lib/@PVER@/py_compile.py $files
+       fi
+    else
+       echo >&2 "@PVER@-minimal: can't get files for byte-compilation"
+    fi
+    bc=no
+    #if [ -z "$2" ] || dpkg --compare-versions "$2" lt 2.5-3 \
+    #    || [ -f /var/lib/python/@PVER@_installed ]; then
+    #  bc=yes
+    #fi
+    if ! grep -sq '^supported-versions[^#]*@PVER@' /usr/share/python/debian_defaults
+    then
+       # FIXME: byte compile anyway?
+       bc=no
+    fi
+    if [ "$bc" = yes ]; then
+       # new installation or installation of first version with hook support
+       if [ "$DEBIAN_FRONTEND" != noninteractive ]; then
+           echo "Linking and byte-compiling packages for runtime @PVER@..."
+       fi
+       version=$(dpkg -s @PVER@-minimal | awk '/^Version:/ {print $2}')
+       for hook in /usr/share/python3/runtime.d/*.rtinstall; do
+           [ -x $hook ] || continue
+           $hook rtinstall @PVER@ "$2" "$version"
+       done
+       if [ -f /var/lib/python/@PVER@_installed ]; then
+           rm -f /var/lib/python/@PVER@_installed
+           rmdir --ignore-fail-on-non-empty /var/lib/python 2>/dev/null
+       fi
+    fi
+fi
+
+#DEBHELPER#
+
+exit 0
diff --git a/PVER-minimal.postrm.in b/PVER-minimal.postrm.in
new file mode 100644 (file)
index 0000000..3f73f54
--- /dev/null
@@ -0,0 +1,13 @@
+#! /bin/sh
+
+set -e
+
+if [ "$1" = "remove" ]; then
+
+    if [ -f /var/lib/python/@PVER@_installed ]; then
+       rm -f /var/lib/python/@PVER@_installed
+       rmdir --ignore-fail-on-non-empty /var/lib/python 2>/dev/null
+    fi
+
+    rmdir --parents /usr/local/lib/@PVER@ 2>/dev/null || true
+fi
diff --git a/PVER-minimal.preinst.in b/PVER-minimal.preinst.in
new file mode 100644 (file)
index 0000000..382e099
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+set -e
+
+case "$1" in
+    install)
+       # remember newly installed runtime
+       mkdir -p /var/lib/python
+       touch /var/lib/python/@PVER@_installed
+    ;;
+    upgrade)
+       :
+    ;;
+
+    abort-upgrade)
+    ;;
+
+    *)
+        echo "preinst called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+#DEBHELPER#
+
+exit 0
diff --git a/PVER-minimal.prerm.in b/PVER-minimal.prerm.in
new file mode 100644 (file)
index 0000000..77c962b
--- /dev/null
@@ -0,0 +1,36 @@
+#! /bin/sh
+
+set -e
+
+case "$1" in
+    remove)
+       if [ "$DEBIAN_FRONTEND" != noninteractive ]; then
+           echo "Unlinking and removing bytecode for runtime @PVER@"
+       fi
+       for hook in /usr/share/python3/runtime.d/*.rtremove; do
+           [ -x $hook ] || continue
+           $hook rtremove @PVER@ || continue
+       done
+
+       if which update-binfmts >/dev/null; then
+           update-binfmts --package @PVER@ --remove @PVER@ /usr/bin/@PVER@
+       fi
+
+       localsite=/usr/local/lib/@PVER@/dist-packages
+       [ -d $localsite ] && rmdir $localsite 2>/dev/null || true
+       [ -d $(dirname $localsite) ] \
+           && rmdir $(dirname $localsite) 2>/dev/null || true
+        ;;
+    upgrade)
+        ;;
+    deconfigure)
+        ;;
+    failed-upgrade)
+        ;;
+    *)
+        echo "prerm called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+#DEBHELPER#
diff --git a/PVER-venv.overrides.in b/PVER-venv.overrides.in
new file mode 100644 (file)
index 0000000..df5377c
--- /dev/null
@@ -0,0 +1 @@
+@PVER@-venv binary: command-with-path-in-maintainer-script
diff --git a/PVER-venv.postinst.in b/PVER-venv.postinst.in
new file mode 100644 (file)
index 0000000..a830485
--- /dev/null
@@ -0,0 +1,20 @@
+#! /bin/sh
+
+set -e
+
+case "$1" in
+    configure)
+    files=$(dpkg -L @PVER@-venv | sed -n '/^\/usr\/lib\/@PVER@\/.*\.py$/p')
+    if [ -n "$files" ]; then
+       /usr/bin/@PVER@ -E -S /usr/lib/@PVER@/py_compile.py $files
+       if grep -sq '^byte-compile[^#]*optimize' /etc/python/debian_config; then
+           /usr/bin/@PVER@ -E -S -O /usr/lib/@PVER@/py_compile.py $files
+       fi
+    else
+       echo >&2 "@PVER@: can't get files for byte-compilation"
+    fi
+esac
+
+#DEBHELPER#
+
+exit 0
diff --git a/PVER-venv.postrm.in b/PVER-venv.postrm.in
new file mode 100644 (file)
index 0000000..ed12298
--- /dev/null
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+set -e
+
+if [ "$1" = "purge" ]; then
+    rm -rf /usr/lib/python-wheels
+    rm -rf /var/lib/python-wheels
+fi
+
+#DEBHELPER#
+
+exit 0
diff --git a/PVER-venv.prerm.in b/PVER-venv.prerm.in
new file mode 100644 (file)
index 0000000..9d864f0
--- /dev/null
@@ -0,0 +1,35 @@
+#! /bin/sh
+
+set -e
+
+remove_bytecode()
+{
+    pkg=$1
+    max=$(LANG=C LC_ALL=C xargs --show-limits < /dev/null 2>&1 | awk '/Maximum length/ {print int($NF / 4)}')
+    dpkg -L $pkg \
+       | awk -F/ 'BEGIN {OFS="/"} /\.py$/ {$NF=sprintf("__pycache__/%s.*.py[co]", substr($NF,1,length($NF)-3)); print}' \
+       | xargs --max-chars="$max" echo \
+       | while read files; do rm -f $files; done
+
+    find /usr/lib/@PVER@/ensurepip \
+       -name __pycache__ -type d -empty -print \
+       | xargs -r rm -rf
+}
+
+case "$1" in
+    remove)
+       remove_bytecode @PVER@-venv
+        ;;
+    upgrade)
+        ;;
+    deconfigure)
+        ;;
+    failed-upgrade)
+        ;;
+    *)
+        echo "prerm called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+#DEBHELPER#
diff --git a/PVER.desktop.in b/PVER.desktop.in
new file mode 100644 (file)
index 0000000..0f954c9
--- /dev/null
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Name=Python (v@VER@)
+Comment=Python Interpreter (v@VER@)
+Exec=/usr/bin/@PVER@
+Icon=/usr/share/pixmaps/@PVER@.xpm
+Terminal=true
+Type=Application
+Categories=Development;
+StartupNotify=true
+NoDisplay=true
diff --git a/PVER.overrides.in b/PVER.overrides.in
new file mode 100644 (file)
index 0000000..9400c8c
--- /dev/null
@@ -0,0 +1,10 @@
+# yes, we have to
+@PVER@ binary: depends-on-python-minimal
+
+@PVER@ binary: desktop-command-not-in-package
+@PVER@ binary: menu-command-not-in-package
+
+# no, not useless
+@PVER@ binary: manpage-has-useless-whatis-entry
+
+@PVER@ binary: command-with-path-in-maintainer-script
diff --git a/PVER.postinst.in b/PVER.postinst.in
new file mode 100644 (file)
index 0000000..073bfb8
--- /dev/null
@@ -0,0 +1,20 @@
+#! /bin/sh
+
+set -e
+
+case "$1" in
+    configure)
+    files=$(dpkg -L lib@PVER@-stdlib@HOST_QUAL@ | sed -n '/^\/usr\/lib\/@PVER@\/.*\.py$/p')
+    if [ -n "$files" ]; then
+       /usr/bin/@PVER@ -E -S /usr/lib/@PVER@/py_compile.py $files
+       if grep -sq '^byte-compile[^#]*optimize' /etc/python/debian_config; then
+           /usr/bin/@PVER@ -E -S -O /usr/lib/@PVER@/py_compile.py $files
+       fi
+    else
+       echo >&2 "@PVER@: can't get files for byte-compilation"
+    fi
+esac
+
+#DEBHELPER#
+
+exit 0
diff --git a/PVER.prerm.in b/PVER.prerm.in
new file mode 100644 (file)
index 0000000..0e7e5c5
--- /dev/null
@@ -0,0 +1,31 @@
+#! /bin/sh
+
+set -e
+
+remove_bytecode()
+{
+    pkg=$1
+    max=$(LANG=C LC_ALL=C xargs --show-limits < /dev/null 2>&1 | awk '/Maximum length/ {print int($NF / 4)}')
+    dpkg -L $pkg \
+       | awk -F/ 'BEGIN {OFS="/"} /\.py$/ {$NF=sprintf("__pycache__/%s.*.py[co]", substr($NF,1,length($NF)-3)); print}' \
+       | xargs --max-chars="$max" echo \
+       | while read files; do rm -f $files; done
+    find /usr/lib/python3 /usr/lib/@PVER@ -name dist-packages -prune -o -name __pycache__ -empty -print \
+       | xargs -r rm -rf
+}
+
+case "$1" in
+    remove|upgrade)
+       remove_bytecode lib@PVER@-stdlib@HOST_QUAL@
+        ;;
+    deconfigure)
+        ;;
+    failed-upgrade)
+        ;;
+    *)
+        echo "prerm called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+#DEBHELPER#
diff --git a/README.Debian.in b/README.Debian.in
new file mode 100644 (file)
index 0000000..20138c1
--- /dev/null
@@ -0,0 +1,8 @@
+The documentation for this package is in /usr/share/doc/@PVER@/.
+
+A draft of the "Debian Python Policy" can be found in
+
+        /usr/share/doc/python
+
+Sometime it will be moved to /usr/share/doc/debian-policy in the
+debian-policy package.
diff --git a/README.PVER.in b/README.PVER.in
new file mode 100644 (file)
index 0000000..a6a03cf
--- /dev/null
@@ -0,0 +1,95 @@
+
+  Python @VER@ for Debian
+  ---------------------
+
+This is Python @VER@ packaged for Debian.
+
+This document contains information specific to the Debian packages of
+Python @VER@.
+
+
+
+   [TODO: This document is not yet up-to-date with the packages.]
+
+Currently, it features those two main topics:
+
+  1. Release notes for the Debian packages:
+  2. Notes for developers using the Debian Python packages:
+
+Release notes and documentation from the upstream package are installed
+in /usr/share/doc/@PVER@/.
+
+There's a mailing list for discussion of issues related to Python on Debian
+systems: debian-python@lists.debian.org. The list is not intended for
+general Python problems, but as a forum for maintainers of Python-related
+packages and interested third parties.
+
+
+
+1. Release notes for the Debian packages:
+
+
+Results of the regression test:
+------------------------------
+
+The package does successfully run the regression tests for all included
+modules. Seven packages are skipped since they are platform-dependent and
+can't be used with Linux.
+
+
+2. Notes for developers using the Debian python packages:
+
+See the draft of the Debian Python policy in /usr/share/doc/python.
+
+distutils can be found in the @PVER@-dev package. Development files
+like the python library or Makefiles can be found in the @PVER@-dev
+package in /usr/lib/@PVER@/config. Therefore, if you need to install 
+a pure python extension, you only need @PVER@. On the other hand, to 
+install a C extension, you need @PVER@-dev.
+
+a) Locally installed Python add-ons
+
+    /usr/local/lib/@PVER@/site-packages/
+    /usr/local/lib/site-python/ (version-independent modules)
+
+b) Python add-ons packaged for Debian
+
+    /usr/lib/@PVER@/site-packages/
+    /usr/lib/site-python/ (version-independent modules)
+
+Note that no package must install files directly into /usr/lib/@PVER@/
+or /usr/local/lib/@PVER@/. Only the site-packages directory is allowed
+for third-party extensions.
+
+Use of the new `package' scheme is strongly encouraged. The `ni' interface
+is obsolete in python 1.5.
+
+Header files for extensions go into /usr/include/@PVER@/.
+
+
+Installing extensions for local use only:
+----------------------------------------
+
+Consider using distutils ...
+
+Most extensions use Python's Makefile.pre.in. Note that Makefile.pre.in
+by default will install files into /usr/lib/, not into /usr/local/lib/,
+which is not allowed for local extensions. You'll have to change the
+Makefile accordingly. Most times, "make prefix=/usr/local install" will
+work.
+
+
+Packaging python extensions for Debian:
+--------------------------------------
+
+Maintainers of Python extension packages should read
+
+       /usr/share/doc/python/python-policy.txt.gz
+
+
+
+    03/09/98
+    Gregor Hoffleit <flight@debian.org>
+
+Last change: 2001-12-14
diff --git a/README.Tk b/README.Tk
new file mode 100644 (file)
index 0000000..7067ecb
--- /dev/null
+++ b/README.Tk
@@ -0,0 +1,8 @@
+Tkinter documentation can be found at
+
+    http://www.pythonware.com/library/index.htm
+
+more specific:
+
+    http://www.pythonware.com/library/tkinter/introduction/index.htm
+    http://www.pythonware.com/library/tkinter/an-introduction-to-tkinter.pdf
diff --git a/README.dbm b/README.dbm
new file mode 100644 (file)
index 0000000..3c5e2bc
--- /dev/null
@@ -0,0 +1,72 @@
+
+ Python and dbm modules on Debian
+ --------------------------------
+
+This file documents the configuration of the dbm modules for Debian. It
+gives hints at the preferred use of the dbm modules.
+
+
+The preferred way to access dbm databases in Python is the anydbm module.
+dbm databases behave like mappings (dictionaries).
+
+Since there exist several dbm database formats, we choose the following
+layout for Python on Debian:
+
+  * creating a new database with anydbm will create a Berkeley DB 2.X Hash
+    database file. This is the standard format used by libdb starting
+    with glibc 2.1.
+
+  * opening an existing database with anydbm will try to guess the format
+    of the file (using whichdb) and then load it using one of the bsddb,
+    bsddb1, gdbm or dbm (only if the python-gdbm package is installed)
+    or dumbdbm modules.
+
+  * The modules use the following database formats:
+
+    - bsddb:   Berkeley DB 2.X Hash (as in libc6 >=2.1 or libdb2)
+    - bsddb1:  Berkeley DB 1.85 Hash (as in libc6 >=2.1 or libdb2)
+    - gdbm:    GNU dbm 1.x or ndbm
+    - dbm:     " (nearly the same as the gdbm module for us)
+    - dumbdbm: a hand-crafted format only used in this module
+
+    That means that all usual formats should be readable with anydbm.
+
+  * If you want to create a database in a format different from DB 2.X,
+    you can still directly use the specified module.
+
+  * I.e. bsddb is the preferred module, and DB 2.X is the preferred format.
+
+  * Note that the db1hash and bsddb1 modules are Debian specific. anydbm
+    and whichdb have been modified to support DB 2.X Hash files (see
+    below for details).
+    
+
+
+For experts only:
+----------------
+
+Although bsddb employs the new DB 2.X format and uses the new Sleepycat
+DB 2 library as included with glibc >= 2.1, it's still using the old
+DB 1.85 API (which is still supported by DB 2).
+
+A more recent version 1.1 of the BSD DB module (available from
+http://starship.skyport.net/robind/python/) directly uses the DB 2.X API.
+It has a richer set of features.
+
+
+On a glibc 2.1 system, bsddb is linked with -ldb, bsddb1 is linked with
+-ldb1 and gdbm as well as dbm are linked with -lgdbm.
+
+On a glibc 2.0 system (e.g. potato for m68k or slink), bsddb will be
+linked with -ldb2 while bsddb1 will be linked with -ldb (therefore
+python-base here depends on libdb2).
+
+
+db1hash and bsddb1 nearly completely identical to dbhash and bsddb. The
+only difference is that bsddb is linked with the real DB 2 library, while
+bsddb1 is linked with an library which provides compatibility with legacy
+DB 1.85 databases.
+
+
+    July 16, 1999
+    Gregor Hoffleit <flight@debian.org>
diff --git a/README.idle-PVER.in b/README.idle-PVER.in
new file mode 100644 (file)
index 0000000..6705049
--- /dev/null
@@ -0,0 +1,14 @@
+
+  The Python IDLE package for Debian
+  ----------------------------------
+
+This package contains Python @VER@'s Integrated DeveLopment Environment, IDLE.
+
+IDLE is included in the Python @VER@ upstream distribution (Tools/idle) and
+depends on Tkinter (available as @PVER@-tk package).
+
+I have written a simple man page.
+
+
+    06/16/1999
+    Gregor Hoffleit <flight@debian.org>
diff --git a/README.maintainers.in b/README.maintainers.in
new file mode 100644 (file)
index 0000000..c0b0cab
--- /dev/null
@@ -0,0 +1,88 @@
+
+Hints for maintainers of Debian packages of Python extensions
+-------------------------------------------------------------
+
+Most of the content of this README can be found in the Debian Python policy.
+See /usr/share/doc/python/python-policy.txt.gz.
+
+Documentation Tools
+-------------------
+
+If your package ships documentation produced in the Python
+documentation format, you can generate it at build-time by
+build-depending on @PVER@-dev, and you will find the
+templates, tools and scripts in /usr/lib/@PVER@/doc/tools --
+adjust your build scripts accordingly.
+
+
+Makefile.pre.in issues
+----------------------
+
+Python comes with a `universal Unix Makefile for Python extensions' in
+/usr/lib/@PVER@/config/Makefile.pre.in (with Debian, this is included
+in the python-dev package), which is used by most Python extensions.
+
+In general, packages using the Makefile.pre.in approach can be packaged
+simply by running dh_make or by using one of debhelper's rules' templates
+(see /usr/doc/debhelper/examples/). Makefile.pre.in works fine with e.g.
+"make prefix=debian/tmp/usr install".
+
+One glitch: You may be running into the problem that Makefile.pre.in
+doesn't try to create all the directories when they don't exist. Therefore,
+you may have to create them manually before "make install". In most cases,
+the following should work:
+
+       ...
+       dh_installdirs /usr/lib/@PVER@
+       $(MAKE) prefix=debian/tmp/usr install
+       ...
+
+
+Byte-compilation
+----------------
+
+For speed reasons, Python internally compiles source files into a byte-code.
+To speed up subsequent imports, it tries to save the byte-code along with
+the source with an extension .pyc (resp. pyo). This will fail if the
+libraries are installed in a non-writable directory, which may be the
+case for /usr/lib/@PVER@/.
+
+Not that .pyc and .pyo files should not be relocated, since for debugging
+purposes the path of the source for is hard-coded into them.
+
+To precompile files in batches after installation, Python has a script
+compileall.py, which compiles all files in a given directory tree. The
+Debian version of compileall has been enhanced to support incremental
+compilation and to feature a ddir (destination dir) option. ddir is
+used to compile files in debian/usr/lib/python/ when they will be
+installed into /usr/lib/python/.
+
+
+Currently, there are two ways to use compileall for Debian packages. The
+first has a speed penalty, the second has a space penalty in the package.
+
+1.) Compiling and removing .pyc files in postinst/prerm:
+
+  Use dh_python(1) from the debhelper packages to add commands to byte-
+  compile on installation and to remove the byte-compiled files on removal.
+  Your package has to build-depend on: debhelper (>= 4.1.67), python.
+
+  In /usr/share/doc/@PVER@, you'll find sample.postinst and sample.prerm.
+  If you set the directory where the .py files are installed, these
+  scripts will install and remove the .pyc and .pyo files for your
+  package after unpacking resp. before removing the package.
+
+2.) Compiling the .pyc files `out of place' during installation:
+
+  As of 1.5.1, compileall.py allows you to specify a faked installation
+  directory using the "-d destdir" option, so that you can precompile
+  the files in their temporary directory
+  (e.g. debian/tmp/usr/lib/python2.1/site-packages/PACKAGE).
+
+
+
+    11/02/98                             
+    Gregor Hoffleit <flight@debian.org>
+
+
+Last modified: 2007-10-14
diff --git a/README.python b/README.python
new file mode 100644 (file)
index 0000000..5aacdf7
--- /dev/null
@@ -0,0 +1,153 @@
+
+  Python 2.x for Debian
+  ---------------------
+
+This is Python 2.x packaged for Debian.
+
+This document contains information specific to the Debian packages of
+Python 2.x.
+
+
+
+   [TODO: This document is not yet up-to-date with the packages.]
+
+
+
+
+
+
+Currently, it features those two main topics:
+
+  1. Release notes for the Debian packages:
+  2. Notes for developers using the Debian Python packages:
+
+Release notes and documentation from the upstream package are installed
+in /usr/share/doc/python/.
+
+Up-to-date information regarding Python on Debian systems is also
+available as http://www.debian.org/~flight/python/.
+
+There's a mailing list for discussion of issues related to Python on Debian
+systems: debian-python@lists.debian.org. The list is not intended for
+general Python problems, but as a forum for maintainers of Python-related
+packages and interested third parties.
+
+
+
+1. Release notes for the Debian packages:
+
+
+Results of the regression test:
+------------------------------
+
+The package does successfully run the regression tests for all included
+modules. Seven packages are skipped since they are platform-dependent and
+can't be used with Linux.
+
+
+Noteworthy changes since the 1.4 packages:
+-----------------------------------------
+
+- Threading support enabled.
+- Tkinter for Tcl/Tk 8.x.
+- New package python-zlib.
+- The dbmmodule was dropped. Use bsddb instead. gdbmmodule is provided
+  for compatibility's sake.
+- python-elisp adheres to the new emacs add-on policy; it now depends
+  on emacsen. python-elisp probably won't work correctly with emacs19.
+  Refer to /usr/doc/python-elisp/ for more information.
+- Remember that 1.5 has dropped the `ni' interface in favor of a generic
+  `packages' concept.
+- Python 1.5 regression test as additional package python-regrtest. You
+  don't need to install this package unless you don't trust the
+  maintainer ;-).
+- once again, modified upstream's compileall.py and py_compile.py.
+  Now they support compilation of optimized byte-code (.pyo) for use
+  with "python -O", removal of .pyc and .pyo files where the .py source
+  files are missing (-d) and finally the fake of a installation directory
+  when .py files have to be compiled out of place for later installation
+  in a different directory (-i destdir, used in ./debian/rules).
+- The Debian packages for python 1.4 do call 
+  /usr/lib/python1.4/compileall.py in their postrm script. Therefore
+  I had to provide a link from /usr/lib/python1.5/compileall.py, otherwise
+  the old packages won't be removed completely. THIS IS A SILLY HACK!
+
+
+
+2. Notes for developers using the Debian python packages:
+
+
+Embedding python:
+----------------
+
+The files for embedding python resp. extending the python interpreter
+are included in the python-dev package. With the configuration in the
+Debian GNU/Linux packages of python 1.5, you will want to use something
+like
+
+    -I/usr/include/python1.5                  (e.g. for config.h)
+    -L/usr/lib/python1.5/config -lpython1.5   (... -lpthread)
+                           (also for Makefile.pre.in, Setup etc.)
+
+Makefile.pre.in automatically gets that right.  Note that unlike 1.4,
+python 1.5 has only one library, libpython1.5.a.
+
+Currently, there's no shared version of libpython. Future version of
+the Debian python packages will support this.
+
+
+Python extension packages:
+-------------------------
+
+According to www.python.org/doc/essays/packages.html, extension packages
+should only install into /usr/lib/python1.5/site-packages/ (resp.
+/usr/lib/site-python/ for packages that are definitely version independent).
+No extension package should install files directly into /usr/lib/python1.5/.
+
+But according to the FSSTND, only Debian packages are allowed to use
+/usr/lib/python1.5/. Therefore Debian Python additionally by default
+searches a second hierarchy in /usr/local/lib/. These directories take
+precedence over their equivalents in /usr/lib/.
+
+a) Locally installed Python add-ons
+
+    /usr/local/lib/python1.5/site-packages/
+    /usr/local/lib/site-python/ (version-independent modules)
+
+b) Python add-ons packaged for Debian
+
+    /usr/lib/python1.5/site-packages/
+    /usr/lib/site-python/ (version-independent modules)
+
+Note that no package must install files directly into /usr/lib/python1.5/
+or /usr/local/lib/python1.5/. Only the site-packages directory is allowed
+for third-party extensions.
+
+Use of the new `package' scheme is strongly encouraged. The `ni' interface
+is obsolete in python 1.5.
+
+Header files for extensions go into /usr/include/python1.5/.
+
+
+Installing extensions for local use only:
+----------------------------------------
+
+Most extensions use Python's Makefile.pre.in. Note that Makefile.pre.in
+by default will install files into /usr/lib/, not into /usr/local/lib/,
+which is not allowed for local extensions. You'll have to change the
+Makefile accordingly. Most times, "make prefix=/usr/local install" will
+work.
+
+
+Packaging python extensions for Debian:
+--------------------------------------
+
+Maintainers of Python extension packages should read README.maintainers.
+
+
+
+    03/09/98
+    Gregor Hoffleit <flight@debian.org>
+
+Last change: 07/16/1999
diff --git a/README.source b/README.source
new file mode 100644 (file)
index 0000000..f31e27c
--- /dev/null
@@ -0,0 +1,7 @@
+The source tarball is lacking the files Lib/profile.py and Lib/pstats.py,
+which Debian considers to have a license non-suitable for main (the use
+of these modules limited to python).
+
+The package uses quilt to apply / unapply patches.
+See /usr/share/doc/quilt/README.source.  The series file is generated
+during the build.
diff --git a/README.venv b/README.venv
new file mode 100644 (file)
index 0000000..9711ee1
--- /dev/null
@@ -0,0 +1,230 @@
+=========================================
+ pyvenv support in Python 3.4 and beyond
+=========================================
+
+In Python 3.3, built-in support for virtual environments (venvs) was added via
+the `pyvenv`_ command.  For building venvs using Python 3, this is
+functionally equivalent to the standalone `virtualenv`_ tool, except that
+before Python 3.4, the pyvenv created venv didn't include pip and setuptools.
+
+In Python 3.4, this was made even more convenient by the `automatic
+inclusion`_ of the `pip`_ command into the venv so that third party libraries
+can be easily installed from the Python Package Index (PyPI_).  The stdlib
+module `ensurepip`_ is run when the `pyvenv-3.4` command is run to create the
+venv.
+
+This poses a problem for Debian.  ensurepip comes bundled with two third party
+libraries, setuptools and pip itself, as these are requirements for pip to
+function properly in the venv.  These are bundled in the ensurepip module of
+the upstream Python 3.4 tarball as `universal wheels`_, essentially a zip of
+the source code and a new ``dist-info`` metadata directory.  Upstream pip
+itself comes bundled with a half dozen or so of *its* dependencies, except
+that these are "vendorized", meaning their unpacked source code lives within
+the pip module, under a submodule from which pip imports them rather than the
+top-level package namespace.
+
+To make matters worse, one of pip's vendorized dependencies, the `requests`_
+module, *also* vendorizes a bunch of its own dependencies.  This stack of
+vendorized and bundled third party libraries fundamentally violates the DFSG
+and Debian policy against including code not built from source available
+within Debian, and for including embedded "convenience" copies of code in
+other packages.
+
+It's worth noting that the virtualenv package actually suffers from the same
+conflict, but its current solution in Debian is `incomplete`_.
+
+
+Solving the conflict
+====================
+
+This conflict between Debian policy and upstream Python convenience must be
+resolved, because pyvenv is the recommended way of creating venvs in Python 3,
+and because at some point, the standalone virtualenv tool will be rewritten as
+a thin layer above pyvenv.  Obviously, we want to provide the best Python
+virtual environment experience to our developers, adherent to Debian policy.
+
+The approach we've taken is layered and nuanced, so I'll provide a significant
+amount of detail to explain both what we do and why.
+
+The first thing to notice is how upstream ensurepip works to have its pip and
+setuptools dependencies available, both at venv creation time and when
+``<venv>/bin/pip`` is run.  When pyvenv-3.4 runs, it ends up calling the
+following Python command::
+
+    <venv>/bin/python -Im ensurepip --upgrade
+
+This runs the ensurepip's ``__main__.py`` module using the venv's Python in
+isolation mode, with a switch to upgrade the setuptools and pip dependencies
+(if for example, they've been updated in a new micro version of Python).
+
+Internally, ensurepip bootstraps itself by byte-copying its embedded wheels
+into a temporary directory, putting those copied wheels on ``sys.path``, and
+then calling into pip as a library.  Because wheels are just elaborate zips,
+Python can execute (pure-Python) code directly from them, if they are on
+``sys.path`` of course.  Once ensurepip has set up its execution environment,
+it calls into pip to install both pip and setuptools into the newly created
+venv.  If you poke inside the venv after successful creation, you'll see
+unpacked pip and setuptools directories in the venv's ``site-packages`
+directory.
+
+The important thing to note here is that ensurepip is *already* able to import
+from and install wheels, and because wheels are self-contained single files
+(of zipped content), it makes manipulating them quite easy.  In order to
+minimize the delta from upstream (and to eventually work with upstream to
+eliminate this delta), it seems optimal that Debian's solution should also be
+based on wheels, and re-use as much of the existing machinery as possible.
+
+The difference for Debian though is that we don't want to use the embedded pip
+and setuptools wheels from upstream Python's ensurepip; we want to use wheels
+created from the pip and setuptools *Debian* packages.  This would solve the
+problem of distributing binary packages not built from source in Debian.
+
+Thus, we modify the python-pip and python-setuptools packages to include new
+binary packages ``python-pip-whl`` and ``python-setuptools-whl` which contain
+*only* the relevant universal wheels.  Those packages ``debian/rules`` files
+gain an extra command::
+
+    python3 setup.py bdist_wheel --universal -d <path>
+
+The ``bdist_wheel`` command is provided by the `wheel`_ package, which as of
+this writing is newly available in Jessie.
+
+Note that the name of the binary packages, and other details of when and how
+wheels may be used in Debian, is described in `Debian Python Policy`_ 0.9.6 or
+newer.
+
+The universal wheels (i.e. pure-Python code compatible with both Python 2 and
+Python 3) are built for pip and setuptools and installed into
+``/usr/share/python-wheels`` when the python-{pip,setuptols}-whl packages are
+installed.  These are not needed for normal, usual, and typical operation of
+Python, so none of these are installed by default.
+
+However, this isn't enough, because since the pip and setuptools wheels are
+built from the *patched* and de-vendorized versions of the code in Debian, the
+wheels will not contain their own recursive dependencies.  That's a good thing
+for Debian policy compliance, but does add complications to the stack of hack.
+
+Using the same approach as for pip and setuptools, we *also* wheelify their
+dependencies, recursively.  As of this writing, the list of packages needing
+to be wheelified are (by Debian source package name):
+
+ * chardet
+ * distlib
+ * html5lib
+ * python-colorama
+ * python-pip
+ * python-setuptools
+ * python-urllib3
+ * requests
+ * six
+
+Most of these are DPMT maintained.  six, distlib, and colorama are not team
+maintained, so coordination with those maintainers is required.  Also note
+that the `bdist_wheel` command is a setuptools extension, so since some of
+those projects use ``distutils.core.setup()`` by default, they must be patched
+to use ``setuptools.setup()`` instead.  This isn't a problem because there's
+no functional difference relevant to those packages; they likely use
+distutils.core to avoid a third party dependency on setuptools.
+
+Each of these Debian source packages grow an additional binary package, just
+like pip and setuptools, e.g. python-chardet-whl which contains the universal
+wheel for that package built from patched Debian source.  As above, when
+installed, these binary packages drop their .whl files into the
+``/usr/share/python-wheels`` directory.
+
+Now comes the fun part.
+
+In the python3.4 source package, we add a new binary package called
+python3.4-venv.  This will only contain the ``/usr/bin/pyvenv-3.4``
+executable, and its associated manpage.  It also includes all the run-time
+dependencies to make pyvenv work *including the wheel packages described
+above*.
+
+(Technically speaking, you should substitute "Python 3.4 or later" for all
+these discussions, and e.g. pyvenv-3.x for all versions subsequent to 3.4.)
+
+Python's ensurepip module has been modified in the following ways (see
+``debian/patches/ensurepip.diff``):
+
+ * When ensurepip is run outside of a venv as root, it raises an exception.
+   This use case is only to be supported by the separate python{,3}-pip
+   packages.
+
+ * When ensurepip is run inside of a venv, it copies all dependent wheels from
+   ``/usr/share/python-wheels``.  This includes the direct dependencies pip
+   and setuptools, as well as the recursive dependencies listed above.  The
+   rest of the ensurepip machinery is unchanged: the wheels are still copied
+   into a temporary directory and placed on ``sys.path``, however only the
+   direct dependencies (i.e. pip and setuptools) are *installed* into the
+   venv's ``site-packages`` directory.  The indirect dependencies are copied
+   to ``<venv>/lib/python-wheels`` since they'll be needed by the venv's pip
+   executable.
+
+Why do we do this latter rather than also installing the recursive
+dependencies into the venv's ``site-packages``?  It's because pip requires a
+very specific set of dependencies and we don't want pip to break when the user
+upgrades or downgrades one of those packages, which is perfectly valid in a
+venv.  It's exactly the same reason why pip vendorizes those libraries in the
+first place; it's just that we're doing it in a more principled way (from the
+point of view of the Debian distribution).
+
+The final piece of the puzzle is that Debian's pip will, when run inside of a
+venv, introspect ``<venv>/lib/python-wheels`` and put every .whl file it sees
+there *at the front of its sys.path*.  Again, this is so that when pip runs,
+it will find the versions of packages known to be good first, rather than any
+other versions in the venv's ``site-packages``.
+
+As an example of the bad things that can happen if you don't do this, try
+installing nose2_ into the venv, followed by genshi_.  nose2 has a hard
+requirement on a version of six that is older than the one used by pip
+(indirectly).  This older version of six is compatible with genshi, but *not*
+with pip, so once nose2 is installed, if pip didn't load its version of six
+from the private wheel, the installation attempt of genshi would traceback.
+As it is, with the wheels early enough on ``sys.path``, pip itself works just
+fine so that both nose2 and genshi can live together in the venv.
+
+
+Updating packages
+=================
+
+Inevitably, new versions of Python or the pyvenv dependent packages will
+appear.  Unfortunately, as currently implemented (by both upstream ensurepip
+and in our ensurepip patch), the versions of both the direct and indirect
+dependencies are hardcoded in ``Lib/ensurepip/__init__.py``.  When a Debian
+developer updates any of the dependent packages, you will need to:
+
+ * *Test that the new version is compatible with ensurepip*.
+
+ * Update the version numbers in the ``debian/control`` file, for the
+   python3.x-venv binary package.
+
+ * ``quilt push`` to the ensurepip patch, and update the version number in
+   ``Lib/ensurepip/__init__.py``
+
+Then rebuild and upload python3.4.
+
+Yes, this isn't ideal, and I am working with upstream to find a good solution
+that we can share.
+
+
+Author
+======
+
+Barry A. Warsaw <barry@debian.org>
+2014-05-15
+
+
+
+.. _pyvenv: http://legacy.python.org/dev/peps/pep-0405/
+.. _virtualenv: https://pypi.python.org/pypi/virtualenv
+.. _`automatic inclusion`: http://legacy.python.org/dev/peps/pep-0453/
+.. _pip: https://pypi.python.org/pypi/pip
+.. _PyPI: https://pypi.python.org/pypi
+.. _ensurepip: https://docs.python.org/3/library/ensurepip.html
+.. _`universal wheels`: http://legacy.python.org/dev/peps/pep-0427/
+.. _requests: https://pypi.python.org/pypi/requests
+.. _incomplete: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=719767
+.. _wheel: https://pypi.python.org/pypi/wheel
+.. _nose2: https://pypi.python.org/pypi/nose2
+.. _genshi: https://pypi.python.org/pypi/Genshi
+.. _`Debian Python Policy`: https://www.debian.org/doc/packaging-manuals/python-policy/
diff --git a/changelog b/changelog
new file mode 100644 (file)
index 0000000..0a074e0
--- /dev/null
+++ b/changelog
@@ -0,0 +1,4417 @@
+python3.9 (3.9.1-4) unstable; urgency=medium
+
+  * Update to the 3.9 branch 2021-02-04.
+  * Fix issue #43030, compiler warning in Py_UNICODE_ISSPACE with
+    signed wchar_t. Closes: #961396.
+  * Depend on media-types instead of mime-support. Closes: #981016.
+  * Fix permissions and group for local directories. Closes: #962422.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 05 Feb 2021 14:46:56 +0100
+
+python3.9 (3.9.1-3) unstable; urgency=medium
+
+  * Update to the 3.9 branch 2021-01-20.
+  * Configure again --with-system-libmpdec.
+  * Update symbols files.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 20 Jan 2021 15:49:22 +0100
+
+python3.9 (3.9.1-2) unstable; urgency=medium
+
+  * Update to the 3.9 branch 2021-01-10.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 10 Jan 2021 16:42:50 +0100
+
+python3.9 (3.9.1-1) unstable; urgency=medium
+
+  * Python 3.9.1 release.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 08 Dec 2020 08:51:42 +0100
+
+python3.9 (3.9.1~rc1-2) unstable; urgency=medium
+
+  * Don't expect the test_ttk_textonly test to pass.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 27 Nov 2020 20:38:39 +0100
+
+python3.9 (3.9.1~rc1-1) unstable; urgency=medium
+
+  * Python 3.9.1 release candidate 1.
+  * libpython3.9-stdlib: Depend on tzdata, recommend ca-certificates.
+  * libpython3.9-stdlib: Depend on media-types | mime-support instead of
+    mime-support.
+  * Update VCS attributes.
+  * Add python3-tk test dependency for the failing-tests* autopkg tests.
+  * Bump standards version.
+  * Add build conflict with git, or else the git information of the packaging
+    is encoded in the upstream version information.
+  * Build with -fno-inline-small-functions on hppa and sh4.
+    Closes: #972458, #972202.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 27 Nov 2020 09:20:22 +0100
+
+python3.9 (3.9.0-5) unstable; urgency=medium
+
+  * Update to the 3.9 branch 2020-10-19.
+  * python3.9-venv: Depend on python3-distutils.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 19 Oct 2020 11:51:18 +0200
+
+python3.9 (3.9.0-4) unstable; urgency=medium
+
+  * Fix module-install-venv autopkg test dependency.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 18 Oct 2020 11:42:38 +0200
+
+python3.9 (3.9.0-3) unstable; urgency=high
+
+  * Update to the 3.9 branch 2020-10-16.
+  * ensurepip: Don't try to import the _bundled module.
+  * Refresh patches.
+  * Add some autopkg tests for venv (Stefano Rivera).
+
+ -- Matthias Klose <doko@debian.org>  Fri, 16 Oct 2020 19:57:59 +0200
+
+python3.9 (3.9.0-2) unstable; urgency=medium
+
+  * Update to the 3.9 branch 2020-10-15.
+  * Build with -O1 on sh4 (Adrian Glaubitz). Closes: #972202.
+  * Don't run test_ttk_guionly test, timing on many buildds.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 15 Oct 2020 13:54:52 +0200
+
+python3.9 (3.9.0-1) unstable; urgency=medium
+
+  * Python 3.9.0 release.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 05 Oct 2020 22:56:51 +0200
+
+python3.9 (3.9.0~rc2-1) unstable; urgency=medium
+
+  * Python 3.9.0 release candidate 2.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 17 Sep 2020 12:40:00 +0200
+
+python3.9 (3.9.0~rc1-1) unstable; urgency=medium
+
+  * Python 3.9.0 release candidate 1.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 12 Aug 2020 12:42:16 +0200
+
+python3.9 (3.9.0~b5-2) unstable; urgency=medium
+
+  * Move typing.py into libpython3.9-minimal.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 23 Jul 2020 11:11:14 +0200
+
+python3.9 (3.9.0~b5-1) unstable; urgency=medium
+
+  * Python 3.9.0 beta 5.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 22 Jul 2020 11:03:53 +0200
+
+python3.9 (3.9.0~b4-2) unstable; urgency=medium
+
+  * Fix symbols file on i386.
+  * Don't run test_concurrent_futures on riscv64, takes ages.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 16 Jul 2020 13:24:24 +0200
+
+python3.9 (3.9.0~b4-1) unstable; urgency=medium
+
+  * Python 3.9.0 beta 4.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 06 Jul 2020 15:22:12 +0200
+
+python3.8 (3.8.4~rc1-1) unstable; urgency=medium
+
+  * Python 3.8.4 release candidate 1.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 01 Jul 2020 17:31:45 +0200
+
+python3.8 (3.8.3-1) unstable; urgency=medium
+
+  * Python 3.8.3 release.
+  * Add XB-Cnf-Visible-Pkgname header on the python*-minimal package to
+    point command-not-found at the full one. LP: #1867157
+
+ -- Matthias Klose <doko@debian.org>  Thu, 14 May 2020 13:03:12 +0200
+
+python3.8 (3.8.3~rc1-1) unstable; urgency=medium
+
+  * Python 3.8.3 release candidate 1.
+    - Issue #38576, CVE-2019-18348: Disallow control characters in hostnames
+      in http.client.
+    - Issue #39503, CVE-2020-8492: Denial of service in
+      urllib.request.AbstractBasicAuthHandler.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 30 Apr 2020 09:33:30 +0200
+
+python3.8 (3.8.2-1) unstable; urgency=medium
+
+  * Python 3.8.2 release.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 25 Feb 2020 14:04:52 +0100
+
+python3.8 (3.8.2~rc2-2) unstable; urgency=medium
+
+  * Ignore some autopkg test failures:
+    - test_ssl: Fails with OPENSSL_TLS_SECURITY_LEVEL=2.
+    - test_io: Fails on Ubuntu's autopkg test infrastructure.
+    - Lower OpenSSL security level from 2 to 1 during testing as test_ssl
+      assumes that (Dimitri John Ledkov).
+
+ -- Matthias Klose <doko@debian.org>  Fri, 21 Feb 2020 12:37:41 +0100
+
+python3.8 (3.8.2~rc2-1) unstable; urgency=medium
+
+  * Python 3.8.2 release candidate 2.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 18 Feb 2020 11:16:50 +0100
+
+python3.8 (3.8.2~rc1-1) unstable; urgency=medium
+
+  * Python 3.8.2 release candidate 1.
+  * Make autopkgtests cross-test-friendly (Steve Langasek).
+  * Bump standards version.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 11 Feb 2020 16:26:48 +0100
+
+python3.8 (3.8.1-2) unstable; urgency=medium
+
+  * Fix KFreeBSD builds (James Cowgill).
+
+ -- Matthias Klose <doko@debian.org>  Mon, 06 Jan 2020 09:48:53 +0100
+
+python3.8 (3.8.1-1) unstable; urgency=medium
+
+  * Python 3.8.1 release.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 19 Dec 2019 10:21:09 +0100
+
+python3.8 (3.8.1~rc1-1) unstable; urgency=medium
+
+  * Python 3.8.1 release candidate 1.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 10 Dec 2019 10:38:12 +0100
+
+python3.8 (3.8.0-5) unstable; urgency=medium
+
+  * Update to 20191123 from the 3.8 branch.
+  * libpython3.8-dbg: Provide a python-$(VER)-dbg-embed.pc pkg-config file.
+    Closes: #944852.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 23 Nov 2019 05:55:55 +0100
+
+python3.8 (3.8.0-4) unstable; urgency=medium
+
+  * Move the test/ann_module{,2,3} modules into libpython-stdlib.
+    Closes: #944303.
+  * Annote python-examples dependency on python.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 07 Nov 2019 16:14:28 +0100
+
+python3.8 (3.8.0-3) unstable; urgency=medium
+
+  * python3.8-dev: Depend on zlib1g-dev, needed to link as an
+    embedded interpreter.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 27 Oct 2019 17:36:55 +0200
+
+python3.8 (3.8.0-2) unstable; urgency=medium
+
+  * Fix a symlink to the shared debug library.
+  * Install the python3.8d-embed pkg-config file.
+  * Don't ship the python3-embed pkg-config file.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 20 Oct 2019 18:00:25 +0200
+
+python3.8 (3.8.0-1) unstable; urgency=medium
+
+  * Python 3.8.0 release.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 15 Oct 2019 11:10:20 +0200
+
+python3.8 (3.8.0~rc1-3) unstable; urgency=medium
+
+  * Apply proposed patch for issue 38368. LP: #1847036. Addresses: #941650.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 09 Oct 2019 11:06:01 +0200
+
+python3.8 (3.8.0~rc1-2) unstable; urgency=medium
+
+  * Python 3.8.0 release candidate 1.
+  * Refresh patches.
+  * Update symbols files.
+  * Bump standards version.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 02 Oct 2019 05:45:03 +0200
+
+python3.8 (3.8.0~b4-1) unstable; urgency=medium
+
+  * Python 3.8.0 beta 4 release.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 31 Aug 2019 16:07:24 +0200
+
+python3.8 (3.8.0~b3-1) unstable; urgency=medium
+
+  * Python 3.8.0 beta 3 release.
+  * Fix FTCBFS: (Helmut Grohne). Closes: #932077.
+    + Build-Depends, when cross compiling we need python3.8.
+    + Export CC, because dtrace needs it.
+    + Honour DEB_BUILD_OPTIONS=nocheck more thoroughly.
+    + Fix up sysconfigdata-name.diff.
+  * Implement the native thread ids for the Hurd and KFreeBSD (Samuel
+    Thibault). Closes: #931624.
+  * Enable pgo/lto builds on arm64. Addresses: #934812.
+  * Update symbols files.
+  * Don't propagate lto flags to the _sysconfigdata module. Addresses: #934771.
+  * d/patches/issue35998.diff: Disable TLS1.3 in the client on all platforms
+    rather than just reducing the payload size (Michael Hudson-Doyle).
+
+ -- Matthias Klose <doko@debian.org>  Wed, 21 Aug 2019 17:32:52 +0200
+
+python3.8 (3.8.0~b2-5) unstable; urgency=high
+
+  * Bump standards version.
+  * Revert the KFreeBSD and Hurd fix for PyThread_get_thread_native_id,
+    and use the implementation from Python3.7.  Mark the symbol as linux only.
+  * Don't encode the MACHDEP into the _sysconfigdata file name.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 11 Jul 2019 11:55:03 +0200
+
+python3.8 (3.8.0~b2-4) unstable; urgency=medium
+
+  * Fix the LTO build.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 07 Jul 2019 14:23:41 +0200
+
+python3.8 (3.8.0~b2-3) unstable; urgency=medium
+
+  * Define PY_HAVE_THREAD_NATIVE_ID for KFreeBSD and Hurd builds.
+  * Fix issue #37504, building the texinfo docs (Dmitry Shachnev).
+  * Enable LTO/PGO builds on some architectures.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 06 Jul 2019 12:00:08 +0200
+
+python3.8 (3.8.0~b2-1) experimental; urgency=medium
+
+  * Python 3.8.0 beta 2 release.
+  * Refresh patches.
+  * Update the symbols files.
+  * Don't build the texinfo documentation, fails. See issue #37504.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 05 Jul 2019 11:20:35 +0200
+
+python3.8 (3.8.0~b1-2) experimental; urgency=medium
+
+  * Fix include links in python3.8-dbg.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 17 Jun 2019 11:41:06 +0200
+
+python3.8 (3.8.0~b1-1) experimental; urgency=medium
+
+  * Python 3.8.0 beta 1 release.
+  * Refresh patches.
+  * Add new importlib dependencies to python3-minimal.
+  * Update symbols files.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 05 Jun 2019 11:23:02 +0200
+
+python3.8 (3.8.0~a4-3) experimental; urgency=medium
+
+  * Update symbols files.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 15 May 2019 00:30:25 +0200
+
+python3.8 (3.8.0~a4-2) experimental; urgency=medium
+
+  * Update to 20190514 from the trunk.
+  * Fix interpreter name in the -dbg autopkg tests.
+  * Enable dtrace/USDT probe support (--with-dtrace) and build-dep on
+    systemtap-sdt-dev (Trent Lloyd). LP: #1818778.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 14 May 2019 15:45:29 +0200
+
+python3.8 (3.8.0~a4-1) experimental; urgency=medium
+
+  * Python 3.8.0 alpha 4 release.
+  * Upstream removed the "m" modifier, directory names now don't have the
+    "m" encoded anymore in file and directory names.
+  * Refresh patches.
+  * Update symbols files.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 07 May 2019 20:35:18 +0200
+
+python3.8 (3.8.0~a3-2) experimental; urgency=medium
+
+  * d/p/arm-alignment.diff: Don't allow unaligned memory accesses in the
+    _sha3 extension (Dave Jones). LP: #1821869. Issue #36515.
+  * Tweak the asyncio/ssl test again.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 03 Apr 2019 09:37:42 +0200
+
+python3.8 (3.8.0~a3-1) experimental; urgency=medium
+
+  * Python 3.8.0 alpha 3 release.
+  * Work around issue #35988, reducing the payload size for the asyncio/ssl
+    tests.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 26 Mar 2019 10:17:13 +0100
+
+python3.8 (3.8.0~a2-1ubuntu1) disco; urgency=medium
+
+  * Update to 20190314 from the trunk.
+  * Use a build profile for libbluetooth-dev (<!pkg.python3.8.nobluetooth>).
+
+ -- Matthias Klose <doko@debian.org>  Thu, 14 Mar 2019 16:06:36 +0100
+
+python3.8 (3.8.0~a2-1) experimental; urgency=medium
+
+  * Python 3.8.0 alpha 2 release.
+  * Update symbols files and refresh patches.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 14 Mar 2019 10:20:00 +0100
+
+python3.8 (3.8.0~a1-1) experimental; urgency=medium
+
+  * Python 3.8.0 alpha 1 release.
+  * Update VCS attributes.
+  * Refresh patches.
+  * Update symbols files.
+  * Fix some lintian warnings.
+  * Add pathlib to the set of the minimal modules.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 06 Feb 2019 16:07:30 +0100
+
+python3.7 (3.7.1-1) unstable; urgency=medium
+
+  * Python 3.7.1 release.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 21 Oct 2018 10:03:53 +0200
+
+python3.7 (3.7.1~rc2-1) unstable; urgency=medium
+
+  * Python 3.7.1 release candidate 2.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 15 Oct 2018 11:24:12 +0200
+
+python3.7 (3.7.1~rc1-1) unstable; urgency=medium
+
+  * Python 3.7.1 release candidate 1.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 27 Sep 2018 11:41:42 +0200
+
+python3.7 (3.7.0-7) unstable; urgency=medium
+
+  * Update to 20180925 from the 3.7 branch.
+  * Don't run OpenSSL related tests during the build. Hanging on
+    some buildds.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 25 Sep 2018 16:01:24 +0200
+
+python3.7 (3.7.0-6) unstable; urgency=medium
+
+  * Update to 20180901 from the 3.7 branch.
+    - Fixes the build with OpenSSL 1.1.1. Closes: #907031.
+  * Don't run the test_ftplib and test_ssl autopkg tests, not yet ready
+    for OpenSSL 1.1.1.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 01 Sep 2018 01:21:37 +0200
+
+python3.7 (3.7.0-5) unstable; urgency=medium
+
+  * Update to 20180820 from the 3.7 branch.
+  * Avoid usage of distutils in the platform module. See issue #26544.
+  * Fix some issues on architectures from the computer museum (Jason Duerstock).
+    Closes: #905536.
+    - Disable -O3 on ia64 (see PR rtl-optimization/85412).
+    - Remove the -O2 override on m68k (see Debian #326903).
+    - Remove the -mieee and -O2 overrides for DEC Alpha (see Debian #212912).
+  * Add more breaks for packages not compatible with Python 3.7:
+    - python3-aiomeasures. See #906159.
+    - python3-motor (updated). See #903527.
+  * Again close the RC issue about the syntax errors triggered by Python 3.7.
+    Closes: #902788.
+  * Update symbols files.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 20 Aug 2018 19:52:20 +0200
+
+python3.7 (3.7.0-4) unstable; urgency=medium
+
+  * Update to 20180802 from the 3.7 branch.
+  * Add more breaks for packages not compatible with Python 3.7:
+    - python3-pyatspi. See #902989.
+  * Move test/__main__.py into libpython3.7-stdlib.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 02 Aug 2018 08:46:56 +0200
+
+python3.7 (3.7.0-3) unstable; urgency=medium
+
+  * Update to 20180730 from the 3.7 branch.
+  * Add more breaks for packages not compatible with Python 3.7:
+    - python3-trollius. See #903888.
+    - python3-sleekxmpp. See #904453.
+    - voltron. See #904657.
+    - visidata. See #904656.
+    - salt-common. See #903654.
+    - python3-yowsup. See #904653.
+    - python3-websockets. See #904650.
+    - python3-txfixtures. See #904649.
+    - python3-tweepy. See #904648.
+    - python3-slixmpp. See #904644.
+    - python3-signaller. See #904642.
+    - python3-rpyc. See #904615.
+    - python3-protorpc-standalone. See #904603.
+    - python3-nova. See #904587.
+    - python3-murano. See #904581.
+    - python3-mastodon. See #904579.
+    - python3-hug. See #904576.
+    - python3-async. See #904492.
+    - python3-pylama. See #904491.
+    - python3-exabgp. See #904390.
+    - python3-glance. See #904389.
+    - python3-gbulb. See #904388.
+    - python3-engineio. See #904383.
+    - python3-doublex. See #904382.
+    - python3-dns. See #904381.
+    - python3-opcua. See #904373.
+    - openscap-daemon. See #904.
+    - oca-core. See #904370.
+    - patroni. See #904369.
+    - python3-panoramisk. See #904368.
+    - linux-show-player-. See #904367.
+    - python3-cs. See #904365.
+    - python3-azure. See #904364.
+    - python3-applicationinsights. See #904363.
+    - python3-aiopg. See #904361.
+    - python3-aiozmq. See #904358.
+    - python3-pysnmp4. See #904357.
+    - python3-astroquery. See #904351.
+    - snakemake. See #904350.
+    - fail2ban. See #902817.
+    - python3-morse-simulator. See #904343.
+    - python3-tango. See #904298.
+    - python3-pycuda. See #903826.
+    - python3-pycsw. See #903784.
+    - gnome3-builder. See #903558.
+  * Close the RC issue about the syntax errors triggered by Python 3.7, now
+    that all the breaks are in place. Closes: #902788.
+  * Mark the lib2to3 and site tests as succeeding again, mark the tcl test
+    as failing (issue #34178).
+
+ -- Matthias Klose <doko@debian.org>  Mon, 30 Jul 2018 06:39:20 +0200
+
+python3.7 (3.7.0-2) unstable; urgency=medium
+
+  * Update to 20180720 from the 3.7 branch.
+  * Add breaks for packages not compatible with Python 3.7:
+    - python3-twisted. See #902766.
+    - python3-pexpect. See #902646.
+    - python3-cxx-dev. See #902673.
+    - libboost-python1.62.0. See #902702.
+    - python3-psycopg2. See #902715.
+    - python3-maxminddb. See #902756.
+    - python3-blist. See #902757.
+    - python3-django. See #902761.
+    - diffoscope. See #902650.
+    - gpodder. See #902704.
+    - python3-http-parser. See: #902759.
+    - python3-celery. See #902900.
+    - python3-astroid. See #902631.
+    - python3-ubjson. See #902762.
+    - python3-protobuf. See #902597.
+    - python3-opengl. See #903218.
+    - python3-ws4py. See #903529.
+    - python3-dropbox. See #903525.
+    - python3-pycuda. See #903826.
+    - python3-libcloud. See #903388.
+    - python3-motor. See #903527.
+    - python3-jira. See #903526.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 20 Jul 2018 15:51:14 +0200
+
+python3.7 (3.7.0-1~18.04) bionic-proposed; urgency=medium
+
+  * SRU: LP: #1792140. Update Python 3.7 to the final 3.7.0 release.
+
+ -- Matthias Klose <doko@ubuntu.com>  Wed, 12 Sep 2018 20:30:08 +0200
+
+python3.7 (3.7.0-1) unstable; urgency=medium
+
+  * Python 3.7.0 release.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 27 Jun 2018 16:40:03 +0200
+
+python3.7 (3.7.0~rc1-3) unstable; urgency=medium
+
+  * Update to 20180622 from the 3.7 branch.
+    - Fix installation of the idlelib tests.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 22 Jun 2018 10:11:22 +0200
+
+python3.7 (3.7.0~rc1-2) unstable; urgency=medium
+
+  * Update to 20180619 from the 3.7 branch.
+  * Let ensurepip work with pip versions 9 or 10. Addresses: #901797.
+  * pdb(1): Fix pointer to HTML documentation. Addresses: #901603.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 19 Jun 2018 09:10:27 +0200
+
+python3.7 (3.7.0~rc1-1) unstable; urgency=medium
+
+  * Python 3.7.0 release candidate 1.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 13 Jun 2018 10:04:13 +0200
+
+python3.7 (3.7.0~b5-1) unstable; urgency=medium
+
+  * Python 3.7.0 beta 5 release.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 31 May 2018 12:14:46 +0200
+
+python3.7 (3.7.0~b4-5) unstable; urgency=medium
+
+  * Update to 20180529 from the 3.7 branch.
+  * sysconfig: The 'posix_local' schema name is the default unless the env var
+    DEB_PYTHON_INSTALL_LAYOUT is set to 'deb' or 'deb_system'.  Use the latter
+    for package buillds.
+
+ -- Matthias Klose <doko@ubuntu.com>  Tue, 29 May 2018 13:54:38 +0200
+
+python3.7 (3.7.0~b4-4) unstable; urgency=medium
+
+  * Update to 20180516 from the 3.7 branch.
+  * Fix building cmath and build cmath as a builtin instead of an extension.
+  * Run the test_code_module, test_dbm, test_zipfile tests in the autopkg
+    tests again.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 16 May 2018 16:51:00 -0400
+
+python3.7 (3.7.0~b4-3) unstable; urgency=medium
+
+  * python3.7: Add breaks on python3-all (<< 3.6.5~rc1-1),
+    python3-dev (<< 3.6.5~rc1-1), python3-venv (<< 3.6.5-2). Addresses: #898401.
+  * Restore the sysconfig-debian-schemes patch.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 11 May 2018 11:18:40 -0400
+
+python3.7 (3.7.0~b4-2) unstable; urgency=medium
+
+  * Fix the lto build for extensions, passing -fPIC to the linker.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 07 May 2018 19:24:57 +0200
+
+python3.7 (3.7.0~b4-1) unstable; urgency=medium
+
+  * Python 3.7.0 beta 4 release.
+  * Fix library name in python debug pkgconfig file. Addresses: #894498.
+  * Re-enable pgo/lto builds.
+  * Update autopkg tests to really run with 3.7.
+  * Make the build of the shared modules verbose again.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 03 May 2018 13:45:04 +0200
+
+python3.7 (3.7.0~b3-1) unstable; urgency=medium
+
+  * Python 3.7.0 beta 3 release.
+  * libpython3.7-stdlib: Add missing python3-distutils breaks. Closes: #894204.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 30 Mar 2018 12:35:22 +0800
+
+python3.7 (3.7.0~b2-2) unstable; urgency=medium
+
+  * libpython3.7-stdlib: Ship again distutils/{__init__,version}.py.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 23 Mar 2018 11:21:34 +0800
+
+python3.7 (3.7.0~b2-1) unstable; urgency=medium
+
+  * Python 3.7.0 beta 2 release.
+    - Fix issue #32185: The SSL module no longer sends IP addresses in SNI TLS
+      extension on platforms with OpenSSL 1.0.2+ or inet_pton. See #892814.
+  * Add support for riscv64 (Aurelien Jarno). Addresses: #892328.
+  * Update symbols files.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 13 Mar 2018 20:55:14 +0100
+
+python3.7 (3.7.0~b1-1) unstable; urgency=medium
+
+  * Python 3.7.0 beta 1 release.
+  * Update symbols files.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 01 Feb 2018 08:36:28 +0100
+
+python3.7 (3.7.0~a4-1) unstable; urgency=medium
+
+  * Python 3.7.0 alpha 4 release.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 10 Jan 2018 13:34:16 +0100
+
+python3.7 (3.7.0~a3-4) unstable; urgency=medium
+
+  * Stop building python3.7-2to3, now replaced by 2to3 and python3-lib2to3.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 05 Jan 2018 03:45:13 +0100
+
+python3.7 (3.7.0~a3-3) unstable; urgency=medium
+
+  * Stop shipping lib2to3, now shipped in python3-lib2to3.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 27 Dec 2017 14:04:53 +0100
+
+python3.7 (3.7.0~a3-2) unstable; urgency=medium
+
+  * Split out a python3.7-2to3 package.
+  * Stop shipping the tkinter and distutils modules in libpython3.7-stdlib.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 13 Dec 2017 12:18:54 +0100
+
+python3.7 (3.7.0~a3-1) unstable; urgency=medium
+
+  * Python 3.7.0 alpha 3 release.
+  * Add support for mipsr6 triplets (YunQiang Su). Addresses: #881942.
+  * Move the idle library into the idle-python3.7 package.
+  * Build documentation in info format (Benjamin Moody). Addresses: #881959.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 06 Dec 2017 13:24:25 +0100
+
+python3.7 (3.7.0~a2-1) experimental; urgency=medium
+
+  * Python 3.7.0 alpha 2 release.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 18 Oct 2017 20:58:26 +0200
+
+python3.7 (3.7.0~a1-2) experimental; urgency=medium
+
+  * Build with -fstack-protector instead of -fstack-protector-strong.
+    Performance improvements of around 1-2% according to LP #1638695.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 20 Sep 2017 14:12:51 +0200
+
+python3.7 (3.7.0~a1-1) experimental; urgency=medium
+
+  * Python 3.7.0 alpha 1 release.
+  * Explicitly use the system python for byte compilation in postinst scripts.
+    Addresses: #852163. LP: #1682934.
+  * Build using -fexceptions on ppc64 and ppc64el.
+    Addresses: #862925. LP: #1691848.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 20 Sep 2017 14:12:51 +0200
+
+python3.7 (3.7-20170522-1) experimental; urgency=medium
+
+  * Python 3.7 snapshot 20170522.
+
+ -- Matthias Klose <doko@ubuntu.com>  Mon, 22 May 2017 14:32:31 -0700
+
+python3.6 (3.6.0~b4-1) experimental; urgency=medium
+
+  * Python 3.6.0 beta 4.
+  * Update symbols files.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 22 Nov 2016 14:41:03 +0100
+
+python3.6 (3.6.0~b3-1) experimental; urgency=medium
+
+  * Python 3.6.0 beta 3.
+  * Update symbols files.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 02 Nov 2016 14:33:32 +0200
+
+python3.6 (3.6.0~b2-1) experimental; urgency=medium
+
+  * Python 3.6.0 beta 2.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 11 Oct 2016 07:27:10 +0200
+
+python3.6 (3.6.0~b1-1) experimental; urgency=medium
+
+  * Python 3.6.0 beta 1.
+  * Don't build the fpectl module on hppa. Addresses: #837314.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 13 Sep 2016 13:59:11 +0200
+
+python3.6 (3.6.0~a4-1) experimental; urgency=medium
+
+  * Python 3.6.0 alpha 4.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 16 Aug 2016 08:29:13 +0200
+
+python3.6 (3.6.0~a3-1) experimental; urgency=medium
+
+  * Python 3.6.0 alpha 3.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 25 Jul 2016 11:12:59 +0200
+
+python3.6 (3.6.0~a2-1) experimental; urgency=medium
+
+  * Python 3.6.0 alpha 2.
+  * Update to 20160614 from the trunk.
+  * Update symbols files.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 14 Jun 2016 13:36:38 +0200
+
+python3.6 (3.6.0~a1-1) experimental; urgency=medium
+
+  * Python 3.6.0 alpha 1.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 18 May 2016 10:11:08 +0200
+
+python3.5 (3.5.1-12) unstable; urgency=medium
+
+  * Update to 20160509 from the 3.5 branch.
+    - Issue #26811: gc.get_objects() no longer contains a broken tuple with
+      NULL pointer.
+    - Issue #20120: Use RawConfigParser for .pypirc parsing, removing support
+      for interpolation unintentionally added with move to Python 3. Behavior
+      no longer does any interpolation in .pypirc files, matching behavior in
+      Python 2.7 and Setuptools 19.0.
+    - Issue #25745: Fixed leaking a userptr in curses panel destructor.
+    - Issue #26881: The modulefinder module now supports extended opcode
+      arguments.
+    - Issue #23815: Fixed crashes related to directly created instances of
+      types in _tkinter and curses.panel modules.
+    - Issue #17765: weakref.ref() no longer silently ignores keyword arguments.
+    - Issue #26873: xmlrpc now raises ResponseError on unsupported type tags
+      instead of silently return incorrect result.
+    - Issue #26881: modulefinder now works with bytecode with extended args.
+    - Issue #26711: Fixed the comparison of plistlib.Data with other types.
+    - Issue #24114: Fix an uninitialized variable in `ctypes.util`.
+    - Issue #26864: In urllib.request, change the proxy bypass host checking
+      against no_proxy to be case-insensitive, and to not match unrelated host
+      names that happen to have a bypassed hostname as a suffix.
+    - Issue #26634: recursive_repr() now sets __qualname__ of wrapper.
+    - Issue #26804: urllib.request will prefer lower_case proxy environment
+      variables over UPPER_CASE or Mixed_Case ones.
+    - Issue #26837: assertSequenceEqual() now correctly outputs non-stringified
+      differing items (like bytes in the -b mode).
+      This affects assertListEqual() and assertTupleEqual().
+    - Issue #26041: Remove "will be removed in Python 3.7" from deprecation
+      messages of platform.dist() and platform.linux_distribution().
+    - Issue #26822: itemgetter, attrgetter and methodcaller objects no longer
+      silently ignore keyword arguments.
+    - Issue #26733: Disassembling a class now disassembles class and static
+      methods.
+    - Issue #26801: Fix error handling in :func:`shutil.get_terminal_size`,
+      catch :exc:`AttributeError` instead of :exc:`NameError`.
+    - Issue #24838: tarfile's ustar and gnu formats now correctly calculate name
+      and link field limits for multibyte character encodings like utf-8.
+    - Issue #26657: Fix directory traversal vulnerability with http.server on
+      Windows.
+    - Issue #26736: Used HTTPS for external links in the documentation if
+      possible.
+    - Issue #22359: Disable the rules for running _freeze_importlib and pgen
+      when cross-compiling.  The output of these programs is normally saved
+      with the source code anyway, and is still regenerated when doing a
+      native build. Closes: #820509.
+    - Issue #21668: Link audioop, _datetime, _ctypes_test modules to libm.
+    - Issue #26799: Fix python-gdb.py: don't get C types once when the Python
+      code is loaded, but get C types on demand. The C types can change if
+      python-gdb.py is loaded before the Python executable.
+  * Fix issue #26673, runtime error in idle3. LP: #1574892.
+  * Update symbols files.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 09 May 2016 13:00:17 +0200
+
+python3.5 (3.5.1-11) unstable; urgency=medium
+
+  * Update to 20160330 from the 3.5 branch.
+    - Issue #26659: Make the builtin slice type support cycle collection.
+    - Issue #26718: super.__init__ no longer leaks memory if called multiple
+      times.  NOTE: A direct call of super.__init__ is not endorsed!
+    - Issue #25339: PYTHONIOENCODING now has priority over locale in setting
+      the error handler for stdin and stdout.
+    - Issue #26717: Stop encoding Latin-1-ized WSGI paths with UTF-8.
+    - Issue #26735: Fix :func:`os.urandom` on Solaris 11.3 and newer when
+      reading more than 1,024 bytes: call ``getrandom()`` multiple times with
+      a limit of 1024 bytes per call.
+    - Issue #16329: Add .webm to mimetypes.types_map.
+    - Issue #13952: Add .csv to mimetypes.types_map.
+    - Issue #26709: Fixed Y2038 problem in loading binary PLists.
+    - Issue #23735: Handle terminal resizing with Readline 6.3+ by installing
+      our own SIGWINCH handler.
+    - Issue #26586: In http.server, respond with "413 Request header fields too
+      large" if there are too many header fields to parse, rather than killing
+      the connection and raising an unhandled exception.
+    - Issue #22854: Change BufferedReader.writable() and
+      BufferedWriter.readable() to always return False.
+    - Issue #6953: Rework the Readline module documentation to group related
+      functions together, and add more details such as what underlying Readline
+      functions and variables are accessed.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 17 Apr 2016 18:14:06 +0200
+
+python3.5 (3.5.1-10) unstable; urgency=medium
+
+  * Update to 20160330 from the 3.5 branch.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 31 Mar 2016 00:46:26 +0200
+
+python3.5 (3.5.1-9) unstable; urgency=medium
+
+  * Update to 20160323 from the 3.5 branch.
+  * Always build _math.o with -fPIC.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 23 Mar 2016 11:47:21 +0100
+
+python3.5 (3.5.1-8) unstable; urgency=medium
+
+  * Update to 20160318 from the 3.5 branch.
+  * Fix python3-venv with updated python-pip packages (Barry Warsaw).
+    Closes: #815014, #815864.
+  * Fix generating devhelp documentation (Simon McVittie).
+    Closes: #816299. LP: #1553633.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 18 Mar 2016 16:12:19 +0100
+
+python3.5 (3.5.1-7) unstable; urgency=medium
+
+  * Update to 20160224 from the 3.5 branch.
+  * python3.5-venv: Drop the dependency on python-setuptools-whl,
+    depend on python-pip-whl (>= 8.0.2-7).
+  * Don't run the test_socket test, hangs on some buildds.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 24 Feb 2016 12:28:57 +0100
+
+python3.5 (3.5.1-6) unstable; urgency=medium
+
+  * Update to 20160221 from the 3.5 branch.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 22 Feb 2016 00:11:32 +0100
+
+python3.5 (3.5.1-5) unstable; urgency=medium
+
+  * Update to 20160113 from the 3.5 branch.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 13 Jan 2016 16:09:18 +0100
+
+python3.5 (3.5.1-4) unstable; urgency=medium
+
+  * Update to 20160111 from the 3.5 branch.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 11 Jan 2016 21:50:55 +0100
+
+python3.5 (3.5.1-3) unstable; urgency=medium
+
+  * Update to 20160105 from the 3.5 branch.
+  * Fix maintainer scripts with findutils 4.6. Closes: #809079.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 05 Jan 2016 12:13:30 +0100
+
+python3.5 (3.5.1-2) unstable; urgency=medium
+
+  * Disable LTO on Debian/s390x.
+  * Don't run test_signal on alpha, currently breaks the testsuite.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 10 Dec 2015 15:34:41 +0100
+
+python3.5 (3.5.1-1) unstable; urgency=medium
+
+  * Python 3.5.1 release.
+  * Fix building architecture independent packages only. Closes: #806870.
+  * Update symbols files for i386.
+  * d/p/fix-sslv3-test.diff: properly handle Ubuntu's openssl having OP_NO_SSLv3
+    forced on by default (Marc Deslauriers).
+
+ -- Matthias Klose <doko@debian.org>  Mon, 07 Dec 2015 11:34:52 +0100
+
+python3.5 (3.5.1~rc1-2) unstable; urgency=medium
+
+  * Build-depend on time.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 24 Nov 2015 08:26:06 +0100
+
+python3.5 (3.5.1~rc1-1) unstable; urgency=medium
+
+  * Python 3.5.1 release candidate 1.
+  * Don't ship menu files anymore, just desktop files.
+  * Update symbols file.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 23 Nov 2015 22:10:38 +0100
+
+python3.5 (3.5.0-4) unstable; urgency=medium
+
+  * Update to 20151028 from the 3.5 branch.
+    - Issue #25274: sys.setrecursionlimit() now raises a RecursionError if the
+      new recursion limit is too low depending at the current recursion depth.
+      Modify also the "lower-water mark" formula to make it monotonic. This mark
+      is used to decide when the overflowed flag of the thread state is reset.
+    - Issue #25447: The lru_cache() wrapper objects now can be copied and
+      pickled (by returning the original object unchanged).
+    - Issue #25390: typing: Don't crash on Union[str, Pattern].
+    - Issue #25441: asyncio: Raise error from drain() when socket is closed.
+    - Issue #25410: Cleaned up and fixed minor bugs in C implementation of
+      OrderedDict.
+    - Issue #25411: Improved Unicode support in SMTPHandler through better use
+      of the email package.
+    - Issue #25407: Remove mentions of the formatter module being removed in
+      Python 3.6.
+    - Issue #25406: Fixed a bug in C implementation of OrderedDict.move_to_end()
+      that caused segmentation fault or hang in iterating after moving several
+      items to the start of ordered dict.
+    - Issue #25380: Fixed protocol for the STACK_GLOBAL opcode in
+      pickletools.opcodes.
+    - Issue #25471: Sockets returned from accept() shouldn't appear to be
+      nonblocking.
+    - Issue #25440: Fix output of python-config --extension-suffix.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 28 Oct 2015 16:31:37 +0100
+
+python3.5 (3.5.0-3) unstable; urgency=medium
+
+  * Update to 20151011 from the 3.5 branch.
+    - Idle updates.
+    - Issue #24402: Fix input() to prompt to the redirected stdout when
+      sys.stdout.fileno() fails.
+    - Issue #24806: Prevent builtin types that are not allowed to be subclassed
+      from being subclassed through multiple inheritance.
+    - Issue #24848: Fixed a number of bugs in UTF-7 decoding of misformed data.
+    - Issue #25280: Import trace messages emitted in verbose (-v) mode are no
+      longer formatted twice.
+    - Issue #25003: On Solaris 11.3 or newer, os.urandom() now uses the
+      getrandom() function instead of the getentropy() function. The getentropy()
+      function is blocking to generate very good quality entropy, os.urandom()
+      doesn't need such high-quality entropy.
+    - Issue #25182: The stdprinter (used as sys.stderr before the io module is
+      imported at startup) now uses the backslashreplace error handler.
+    - Issue #25131: Make the line number and column offset of set/dict literals
+      and comprehensions correspond to the opening brace.
+    - Issue #25364: zipfile now works in threads disabled builds.
+    - Issue #25328: smtpd's SMTPChannel now correctly raises a ValueError if
+      both decode_data and enable_SMTPUTF8 are set to true.
+    - Issue #25316: distutils raises OSError instead of DistutilsPlatformError
+      when MSVC is not installed.
+    - Issue #23972: Updates asyncio datagram create method allowing reuseport
+      and reuseaddr socket options to be set prior to binding the socket.
+      Mirroring the existing asyncio create_server method the reuseaddr option
+      for datagram sockets defaults to True if the O/S is 'posix' (except if
+      the platform is Cygwin).
+    - Issue #25304: Add asyncio.run_coroutine_threadsafe().  This lets you
+      submit a coroutine to a loop from another thread, returning a
+      concurrent.futures.Future.
+    - Issue #25232: Fix CGIRequestHandler to split the query from the URL at the
+      first question mark (?) rather than the last.
+    - Issue #24657: Prevent CGIRequestHandler from collapsing slashes in the
+      query part of the URL as if it were a path.
+    - Issue #24483: C implementation of functools.lru_cache() now calculates
+      key's hash only once.
+    - Issue #22958: Constructor and update method of weakref.WeakValueDictionary
+      now accept the self and the dict keyword arguments.
+    - Issue #22609: Constructor of collections.UserDict now accepts the self
+      keyword argument.
+    - Issue #25111: Fixed comparison of traceback.FrameSummary.
+    - Issue #25262. Added support for BINBYTES8 opcode in Python implementation
+      of unpickler.
+    - Issue #25034: Fix string.Formatter problem with auto-numbering and
+      nested format_specs.
+    - Issue #25233: Rewrite the guts of asyncio.Queue and
+      asyncio.Semaphore to be more understandable and correct.
+    - Issue #25203: Failed readline.set_completer_delims() no longer left the
+      module in inconsistent state.
+    - Issue #23600: Default implementation of tzinfo.fromutc() was returning
+      wrong results in some cases.
+    - Issue #23329: Allow the ssl module to be built with older versions of
+      LibreSSL.
+    - Issue #25319: When threading.Event is reinitialized, the underlying
+      condition should use a regular lock rather than a recursive lock.
+    - Issue #25099: Make test_compileall not fail when a entry on sys.path
+      cannot be written to.
+    - Issue #23919: Prevents assert dialogs appearing in the test suite.
+  * Back-out the local patch for issue 21264, supposed to be fixed by #25099.
+  * Adjust setting DH_COMPAT for dh_movefiles with updated debhelper supporting
+    globbing of arguments. Closes: #800247.
+  * pydoc: use the pager command if available. Addresses: #799555.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 11 Oct 2015 11:05:38 +0200
+
+python3.5 (3.5.0-2) unstable; urgency=medium
+
+  * Update to 20150924 from the 3.5 branch.
+  * Expect the test_code_module test to fail in the autopkg tests.
+    See upstream issue #25109.
+  * Provide some user-friendly advice when `python3 -m venv` fails because the
+    python3-venv package is not installed (Barry Warsaw).
+
+ -- Matthias Klose <doko@debian.org>  Thu, 24 Sep 2015 01:01:34 +0200
+
+python3.5 (3.5.0-1) unstable; urgency=medium
+
+  * Python 3.5.0 release.
+  * Drop the no-zip-on-sys.path patch; not worth saving, and the test suite
+    needs adjustments ...
+  * Mark the test_site test as failing. Investigate why this fails.
+    The package has one sitedir less than expected.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 13 Sep 2015 16:38:26 +0200
+
+python3.5 (3.5.0~rc3-1) unstable; urgency=medium
+
+  * Python 3.5.0 release candidate 3.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 08 Sep 2015 09:56:15 +0200
+
+python3.5 (3.5.0~rc2-1) unstable; urgency=medium
+
+  * Python 3.5.0 release candidate 2.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 25 Aug 2015 22:29:07 +0200
+
+python3.5 (3.5.0~rc1-1) unstable; urgency=medium
+
+  * Python 3.5.0 release candidate 1.
+  * Update symbols file.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 12 Aug 2015 16:57:46 +0200
+
+python3.5 (3.5.0~b4-1) unstable; urgency=medium
+
+  * Python 3.5.0 beta 4.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 27 Jul 2015 12:27:48 +0200
+
+python3.5 (3.5.0~b3-2) unstable; urgency=medium
+
+  * Fix expansion of makefile macros for _sysconfigdata. Issue #24705.
+    LP: #1477759.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 24 Jul 2015 15:25:23 +0200
+
+python3.5 (3.5.0~b3-1) unstable; urgency=medium
+
+  * Python 3.5.0 beta 3.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 06 Jul 2015 13:55:07 +0200
+
+python3.5 (3.5.0~b2-1) unstable; urgency=medium
+
+  * Python 3.5.0 beta 2.
+  * Make the build reproducible (Jérémy Bobbio). Closes: #786959.
+    - Pass time of latest debian/changelog entry to sphinx via SPHINXOPTS.
+    - Do not store a timestamps when compressing devhelp.
+  * Pass DATE and TIME macros matching the current debian/changelog entry
+    when building getbuildinfo.o.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 01 Jun 2015 12:18:33 +0200
+
+python3.5 (3.5.0~b1-1ubuntu1) wily; urgency=medium
+
+  * Disable pgo optimization on i386.
+
+ -- Matthias Klose <doko@ubuntu.com>  Tue, 26 May 2015 23:30:38 +0200
+
+python3.5 (3.5.0~b1-1) unstable; urgency=medium
+
+  * Python 3.5.0 beta 1.
+  * Refresh patches.
+  * Update symbols files.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 26 May 2015 02:08:13 +0200
+
+python3.5 (3.5.0~a4-5) unstable; urgency=medium
+
+  * Update to 20150519 from the trunk.
+    - Fix issue #24226, parsing of many sequential one-line 'def' statements.
+  * Don't rename extensions when they already have the multiarch tag.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 19 May 2015 09:55:39 +0200
+
+python3.5 (3.5.0~a4-4) unstable; urgency=medium
+
+  * Update to 20150518 from the trunk.
+    - Fix build on big endian targets.
+  * Work around issue #24226, byte compilation of IN.py.
+  * Disable PGO (fails to build in unstable).
+
+ -- Matthias Klose <doko@debian.org>  Mon, 18 May 2015 13:48:38 +0200
+
+python3.5 (3.5.0~a4-3) unstable; urgency=medium
+
+  * Update to 20150517 from the trunk.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 17 May 2015 17:22:56 +0200
+
+python3.5 (3.5.0~a4-2) experimental; urgency=medium
+
+  * Update to 20150421 from the trunk.
+  * Fix renaming of extensions. Closes: #783090.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 22 Apr 2015 14:41:45 +0200
+
+python3.5 (3.5.0~a4-1) experimental; urgency=medium
+
+  * Python 3.5.0 alpha 4.
+  * Update to 20150420 from the trunk.
+  * Build debug builds with -Og.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 20 Apr 2015 20:59:53 +0200
+
+python3.5 (3.5.0~a3-1) experimental; urgency=medium
+
+  * Python 3.5.0 alpha 3.
+  * Update to 20150415 from the trunk.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 15 Apr 2015 21:43:00 +0200
+
+python3.4 (3.4.3-3) experimental; urgency=medium
+
+  * Update to 20150311 from the 3.4 branch.
+  * Relax the version check for mpdecimal (all required patches applied
+    in the distro version of mpdecimal 2.4.0).
+  * When using GCC versions older than 4.9 for extension builds, automagically
+    mangle -fstack-protector-strong to -fstack-protector.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 11 Apr 2015 20:50:40 +0200
+
+python3.4 (3.4.3-2) experimental; urgency=medium
+
+  * debian/tests: Use init system agnostic "service" command instead of
+    upstart specific "stop". Also drop unnecessary "status" call right after
+    stopping apport (Martin Pitt).
+
+ -- Matthias Klose <doko@debian.org>  Tue, 10 Mar 2015 20:28:20 +0100
+
+python3.4 (3.4.3-1) experimental; urgency=medium
+
+  * Python 3.4.3 release.
+  * Changes since 20141202 (3.4.2-4):
+    - Issue #22896: Avoid using PyObject_AsCharBuffer(),
+      PyObject_AsReadBuffer(), and PyObject_AsWriteBuffer().
+    - Issue #21295: Revert some changes (issue #16795) to AST line numbers and
+      column offsets that constituted a regression.
+    - Issue #21408: The default __ne__() now returns NotImplemented if __eq__()
+      returned NotImplemented.
+    - Issue #23321: Fixed a crash in str.decode() when error handler returned
+      replacment string longer than mailformed input data.
+    - Issue #23048: Fix jumping out of an infinite while loop in the pdb.
+    - Issue #23165: Perform overflow checks before allocating memory in the
+      _Py_char2wchar function.
+    - Issue #23099: Closing io.BytesIO with exported buffer is rejected now to
+      prevent corrupting exported buffer.
+    - Issue #23363: Fix possible overflow in itertools.permutations.
+    - Issue #23364: Fix possible overflow in itertools.product.
+    - Issue #23366: Fixed possible integer overflow in itertools.combinations.
+    - Issue #23369: Fixed possible integer overflow in
+      _json.encode_basestring_ascii.
+    - Issue #23353: Fix the exception handling of generators in
+      PyEval_EvalFrameEx(). At entry, save or swap the exception state even if
+      PyEval_EvalFrameEx() is called with throwflag=0. At exit, the exception
+      state is now always restored or swapped, not only if why is WHY_YIELD or
+      WHY_RETURN.
+    - Issue #18518: timeit now rejects statements which can't be compiled
+      outside a function or a loop (e.g. "return" or "break").
+    - Issue #23094: Fixed readline with frames in Python implementation of
+      pickle.
+    - Issue #23268: Fixed bugs in the comparison of ipaddress classes.
+    - Issue #21408: Removed incorrect implementations of __ne__() which didn't
+      returned NotImplemented if __eq__() returned NotImplemented.  The default
+      __ne__() now works correctly.
+    - Issue #19996: :class:`email.feedparser.FeedParser` now handles
+      (malformed) headers with no key rather than amusing the body has started.
+    - Issue #23248: Update ssl error codes from latest OpenSSL git master.
+    - Issue #23098: 64-bit dev_t is now supported in the os module.
+    - Issue #23250: In the http.cookies module, capitalize "HttpOnly" and
+      "Secure" as they are written in the standard.
+    - Issue #23063: In the disutils' check command, fix parsing of reST with
+      code or code-block directives.
+    - Issue #23209, #23225: selectors.BaseSelector.close() now clears its
+      internal reference to the selector mapping to break a reference cycle.
+    - Issue #21356: Make ssl.RAND_egd() optional to support LibreSSL. The
+      availability of the function is checked during the compilation.
+    - Issue #20896, #22935: The :func:`ssl.get_server_certificate` function
+      now uses the :data:`~ssl.PROTOCOL_SSLv23` protocol by default, not
+      :data:`~ssl.PROTOCOL_SSLv3`, for maximum compatibility and support
+      platforms where :data:`~ssl.PROTOCOL_SSLv3` support is disabled.
+    - Issue #23111: In the ftplib, make ssl.PROTOCOL_SSLv23 the default
+      protocol version.
+    - Issue #23132: Mitigate regression in speed and clarity in
+      functools.total_ordering.
+    - Issue #22585: On OpenBSD 5.6 and newer, os.urandom() now calls
+      getentropy(), instead of reading /dev/urandom, to get pseudo-random
+      bytes.
+    - Issue #23112: Fix SimpleHTTPServer to correctly carry the query string
+      and fragment when it redirects to add a trailing slash.
+    - Issue #23093: In the io, module allow more operations to work on detached
+      streams.
+    - Issue #19104: pprint now produces evaluable output for wrapped strings.
+    - Issue #23071: Added missing names to codecs.__all__.
+    - Issue #15513: Added a __sizeof__ implementation for pickle classes.
+    - Issue #19858: pickletools.optimize() now aware of the MEMOIZE opcode, can
+      produce more compact result and no longer produces invalid output if
+      input data contains MEMOIZE opcodes together with PUT or BINPUT opcodes.
+    - Issue #22095: Fixed HTTPConnection.set_tunnel with default port.
+      The port value in the host header was set to "None".
+    - Issue #23016: A warning no longer produces an AttributeError when the
+      program is run with pythonw.exe.
+    - Issue #21775: shutil.copytree(): fix crash when copying to VFAT. An
+      exception handler assumed that that OSError objects always have a
+      'winerror' attribute.  That is not the case, so the exception handler
+      itself raised AttributeError when run on Linux (and, presumably,
+      any other non-Windows OS).
+    - Issue #1218234: Fix inspect.getsource() to load updated source of
+      reloaded module.
+    - Issue #22959: In the constructor of http.client.HTTPSConnection, prefer
+      the context's check_hostname attribute over the *check_hostname*
+      parameter.
+    - Issue #23009: Make sure selectors.EpollSelecrtor.select() works when no
+      FD is registered.
+    - Issue #20577: Configuration of the max line length for the
+      FormatParagraph extension has been moved from the General tab of the
+      Idle preferences dialog to the FormatParagraph tab of the Config
+      Extensions dialog.
+    - Issue #16893: Update Idle doc chapter to match current Idle and add new
+      information.
+    - Issue #23180: Rename IDLE "Windows" menu item to "Window".
+    - Issue #19548: Added some additional checks to test_codecs to ensure that
+      statements in the updated documentation remain accurate.
+    - Issue #15506: Use standard PKG_PROG_PKG_CONFIG autoconf macro in the
+      configure script.
+    - Issue #22935: Allow the ssl module to be compiled if openssl doesn't
+      support SSL 3.
+    - Issue #22079: PyType_Ready() now checks that statically allocated type
+      has no dynamically allocated bases.
+    - Issue #19548: Update the codecs module documentation to better cover the
+      distinction between text encodings and other codecs, together with other
+      clarifications.
+    - Issue #22914: Update the Python 2/3 porting HOWTO to describe a more
+      automated approach.
+    - Issue #22735: Fix many edge cases (including crashes) involving custom
+      mro() implementations.
+    - Issue #23399: pyvenv creates relative symlinks where possible.
+    - Issue #23392: Added tests for marshal C API that works with FILE*.
+    - Issue #18982: Add tests for CLI of the calendar module.
+    - Issue #23345: Prevent test_ssl failures with large OpenSSL patch level
+      values (like 0.9.8zc).
+  * Remove LTO sections from the static libraries.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 26 Feb 2015 10:07:08 +0100
+
+python3.4 (3.4.2-4) unstable; urgency=medium
+
+  * Fix issue #22935: Fix ssl module when SSLv3 protocol is not supported.
+  * Fix issue #16043: Add a default limit for the amount of data
+    xmlrpclib.gzip_decode will return. CVE-2013-1753. Closes: #742927.
+  * Disable ensurepip for the system installation, only enable it for virtual
+    environments. Closes: #772730.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 27 Dec 2014 12:23:33 +0100
+
+python3.4 (3.4.2-3) unstable; urgency=medium
+
+  * Update to 20141202 from the 3.4 branch.
+    - Issue #20335: bytes constructor now raises TypeError when encoding or
+      errors is specified with non-string argument.
+    - Issue #21971: Update turtledemo doc and add module to the index.
+    - Issue #21032. Fixed socket leak if HTTPConnection.getresponse() fails.
+    - Issue #22960: Add a context argument to xmlrpclib.ServerProxy constructor.
+    - Issue #22915: SAX parser now supports files opened with file descriptor
+      or bytes path.
+    - Issue #22609: Constructors and update methods of mapping classes in the
+      collections module now accept the self keyword argument.
+    - Issue #22788: Add *context* parameter to logging.handlers.HTTPHandler.
+    - Issue #22921: Allow SSLContext to take the *hostname* parameter even if
+      OpenSSL doesn't support SNI.
+    - Issue #22894: TestCase.subTest() would cause the test suite to be stopped
+      when in failfast mode, even in the absence of failures.
+    - Issue #22638: SSLv3 is now disabled throughout the standard library.
+      It can still be enabled by instantiating a SSLContext manually.
+    - Issue #22370: Windows detection in pathlib is now more robust.
+    - Issue #22841: Reject coroutines in asyncio add_signal_handler().
+    - Issue #22838: All test_re tests now work with unittest test discovery.
+    - Issue #21514: The documentation of the json module now refers to new
+      JSON RFC 7159 instead of obsoleted RFC 4627.
+    - Issue #22314: pydoc now works when the LINES environment variable is set.
+    - IDLE updates.
+  * Fix byte-code removal for the __phello__ module (mismatching source
+    and byte-code file name). Closes: #769769.
+  * Let ensurepip use a temporary location for the copy of the wheels.
+    Remove the ad-hoc /usr/lib/python-wheels location on package purge.
+    Let python3.4-venv break python3-pip (<< 1.5.6-4).  Closes: #769449.
+  * Don't pass default compiler search directories in the pkgconfig file.
+    Closes: #770936.
+  * Don't run pyexpat.test_exception as an autopkg test, requires a source
+    file.
+  * Allow building and testing without SSLv3 support (Kurt Roeckx).
+    Addresses: #768611.
+  * Fix issue 22966, when byte compiling, keep the base name of a file
+    containing dots. Closes: #769769.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 02 Dec 2014 14:39:00 +0100
+
+python3.4 (3.4.2-2) unstable; urgency=medium
+
+  * Repackage the upstream source without the bundled ensurepip wheels (using
+    package format 3.0 (quilt)).
+  * Update to 20141112 from the 3.4 branch.
+    - Issue #19524: Fixed resource leak in the HTTP connection when an invalid
+      response is received.
+    - Issue #22216: smtplib now resets its state more completely after a quit.
+      The most obvious consequence of the previous behavior was a STARTTLS
+      failure during a connect/starttls/quit/connect/starttls sequence.
+    - Issue #22185: Fix an occasional RuntimeError in threading.Condition.wait()
+      caused by mutation of the waiters queue without holding the lock.
+    - Issue #22182: Use e.args to unpack exceptions correctly in
+      distutils.file_util.move_file.
+    - The webbrowser module now uses subprocess's start_new_session=True rather
+      than a potentially risky preexec_fn=os.setsid call.
+    - Issue #22191: Fix warnings.__all__.
+    - Issue #8797: Raise HTTPError on failed Basic Authentication immediately.
+    - Issue #21166: Prevent possible segfaults and other random failures of
+      python --generate-posix-vars in pybuilddir.txt build target.
+    - Idle changes:
+      - Issue #17390: Adjust Editor window title; remove 'Python',
+        move version to end.
+      - Issue #14105: Idle debugger breakpoints no longer disappear
+        when inseting or deleting lines.
+      - Issue #17172: Turtledemo can now be run from Idle.
+      - Issue #22236: Tkinter tests now don't reuse default root window.
+        New root window is created for every test class.
+    - Tk changes:
+      - Issue #22226: First letter no longer is stripped from the "status" key
+        in the result of Treeview.heading().
+      - Issue #22051: turtledemo no longer reloads examples to re-run them.
+        Initialization of variables and gui setup should be done in main(),
+        which is called each time a demo is run, but not on import.
+      - Issue #21933: Turtledemo users can change the code font size with a
+        menu selection or control(command) '-' or '+' or control-mousewheel.
+      - Issue #21597: The separator between the turtledemo text pane and the
+        drawing canvas can now be grabbed and dragged with a mouse.  The code
+        text pane can be widened to easily view or copy the full width of the
+        text.
+        The canvas can be widened on small screens.
+      - Issue #18132: Turtledemo buttons no longer disappear when the window
+        is shrunk.
+      - Issue #22236: Fixed Tkinter images copying operations in NoDefaultRoot
+        mode.
+  * Fix maintainer scripts for byte-code removal. Closes: #769079.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 13 Nov 2014 04:33:52 +0100
+
+python3.4 (3.4.2-1) unstable; urgency=medium
+
+  * Python 3.4.2 release.
+  * Refresh patches.
+  * Bump standards version to 3.9.6.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 08 Oct 2014 11:25:34 +0200
+
+python3.4 (3.4.2~rc1-1) unstable; urgency=medium
+
+  * Python 3.4.2 release candidate 1.
+  * Update to 20140930 from the 3.4 branch.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 30 Sep 2014 01:51:50 +0200
+
+python3.4 (3.4.1-11) unstable; urgency=medium
+
+  * Update to 20140910 from the 3.4 branch.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 10 Sep 2014 20:21:04 +0200
+
+python3.4 (3.4.1-10) unstable; urgency=medium
+
+  * Update to 20140818 from the 3.4 branch.
+  * Build-depend on dpkg-dev (>= 1.17.11).
+
+ -- Matthias Klose <doko@debian.org>  Mon, 18 Aug 2014 10:00:55 +0200
+
+python3.4 (3.4.1-9) unstable; urgency=medium
+
+  * Update to 20140810 from the 3.4 branch.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 10 Aug 2014 14:53:46 +0200
+
+python3.4 (3.4.1-8) unstable; urgency=medium
+
+  * Update to 20140726 from the 3.4 branch.
+  * Move turtledemo from libpython3.4-testsuite to python3.4-examples.
+  * Call dpkg -L in the maintainer scripts with an architecture qualifier
+    for M-A: same packages. Closes: #754914.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 26 Jul 2014 14:16:56 +0200
+
+python3.4 (3.4.1-7) unstable; urgency=medium
+
+  * Update to 20140706 from the 3.4 branch.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 06 Jul 2014 21:37:36 +0200
+
+python3.4 (3.4.1-6) unstable; urgency=medium
+
+  * Fix logic to disable running the pystone benchmark on KFreeBSD (Steven
+    Chamberlain).
+
+ -- Matthias Klose <doko@ubuntu.com>  Mon, 09 Jun 2014 12:06:18 +0200
+
+python3.4 (3.4.1-5) unstable; urgency=medium
+
+  * Update to 20140608 from the 3.4 branch.
+  * Disable running the pystone benchmark on KFreeBSD.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 08 Jun 2014 11:43:44 +0200
+
+python3.4 (3.4.1-4) unstable; urgency=medium
+
+  * Disable running the pybench benchmark on KFreeBSD.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 07 Jun 2014 14:01:35 +0200
+
+python3.4 (3.4.1-3) unstable; urgency=medium
+
+  * Update to 20140605 from the 3.4 branch.
+    - pull in pyvenv changes.
+  * Update the ensurepip-wheels patch (Barry Warsaw).
+  * Fix python3.4-venv package removal.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 05 Jun 2014 11:57:51 +0200
+
+python3.4 (3.4.1-2) unstable; urgency=medium
+
+  * Update to 20140603 from the 3.4 branch.
+  * Remove the __pycache__ directories on libpython3.4-testsuite package
+    removal. Closes: #749999.
+  * In the autopkg tests, set HOME to the temporary home directory after
+    the su call.
+  * In the autopkg tests, make $ADTTMP accessible to the su user, and
+    re-enable the test_site autopkg test.
+  * Don't try to access the pip module in ensurepip, when the wheels
+    are not available.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 03 Jun 2014 23:58:48 +0200
+
+python3.4 (3.4.1-1) unstable; urgency=medium
+
+  * Python 3.4.1 release.
+  * Set a temporary home directory for the build and the autopkg tests.
+  * Fix issue #17752, test_distutils failures in the installed location.
+  * Update pydoc_data/topics.py, broken in the release candidate.
+  * Run again the test_code_module test in the autopkg tests.
+  * Fix issue #21264, test_compileall test failures in the installed
+    location. Re-enable in autopkg tests. LP: #1264554.
+  * ensurepip and pyvenv:
+    - Split out a python3.4-venv package, include the pyvenv-3.4 binary
+      and the ensurepip package.
+    - Adjust the ensurepip patch so that the wheels are installed from
+      the universal wheel packages (Barry Warsaw).
+    - Let ensurepip read wheel dependencies from a file shipped in the
+      -whl packages.
+    - Remove any version check on required pip and setuptools versions.
+      These are handled within these packages if necessary.
+  * Re-enable the pgo build.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 21 May 2014 22:17:32 +0200
+
+python3.4 (3.4.1~rc1-1) unstable; urgency=medium
+
+  * Python 3.4.1 release candidate 1.
+  * Don't run test_code_module in the autopkg test environment, fails there
+    but succeeds during the build. See issue #17756. Applied workaround
+    for the test case.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 05 May 2014 16:10:23 +0200
+
+python3.4 (3.4.0+20140427-1) unstable; urgency=medium
+
+  * Update to 20140427 from the 3.4 branch.
+  * Fix dependency for the -testsuite package: Closes: #745879.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 27 Apr 2014 18:48:54 +0200
+
+python3.4 (3.4.0+20140425-1) unstable; urgency=medium
+
+  * Update to 20140425 from the 3.4 branch.
+  * Don't try to byte-compile bad syntax files in the testsuite.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 25 Apr 2014 13:52:11 +0200
+
+python3.4 (3.4.0+20140417-1) unstable; urgency=medium
+
+  * Update to 20140417 from the 3.4 branch.
+    - Fix the test_site test failure.
+  * Repackage as a new tarball and remove the wheels shipped with ensurepip.
+  * Re-enable running some tests, disable some tests:
+    - Re-enable test_platform, test_subprocess, test_code_module, test_pydoc,
+    - Fix a distutils test error, skip a Solaris distutils test error.
+    - Skip the test_platform encoding test, failing with the lsb-release patch.
+    - Skip tests which are failing with python3.4.zip removed from sys.path.
+      Tracked in issue #21249.
+  * Byte-compile the files in the libpython3.4-testsuite package.
+  * d/p/distutils-install-layout.diff, d/p/site-locations.diff: Adjust the
+    "am I in a virtual environment" tests to include checking
+    sys.base_prefix != sys.prefix.  This is the definitive such test for
+    pyvenv created virtual environments (Barry Warsaw).
+  * Disallow running ensurepip with the system python, when not used in
+    a virtual environment (Barry Warsaw).
+  * Don't yet install the ensurepip module, requires further work.
+    ensurepip wants to install bundled modules setuptools and python-pip,
+    which should be built from the distro packages instead of using the
+    bundled code.
+  * python3.4-dbg: Add a python3.4-dbg.py symlink.
+  * Remove the linecache patch, not needed anymore in 3.4.
+  * Remove the disable-utimes patch, not needed anymore since glibc-2.4.
+  * Remove the statvfs-f_flag-constants, avoid-rpath, hurd-path_max,
+    kfreebsd-xattrs, freebsd-testsuite and ncurses-configure patches
+    applied upstream.
+  * Don't add runtime paths for libraries found in multiarch locations.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 17 Apr 2014 21:05:04 +0200
+
+python3.4 (3.4.0-2) unstable; urgency=medium
+
+  * Update to 20140407 from the 3.4 branch.
+    - Issue #21134: Fix segfault when str is called on an uninitialized
+      UnicodeEncodeError, UnicodeDecodeError, or UnicodeTranslateError object.
+    - Issue #19537: Fix PyUnicode_DATA() alignment under m68k.
+    - Issue #21155: asyncio.EventLoop.create_unix_server() now raises
+      a ValueError if path and sock are specified at the same time.
+    - Issue #21149: Improved thread-safety in logging cleanup during
+      interpreter shutdown.
+    - Issue #20145: `assertRaisesRegex` and `assertWarnsRegex` now raise a
+      TypeError if the second argument is not a string or compiled regex.
+    - Issue #21058: Fix a leak of file descriptor in
+      :func:`tempfile.NamedTemporaryFile`, close the file descriptor if
+      :func:`io.open` fails.
+    - Issue #21013: Enhance ssl.create_default_context() when used for server
+      side sockets to provide better security by default.
+    - Issue #20633: Replace relative import by absolute import.
+    - Issue #20980: Stop wrapping exception when using ThreadPool.
+    - Issue #21082: In os.makedirs, do not set the process-wide umask.
+      Note this changes behavior of makedirs when exist_ok=True.
+    - Issue #20990: Fix issues found by pyflakes for multiprocessing.
+    - Issue #21015: SSL contexts will now automatically select an elliptic
+      curve for ECDH key exchange on OpenSSL 1.0.2 and later, and otherwise
+      default to "prime256v1".
+    - Issue #20816: Fix inspect.getcallargs() to raise correct TypeError for
+      missing keyword-only arguments.
+    - Issue #20817: Fix inspect.getcallargs() to fail correctly if more
+      than 3 arguments are missing.
+    - Issue #6676: Ensure a meaningful exception is raised when attempting
+      to parse more than one XML document per pyexpat xmlparser instance.
+    - Issue #20942: PyImport_ImportFrozenModuleObject() no longer sets __file__
+      to match what importlib does; this affects _frozen_importlib as well as
+      any module loaded using imp.init_frozen().
+    - Documentation, tools, demo and test updates.
+  * Depend on the python3-tk packages in the autopkg tests.
+  * Fix LTO builds with GCC 4.9.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 07 Apr 2014 11:46:02 +0200
+
+python3.4 (3.4.0-1) unstable; urgency=medium
+
+  * Python 3.4.0 release.
+  * Update to 20140322 from the 3.4 branch.
+
+  * Build without ffi on or1k. Addresses: #738519.
+  * Update autopkg tests (Martin Pitt):
+    - Don't fail if apport is not installed.
+    - Call su with explicit shell, as nobody has nologin as default shell now.
+    - Only use $SUDO_USER if that user actually exists in the testbed.
+    - Drop obsolete chowning of $TMPDIR and $ADTTMP; with current autopkgtest
+      $TMPDIR has appropriate permissions, and $ADTTMP is not being used.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 22 Mar 2014 13:39:34 +0100
+
+python3.4 (3.4~rc2-1) unstable; urgency=medium
+
+  * Python 3.4 release candidate 2.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 24 Feb 2014 10:40:55 +0100
+
+python3.4 (3.4~rc1-1) unstable; urgency=medium
+
+  * Python 3.4 release candidate 1.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 11 Feb 2014 13:38:50 +0100
+
+python3.4 (3.4~b3-1) unstable; urgency=medium
+
+  * Python 3.4 beta 3.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 27 Jan 2014 10:54:10 +0000
+
+python3.4 (3.4~b2-1) unstable; urgency=medium
+
+  * Python 3.4 beta 2.
+  * Configure --with-system-libmpdec.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 05 Jan 2014 23:34:17 +0100
+
+python3.4 (3.4~b1-5ubuntu2) trusty; urgency=medium
+
+  * Disable the test_dbm autopkg test, failing from time to time ...
+
+ -- Matthias Klose <doko@ubuntu.com>  Fri, 03 Jan 2014 02:25:31 +0100
+
+python3.4 (3.4~b1-5ubuntu1) trusty; urgency=medium
+
+  * Build for Tcl/Tk 8.6.
+
+ -- Matthias Klose <doko@ubuntu.com>  Thu, 02 Jan 2014 18:05:27 +0100
+
+python3.4 (3.4~b1-5) unstable; urgency=medium
+
+  * Update to 20131231 from the trunk.
+    - Fix issue #20070, don't run test_urllib2net when network resources
+      are not enabled.
+  * Move the _sitebuiltins module into libpython3.4-minimal.
+  * distutils: On installation with --install-layout=deb, rename extensions
+    to include the multiarch tag.
+    Renaming of extensions for python3.4 is currently not done by dh-python.
+    See Debian #733128.
+  * autopkg tests:
+    - Update debian/tests/control to refer to python3.4.
+    - Generate locales for running the autopkg tests.
+    - Disable some currently failing autopkg tests. LP: #1264554.
+    - Disable test_compileall for the autopkg tests, fails only there.
+  * Don't run test_faulthandler on Aarch64, hangs on the buildds.
+    See LP: #1264354.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 31 Dec 2013 13:29:08 +0100
+
+python3.4 (3.4~b1-4) unstable; urgency=medium
+
+  * Update to 20131225 from the trunk.
+  * Fix python3.4--config --configdir. Closes: #733050.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 25 Dec 2013 21:56:04 +0100
+
+python3.4 (3.4~b1-3) experimental; urgency=medium
+
+  * Update to 20131221 from the trunk.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 21 Dec 2013 15:20:38 +0100
+
+python3.4 (3.4~b1-2) experimental; urgency=low
+
+  * Update to 20131202 from the trunk.
+  * Fix dbg symbols file for i386.
+  * Don't provide python3.4-dbm, available in a separate package.
+  * (Build-)depend on net-tools, test_uuid requires ifconfig.
+  * Fix distutils.sysconfig.get_makefile_filename().
+  * Move operator module to the -minimal package. Closes: #731100.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 02 Dec 2013 14:36:44 +0100
+
+python3.4 (3.4~b1-1) experimental; urgency=low
+
+  * Python 3.4 beta 1.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 24 Nov 2013 23:21:49 +0100
+
+python3.3 (3.3.3-2) unstable; urgency=low
+
+  * Update to 20131123 from the 3.3 branch.
+  * Update hurd-path_max.diff.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 23 Nov 2013 08:57:21 +0100
+
+python3.3 (3.3.3-1) unstable; urgency=low
+
+  * Python 3.3.3 release.
+  * Update to 20131119 from the 3.3 branch.
+  * Regenerate the patches.
+  * Update the symbols files.
+  * Fix test support when the running kernel doesn't handle port reuse.
+  * libpython3.3-minimal replaces libpython3.3-stdlib (<< 3.2.3-7).
+    Closes: #725240.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 19 Nov 2013 08:46:55 +0100
+
+python3.3 (3.3.2-7) unstable; urgency=low
+
+  * Update to 20130918 from the 3.3 branch.
+  * Update symbols file.
+  * Fail the build if extensions for the minimal package are not in
+    the libpython-minimal package. Closes: #723624.
+  * Fix indentation in regenerated platform-lsbrelease.diff (Dmitry Shachnev).
+    LP: #1220508.
+  * Point to the python3-tk (instead of the python-tk) package when missing.
+    LP: #1184082.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 18 Sep 2013 12:19:47 +0200
+
+python3.3 (3.3.2-6) unstable; urgency=medium
+
+  * Update to 20130917 from the 3.3 branch.
+    - Fix SSL module to handle NULL bytes inside subjectAltNames general
+      names (CVE-2013-4238). Closes: #719567.
+  * Don't run the curses autopkg test.
+  * Set Multi-Arch attributes for binary packages.
+  * Fix multiarch include header for sparc64. Closes: #714802.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 17 Sep 2013 15:12:00 +0200
+
+python3.3 (3.3.2-5) unstable; urgency=low
+
+  * Update to 20130803 from the 3.3 branch.
+    - Fix fcntl test case on KFreeBSD (Petr Salinger).
+  * Disable some socket tests on KFreeBSD (Petr Salinger).
+  * Fix multiarch include header for sparc64. Closes: #714802.
+  * Update package descriptions (Filipus Klutiero). Closes: #715801.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 04 Aug 2013 17:38:35 +0200
+
+python3.3 (3.3.2-4) unstable; urgency=low
+
+  * Update to 20130612 from the 3.3 branch.
+  * Refresh patches.
+  * Don't run consistency check for cross builds.
+  * Really skip byte compile of non-existing sitecustomize.py.
+  * Fix the multiarch header file for mips64 (YunQiang Su). Closes: #710374.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 12 Jun 2013 22:55:02 +0200
+
+python3.3 (3.3.2-3) unstable; urgency=low
+
+  * Update to 20130527 from the 3.3 branch.
+    - Fix #17980, possible abuse of ssl.match_hostname() for denial of service
+      using certificates with many wildcards (CVE-2013-2099). Closes: #708530.
+  * Disable the test_io test on armel, armhf, mips, mipsel. Hangs the
+    buildds.
+  * Don't try to byte-compile sitecustomize.py if the target of the
+    symlink doesn't exist anymore. Addresses: #709157.
+  * Fix directory removal in maintainer scripts. Closes: #709963.
+  * Handle byte compilation in python3.3{-minimal,}, byte removal in
+    libpython3.3{-minimal,-stdlib}.
+  * Backport patch to fix issue #13146, possible race conditions when writing
+    .pyc/.pyo files in py_compile.py (Barry Warsaw). LP: #1058884.
+  * Mark all _Py_dg_* symbols as optional on m68k. Closes: #709888.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 27 May 2013 20:44:03 +0200
+
+python3.3 (3.3.2-2) unstable; urgency=high
+
+  * Fix the multiarch header file for ppc64. Closes: #708646.
+  * Disable running the tests on kfreebsd and the hurd.  Please
+    follow-up in #708652 and #708653.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 17 May 2013 23:16:04 +0200
+
+python3.3 (3.3.2-1) unstable; urgency=low
+
+  * Python 3.3.2 release.
+  * Fix sysconfig.get_makefile_name() for the multiarch location.
+  * Set the platinclude dir back to the non-multiarch include path,
+    where the multiarch pyconfig.h compatibility header is found.
+  * Remove obsolete profile-doc patch.
+  * Run the pgo profile task in batches to avoid crashes during the
+    pgo profile run.
+  * Don't set yet any Multi-Arch: attributes in Debian.
+  * Build a libpython3.3-testsuite package.
+  * Add autopkg tests to run the installed testsuite in normal and debug
+    mode.
+  * Re-enable running the tests during the build.
+  * Add pyconfig.h compatibility headers.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 15 May 2013 19:41:15 +0200
+
+python3.3 (3.3.1-1ubuntu5) raring; urgency=low
+
+  * Remove obsolete profile-doc patch.
+  * Run the pgo profile task in batches to avoid crashes during the
+    pgo profile run.
+  * Disable the lto build on armhf for now.
+  * Final (?) set of autopkg test fixes.
+  * Issue #17012: shutil.which() no longer fallbacks to the PATH environment.
+    variable if empty path argument is specified.
+  * Issue #17782: Fix undefined behaviour on platforms where
+    ``struct timespec``'s "tv_nsec" member is not a C long.
+
+ -- Matthias Klose <doko@ubuntu.com>  Wed, 17 Apr 2013 23:35:49 +0200
+
+python3.3 (3.3.1-1ubuntu4) raring; urgency=low
+
+  * Don't run the test suite in random order.
+  * More autopkg test fixes.
+
+ -- Matthias Klose <doko@ubuntu.com>  Wed, 17 Apr 2013 13:33:00 +0200
+
+python3.3 (3.3.1-1ubuntu3) raring; urgency=low
+
+  * Fix sysconfig.get_makefile_name() for the multiarch location.
+  * Set the platinclude dir back to the non-multiarch include path,
+    where the multiarch pyconfig.h compatibility header is found.
+  * Fix autopkg tests.
+  * More autopkgtest fixes (Jean-Baptiste Lallement):
+    - redirect stderr of command 'stop apport' to /dev/null. output to stderr
+      is an error for adt.
+    - script.py waits for child to exit and exit with child's return code.
+    - xpickle is not a valid value for option -u of regrtest.py. Removed it
+      LP: #1169150.
+  * Issue #17754, setting LANG and LC_ALL for the compiler call in ctypes/util.
+  * Issue #17761, platform._parse_release_file doesn't close the
+    /etc/lsb-release file, and doesn't know about 'Ubuntu'.
+
+ -- Matthias Klose <doko@ubuntu.com>  Tue, 16 Apr 2013 17:33:35 +0200
+
+python3.3 (3.3.1-1ubuntu2) raring; urgency=low
+
+  * Idle updates:
+    - Issue #17657: Show full Tk version in IDLE's about dialog.
+    - Issue #17613: Prevent traceback when removing syntax colorizer.
+    - Issue #1207589: Backwards-compatibility patch for right-click menu.
+    - Issue #16887: Now accepts Cancel in tabify/untabify dialog box.
+    - Issue #17625: Close the replace dialog after it is used.
+    - Issue #14254: Now handles readline correctly across shell restarts.
+    - Issue #17614: No longer raises exception when quickly closing a file.
+    - Issue #6698: Now opens just an editor window when configured to do so.
+    - Issue #8900: Using keyboard shortcuts in IDLE to open a file no longer
+      raises an exception.
+    - Issue #6649: Fixed missing exit status.
+  * Build a libpython3.3-testsuite package. LP: #301629.
+  * Add autopkg tests to run the installed testsuite in normal and debug
+    mode.
+  * Re-enable running the tests during the build.
+  * Add pyconfig.h compatibility headers. LP: #1094246.
+
+ -- Matthias Klose <doko@ubuntu.com>  Wed, 10 Apr 2013 23:05:23 +0200
+
+python3.3 (3.3.1-1ubuntu1) raring; urgency=low
+
+  * Merge with Debian; remaining changes:
+    - Build-depend on python3:any instead of python3.
+
+ -- Matthias Klose <doko@ubuntu.com>  Sat, 06 Apr 2013 16:21:34 +0200
+
+python3.3 (3.3.1-1) unstable; urgency=low
+
+  * Python 3.3.1 release.
+  * Call python with -E -S for the byte compilation.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 06 Apr 2013 15:12:07 +0200
+
+python3.3 (3.3.1~rc1-2) experimental; urgency=low
+
+  * Fix byte-compiliation/-removal for the split-out library packages.
+    LP: #1160944.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 30 Mar 2013 13:36:40 +0100
+
+python3.3 (3.3.1~rc1-1) experimental; urgency=low
+
+  * Python 3.3.1 release candidate 1.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 26 Mar 2013 10:45:37 +0100
+
+python3.3 (3.3.0-12) experimental; urgency=low
+
+  * Update to 20130306 from the 3.3 branch.
+  * Remove the HAVE_FSYNC configure workaround, not needed for 3.3.
+  * Remove the python3 manual symlink (now shipped upstream by default).
+    Closes: #701051.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 06 Mar 2013 16:38:41 +0800
+
+python3.3 (3.3.0-11) experimental; urgency=low
+
+  * Update to 20130220 from the 3.3 branch.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 20 Feb 2013 15:40:05 +0100
+
+python3.3 (3.3.0-10) experimental; urgency=low
+
+  * Update to 20130126 from the 3.3 branch.
+  * Update hurd patches.
+  * python3.3-dbg, libpython3.3-dbg: Drop dependency on python.
+  * python3.3-dbg: Make gdb (not gdb-minimal) a recommendation.
+  * Git rid of build-dependency on python.
+  * Add site-packages in virtual environments created by pyvenv.
+    Closes: #698777.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 26 Jan 2013 12:17:05 +0100
+
+python3.3 (3.3.0-9) experimental; urgency=low
+
+  * Update to 20130125 from the 3.3 branch.
+  * Update cross build patches, and allow the package to cross build.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 25 Jan 2013 17:06:25 +0100
+
+python3.3 (3.3.0-8) experimental; urgency=low
+
+  * Update to 20130105 from the 3.3 branch.
+  * python-config --help returns with an exit value 0. LP: #1093860.
+  * Update package description for the -dbg packages. Closes: #696616.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 05 Jan 2013 18:39:32 +0100
+
+python3.3 (3.3.0-7) experimental; urgency=low
+
+  * Update to 20121220 from the 3.3 branch.
+  * debian/patches/sys-multiarch.diff: Expose multiarch triplet value
+    as sys.implementation._multiarch (Barry Warsaw).  Closes: #695959.
+    Note: Usage of sysconfig.get_config_var('MULTIARCH') is preferred.
+  * Set the install schema to `unix_prefix', if a virtual environment
+    is detected (VIRTUAL_ENV env var present). Closes: #695758.
+  * python3.3-dev, libpython3.3-dev: Drop the dependency on libssl-dev.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 21 Dec 2012 07:24:41 +0100
+
+python3.3 (3.3.0-6) experimental; urgency=low
+
+  * Don't use xattrs on kfreebsd and the Hurd.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 04 Dec 2012 04:36:42 +0100
+
+python3.3 (3.3.0-5) experimental; urgency=low
+
+  * Update to 20121203 from the 3.3 branch.
+  * Make python3.3, python3.3-{minimal,dev,dbg} Multi-Arch: allowed.
+  * Use a shell implementation for the python-config script.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 03 Dec 2012 21:52:33 +0100
+
+python3.3 (3.3.0-4) experimental; urgency=low
+
+  * Update to 20121128 from the 3.3 branch.
+  * Don't link extensions with the shared libpython library.
+  * Override pointless lintian warning `hardening-no-fortify-functions'
+    for binaries built without optimization.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 28 Nov 2012 13:47:16 +0100
+
+python3.3 (3.3.0-3) experimental; urgency=low
+
+  * Update to 20121106 from the 3.3 branch.
+  * Filter-out cflags for profiled builds from _sysconfigdata.
+  * Fix multiarch plat-linux installation. LP: #1075891.
+  * Install _sysconfigdata.py from the shared builds. LP: #1075903.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 07 Nov 2012 14:31:02 +0100
+
+python3.3 (3.3.0-2) experimental; urgency=low
+
+  * Update to 20121021 from the 3.3 branch.
+  * Fix the interpreter name for the python3.3-dbg-config script.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 21 Oct 2012 09:51:05 +0200
+
+python3.3 (3.3.0-1) experimental; urgency=low
+
+  * Python 3.3.0 release.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 29 Sep 2012 12:59:24 +0200
+
+python3.3 (3.3.0~rc3-1) experimental; urgency=low
+
+  * Python 3.3.0 release candidate 3.
+  * Don't try to write lib2to3's pickled grammar files. Closes: #687200.
+  * Fix python-config manpage symlink. Closes: #687201.
+
+ -- Matthias Klose <doko@ubuntu.com>  Mon, 24 Sep 2012 16:22:17 +0200
+
+python3.3 (3.3.0~rc2-2ubuntu1) quantal; urgency=low
+
+  * Encode the version in the devhelp documentation name. LP: #787039.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 10 Sep 2012 12:56:13 +0200
+
+python3.3 (3.3.0~rc2-2) experimental; urgency=low
+
+  * Fix typo fixing the pkgconfig file.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 10 Sep 2012 11:13:51 +0200
+
+python3.3 (3.3.0~rc2-1) experimental; urgency=low
+
+  * Python 3.3.0 release candidate 2.
+  * Add the platform include dir to pkgconfig's CFlags.
+  * Hint on installing the python-gdbm package on failing _gdbm import.
+    LP: #995616.
+  * libpython3.3: Fix libpython3.3.so symlink. Closes: #686377.
+  * Don't use `-n' anymore to start idle in the desktop/menu files.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 09 Sep 2012 13:38:55 +0200
+
+python3.3 (3.3.0~rc1-2) experimental; urgency=low
+
+  * distutils: Add the multiarch python path to the include directories.
+    Closes: #685041.
+  * Remove /etc/python3.3 in libpython3.3-minimal instead of python3.3-minimal.
+    Closes: #681979.
+  * Remove /etc/python/sysconfig.cfg, not available anymore in python3.3.
+    Closes: #685016.
+  * Don't ship the _gdbm and _tkinter extensions in the -dbg package.
+    Closes: #685261.
+  * Fix verbose parallel builds for the sharedmods target.
+  * Don't install the pickled lib2to3 grammar files. Closes: #685214.
+  * Build extensions with fortify flags.
+  * Overwrite arch-dependent-file-not-in-arch-specific-directory warnings.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 28 Aug 2012 19:47:58 +0200
+
+python3.3 (3.3.0~rc1-1) experimental; urgency=low
+
+  * Python 3.3.0 release candidate 1.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 26 Aug 2012 23:15:00 +0200
+
+python3.3 (3.3.0~b2-1) experimental; urgency=low
+
+  * Python 3.3.0 beta2 release.
+  * Fix removal of the _tkinter and dbm extensions for multiarch builds.
+    Closes: #684461.
+  * Use _sysconfigdata.py in distutils to initialize distutils.
+    Closes: #682475.
+  * Fix symlink for static libpython. Closes: #684608.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 13 Aug 2012 11:05:00 +0200
+
+python3.3 (3.3.0~b1-3) experimental; urgency=low
+
+  * Update to 20120712 from the trunk.
+  * Install separate _sysconfigdata.py for normal and debug builds.
+  * Install into multiarch locations.
+  * Split out multiarch packages libpython3.3-{minimal,stdlib,dev,dbg}.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 13 Jul 2012 00:43:42 +0200
+
+python3.3 (3.3.0~b1-2) experimental; urgency=low
+
+   * Update to 20120701 from the trunk.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 01 Jul 2012 11:45:12 +0200
+
+python3.3 (3.3.0~b1-1) experimental; urgency=low
+
+  * Python 3.3.0 beta1 release.
+  * Fix symlink for the -gdb.py file.
+  * debian/copyright: Add libmpdec license.
+  * Enable fortified build.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 27 Jun 2012 08:44:56 +0200
+
+python3.3 (3.3.0~a4-1) experimental; urgency=low
+
+  * Python 3.3.0 alpha4 release.
+  * Update to 20120620 from the trunk.
+  * Build _ctypes as an extension, not a builtin.
+  * Mark symbols defined in the _ctypes extension as optional.
+  * Remove references to the removed pyton3.3-documenting file.
+  * The wininst-* files cannot be built within Debian from the included
+    sources, needing a zlib mingw build, which the zlib maintainer isn't
+    going to provide.
+  * Use the underscore.js file provided by the libjs-underscore package.
+  * Let pydoc handle dist-packages the same as site-packages.
+  * Avoid runtime path for the sqlite extension.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 20 Jun 2012 13:09:19 +0200
+
+python3.3 (3.3.0~a3-1) experimental; urgency=low
+
+  * Python 3.3.0 alpha3 release.
+  * Build the dbm extension using db5.3.
+  * Update symbols file for a3.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 02 May 2012 23:28:46 +0200
+
+python3.3 (3.3.0~a2-1) experimental; urgency=low
+
+  * Python 3.3.0 alpha2 release.
+  * Update to 20120404 from the trunk.
+  * Build-depend on expat (>= 2.1).
+
+ -- Matthias Klose <doko@debian.org>  Wed, 04 Apr 2012 16:31:34 +0200
+
+python3.3 (3.3.0~a1-1) experimental; urgency=low
+
+  * Python 3.3.0 alpha1 release.
+  * Update to 20120321 from the trunk.
+  * Update debian/copyright.
+  * Build-depend on expat (>= 2.1~).
+
+ -- Matthias Klose <doko@debian.org>  Thu, 22 Mar 2012 06:14:01 +0100
+
+python3.3 (3.3~20120109-1) experimental; urgency=low
+
+  * 3.3 20120109 snapshot from the trunk.
+  * Merge packaging from python3.2 3.2.2-4.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 08 Jan 2012 09:44:33 +0100
+
+python3.3 (3.3~20110523-1) experimental; urgency=low
+
+  * Initial Python 3.3 packaging.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 23 May 2011 09:20:52 +0200
+
+python3.2 (3.2.2-4) unstable; urgency=low
+
+  * The static library belongs into the -dev package.
+  * Remove obsolete attributes in the control file.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 07 Jan 2012 20:46:39 +0100
+
+python3.2 (3.2.2-3) unstable; urgency=low
+
+  * Update to 20120106 from the 3.2 branch.
+  * Install manual pages for 2to3 and python-config.
+  * Fix file permission of token.py module.
+  * Add the ability to build an python3.x udeb, as copy of the
+    python3.x-minimal package (Colin Watson).
+  * Overwrite some lintian warnings:
+    - The -dbg interpreters are not unusual.
+    - The -gdb.py files don't need a python dependency.
+    - lintian can't handle a whatis entry starting with one word on the line.
+  * Fix test failures related to distutils debian installation layout.
+  * Update symbols files.
+  * Add build-arch/build-indep targets.
+  * Regenerate Setup and Makefiles after correcting Setup.local.
+  * profiled-build.diff: Pass PY_CFLAGS instead of CFLAGS for the profiled
+    build.
+  * Pass dpkg-buildflags to the build process, and build third party
+    extensions with these flags.
+  * Add support to build using -flto (and -g1) on some architectures.
+  * Disable pgo builds for some architectures (for now, keep just
+    amd64 armel armhf i386 powerpc ppc64).
+  * Build-depend on libgdbm-dev to build and run the gdbm tests.
+  * Build-depend on xvfb to run the tkinter tests.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 06 Jan 2012 20:10:13 +0100
+
+python3.2 (3.2.2-2) unstable; urgency=low
+
+  * Update platform patches (alpha, hppa, mips, sparc).
+
+ -- Matthias Klose <doko@debian.org>  Fri, 02 Dec 2011 10:24:05 +0100
+
+python3.2 (3.2.2-1) unstable; urgency=low
+
+  * Python 3.2.2 release.
+  * Update to 20111201 from the 3.2 branch.
+  * Search headers in /usr/include/ncursesw for the curses/panel extensions.
+  * New patch, ctypes-arm, allow for ",hard-float" after libc6 in ldconfig -p
+    output (Loic Minier). LP: #898172.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 01 Dec 2011 13:19:16 +0100
+
+python3.2 (3.2.2~rc1-1) unstable; urgency=low
+
+  * Python 3.2.2 release candidate 1.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 14 Aug 2011 20:25:35 +0200
+
+python3.2 (3.2.1-2) unstable; urgency=low
+
+  * Update to 20110803 from the 3.2 branch.
+  * Revert previous change to treat Linux 3.x as Linux 2. Use the
+    plat-linux3 directory instead.
+  * Use linux-any for some build dependencies. Closes: #634310.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 03 Aug 2011 15:16:05 +0200
+
+python3.2 (3.2.1-1) unstable; urgency=medium
+
+  * Python 3.2.1 release.
+  * Update lib-argparse patch (Pino Toscano). Closes: #631635.
+  * Treat Linux 3.x as Linux 2. Closes: #633015.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 10 Jul 2011 21:46:36 +0200
+
+python3.2 (3.2.1~rc2-1) unstable; urgency=low
+
+  * Python 3.2.1 release candidate 2.
+  * Add profile/pstats to the python3.2 package, update debian copyright.
+  * Don't run the benchmark on hurd-i386.
+  * Disable threading tests on hurd-i386. Closes: #631634.
+  * Don't add the bsddb multilib path, if already in the standard lib path.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 04 Jul 2011 20:27:52 +0200
+
+python3.2 (3.2.1~rc1-1) unstable; urgency=low
+
+  * Python 3.2.1 release candidate 1.
+  * Only enable sphinx-0.x patches when building with sphinx-0.x.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 18 May 2011 12:15:47 +0200
+
+python3.2 (3.2-4) unstable; urgency=low
+
+  * Update to 20110504 from the 3.2 branch.
+  * Disable the profiled build on ia64 and m68k.
+  * Update symbols file for m68k (Thorsten Glaser).
+
+ -- Matthias Klose <doko@debian.org>  Wed, 04 May 2011 21:32:08 +0200
+
+python3.2 (3.2-3) unstable; urgency=low
+
+  * Update to 20110427 from the 3.2 branch.
+    - Fix argparse import. Closes: #624277.
+  * Keep the ssl.PROTOCOL_SSLv2 module constant , just raise an exception
+    when trying to create a PySSL object. #624127.
+  * Don't depend on the locale and specific awk implementations in prerm.
+    Closes: #623466, #620836.
+  * Remove the old local site directory. Closes: #623057.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 27 Apr 2011 20:40:29 +0200
+
+python3.2 (3.2-2) unstable; urgency=low
+
+  * Update to 20110419 from the 3.2 branch.
+  * Re-enable profile-guided builds.
+  * Build without OpenSSL v2 support. Closes: #622004.
+  * Force linking the curses module against libncursesw. Closes: #622064.
+  * Re-enable running the testsuite during the build.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 19 Apr 2011 17:54:36 +0200
+
+python3.2 (3.2-1) unstable; urgency=low
+
+  * Python 3.2 final release.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 20 Feb 2011 19:22:24 +0100
+
+python3.2 (3.2~rc3-1) experimental; urgency=low
+
+  * Python 3.2 release candidate 3.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 14 Feb 2011 16:12:14 +0100
+
+python3.2 (3.2~rc1-2) experimental; urgency=low
+
+  * Fix upgrade of the python3.2-dev package. Closes: #610370.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 19 Jan 2011 02:21:19 +0100
+
+python3.2 (3.2~rc1-1) experimental; urgency=low
+
+  * Python 3.2 release candidate 1.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 16 Jan 2011 22:17:09 +0100
+
+python3.2 (3.2~b2-1) experimental; urgency=low
+
+  * Python 3.2 beta2 release.
+  * Fix FTBFS on hurd-i386 (Pino Toscano). Closes: #606152).
+
+ -- Matthias Klose <doko@debian.org>  Tue, 21 Dec 2010 21:23:21 +0100
+
+python3.2 (3.2~b1-1) experimental; urgency=low
+
+  * Python 3.2 beta1 release.
+  * Configure with --enable-loadable-sqlite-extensions.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 06 Dec 2010 12:19:09 +0100
+
+python3.2 (3.2~a4-2) experimental; urgency=low
+
+  * Fix build failure on the hurd.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 26 Nov 2010 06:38:41 +0100
+
+python3.2 (3.2~a4-1) experimental; urgency=low
+
+  * Python 3.2 alpha4 release.
+  * Update to the py3k branch (20101124).
+  * Move the Makefile into the -min package, required by sysconfig.
+    Addresses: #603237.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 24 Nov 2010 22:20:32 +0100
+
+python3.2 (3.2~a3-2) experimental; urgency=low
+
+  * Update to the py3k branch (20101018).
+    - Issue #10094: Use versioned .so files on GNU/kfreeBSD and the GNU Hurd.
+      Closes: #600183.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 18 Oct 2010 19:34:39 +0200
+
+python3.2 (3.2~a3-1) experimental; urgency=low
+
+  * Python 3.2 alpha3 release.
+  * Make Lib/plat-gnukfreebsd[78] ready for python3. Closes: #597874.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 12 Oct 2010 16:13:15 +0200
+
+python3.2 (3.2~a2-7) experimental; urgency=low
+
+  * Update to the py3k branch (20100926).
+
+ -- Matthias Klose <doko@debian.org>  Sun, 26 Sep 2010 14:41:18 +0200
+
+python3.2 (3.2~a2-6) experimental; urgency=low
+
+  * Update to the py3k branch (20100919).
+  * Update GNU/Hurd patches (Pino Toscano). Closes: #597320.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 19 Sep 2010 12:45:14 +0200
+
+python3.2 (3.2~a2-5) experimental; urgency=low
+
+  * Update to the py3k branch (20100916).
+  * Provide Lib/plat-gnukfreebsd[78] (Jakub Wilk). Addresses: #593818.
+  * Assume working semaphores, don't rely on running kernel for the check.
+    LP: #630511.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 16 Sep 2010 14:41:58 +0200
+
+python3.2 (3.2~a2-4) experimental; urgency=low
+
+  * Update to the py3k branch (20100911).
+  * Add the sysconfig module to python3.2-minimal.
+  * Remove dist-packages/README.
+  * Make xargs --show-limits in the maintainer scripts independent from
+    the locale.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 11 Sep 2010 20:59:47 +0200
+
+python3.2 (3.2~a2-3) experimental; urgency=low
+
+  * Update to the py3k branch (20100910).
+  * Disable profile feedback based optimization on armel.
+  * Add copyright information for expat, libffi and zlib. Sources
+    for the wininst-* files are in PC/bdist_wininst. Closes: #596276.
+  * Run the testsuite in parallel, when parallel= is set in DEB_BUILD_OPTIONS.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 10 Sep 2010 20:28:16 +0200
+
+python3.2 (3.2~a2-2) experimental; urgency=low
+
+  * Fix distutils.sysconfig.get_makefile_name for debug builds.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 09 Sep 2010 02:40:11 +0200
+
+python3.2 (3.2~a2-1) experimental; urgency=low
+
+  * Python 3.2 alpha2 release.
+  * Update to the py3k branch (20100908).
+  * Provide /usr/lib/python3/dist-packages as location for public python
+    packages.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 08 Sep 2010 17:36:06 +0200
+
+python3.2 (3.2~a1-1) experimental; urgency=low
+
+  * Python 3.2 alpha1 release.
+    - Files removed: Lib/profile.py, Lib/pstats.py, PC/icons/source.xar.
+  * Update to the py3k branch (20100827).
+  * Fix detection of ffi.h header file. Closes: #591408.
+  * python3.1-dev: Depend on libssl-dev. LP: #611845.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 27 Aug 2010 21:40:31 +0200
+
+python3.2 (3.2~~20100707-0ubuntu1) maverick; urgency=low
+
+  * Move the pkgconfig file into the -dev package.
+  * Update preremoval scripts for __pycache__ layout.
+  * Run hooks from /usr/share/python3/runtime.d/
+  * Update distutils-install-layout and debug-build patches.
+
+ -- Matthias Klose <doko@ubuntu.com>  Wed, 07 Jul 2010 12:38:52 +0200
+
+python3.2 (3.2~~20100706-0ubuntu1) maverick; urgency=low
+
+  * Test build, taken from the py3k branch (20100706).
+  * Merge with the python3.1 packaging.
+
+ -- Matthias Klose <doko@ubuntu.com>  Tue, 06 Jul 2010 17:10:51 +0200
+
+python3.2 (3.2~~20100704-0ubuntu1) maverick; urgency=low
+
+  * Test build, taken from the py3k branch (20100704).
+
+ -- Matthias Klose <doko@ubuntu.com>  Sun, 04 Jul 2010 16:04:45 +0200
+
+python3.2 (3.2~~20100421-0ubuntu1) lucid; urgency=low
+
+  * Test build, taken from the py3k branch (20100421).
+
+ -- Matthias Klose <doko@ubuntu.com>  Wed, 21 Apr 2010 22:04:14 +0200
+
+python3.1 (3.1.2+20100703-1) unstable; urgency=low
+
+  * Update to the 3.1 release branch, 20100703.
+  * Convert internal dpatch system to quilt.
+  * Update module list for python3-minimal.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 03 Jul 2010 14:18:18 +0200
+
+python3.1 (3.1.2-3) unstable; urgency=low
+
+  * Update to the 3.1 release branch, 20100508.
+  * Fix backport of issue #8140. Closes: #578896.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 08 May 2010 15:37:35 +0200
+
+python3.1 (3.1.2-2) unstable; urgency=low
+
+  * Update to the 3.1 release branch, 20100421.
+  * Update patch for issue #8032, gdb7 hooks for debugging.
+  * Fix issue #8233: When run as a script, py_compile.py optionally
+    takes a single argument `-`.
+  * Don't build-depend on locales on avr32.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 21 Apr 2010 21:12:37 +0200
+
+python3.1 (3.1.2-1) unstable; urgency=low
+
+  * Python 3.1.2 release.
+  * Fix issue #4961: Inconsistent/wrong result of askyesno function in
+    tkMessageBox with Tcl8.5. LP: #462950.
+  * Don't complain when /usr/local is not writable on installation.
+  * Apply proposed patch for issue #8032, gdb7 hooks for debugging.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 21 Mar 2010 17:59:49 +0100
+
+python3.1 (3.1.2~rc1-2) unstable; urgency=low
+
+  * Update to the 3.1 release branch, 20100316.
+  * Backport issue #8140: Extend compileall to compile single files.
+    Add -i option.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 16 Mar 2010 02:38:45 +0100
+
+python3.1 (3.1.2~rc1-1) unstable; urgency=low
+
+  * Python 3.1.2 release candidate 1.
+    - Replace the Monty Python audio test file. Closes: #568676.
+  * Build using libdb4.8-dev. Only used for the dbm extension; the bsddb3
+    extension isn't built from the core packages anymore.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 11 Mar 2010 17:26:17 +0100
+
+python3.1 (3.1.1-3) unstable; urgency=low
+
+  * Update to the 3.1 release branch, 20100119.
+  * Hurd fixes (Pino Toscano):
+    - hurd-broken-poll.dpatch: ported from 2.5.
+    - hurd-disable-nonworking-constants.dpatch: disable a few constants from
+      the public API whose C counterparts are not implemented, so using them
+      either always blocks or always fails (caused issues in the test suite).
+    - hurd-path_max.dpatch (hurd only): change few PATH_MAX occurrences to
+      MAXPATHLEN (which is defined by the python lib if not defined by the OS).
+    - cthreads.dpatch: Refresh.
+    - Exclude the profiled build for hurd.
+    - Disable six blocking tests from the test suite.
+  * Don't run the testsuite on armel and hppa until someone figures out
+    the blocking tests.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 19 Jan 2010 22:02:14 +0100
+
+python3.1 (3.1.1-2) unstable; urgency=low
+
+  * Update to the 3.1 release branch, 20100116.
+  * Fix bashism in makesetup shell script. Closes: #530170, #530171.
+  * Fix build issues on avr (Bradley Smith). Closes: #528439.
+    - Configure --without-ffi.
+    - Don't run lengthly tests.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 16 Jan 2010 23:28:05 +0100
+
+python3.1 (3.1.1-1) experimental; urgency=low
+
+  * Python 3.1.1 final release.
+  * Update to the 3.1 release branch, 20091011.
+  * Remove /usr/local/lib/python3.1 on package removal, if empty.
+  * Build _hashlib as a builtin. LP: #445530.
+  * python3.1-doc: Don't compress the sphinx inventory.
+  * python3.1-doc: Fix jquery.js symlink. LP: #447370.
+  * Run the benchmark with -C 2 -n 5 -w 4 on all architectures.
+  * python3.1-dbg: Don't create debug subdirectory in /usr/local. No
+    separate debug directory needed anymore.
+  * Fix title of devhelp document. LP: #423551.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 11 Oct 2009 22:01:57 +0200
+
+python3.1 (3.1-1) experimental; urgency=low
+
+  * Python 3.1 final release.
+  * Update to the 3.1 release branch, 20090723.
+  * Add explicit build dependency on tk8.5-dev.
+
+ -- Matthias Klose <doko@ubuntu.com>  Thu, 23 Jul 2009 15:20:35 +0200
+
+python3.1 (3.1-0ubuntu2) karmic; urgency=low
+
+  * Disable profile feedback based optimization on amd64 (GCC
+    PR gcov-profile/38292).
+
+ -- Matthias Klose <doko@ubuntu.com>  Fri, 24 Jul 2009 16:27:22 +0200
+
+python3.1 (3.1-0ubuntu1) karmic; urgency=low
+
+  * Python 3.1 final release.
+  * Update to the 3.1 release branch, 20090723.
+  * Add explicit build dependency on tk8.5-dev.
+
+ -- Matthias Klose <doko@ubuntu.com>  Thu, 23 Jul 2009 18:52:17 +0200
+
+python3.1 (3.1~rc2+20090622-1) experimental; urgency=low
+
+  [Matthias Klose]
+  * Python 3.1 rc2 release. Closes: #529320.
+  * Update to the trunk, 20090622, remove patches integrated upstream.
+  * Configure with --with-fpectl --with-dbmliborder=bdb --with-wide-unicode.
+    NOTE: The --with-wide-unicode configuration will break most extensions
+    built with 3.1~a1, but is consistent with python2.x configurations.
+  * Add symbols files for libpython3.1 and python3.1-dbg, don't include symbols
+    from builtins, which can either be built as builtins or extensions.
+  * Keep an empty lib-dynload in python3.1-minimal to avoid a warning on
+    startup.
+  * python3.1-doc: Depend on libjs-jquery, use jquery.js from this package.
+    Closes: #523485.
+  * Do not add /usr/lib/pythonXY.zip on sys.path.
+  * Add symbols files for libpython3.1 and python3.1-dbg, don't include symbols
+    from builtins, which can either be built as builtins or extensions.
+  * Keep an empty lib-dynload in python3.1-minimal to avoid a warning on
+    startup.
+  * Fix some lintian warnings.
+  * Use the information in /etc/lsb-release for platform.dist(). LP: #196526.
+  * Move the bdist_wininst files into the -dev package (only needed to build
+    windows installers).
+  * Document changes to the site directory name in the installation manual.
+  * Don't build a profiled binary. Closes: #521811.
+
+  * Address issues when working with PYTHONUSERBASE and non standard prefix
+    (pointed out by Larry Hastings):
+    - distutils.sysconfig.get_python_lib(): Only return ".../dist-packages" if
+      prefix is the default prefix and if PYTHONUSERBASE is not set in the
+      environment.
+    - site.addusersitepackages(): Add USER_BASE/.../dist-packages to sys.path.
+  * Always use the `unix_prefix' scheme for setup.py install in a virtualenv
+    setup. LP: #339904.
+  * Don't make the setup.py install options --install-layout=deb and --prefix
+    conflict with each other.
+  * distutils: Always install into `/usr/local/lib/python3.1/dist-packages'
+    if an option `--prefix=/usr/local' is present (except for virtualenv
+    and PYTHONUSERBASE installations). LP: #362570.
+  * Always use `site-packages' as site directory name in virtualenv.
+
+  [Marc Deslauriers]
+  * debian/pyhtml2devhelp.py: update for sphinx generated documentation.
+  * debian/rules: re-enable documentation files for devhelp.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 22 Jun 2009 16:18:39 +0200
+
+python3.1 (3.1~a1+20090322-1) experimental; urgency=low
+
+  * Python 3.1 alpha1 release.
+  * Update to the trunk, 20090322.
+  * Update installation schemes: LP: #338395.
+    - When the --prefix option is used for setup.py install, Use the
+      `unix_prefix' scheme.
+    - Use the `deb_system' scheme if --install-layout=deb is specified.
+    - Use the the `unix_local' scheme if neither --install-layout=deb
+      nor --prefix is specified.
+  * Use the information in /etc/lsb-release for platform.dist(). LP: #196526.
+  * pydoc: Fix detection of local documentation files.
+  * Build a shared library configured --with-pydebug. LP: #322580.
+  * Fix some lintian warnings.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 23 Mar 2009 00:01:27 +0100
+
+python3.1 (3.1~~20090226-1) experimental; urgency=low
+
+  * Python-3.1 snapshot (20090226), upload to experimental.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 26 Feb 2009 16:18:41 +0100
+
+python3.1 (3.1~~20090222-0ubuntu1) jaunty; urgency=low
+
+  * Python-3.1 snapshot (20090222).
+  * Build the _dbm extension using the Berkeley DB backend.
+
+ -- Matthias Klose <doko@ubuntu.com>  Sun, 22 Feb 2009 12:58:58 +0100
+
+python3.0 (3.0.1-0ubuntu4) jaunty; urgency=low
+
+  * Don't build-depend on locales on sparc. Currently not installable.
+
+ -- Matthias Klose <doko@ubuntu.com>  Sun, 22 Feb 2009 12:48:38 +0100
+
+python3.0 (3.0.1-0ubuntu3) jaunty; urgency=low
+
+  * Update to 20090222 from the release30-maint branch.
+
+ -- Matthias Klose <doko@ubuntu.com>  Sun, 22 Feb 2009 11:09:58 +0100
+
+python3.0 (3.0.1-0ubuntu2) jaunty; urgency=low
+
+  * Allow docs to be built with Sphinx 0.5.x.
+
+ -- Matthias Klose <doko@ubuntu.com>  Tue, 17 Feb 2009 12:58:02 +0100
+
+python3.0 (3.0.1-0ubuntu1) jaunty; urgency=low
+
+  * New upstream version.
+
+ -- Matthias Klose <doko@ubuntu.com>  Mon, 16 Feb 2009 17:18:23 +0100
+
+python3.0 (3.0-0ubuntu2) jaunty; urgency=low
+
+  * Update to 20090213 from the release30-maint branch.
+
+ -- Matthias Klose <doko@ubuntu.com>  Fri, 13 Feb 2009 15:49:12 +0100
+
+python3.0 (3.0-0ubuntu1) jaunty; urgency=low
+
+  * Final Python-3.0 release.
+
+ -- Matthias Klose <doko@ubuntu.com>  Thu, 04 Dec 2008 09:00:09 +0100
+
+python3.0 (3.0~rc3-0ubuntu4) jaunty; urgency=low
+
+  * Update to 20081127 from the py3k branch.
+  * Ensure that all extensions from the -minimal package are statically
+    linked into the interpreter. LP: #301597.
+  * Include expat, _elementtree, datetime in -minimal to link
+    these extensions statically.
+
+ -- Matthias Klose <doko@ubuntu.com>  Thu, 27 Nov 2008 08:49:02 +0100
+
+python3.0 (3.0~rc3-0ubuntu3) jaunty; urgency=low
+
+  * Ignore errors when running the profile task.
+
+ -- Matthias Klose <doko@ubuntu.com>  Sun, 23 Nov 2008 15:50:17 +0100
+
+python3.0 (3.0~rc3-0ubuntu2) jaunty; urgency=low
+
+  * Don't run test_ioctl on the buildd, before the buildd chroot is fixed:
+    Unable to open /dev/tty.
+
+ -- Matthias Klose <doko@ubuntu.com>  Sun, 23 Nov 2008 15:28:02 +0100
+
+python3.0 (3.0~rc3-0ubuntu1) jaunty; urgency=low
+
+  * Update to the python-3.0 release candidate 3.
+
+ -- Matthias Klose <doko@ubuntu.com>  Sun, 23 Nov 2008 13:14:20 +0100
+
+python3.0 (3.0~rc1+20081027-0ubuntu1) intrepid; urgency=low
+
+  * Update to 20081027 from the py3k branch. LP: #279227.
+  * Fix typos and section names in doc-base files. LP: #273344.
+  * Build a new package libpython3.0.
+  * For locally installed packages, create a directory
+    /usr/local/lib/python3.0/dist-packages. This is the default for
+    installations done with distutils and setuptools. Third party stuff
+    packaged within the distribution goes to /usr/lib/python3.0/dist-packages.
+    There is no /usr/lib/python3.0/site-packages in the file system and
+    on sys.path. No package within the distribution must not install
+    anything in this location.
+  * distutils: Add an option --install-layout=deb, which
+    - installs into $prefix/dist-packages instead of $prefix/site-packages.
+    - doesn't encode the python version into the egg name.
+
+ -- Matthias Klose <doko@ubuntu.com>  Mon, 27 Oct 2008 23:38:42 +0100
+
+python3.0 (3.0~b3+20080915-0ubuntu1) intrepid; urgency=low
+
+  * Update to 20080915 from the py3k branch.
+  * Build gdbm
+
+ -- Matthias Klose <doko@ubuntu.com>  Mon, 15 Sep 2008 23:56:44 +0200
+
+python3.0 (3.0~b3-0ubuntu1~ppa1) intrepid; urgency=low
+
+  * Python 3.0 beta3 release.
+
+ -- Matthias Klose <doko@ubuntu.com>  Sun, 24 Aug 2008 03:49:26 +0200
+
+python3.0 (3.0~b2-0ubuntu1~ppa1) intrepid; urgency=low
+
+  * Python 3.0 beta2 release.
+
+ -- Matthias Klose <doko@ubuntu.com>  Thu, 07 Aug 2008 14:57:02 +0000
+
+python3.0 (3.0~b1-0ubuntu1~ppa1) intrepid; urgency=low
+
+  * Python 3.0 beta1 release.
+
+ -- Matthias Klose <doko@ubuntu.com>  Tue, 15 Jul 2008 16:10:52 +0200
+
+python3.0 (3.0~a5+0530-0ubuntu1) intrepid; urgency=low
+
+  * Update to snapshot taken from the py3k branch.
+
+ -- Matthias Klose <doko@ubuntu.com>  Thu, 29 May 2008 15:50:55 +0200
+
+python3.0 (3.0~a1-0ubuntu2) gutsy; urgency=low
+
+  * Disable running the benchmark.
+
+ -- Matthias Klose <doko@ubuntu.com>  Fri, 31 Aug 2007 23:22:34 +0000
+
+python3.0 (3.0~a1-0ubuntu1) gutsy; urgency=low
+
+  * First Python-3.0 alpha release.
+
+ -- Matthias Klose <doko@ubuntu.com>  Fri, 31 Aug 2007 21:26:21 +0200
+
+python2.6 (2.6~alpha~pre1-~0ubuntu1~ppa1) gutsy; urgency=low
+
+  * Snapshot build, an "how to use tilde in version numbers" upload.
+  * SVN 20070831.
+
+ -- Matthias Klose <doko@ubuntu.com>  Fri, 31 Aug 2007 15:56:09 +0200
+
+python2.5 (2.5.2-4) unstable; urgency=low
+
+  * Update to 20080427, taken from the 2.5 release branch.
+    - Fix issues #2670, #2682.
+  * Disable running pybench on the hppa buildd (ftbfs).
+  * Allow setting BASECFLAGS, OPT and EXTRA_LDFLAGS (like, CC, CXX, CPP,
+    CFLAGS, CPPFLAGS, CCSHARED, LDSHARED) from the environment.
+  * Support parallel=<n> in DEB_BUILD_OPTIONS (see #209008).
+
+ -- Matthias Klose <doko@debian.org>  Sun, 27 Apr 2008 10:40:51 +0200
+
+python2.5 (2.5.2-3) unstable; urgency=medium
+
+  * Update to 20080416, taken from the 2.5 release branch.
+    - Fix CVE-2008-1721, integer signedness error in the zlib extension module.
+    - Fix urllib2 file descriptor happens byte-at-a-time, reverting
+      a fix for excessively large memory allocations when calling .read()
+      on a socket object wrapped with makefile(). 
+  * Disable some regression tests on some architectures:
+    - arm: test_compiler, test_ctypes.
+    - armel: test_compiler.
+    - hppa: test_fork1, test_wait3.
+    - m68k: test_bsddb3, test_compiler.
+  * Build-depend on libffi-dev instead of libffi4-dev.
+  * Fix CVE-2008-1679, integer overflows in the imageop module.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 16 Apr 2008 23:37:46 +0200
+
+python2.5 (2.5.2-2) unstable; urgency=low
+
+  * Use site.addsitedir() to add directories in /usr/local to sys.path.
+    Addresses: #469157, #469818.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 08 Mar 2008 16:11:23 +0100
+
+python2.5 (2.5.2-1) unstable; urgency=low
+
+  * Python 2.5.2 release.
+  * Merge from Ubuntu:
+    - Move site customization into sitecustomize.py, don't make site.py
+      a config file. Addresses: #309719, #413172, #457361.
+    - Move site.py to python2.4-minimal, remove `addbuilddir' from site.py,
+      which is unnecessary for installed builds.
+    - python2.5-dev: Recommend libc-dev instead of suggesting it. LP: #164909.
+    - Fix issue 961805, Tk Text.edit_modified() fails. LP: #84720.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 28 Feb 2008 23:18:52 +0100
+
+python2.5 (2.5.1-7) unstable; urgency=low
+
+  * Update to 20080209, taken from the 2.5 release branch.
+  * Build the _bsddb extension with db-4.5 again; 4.6 is seriously
+    broken when used with the _bsddb extension.
+  * Do not run pybench on arm and armel.
+  * python2.5: Provide python2.5-wsgiref.
+  * Fix a pseudo RC report with duplicated attributes in the control
+    file. Closes: #464307.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 10 Feb 2008 00:22:57 +0100
+
+python2.5 (2.5.1-6) unstable; urgency=low
+
+  * Update to 20080102, taken from the 2.5 release branch.
+    - Only define _BSD_SOURCE on OpenBSD systems. Closes: #455400.
+  * Fix handling of packages in linecache.py (Kevin Goodsell). LP: #70902.
+  * Bump debhelper to v5.
+  * Register binfmt for .py[co] files.
+  * Use absolute paths when byte-compiling files. Addresses: #453346.
+    Closes: #413566, LP: #177722.
+  * CVE-2007-4965, http://bugs.python.org/issue1179:
+    Multiple integer overflows in the imageop module in Python 2.5.1 and
+    earlier allow context-dependent attackers to cause a denial of service
+    (application crash) and possibly obtain sensitive information (memory
+    contents) via crafted arguments to (1) the tovideo method, and unspecified
+    other vectors related to (2) imageop.c, (3) rbgimgmodule.c, and other
+    files, which trigger heap-based buffer overflows.
+    Patch prepared by Stephan Herrmann. Closes: #443333, LP: #163845.
+  * Register info docs when doing source only uploads. LP: #174786.
+  * Remove deprecated value from categories in desktop file. LP: #172874.
+  * python2.5-dbg: Don't include the gdbm and _tkinter extensions, now provided
+    in separate packages.
+  * Provide a symlink changelog -> NEWS. Closes: #439271.
+  * Fix build failure on hurd, working around poll() on systems on which it
+    returns an error on invalid FDs. Closes: #438914.
+  * Configure --with-system-ffi on all architectures. Closes: #448520.
+  * Fix version numbers in copyright and README files (Dan O'Huiginn).
+    Closes: #446682.
+  * Move some documents from python2.5 to python2.5-dev.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 02 Jan 2008 22:22:19 +0100
+
+python2.5 (2.5.1-5) unstable; urgency=low
+
+  * Build the _bsddb extension with db-4.6.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 17 Aug 2007 00:39:35 +0200
+
+python2.5 (2.5.1-4) unstable; urgency=low
+
+  * Update to 20070813, taken from the 2.5 release branch.
+  * Include plat-mac/plistlib.py (plat-mac is not in sys.path by default.
+    Closes: #435826.
+  * Use emacs22 to build the documentation in info format. Closes: #434969.
+  * Build-depend on db-dev (>= 4.6). Closes: #434965.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 13 Aug 2007 22:22:44 +0200
+
+python2.5 (2.5.1-3) unstable; urgency=high
+
+  * Support mixed-endian IEEE floating point, as found in the ARM old-ABI
+    (Aurelien Jarno). Closes: #434905.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 27 Jul 2007 20:01:35 +0200
+
+python2.5 (2.5.1-2) unstable; urgency=low
+
+  * Update to 20070717, taken from the 2.5 release branch.
+  * Fix reference count for sys.pydebug variable. Addresses: #431393.
+  * Build depend on libbluetooth-dev instead of libbluetooth2-dev.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 17 Jul 2007 14:09:47 +0200
+
+python2.5 (2.5.1-1) unstable; urgency=low
+
+  * Python-2.5.1 release.
+  * Build-depend on gcc-4.1 (>= 4.1.2-4) on alpha, powerpc, s390, sparc.
+  * Merge from Ubuntu:
+    - Add debian/patches/subprocess-eintr-safety.dpatch (LP: #87292):
+      - Create and use wrappers around read(), write(), and os.waitpid() in the
+        subprocess module which retry the operation on an EINTR (which happens
+        if e. g. an alarm was raised while the system call was in progress).
+        It is incredibly hard and inconvenient to sensibly handle this in
+        applications, so let's fix this at the right level.
+      - Patch based on original proposal of Peter <C3><85>strand
+        in http://python.org/sf/1068268.
+      - Add two test cases.
+    - Change the interpreter to build and install python extensions
+      built with the python-dbg interpreter with a different name into
+      the same path (by appending `_d' to the extension name). The debug build
+      of the interpreter tries to first load a foo_d.so or foomodule_d.so
+      extension, then tries again with the normal name.
+    - When trying to import the profile and pstats modules, don't
+      exit, add a hint to the exception pointing to the python-profiler
+      package, don't exit.
+    - Keep the module version in the .egg-info name, only remove the
+      python version.
+    - python2.5-dbg: Install Misc/SpecialBuilds.txt, document the
+      debug changes in README.debug.
+  * Update to 20070425, taken from the 2.5 release branch.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 25 Apr 2007 22:12:50 +0200
+
+python2.5 (2.5-6) unstable; urgency=medium
+
+  * webbrowser.py: Recognize other browsers: www-browser, x-www-browser,
+    iceweasel, iceape.
+  * Move pyconfig.h from the python2.5-dev into the python2.5 package;
+    required by builds for pure python modules without having python2.5-dev
+    installed (matching the functionality in python2.4).
+  * Move the unicodedata module into python2.5-minimal; allows byte compilation
+    of UTF8 encoded files.
+  * Do not install anymore outdated debhelper sample scripts.
+  * Install Misc/SpecialBuilds.txt as python2.5-dbg document.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 21 Feb 2007 01:17:12 +0100
+
+python2.5 (2.5-5) unstable; urgency=high
+
+  * Do not run the python benchmark on m68k. Timer problems.
+    Fixes FTBFS on m68k.
+  * Update to 20061209, taken from the 2.5 release branch.
+    -  Fixes building the library reference in info format.
+
+ -- Matthias Klose <doko@debian.org>  Sat,  9 Dec 2006 13:40:48 +0100
+
+python2.5 (2.5-4) unstable; urgency=medium
+
+  * Update to 20061203, taken from the 2.5 release branch.
+    - Fixes build failures on knetfreebsd and the hurd. Closes: #397000.
+  * Clarify README about distutils. Closes: #396394.
+  * Move python2.5-config to python2.5-dev. Closes: #401451.
+  * Cleanup build-conflicts. Addresses: #394512.
+
+ -- Matthias Klose <doko@debian.org>  Sun,  3 Dec 2006 18:22:49 +0100
+
+python2.5 (2.5-3.1) unstable; urgency=low
+
+  * Non-maintainer upload.
+  * python2.5-minimal depends on python-minimal (>= 2.4.4-1) because it's the
+    first version which lists python2.5 as an unsupported runtime (ie a
+    runtime that is available but for which modules are not auto-compiled).
+    And being listed there is required for python-central to accept the
+    installation of python2.5-minimal. Closes: #397006
+
+ -- Raphael Hertzog <hertzog@debian.org>  Wed, 22 Nov 2006 15:41:06 +0100
+
+python2.5 (2.5-3) unstable; urgency=medium
+
+  * Update to 20061029 (2.4.4 was released on 20061019), taken from
+    the 2.5 release branch. We do not want to have regressions in
+    2.5 compared to the 2.4.4 release.
+  * Don't run pybench on m68k, fails in the calibration loop. Closes: #391030.
+  * Run the installation/removal hooks. Closes: #383292, #391036.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 29 Oct 2006 11:35:19 +0100
+
+python2.5 (2.5-2) unstable; urgency=medium
+
+  * Update to 20061003, taken from the 2.5 release branch.
+  * On arm and m68k, don't run the pybench in debug mode.
+  * Fix building the source within exec_prefix (Alexander Wirt).
+    Closes: #385336.
+
+ -- Matthias Klose <doko@debian.org>  Tue,  3 Oct 2006 10:08:36 +0200
+
+python2.5 (2.5-1) unstable; urgency=low
+
+  * Python 2.5 release.
+  * Update to 20060926, taken from the 2.5 release branch.
+  * Run the Python benchmark during the build, compare the results
+    of the static and shared builds.
+  * Fix invalid html in python2.5.devhelp.gz.
+  * Add a python2.5 console entry to the menu (hidden by default).
+  * python2.5: Suggest python-profiler.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 26 Sep 2006 02:36:11 +0200
+
+python2.5 (2.5~c1-1) unstable; urgency=low
+
+  * Python 2.5 release candidate 1.
+  * Update to trunk 20060818.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 19 Aug 2006 19:21:05 +0200
+
+python2.5 (2.5~b3-1) unstable; urgency=low
+
+  * Build the _ctypes module for m68k-linux.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 11 Aug 2006 18:19:19 +0000
+
+python2.5 (2.5~b3-0ubuntu1) edgy; urgency=low
+
+  * Python 2.5 beta3 release.
+  * Update to trunk 20060811.
+  * Rebuild the documentation.
+  * Fix value of sys.exec_prefix in the debug build.
+  * Do not build the library reference in info format; fails to build.
+  * Link the interpreter against the shared runtime library. With
+    gcc-4.1 the difference in the pystones benchmark dropped from about
+    12% to about 6%.
+  * Install the statically linked version of the interpreter as
+    python2.5-static for now.
+  * Link the shared libpython with -O1.
+
+ -- Matthias Klose <doko@ubuntu.com>  Thu, 10 Aug 2006 14:04:48 +0000
+
+python2.5 (2.4.3+2.5b2-3) unstable; urgency=low
+
+  * Disable the testsuite on s390; don't care about "minimally configured"
+    buildd's.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 23 Jul 2006 11:45:03 +0200
+
+python2.5 (2.4.3+2.5b2-2) unstable; urgency=low
+
+  * Update to trunk 20060722.
+  * Merge idle-lib from idle-python2.5 into python2.5.
+  * Merge lib-tk from python-tk into python2.5.
+  * Tkinter.py: Suggest installation of python-tk package on failed
+    import of the _tkinter extension.
+  * Don't run the testsuite for the debug build on alpha.
+  * Don't run the test_compiler test on m68k. Just takes too long.
+  * Disable building ctypes on m68k (requires support for closures).
+
+ -- Matthias Klose <doko@debian.org>  Sat, 22 Jul 2006 22:26:42 +0200
+
+python2.5 (2.4.3+2.5b2-1) unstable; urgency=low
+
+  * Python 2.5 beta2 release.
+  * Update to trunk 20060716.
+  * When built on a buildd, do not run the following test which try to
+    access the network: test_codecmaps_cn, test_codecmaps_hk, test_codecmaps_jp,
+    test_codecmaps_kr, test_codecmaps_tw, test_normalization.
+  * When built on a buildd, do not run tests requiring missing write permissions:
+    test_ossaudiodev.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 16 Jul 2006 02:53:50 +0000
+
+python2.5 (2.4.3+2.5b2-0ubuntu1) edgy; urgency=low
+
+  * Python 2.5 beta2 release.
+
+ -- Matthias Klose <doko@ubuntu.com>  Thu, 13 Jul 2006 17:16:52 +0000
+
+python2.5 (2.4.3+2.5b1-1ubuntu2) edgy; urgency=low
+
+  * Fix python-dev dependencies.
+  * Update to trunk 20060709.
+
+ -- Matthias Klose <doko@ubuntu.com>  Sun,  9 Jul 2006 18:50:32 +0200
+
+python2.5 (2.4.3+2.5b1-1ubuntu1) edgy; urgency=low
+
+  * Python 2.5 beta1 release.
+  * Update to trunk 20060623.
+  * Merge changes from the python2.4 packages.
+  * python2.5-minimal: Add _struct.
+
+ -- Matthias Klose <doko@ubuntu.com>  Fri, 23 Jun 2006 16:04:46 +0200
+
+python2.5 (2.4.3+2.5a1-1) experimental; urgency=low
+
+  * Update to trunk 20060409.
+  * Run testsuite for debug build as well.
+  * Build-depend on gcc-4.1.
+
+ -- Matthias Klose <doko@debian.org>  Sun,  9 Apr 2006 22:27:05 +0200
+
+python2.5 (2.4.3+2.5a1-0ubuntu1) dapper; urgency=low
+
+  * Python 2.5 alpha1 release.
+  * Drop integrated patches.
+  * Add build dependencies on libsqlite3-dev and libffi4-dev.
+  * Add (build-)dependency on mime-support, libgpmg1 (test suite).
+  * Build using the system FFI.
+  * python2.5 provides python2.5-ctypes and python2.5-pysqlite2,
+    python2.5-elementtree.
+  * Move hashlib.py to python-minimal.
+  * Lib/hotshot/pstats.py: Error out on missing profile/pstats modules.
+
+ -- Matthias Klose <doko@ubuntu.com>  Wed,  5 Apr 2006 14:56:15 +0200
+
+python2.4 (2.4.3-8ubuntu1) edgy; urgency=low
+
+  * Resynchronize with Debian unstable. Remaining changes:
+    - Apply langpack-gettext patch.
+    - diff.gz contains pregenerated html and info docs.
+    - Build the -doc package from this source.
+
+ -- Matthias Klose <doko@ubuntu.com>  Thu, 22 Jun 2006 18:39:57 +0200
+
+python2.4 (2.4.3-8) unstable; urgency=low
+
+  * Remove python2.4's dependency on python-central. On installation of
+    the runtime, call hooks /usr/share/python/runtime.d/*.rtinstall.
+    On removal, call hooks /usr/share/python/runtime.d/*.rtremove.
+    Addresses: #372658.
+  * Call the rtinstall hooks only, if it's a new installation, or the first
+    installation using the hooks. Adresses: #373677.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 18 Jun 2006 00:56:13 +0200
+
+python2.4 (2.4.3-7) unstable; urgency=medium
+
+  * Reupload, depend on python-central (>= 0.4.15).
+  * Add build-conflict on python-xml.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 14 Jun 2006 18:56:57 +0200
+
+python2.4 (2.4.3-6) medium; urgency=low
+
+  * idle-python2.4: Remove the old postinst and prerm scripts.
+  * Name the runtime correctly in python2.4-minimal's installation
+    scripts.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 12 Jun 2006 17:39:56 +0000
+
+python2.4 (2.4.3-5) unstable; urgency=low
+
+  * python2.4-prerm: Handle the case, when python-central is not installed.
+  * idle-python2.4: Depend on python-tk instead of python2.4-tk.
+
+ -- Matthias Klose <doko@debian.org>  Fri,  9 Jun 2006 05:17:17 +0200
+
+python2.4 (2.4.3-4) unstable; urgency=low
+
+  * SVN update up to 2006-06-07
+  * Use python-central.
+  * Don't build the -tk and -gdbm packages from this source; now built
+    from the python-stdlib-extensions source.
+  * Remove leftover build dependency on libgmp3-dev.
+  * Do not build-depend on libbluetooth1-dev and libgpmg1-dev on
+    hurd-i386, kfreebsd-i386, kfreebsd-amd64. Closes: #365830.
+  * Do not run the test_tcl test; hangs for unknown reasons on at least
+    the following buildds: vivaldi(m68k), goedel (alpha), mayer (mipsel).
+    And no virtual package to file bug reports for the buildds ...
+    Closes: #364419.
+  * Move the Makefile from python2.4-dev to python2.4. Closes: #366473.
+  * Fix typo in pdb(1). Closes: #365772.
+  * New autoconf likes the mandir in /usr/share instead of /usr; work
+    with both locations. Closes: #367618.
+       
+ -- Matthias Klose <doko@debian.org>  Wed,  7 Jun 2006 21:37:20 +0200
+
+python2.4 (2.4.3-3) unstable; urgency=low
+
+  * SVN update up to 2006-04-21
+  * Update locale aliases from /usr/share/X11/locale/locale.alias.
+  * Start idle with option -n from the desktop menu, so that the program
+    can be started in parallel.
+  * Testsuite related changes only:
+    - Add build dependencies mime-support, libgpmg1 (needed by test cases).
+    - Run the testsuite with bsddb, audio and curses resources enabled.
+    - Re-run the failed tests in verbose mode.
+    - Run the test suite for the debug build as well.
+    - Build depend on netbase, needed by test_socketmodule.
+    - Build depend on libgpmg1, needed by test_curses.
+    - On the buildds do not run the tests needing the network resource.
+  * Update python logo.
+  * Check for the availability of the profile and pstats modules when
+    importing hotshot.pstats. Closes: #334067.
+  * Don't build the -doc package from the python2.4 source.
+  * Set OPT in the installed Makefile to -O2.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 21 Apr 2006 19:58:43 +0200
+
+python2.4 (2.4.3-2) unstable; urgency=low
+
+  * Add (build-)dependency on mime-support.
+
+ -- Matthias Klose <doko@ubuntu.com>  Tue,  4 Apr 2006 22:21:41 +0200
+
+python2.4 (2.4.3-1) unstable; urgency=low
+
+  * Python 2.4.3 release.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 30 Mar 2006 23:42:37 +0200
+
+python2.4 (2.4.3-0ubuntu1) dapper; urgency=low
+
+  * Python 2.4.3 release.
+    - Fixed a bug that the gb18030 codec raises RuntimeError on encoding
+      surrogate pair area on UCS4 build. Ubuntu: #29289.
+
+ -- Matthias Klose <doko@ubuntu.com>  Thu, 30 Mar 2006 10:57:32 +0200
+
+python2.4 (2.4.2+2.4.3c1-0ubuntu1) dapper; urgency=low
+
+  * SVN update up to 2006-03-25 (2.4.3 candidate 1).
+    - Regenerate the documentation.
+
+ -- Matthias Klose <doko@ubuntu.com>  Mon, 27 Mar 2006 12:03:05 +0000
+
+python2.4 (2.4.2-1ubuntu3) dapper; urgency=low
+
+  * SVN update up to 2006-03-04
+    - Regenerate the documentation.
+    - map.mmap(-1, size, ...) can return anonymous memory again on Unix.
+      Ubuntu #26201.
+  * Build-depend on libncursesw5-dev, ncursesw5 is preferred for linking.
+    Provides UTF-8 compliant curses bindings.
+  * Fix difflib where certain patterns of differences were making difflib
+    touch the recursion limit.
+
+ -- Matthias Klose <doko@ubuntu.com>  Sat,  4 Mar 2006 21:38:24 +0000
+
+python2.4 (2.4.2-1ubuntu2) dapper; urgency=low
+
+  * SVN update up to 2006-01-17
+    - pwd is now a builtin module, remove it from python-minimal.
+    - Regenerate the documentation.
+  * python2.4-tk: Suggest tix instead of tix8.1.
+  * Move config/Makefile from the -dev package into the runtime package
+    to be able to use the bdist_wininst distutils command. Closes: #348335.
+
+ -- Matthias Klose <doko@ubuntu.com>  Tue, 17 Jan 2006 11:02:24 +0000
+
+python2.4 (2.4.2-1ubuntu1) dapper; urgency=low
+
+  * Temporarily remove build dependency on lsb-release.
+
+ -- Matthias Klose <doko@ubuntu.com>  Sun, 20 Nov 2005 17:40:18 +0100
+
+python2.4 (2.4.2-1build1) dapper; urgency=low
+
+  * Rebuild (openssl-0.9.8).
+
+ -- Matthias Klose <doko@ubuntu.com>  Sun, 20 Nov 2005 15:27:24 +0000
+
+python2.4 (2.4.2-1) unstable; urgency=low
+
+  * Python 2.4.2 release.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 29 Sep 2005 01:49:28 +0200
+
+python2.4 (2.4.1+2.4.2rc1-1) unstable; urgency=low
+
+  * Python 2.4.2 release candidate 1.
+  * Fix "Fatal Python error" from cStringIO's writelines.
+    Patch by Andrew Bennetts.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 22 Sep 2005 10:33:22 +0200
+
+python2.4 (2.4.1-5) unstable; urgency=low
+
+  * CVS update up to 2005-09-14
+    - Regenerate the html and info docs.
+  * Add some more locale aliases.
+  * Fix substitution pf python version in README.python2.4-minimal.
+    Closes: #327487.
+  * On m68k, build using -O2 (closes: #326903).
+  * On Debian, don't configure --with-fpectl, which stopped working with
+    glibc-2.3.5.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 14 Sep 2005 17:32:56 +0200
+
+python2.4 (2.4.1-4) unstable; urgency=low
+
+  * CVS update up to 2005-09-04
+    - teTeX 3.0 related fixes (closes: #322407).
+    - Regenerate the html and info docs.
+  * Add entry for IDLE in the Gnome menus.
+  * Don't build-depend on libbluetooth-dev on the Hurd (closes: #307037).
+  * Reenable the cthreads patch for the Hurd (closes: #307052).
+
+ -- Matthias Klose <doko@debian.org>  Sun,  4 Sep 2005 18:31:42 +0200
+
+python2.4 (2.4.1-3) unstable; urgency=low
+
+  * Synchronise with Ubuntu:
+    - Build a python2.4-minimal package.
+
+ -- Matthias Klose <doko@debian.org>  Tue, 12 Jul 2005 00:23:10 +0000
+
+python2.4 (2.4.1-2ubuntu3) breezy; urgency=low
+
+  * CVS update up to 2005-07-07
+  * Regenerate the documentation.
+
+ -- Matthias Klose <doko@ubuntu.com>  Thu,  7 Jul 2005 09:21:28 +0200
+
+python2.4 (2.4.1-2ubuntu2) breezy; urgency=low
+
+  * CVS update up to 2005-06-15
+  * Regenerate the documentation.
+  * Synchronize with Debian. Ubuntu 10485.
+  * idle-python2.4 enhances python2.4. Ubuntu 11562.
+  * README.Debian: Fix reference to the doc directory (closes: #311677).
+
+ -- Matthias Klose <doko@debian.org>  Wed, 15 Jun 2005 08:56:57 +0200
+
+python2.4 (2.4.1-2ubuntu1) breezy; urgency=low
+
+  * Update build dependencies:
+      db4.2-dev -> db4.3-dev,
+      libreadline4-dev -> libreadline5-dev.
+  * python2.4-dev: Add missing templates to generate HTML docs. Ubuntu 11531.
+
+ -- Matthias Klose <doko@ubuntu.com>  Sun, 29 May 2005 00:01:05 +0200
+
+python2.4 (2.4.1-2) unstable; urgency=low
+
+  * Add the debug symbols for the python2.4, python2.4-gdbm
+    and python2.4-tk packages to the python2.4-dbg package.
+  * Add gdbinit example to doc directory.
+
+ -- Matthias Klose <doko@debian.org>  Thu,  5 May 2005 11:12:32 +0200
+
+python2.4 (2.4.1-1ubuntu2) breezy; urgency=low
+
+  * Add the debug symbols for the python2.4, python2.4-minimal, python2.4-gdbm
+    and python2.4-tk packages to the python2.4-dbg package. Ubuntu 10261, 
+  * Add gdbinit example to doc directory.
+  * For os.utime, use utimes(2), correctly working with glibc-2.3.5.
+    Ubuntu 10294.
+
+ -- Matthias Klose <doko@ubuntu.com>  Thu,  5 May 2005 09:06:07 +0200
+
+python2.4 (2.4.1-1ubuntu1) breezy; urgency=low
+
+  * Reupload as 2.4.1-1ubuntu1.
+
+ -- Matthias Klose <doko@ubuntu.com>  Thu, 14 Apr 2005 10:46:32 +0200
+
+python2.4 (2.4.1-1) unstable; urgency=low
+
+  * Python 2.4.1 release.
+  * Fix noise in python-doc installation/removal.
+  * New Python section for the info docs.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 30 Mar 2005 19:42:03 +0200
+
+python2.4 (2.4.1-0) hoary; urgency=low
+
+  * Python 2.4.1 release.
+  * Fix noise in python-doc installation/removal.
+  * New Python section for the info docs.
+
+ -- Matthias Klose <doko@ubuntu.com>  Wed, 30 Mar 2005 16:35:34 +0200
+
+python2.4 (2.4+2.4.1rc2-2) unstable; urgency=low
+
+  * Add the valgrind support file to /etc/python2.4
+  * Build the -dbg package with -DPy_USING_MEMORY_DEBUGGER.
+  * Lib/locale.py:
+    - correctly parse LANGUAGE as a colon separated list of languages.
+    - prefer LC_ALL, LC_CTYPE and LANG over LANGUAGE to get the correct
+      encoding.
+    - Don't map 'utf8', 'utf-8' to 'utf', which is not a known encoding
+      for glibc.
+  * Fix two typos in python(1). Addresses: #300124.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 19 Mar 2005 21:50:14 +0100
+
+python2.4 (2.4+2.4.1rc2-1) unstable; urgency=low
+
+  * Python 2.4.1 release candidate 2.
+  * Build-depend on libbluetooth1-dev.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 19 Mar 2005 00:57:14 +0100
+
+python2.4 (2.4dfsg-2) unstable; urgency=low
+
+  * CVS update up to 2005-03-03
+
+ -- Matthias Klose <doko@debian.org>  Thu,  3 Mar 2005 22:22:16 +0100
+
+python2.4 (2.4dfsg-1ubuntu4) hoary; urgency=medium
+
+  * Move exception finalisation later in the shutdown process - this
+    fixes the crash seen in bug #1165761, taken from CVS.
+  * codecs.StreamReader: Reset codec when seeking. Ubuntu #6972.
+  * Apply fix for SF1124295, fixing an obscure bit of Zope's security machinery.
+  * distutils: Don't add standard library dirs to library_dirs
+    and runtime_library_dirs. On amd64, runtime paths pointing to /usr/lib64
+    aren't recognized by dpkg-shlibdeps, and the packages containing these
+    libraries aren't added to ${shlibs:Depends}.
+  * Lib/locale.py:
+    - correctly parse LANGUAGE as a colon separated list of languages.
+    - prefer LC_ALL, LC_CTYPE and LANG over LANGUAGE to get the correct
+      encoding.
+    - Don't map 'utf8', 'utf-8' to 'utf', which is not a known encoding
+      for glibc.
+  * os.py: Avoid using items() in environ.update(). Fixes #1124513.
+  * Python/pythonrun.c: 
+  * Build depend on locales, generate the locales needed for the
+    testsuite.
+  * Add build dependency on libbluetooth1-dev, adding some bluetooth
+    functionality to the socket module.
+  * Lib/test/test_sundry.py: Don't fail on import of profile & pstats,
+    which are separated out to the python-profiler package.
+  * Fix typos in manpage.
+
+ -- Matthias Klose <doko@ubuntu.com>  Tue, 29 Mar 2005 13:35:53 +0200
+
+
+python2.4 (2.4dfsg-1ubuntu3) hoary; urgency=low
+
+  * debian/patches/langpack-gettext.dpatch:
+    - langpack support for python-gettext added
+
+ -- Michael Vogt <michael.vogt@ubuntu.com>  Tue,  1 Mar 2005 13:13:36 +0100
+
+python2.4 (2.4dfsg-1ubuntu2) hoary; urgency=low
+
+  * Revert 'essential' status on python2.4-minimal. This status on
+    on python-minimal is sufficient (Ubuntu #6392).
+
+ -- Matthias Klose <doko@ubuntu.com>  Wed,  9 Feb 2005 23:09:42 +0100
+
+python2.4 (2.4dfsg-1ubuntu1) hoary; urgency=low
+
+  * Resyncronise with Debian.
+  * Mark the python2.4-minimal package as 'essential'.
+
+ -- Matthias Klose <doko@ubuntu.com>  Wed,  9 Feb 2005 13:31:09 +0100
+
+python2.4 (2.4dfsg-1) unstable; urgency=medium
+
+  * Add licenses and acknowledgements for incorporated software in the
+    debian/copyright file (addresses: #293932).
+  * Replace md5 implementation with one having a DFSG conforming license.
+  * Remove the profile.py and pstats.py modules from the source package,
+    not having a DFSG conforming license. The modules can be found in
+    the python2.x-profile package in the non-free section.
+    Addresses: #293932.
+  * Add missing norwegian locales (Tollef Fog Heen).
+  * CVS updates of the release24-maint branch upto 2005-02-08 (date of
+    the Python 2.3.5 release).
+
+ -- Matthias Klose <doko@debian.org>  Tue,  8 Feb 2005 19:13:10 +0100
+
+python2.4 (2.4-7ubuntu1) hoary; urgency=low
+
+  * Fix the name of the python-dbg man page.
+  * Resyncronise with Debian.
+  * Move more modules to -minimal (new code in copy.py requires these):
+    dis, inspect, opcode, token, tokenize.
+
+ -- Matthias Klose <doko@ubuntu.com>  Tue,  8 Feb 2005 19:13:10 +0100
+
+python2.4 (2.4-7) unstable; urgency=medium
+
+  * Add licenses and acknowledgements for incorporated software in the
+    debian/copyright file (addresses: #293932).
+  * Replace md5 implementation with one having a DFSG conforming license.
+  * Add missing norwegian locales (Tollef Fog Heen).
+  * CVS updates of the release24-maint branch upto 2005-02-08 (date of
+    the Python 2.3.5 release).
+
+ -- Matthias Klose <doko@debian.org>  Tue,  8 Feb 2005 19:13:10 +0100
+
+python2.4 (2.4-6) unstable; urgency=low
+
+  * Build a python2.4-dbg package using --with-pydebug. Add a debug
+    directory <prefix>/lib-dynload/debug to sys.path instead of
+    <prefix>/lib-dynload und install the extension modules of the
+    debug build in this directory.
+    Change the module load path to load extension modules from other
+    site-packages/debug directories (for further details see the
+    README in the python2.4-dbg package).  Closes: #5415.
+  * Apply the pydebug-path patch. The package was already built in -5.
+
+ -- Matthias Klose <doko@debian.org>  Fri,  4 Feb 2005 22:15:13 +0100
+
+python2.4 (2.4-5) unstable; urgency=high
+
+  * Fix a flaw in SimpleXMLRPCServerthat can affect any XML-RPC servers.  
+    This affects any programs have been written that allow remote 
+    untrusted users to do unrestricted traversal and can allow them to
+    access or change function internals using the im_* and func_* attributes.
+    References: CAN-2005-0089.
+  * CVS updates of the release24-maint branch upto 2005-02-04.
+
+ -- Matthias Klose <doko@debian.org>  Fri,  4 Feb 2005 08:12:10 +0100
+
+python2.4 (2.4-4) unstable; urgency=medium
+
+  * Update debian/copyright to the 2.4 license text (closes: #290898).
+  * Remove /usr/bin/smtpd.py (closes: #291049).
+
+ -- Matthias Klose <doko@debian.org>  Mon, 17 Jan 2005 23:54:37 +0100
+
+python2.4 (2.4-3ubuntu6) hoary; urgency=low
+
+  * Use old-style dpatches instead of dpatch-run.
+
+ -- Tollef Fog Heen <tfheen@canonical.com>  Mon,  7 Feb 2005 15:58:05 +0100
+
+python2.4 (2.4-3ubuntu5) hoary; urgency=low
+
+  * Actually apply the patch as well (add to list of patches in
+    debian/rules)
+
+ -- Tollef Fog Heen <tfheen@canonical.com>  Sun,  6 Feb 2005 15:12:58 +0100
+
+python2.4 (2.4-3ubuntu4) hoary; urgency=low
+
+  * Add nb_NO and nn_NO locales to Lib/locale.py
+
+ -- Tollef Fog Heen <tfheen@canonical.com>  Sun,  6 Feb 2005 14:33:05 +0100
+
+python2.4 (2.4-3ubuntu3) hoary; urgency=low
+
+  * Fix a flaw in SimpleXMLRPCServerthat can affect any XML-RPC servers.
+    This affects any programs have been written that allow remote
+    untrusted users to do unrestricted traversal and can allow them to
+    access or change function internals using the im_* and func_* attributes.
+    References: CAN-2005-0089.
+
+ -- Matthias Klose <doko@ubuntu.com>  Wed,  2 Feb 2005 09:08:20 +0000
+
+python2.4 (2.4-3ubuntu2) hoary; urgency=low
+
+  * Build a python2.4-dbg package using --with-pydebug. Add a debug
+    directory <prefix>/lib-dynload/debug to sys.path instead of
+    <prefix>/lib-dynload und install the extension modules of the
+    debug build in this directory.
+    Change the module load path to load extension modules from other
+    site-packages/debug directories (for further details see the
+    README in the python2.4-dbg package).  Closes: #5415.
+  * Update debian/copyright to the 2.4 license text (closes: #290898).
+  * Add operator and copy to the -minimal package.
+
+ -- Matthias Klose <m@klose.in-berlin.de>  Mon, 17 Jan 2005 23:19:47 +0100
+
+python2.4 (2.4-3ubuntu1) hoary; urgency=low
+
+  * Resynchronise with Debian.
+  * python2.4: Depend on the very same version of python2.4-minimal.
+  * Docment, that time.strptime currently cannot be used, if the
+    python-minimal package is installed without the python package.
+
+ -- Matthias Klose <m@klose.in-berlin.de>  Sun,  9 Jan 2005 19:35:48 +0100
+
+python2.4 (2.4-3) unstable; urgency=medium
+
+  * Build the fpectl module.
+  * Updated to CVS release24-maint 20050107.
+
+ -- Matthias Klose <doko@debian.org>  Sat,  8 Jan 2005 19:05:21 +0100
+
+python2.4 (2.4-2ubuntu5) hoary; urgency=low
+
+  * Updated to CVS release24-maint 20050102.
+  * python-minimal:
+    - os.py: Use dict instead of UserDict, remove UserDict from -minimal.
+    - add pickle, threading, needed for subprocess module.
+    - optparse.py: conditionally import gettext, if not available,
+      define _ as the identity function. Patch taken from the trunk.
+      Avoids import of _locale, locale, gettext, copy, repr, itertools,
+      collections, token, tokenize.
+    - Add a build check to make sure that the minimal module list is
+      closed under dependency.
+  * Fix lintian warnings.
+
+ -- Matthias Klose <m@klose.in-berlin.de>  Sun,  2 Jan 2005 22:00:14 +0100
+
+python2.4 (2.4-2ubuntu4) hoary; urgency=low
+
+  * Add UserDict.py to the -minimal package, since os.py needs it.
+
+ -- Colin Watson <cjwatson@canonical.com>  Thu, 30 Dec 2004 20:41:28 +0000
+
+python2.4 (2.4-2ubuntu3) hoary; urgency=low
+
+  * Add os.py and traceback.py to the -minimal package, get the list
+    of modules from the README.
+
+ -- Matthias Klose <m@klose.in-berlin.de>  Mon, 27 Dec 2004 08:20:45 +0100
+
+python2.4 (2.4-2ubuntu2) hoary; urgency=low
+
+  * Add compileall.py and py_compile.py to the -minimal package, not
+    just to the README ...
+
+ -- Matthias Klose <m@klose.in-berlin.de>  Sat, 25 Dec 2004 22:24:56 +0100
+
+python2.4 (2.4-2ubuntu1) hoary; urgency=low
+
+  * Separate the interpreter and a minimal subset of modules into
+    a python2.4-minimal package. See the README.Debian.gz in this
+    package.
+  * Move site.py to python2.4-minimal as well.
+  * Add documentation files for devhelp.
+
+ -- Matthias Klose <m@klose.in-berlin.de>  Sun, 19 Dec 2004 22:47:32 +0100
+
+python2.4 (2.4-2) unstable; urgency=medium
+
+  * Updated patch for #283108. Thanks to Jim Meyering.
+
+ -- Matthias Klose <doko@debian.org>  Fri,  3 Dec 2004 17:00:16 +0100
+
+python2.4 (2.4-1) unstable; urgency=low
+
+  * Final 2.4 release.
+  * Flush stdout/stderr if closed (SF #1074011).
+
+ -- Matthias Klose <doko@debian.org>  Wed,  1 Dec 2004 07:54:34 +0100
+
+python2.4 (2.3.97-2) unstable; urgency=low
+
+  * Don't run test_tcl, hanging on the buildds.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 19 Nov 2004 23:48:42 +0100
+
+python2.4 (2.3.97-1) unstable; urgency=low
+
+  * Python 2.4 Release Candidate 1.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 19 Nov 2004 21:27:02 +0100
+
+python2.4 (2.3.96-1) experimental; urgency=low
+
+  * Updated to CVS release24-maint 20041113.
+  * Build the docs in info format again.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 13 Nov 2004 21:21:10 +0100
+
+python2.4 (2.3.95-2) experimental; urgency=low
+
+  * Move distutils package from the python2.4-dev into the python2.4
+    package.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 11 Nov 2004 22:56:14 +0100
+
+python2.4 (2.3.95-1) experimental; urgency=low
+
+  * Python 2.4 beta2 release.
+
+ -- Matthias Klose <doko@debian.org>  Thu,  4 Nov 2004 23:43:47 +0100
+
+python2.4 (2.3.94-1) experimental; urgency=low
+
+  * Python 2.4 beta1 release.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 16 Oct 2004 08:33:57 +0200
+
+python2.4 (2.3.93-1) experimental; urgency=low
+
+  * Python 2.4 alpha3 release.
+
+ -- Matthias Klose <doko@debian.org>  Fri,  3 Sep 2004 21:53:47 +0200
+
+python2.4 (2.3.92-1) experimental; urgency=low
+
+  * Python 2.4 alpha2 release.
+
+ -- Matthias Klose <doko@debian.org>  Thu,  5 Aug 2004 23:53:18 +0200
+
+python2.4 (2.3.91-1) experimental; urgency=low
+
+  * Python 2.4 alpha1 release.
+    Highlights: http://www.python.org/2.4/highlights.html
+
+ -- Matthias Klose <doko@debian.org>  Fri,  9 Jul 2004 17:38:54 +0200
+
+python2.4 (2.3.90-1) experimental; urgency=low
+
+  * Package HEAD branch (pre alpha ..).
+
+ -- Matthias Klose <doko@debian.org>  Mon, 14 Jun 2004 23:19:57 +0200
+
+python2.3 (2.3.4-1) unstable; urgency=medium
+
+  * Final Python 2.3.4 Release.
+  * In the API docs, fix signature of PyModule_AddIntConstant (closes: #250826).
+  * locale.getdefaultlocale: don't fail with empty environment variables.
+    Closes: #249816.
+  * Include distutils/command/wininst.exe in -dev package (closes: #249006).
+  * Disable cthreads on the Hurd (Michael Banck). Closes: #247211.
+  * Add a note to pygettext(1), that this program is deprecated in favour
+    of xgettext, which now includes support for Python as well.
+    Closes: #246332.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 28 May 2004 22:59:42 +0200
+
+python2.3 (2.3.3.91-1) unstable; urgency=low
+
+  * Python 2.3.4 Release Candidate 1.
+  * Do not use the default namespace for attributes. Patch taken from the
+    2.3 maintenance branch.
+    The xmllib module is obsolete.  Use xml.sax instead.
+  * http://python.org/sf/945642 - fix nonblocking i/o with ssl socket.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 13 May 2004 21:24:52 +0200
+
+python2.3 (2.3.3-7) unstable; urgency=low
+
+  * Add a workaround for GNU libc nl_langinfo()'s returning NULL.
+    Closes: #239237.
+    Patch taken from 2.3 maintenance branch.
+  * threading.py: Remove calls to currentThread() in _Condition methods that
+    were side-effect. Side-effects were deemed unnecessary and were causing
+    problems at shutdown time when threads were catching exceptions at start
+    time and then triggering exceptions trying to call currentThread() after
+    gc'ed.  Masked the initial exception which was deemed bad.
+    Closes: #195812.
+  * Properly support normalization of empty unicode strings. Closes: #239986.
+    Patch taken from 2.3 maintenance branch.
+  * README.maintainers: Add section where to find the documentation tools.
+  * Fix crash in pyexpat module (closes: #229281).
+  * For the Hurd, set the interpreters recursion limit to 930.
+  * Do not try to byte-compile the test files on installation; this
+    currently breaks the Hurd install.
+
+ -- Matthias Klose <doko@debian.org>  Sat,  1 May 2004 07:50:46 +0200
+
+python2.3 (2.3.3-6) unstable; urgency=low
+
+  * Don't build the unversioned python{,-*} packages anymore. Now
+    built from the python-defaults package.
+  * Update to the proposed python-policy: byte-compile using -E.
+  * Remove python-elisp's dependency on emacs20 (closes: #232785).
+  * Don't build python-elisp from the python2.3 source anymore,
+    get it from python-mode.sf.net as a separate source package.
+  * python2.3-dev suggests libc-dev (closes: #231091).
+  * get LDSHARED and CCSHARED (like, CC, CXX, CPP, CFLAGS) from 
+    the environment
+  * Set CXX in installed config/Makefile (closes: #230273).
+
+ -- Matthias Klose <doko@debian.org>  Tue, 24 Feb 2004 07:07:51 +0100
+
+python2.3 (2.3.3-5) unstable; urgency=low
+
+  * Build-depend on libdb4.2-dev, instead of libdb4.1-dev. According
+    to the docs the file format is compatible.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 12 Jan 2004 10:37:45 +0100
+
+python2.3 (2.3.3-4) unstable; urgency=low
+
+  * Fix broken _bsddb module. setup.py picked up the wrong library.
+
+ -- Matthias Klose <doko@debian.org>  Sun,  4 Jan 2004 11:30:00 +0100
+
+python2.3 (2.3.3-3) unstable; urgency=low
+
+  * Fix typo in patch (closes: #224797, #226064).
+
+ -- Matthias Klose <doko@debian.org>  Sun,  4 Jan 2004 09:23:21 +0100
+
+python2.3 (2.3.3-2) unstable; urgency=medium
+
+  * Lib/email/Charset: use locale unaware function to lower case of locale
+    name (closes: #224797).
+  * Update python-mode to version from python-mode.sf.net. Fixes highlighting
+    problems (closes: #223520).
+  * Backport from mainline: Add IPV6_ socket options from RFCs 3493 and 3542.
+
+ -- Matthias Klose <doko@debian.org>  Fri,  2 Jan 2004 14:03:26 +0100
+
+python2.3 (2.3.3-1) unstable; urgency=low
+
+  * New upstream release.
+  * Copy the templates, tools and scripts from the Doc dir in the source
+    to /usr/share/lib/python2.3/doc in the python2.3-dev package. Needed
+    for packages building documentation like python does (closes: #207337).
+
+ -- Matthias Klose <doko@debian.org>  Fri, 19 Dec 2003 10:57:39 +0100
+
+python2.3 (2.3.2.91-1) unstable; urgency=low
+
+  * New upstream version (2.3.3 release candidate).
+  * Update python-mode.el (closes: #158811, #159630).
+    Closing unreproducible report (closes: #159628).
+
+ -- Matthias Klose <doko@debian.org>  Sat,  6 Dec 2003 14:41:14 +0100
+
+python2.3 (2.3.2-7) unstable; urgency=low
+
+  * Put the conflict in the correct direction. python2.3 (2.3.2-6) doesn't
+    conflict with python (<= 2.3.2-5) but python (2.3.2-6) conflicts with
+    python2.3 (<= 2.3.2-5) (thanks to Brian May). Really closes #221791.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 21 Nov 2003 00:20:02 +0100
+
+python2.3 (2.3.2-6) unstable; urgency=low
+
+  * Add conflicts with older python{,2.3} packages to fix overwrite
+    errors (closes: #221791).
+
+ -- Matthias Klose <doko@debian.org>  Thu, 20 Nov 2003 07:24:36 +0100
+
+python2.3 (2.3.2-5) unstable; urgency=low
+
+  * Updated to CVS release23-maint 20031119.
+  * Re-upgrade the dependency of python2.3 on python (>= 2.3) to
+    a dependency (closes: #221523).
+
+ -- Matthias Klose <doko@debian.org>  Wed, 19 Nov 2003 00:30:27 +0100
+
+python2.3 (2.3.2-4) unstable; urgency=low
+
+  * Don't build-depend on latex2html (moved to non-free), but keep
+    the prebuilt docs in debian/patches (closes: #221347).
+  * Fix typos in the library reference (closes: #220510, #220954).
+  * Fix typo in python-elisp's autoloading code (closes: #220308).
+  * Update proposed python policy: private modules can be installed
+    into /usr/lib/<module> (arch dependent) and into /usr/share/<module>
+    (arch independent).
+
+ -- Matthias Klose <doko@debian.org>  Tue, 18 Nov 2003 00:41:39 +0100
+
+python2.3 (2.3.2-3) unstable; urgency=low
+
+  * Downgrade the dependency of python2.3 on python (>= 2.3) to
+    a recommendation.
+  * Fix path to interpreter in binfmt file.
+  * Fix segfault in unicodedata module (closes: #218697).
+  * Adjust python-elisp autoload code (closes: #219821).
+
+ -- Matthias Klose <doko@debian.org>  Sun,  9 Nov 2003 19:43:37 +0100
+
+python2.3 (2.3.2-2) unstable; urgency=medium
+
+  * Fix broken doc link (closes: #214217).
+  * Disable wrongly detected large file support for GNU/Hurd.
+  * Really fix the  FTBFS for the binary-indep target (closes: #214303).
+
+ -- Matthias Klose <doko@debian.org>  Mon,  6 Oct 2003 07:54:58 +0200
+
+python2.3 (2.3.2-1) unstable; urgency=low
+
+  * New upstream version.
+  * Fix a FTBFS for the binary-indep target.
+
+ -- Matthias Klose <doko@debian.org>  Sat,  4 Oct 2003 10:20:15 +0200
+
+python2.3 (2.3.1-3) unstable; urgency=low
+
+  * Fix names of codec packages in recommends.
+  * On alpha compile using -mieee (see #212912).
+
+ -- Matthias Klose <doko@debian.org>  Sun, 28 Sep 2003 10:48:12 +0200
+
+python2.3 (2.3.1-2) unstable; urgency=low
+
+  * Update python policy draft (closes: #128911, #163785).
+  * Re-add os.fsync function (closes: #212672).
+  * Let python2.3-doc conflict with older python2.3 versions (closes: #211882).
+  * Add recommends for pythonX.Y-japanese-codecs, pythonX.Y-iconvcodec,
+    pythonX.Y-cjkcodecs, pythonX.Y-korean-codecs (closes: #207161).
+  * Generate binfmt file (closes: #208005).
+  * Add IPPROTO_IPV6 option to the socketmodule (closes: #206569).
+  * Bugs reported against python2.2 and fixed in python2.3:
+    - Crashes in idle (closes: #186887, #200084).
+
+ -- Matthias Klose <doko@debian.org>  Sat, 27 Sep 2003 11:21:47 +0200
+
+python2.3 (2.3.1-1) unstable; urgency=low
+
+  * New upstream version (bug fix release).
+
+ -- Matthias Klose <doko@debian.org>  Wed, 24 Sep 2003 11:27:43 +0200
+
+python2.3 (2.3-4) unstable; urgency=high
+
+  * Disable check for utimes function, which is broken in glibc-2.3.2.
+    Packages using distutils had '1970/01/01-01:00:01' timestamps in files.
+  * Bugs fixed by making python2.3 the default python version:
+    - Canvas.scan_dragto() takes a 3rd optional parmeter "gain".
+      Closes: #158168.
+    - New command line parsing module (closes: #38628).
+    - compileall.py allows compiling single files (closes: #139971).
+  * Bugs reported for 2.2 and fixed in 2.3:
+    - Idle does save files with ASCII characters (closes: #179313).
+    - imaplib support for prefix-quoted strings (closes: #150485).
+    - posixpath includes getctime (closes: #173827).
+    - pydoc has support for keywords (closes: #186775).
+  * Bugs reported for 2.1 and fixed in 2.3:
+    - Fix handling of "#anchor" URLs in urlparse (closes: #147844).
+    - Fix readline if C stdin is not a tty, even if sys.stdin is.
+      Closes: #131810.
+  * Updated to CVS release23-maint 20030810 (fixing memory leaks in
+    array and socket modules).
+  * pydoc's usage output uses the basename of the script.
+  * Don't explicitely remove /etc/python2.3 on purge (closes: #202864).
+  * python conflicts with python-xmlbase (closes: #204773).
+  * Add dependency python (>= 2.3) to python2.3, so make sure the
+    unversioned names can be used.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 10 Aug 2003 09:27:52 +0200
+
+python2.3 (2.3-3) unstable; urgency=medium
+
+  * Fix shlibs file.
+
+ -- Matthias Klose <doko@debian.org>  Fri,  8 Aug 2003 08:45:12 +0200
+
+python2.3 (2.3-2) unstable; urgency=medium
+
+  * Make python2.3 the default python version.
+
+ -- Matthias Klose <doko@debian.org>  Tue,  5 Aug 2003 22:13:22 +0200
+
+python2.3 (2.3-1) unstable; urgency=low
+
+  * Python 2.3 final release.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 30 Jul 2003 08:12:28 +0200
+
+python2.3 (2.2.107-1rc2) unstable; urgency=medium
+
+  * Python 2.3 release candidate 2.
+  * Don't compress .txt files referenced by the html docs (closes: #200298).
+  * Include the email/_compat* files (closes: #200349).
+
+ -- Matthias Klose <doko@debian.org>  Fri, 25 Jul 2003 07:08:09 +0200
+
+python2.3 (2.2.106-2beta2) unstable; urgency=medium
+
+  * Python 2.3 beta2 release, updated to CVS 20030704.
+    - Fixes AssertionError in httplib (closed: #192452).
+    - Fixes uncaught division by zero in difflib.py (closed: #199287).
+  * Detect presence of setgroups(2) at configure time (closes: #199839).
+  * Use default gcc on arm as well.
+
+ -- Matthias Klose <doko@debian.org>  Sat,  5 Jul 2003 10:21:33 +0200
+
+python2.3 (2.2.105-1beta2) unstable; urgency=low
+
+  * Python 2.3 beta2 release.
+    - Includes merged idle fork.
+    - Fixed socket.setdefaulttimeout(). Closes: #189380.
+    - socket.ssl works with _socketobj. Closes: #196082.
+  * Do not link libtix to the _tkinter module. It's loaded via
+   'package require tix' at runtime. python2.3-tkinter now
+    suggests tix8.1 instead.
+  * On arm, use gcc-3.2 to build.
+  * Add -fno-strict-aliasing rules to OPT to avoid warnings
+    "dereferencing type-punned pointer will break strict-aliasing rules",
+    when building with gcc-3.3.
+
+ -- Matthias Klose <doko@debian.org>  Mon, 30 Jun 2003 00:19:32 +0200
+
+python2.3 (2.2.104-1beta1.1) unstable; urgency=low
+
+  * Non-maintainer upload with maintainer consent.
+  * debian/control (Build-Depends): s/libgdbmg1-dev/libgdbm-dev/.
+
+ -- James Troup <james@nocrew.org>  Wed,  4 Jun 2003 02:24:27 +0100
+
+python2.3 (2.2.104-1beta1) unstable; urgency=low
+
+  * Python 2.3 beta1 release, updated to CVS 20030514.
+    - build the current documentation.
+  * Reenable Tix support.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 14 May 2003 07:38:57 +0200
+
+python2.3 (2.2.103-1beta1) unstable; urgency=low
+
+  * Python 2.3 beta1 release, updated to CVS 20030506.
+    - updated due to build problems on mips/mipsel.
+    - keep the 2.3b1 documentation (doc build problems with cvs).
+
+ -- Matthias Klose <doko@debian.org>  Wed,  7 May 2003 06:26:39 +0200
+
+python2.3 (2.2.102-1beta1) unstable; urgency=low
+
+  * Python 2.3 beta1 release.
+
+ -- Matthias Klose <doko@debian.org>  Sat,  3 May 2003 22:45:16 +0200
+
+python2.3 (2.2.101-1exp1) unstable; urgency=medium
+
+  * Python 2.3 alpha2 release, updated to CVS 20030321.
+  * Tkinter: Catch exceptions thrown for undefined substitutions in
+    events (needed for tk 8.4.2).
+
+ -- Matthias Klose <doko@debian.org>  Fri, 21 Mar 2003 21:32:14 +0100
+
+python2.3 (2.2.100-1exp1) unstable; urgency=low
+
+  * Python 2.3 alpha2 release, updated to CVS 20030221.
+
+ -- Matthias Klose <doko@debian.org>  Fri, 21 Feb 2003 19:37:17 +0100
+
+python2.3 (2.2.99-1exp1) unstable; urgency=low
+
+  * Python 2.3 alpha1 release updated to CVS 20030123.
+    - should fix the testsuite (and package build) failure on alpha.
+  * Remove build dependency on libexpat1-dev. Merge the python2.3-xmlbase
+    package into python2.3 (closes: #177739).
+
+ -- Matthias Klose <doko@debian.org>  Thu, 23 Jan 2003 22:48:12 +0100
+
+python2.3 (2.2.98-1exp1) unstable; urgency=low
+
+  * Python 2.3 alpha1 release updated to CVS 20030117.
+  * Build using libdb4.1.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 18 Jan 2003 00:14:01 +0100
+
+python2.3 (2.2.97-1exp1) unstable; urgency=low
+
+  * Python 2.3 alpha1 release updated to CVS 20030109.
+  * Build-Depend on g++ (>= 3:3.2).
+  * Python package maintainers: please wait uploading python dependent
+    packages until python2.2 and python2.1 are compiled using gcc-3.2.
+
+ -- Matthias Klose <doko@debian.org>  Thu,  9 Jan 2003 23:56:42 +0100
+
+python2.3 (2.2.96-1exp1) unstable; urgency=low
+
+  * Python 2.3 alpha1 release (not exactly the tarball, but taken from
+    CVS 20030101).
+    - Includes support for linking with threaded tk8.4 (closes: #172714).
+  * Install and register whatsnew document (closes: #173859).
+  * Properly unregister info documentation.
+
+ -- Matthias Klose <doko@debian.org>  Wed,  1 Jan 2003 17:38:54 +0100
+
+python2.3 (2.2.95-1exp1) unstable; urgency=low
+
+  * Experimental packages from CVS 021212.
+    - data in unicodedate module is up to date (closes: #171061).
+  * Fix idle packaging (closes: #170394).
+  * Configure using unicode UCS-4 (closes: #171062).
+    This change breaks compatibility with binary modules, but what do you
+    expect from experimental packages ... Please recompile dependent packages.
+  * Don't strip binaries for now.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 12 Dec 2002 21:42:27 +0100
+
+python2.3 (2.2.94-1exp1) unstable; urgency=low
+
+  * Experimental packages from CVS 021120.
+  * Remove outdated README.dbm.
+  * Depend on tk8.4.
+  * python-elisp: Install emacsen install file with mode 644 (closes: #167718).
+
+ -- Matthias Klose <doko@debian.org>  Thu, 21 Nov 2002 01:04:51 +0100
+
+python2.3 (2.2.93-1exp1) unstable; urgency=medium
+
+  * Experimental packages from CVS 021015.
+  * Build a static library libpython2.3-pic.a.
+  * Enable large file support for the Hurd (closes: #164602).
+
+ -- Matthias Klose <doko@debian.org>  Tue, 15 Oct 2002 21:06:27 +0200
+
+python2.3 (2.2.92-1exp1) unstable; urgency=low
+
+  * Experimental packages from CVS 020922.
+  * Fix build error on ia64 (closes: #161234).
+  * Build depend on gcc-3.2-3.2.1-0pre2 to fix build error on arm.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 22 Sep 2002 18:30:28 +0200
+
+python2.3 (2.2.91-1exp1) unstable; urgency=low
+
+  * Experimental packages from CVS 020906.
+  * idle-python2.3: Fix conflict (closes: #159267).
+  * Fix location of python-mode.el (closes: #159564, #159619).
+  * Use tix8.1.
+  * Apply fix for distutils/ccompiler problem (closes: #159288).
+
+ -- Matthias Klose <doko@debian.org>  Sat,  7 Sep 2002 09:55:07 +0200
+
+python2.3 (2.2.90-1exp1) unstable; urgency=low
+
+  * Experimental packages from CVS 020820.
+  * Don't build python2.3-elisp, but put the latest version into
+    python-elisp.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 22 Aug 2002 21:52:04 +0200
+
+python2.2 (2.2.1-6) unstable; urgency=low
+
+  * CVS updates of the release22-maint branch upto 2002-07-23.
+  * Enable IPv6 support (closes: #152543).
+  * Add python2.2-tk suggestion for python2.2 (pydoc -g).
+  * Fix from SF patch #527518: proxy config with user+pass authentication.
+  * Point pydoc to the correct location of the docs (closes: #147579).
+  * Remove '*.py[co]' files, when removing the python package,
+    not when purging (closes: #147130).
+  * Update to new py2texi.el version (Milan Zamazal).
+
+ -- Matthias Klose <doko@debian.org>  Mon, 29 Jul 2002 23:11:32 +0200
+
+python2.2 (2.2.1-5) unstable; urgency=low
+
+  * CVS updates of the release22-maint branch upto 2002-05-03.
+  * Build the info docs (closes: #145653).
+
+ -- Matthias Klose <doko@debian.org>  Fri,  3 May 2002 22:35:46 +0200
+
+python2.2 (2.2.1-4) unstable; urgency=high
+
+  * Fix indentation errors introduced in last upload (closes: #143809).
+
+ -- Matthias Klose <doko@debian.org>  Sun, 21 Apr 2002 01:00:14 +0200
+
+python2.2 (2.2.1-3) unstable; urgency=high
+
+  * Add Build-Conflicts: tcl8.0-dev, tk8.0-dev, tcl8.2-dev, tk8.2-dev.
+    Closes: #143534 (build a working _tkinter module, on machines, where
+    8.0's tk.h gets included).
+  * CVS updates of the release22-maint branch upto 2002-04-20.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 20 Apr 2002 09:22:37 +0200
+
+python2.2 (2.2.1-2) unstable; urgency=low
+
+  * Forgot to copy the dlmodule patch from the 2.1.3 package. Really
+    closes: #141681.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 13 Apr 2002 01:28:05 +0200
+
+python2.2 (2.2.1-1) unstable; urgency=high
+
+  * Final 2.2.1 release.
+  * According to report #131813, the python interpreter is much faster on some
+    architectures, when beeing linked statically with the python library (25%).
+    Gregor and me tested on i386, m68k and alpha, but we could not reproduce
+    such a speedup (generally between 5% and 10%). But we are linking the
+    python executable now statically ...
+  * Build info docs from the tex source, merge the python-doc-info
+    package into the python-doc package.
+  * Always build the dl module. Failure in case of
+        sizeof(int)!=sizeof(long)!=sizeof(void*)
+    is delayed until dl.open is called. Closes: #141681.
+
+ -- Matthias Klose <doko@debian.org>  Thu, 11 Apr 2002 00:19:19 +0200
+
+python2.2 (2.2.0.92-0) unstable; urgency=low
+
+  * Package CVS sources, omit cvs-updates.dpatch (closes: #140977).
+
+ -- Matthias Klose <doko@debian.org>  Wed,  3 Apr 2002 08:20:52 +0200
+
+python2.2 (2.2-6) unstable; urgency=medium
+
+  * Update to python-2.2.1 release candidate 2 (final release scheduled
+    for April 10).
+  * Enable dl module (closes: #138992).
+  * Build doc files with python binary from package (closes: #139657).
+  * Build _tkinter module with BLT and Tix support.
+  * python2.2-elisp: Conflict with python2-elisp (closes: #138970).
+  * string.split docs updated in python-2.2.1 (closes: #129272).
+
+ -- Matthias Klose <doko@debian.org>  Mon,  1 Apr 2002 13:52:36 +0200
+
+python2.2 (2.2-5) unstable; urgency=low
+
+  * CVS updates of the release22-maint branch upto 20020310 (aproaching
+    the first 2.2.1 release candidate).
+  * Stolen from HEAD: check argument of locale.nl_langinfo (closes: #137371).
+
+ -- Matthias Klose <doko@debian.org>  Fri, 15 Mar 2002 01:05:59 +0100
+
+python2.2 (2.2-4) unstable; urgency=medium
+
+  * Include test/{__init__.py,README,pystone.py} in package (closes: #129013).
+  * Fix python-elisp conflict (closes: #129046).
+  * Don't compress stylesheets (closes: #133179).
+  * CVS updates of the release22-maint branch upto 20020310.
+
+ -- Matthias Klose <doko@debian.org>  Sun, 10 Mar 2002 23:32:28 +0100
+
+python2.2 (2.2-3) unstable; urgency=medium
+
+  * Updates from the CVS python22-maint branch up to 20020107.
+    webbrowser.py: properly escape url's.
+  * The Hurd does not have large file support: disabled.
+
+ -- Matthias Klose <doko@debian.org>  Mon,  7 Jan 2002 21:55:57 +0100
+
+python2.2 (2.2-2) unstable; urgency=medium
+
+  * CVS updates of the release22-maint branch upto 20011229. Fixes:
+    - Include TCP_CORK flag in plat-linux2 headers (fixes: #84340).
+    - Update CDROM.py module (fixes: #125785).
+  * Add missing chunk of the GNU/Hurd patch (therefore urgency medium).
+  * Send anonymous password when using anonftp (closes: #126814).
+
+ -- Matthias Klose <doko@debian.org>  Sat, 29 Dec 2001 20:18:26 +0100
+
+python2.2 (2.2-1) unstable; urgency=low
+
+  * New upstream version: 2.2.
+  * Bugs fixed upstream:
+    - Docs for os.kill reference the signal module for constants.
+    - Documentation strings in the tutorial end with a period (closes: #94770).
+    - Tk: grid_location method moved from Grid to Misc (closes: #98338).
+    - mhlib.SubMessage.getbodytext takes decode parameter (closes: #31876).
+    - Strings in modules are locale aware (closes: #51444).
+    - Printable 8-bit characters in strings are correctly printed
+      (closes: #64354).
+    - Dictionary can be updated with abstract mapping object (closes: #46566).
+  * Make site.py a config files.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 22 Dec 2001 00:51:46 +0100
+
+python2.2 (2.1.99c1-1) unstable; urgency=low
+
+  * New upstream version: 2.2c1 (release candidate).
+  * Do not provide python2.2-base anymore.
+  * Install correct README.Debian for python2.2 package. Include hint
+    where to find Makefile.pre.in.
+  * Suggest installation of python-ssl.
+  * Remove idle config files on purge.
+  * Remove empty /usr/lib/python2.2 directory on purge.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 15 Dec 2001 17:56:27 +0100
+
+python2.2 (2.1.99beta2-1) unstable; urgency=high
+
+  * debian/rules: Reflect removal of regrtest package (closes: #122278).
+    Resulted in build failures on all architectures.
+  * Build -doc package from source.
+
+ -- Matthias Klose <doko@debian.org>  Sat,  8 Dec 2001 00:38:41 +0100
+
+python2.2 (2.1.99beta2-0.1) unstable; urgency=low
+
+  * Non maintainer upload.
+  * New upstream version (this is 2.2beta2).
+  * Do not build the python-regrtest package anymore; keep the test framework
+    components test/regrtest.py and test/test_support.py in the python
+    package (closes: #119408).
+
+ -- Gregor Hoffleit <flight@debian.org>  Tue, 27 Nov 2001 09:53:26 +0100
+
+python2.2 (2.1.99beta1-4) unstable; urgency=low
+
+  * Configure with --with-fpectl (closes: #118125).
+  * setup.py: Remove broken check for _curses_panel module (#116081).
+  * idle: Move config-* files to /etc and mark as conffiles (#106390).
+  * Move idle packages to section `devel'.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 31 Oct 2001 10:56:45 +0100
+
+python2.2 (2.1.99beta1-3) unstable; urgency=low
+
+  * Fix shlibs file (was still referring to 2.1). Closes: #116810.
+  * README.Debian: point to draft of python-policy in the python package.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 31 Oct 2001 10:56:45 +0100
+
+python2.2 (2.1.99beta1-2) unstable; urgency=medium
+
+  * Fix shlibs file (was still referring to 2.1). Closes: #116810.
+  * Rename package python2.2-base to python2.2.
+
+ -- Matthias Klose <doko@debian.org>  Wed, 24 Oct 2001 23:00:50 +0200
+
+python2.2 (2.1.99beta1-1) unstable; urgency=low
+
+  * New upstream version (beta). Call the package version 2.1.99beta1-1.
+  * New maintainer until the final 2.2 release.
+  * Updated the debian patches.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 20 Oct 2001 18:56:26 +0200
+
+python2.1 (2.1.1-1.2) unstable; urgency=low
+
+  * Really remove the python alternative.
+
+ -- Matthias Klose <doko@debian.org>  Sat, 20 Oct 2001 15:16:56 +0200
+
+python2.1 (2.1.1-1.1) unstable; urgency=low
+
+  * README FOR PACKAGE MAINTAINERS: It is planned to remove the python2-XXX
+    packages from unstable and move on to python2.1.
+    If you repackage/adapt your modules for python2.1, don't build
+    python2-XXX and python2.1-XXX packages from the same source package,
+    so that the python2-XXX package can be removed without influencing the
+    python2.1-XXX package.
+
+    See the debian-python mailing list at http://lists.debian.org/devel.html
+    for details and the current discussion and a draft for a debian-python
+    policy (August to October 2001).
+
+  * Remove alternative for /usr/bin/python. The python-base package now
+    provides the default python version.
+
+  * Regenerate control file to fix build dependencies (closes: #116190).
+  * Remove alternative for /usr/bin/{python,pydoc}.
+  * Provide a libpython2.1.so symlink in /usr/lib/python2.1/config,
+    so that the shared library is found when -L/usr/lib/python2.1/config
+    is specified.
+  * Conflict with old package versions, where /usr/bin/python is a real
+    program (closes: #115943).
+  * python2.1-elisp conflicts with python-elisp (closes: #115895).
+  * We now have 2.1 (closes: #96851, #107849, #110243).
+
+ -- Matthias Klose <doko@debian.org>  Fri, 19 Oct 2001 17:34:41 +0200
+
+python2.1 (2.1.1-1) unstable; urgency=low
+
+  * Incorporated Matthias' modifications.
+
+ -- Gregor Hoffleit <flight@debian.org>  Thu, 11 Oct 2001 00:16:42 +0200
+
+python2.1 (2.1.1-0.2) unstable; urgency=low
+
+  * New upstream 2.1.1.
+  * GPL compatible licence (fixes #84080, #102949, #110643).
+  * Fixed upstream (closes: #99692, #111340).
+  * Build in separate build directory.
+  * Split Debian patches into debian/patches directory.
+  * Build dependencies: Add libgmp3-dev, libexpat1-dev, tighten
+    debhelper dependency.
+  * debian/rules: Updated a "bit".
+  * python-elisp: Remove custom dependency (closes: #87783),
+    fix emacs path (closes: #89712), remove emacs19 dependency (#82694).
+  * Mention distutils in python-dev package description (closes: #108170).
+  * Update README.Debian (closes: #85430).
+  * Run versioned python in postinsts (closes: #113349).
+  * debian/sample.{postinst,prerm}: Change to version independent scripts.
+  * Use '/usr/bin/env python2.1' as interpreter for all python scripts.
+  * Add libssl-dev to Build-Conflicts.
+  * python-elisp: Add support for emacs21 (closes: #98635).
+  * Do not compress .py files in doc directories.
+  * Don't link explicitely with libc.
+
+ -- Matthias Klose <doko@debian.org>  Wed,  3 Oct 2001 09:53:08 +0200
+
+python2.1 (2.1.1-0.1) unstable; urgency=low
+
+  * New upstream version (CVS branch release21-maint, will become 2.1.1):
+    This CVS branch will be released as 2.1.1 under a GPL compatible
+    license.
+
+ -- Gregor Hoffleit <flight@debian.org>  Wed, 27 Jun 2001 22:47:58 +0200
+
+python2 (2.1-0.1) unstable; urgency=low
+
+  * Fixed Makefile.pre.in.
+  * Fixed the postinst files in order to use 2.1 (instead of 2.0).
+  * Mention the immanent release of 2.0.1 and 2.1.1, with a GPL
+    compatible license.
+
+ -- Gregor Hoffleit <flight@debian.org>  Sun, 17 Jun 2001 21:05:25 +0200
+
+python2 (2.1-0) unstable; urgency=low
+
+  * New upstream version.
+  * Experimental packages.
+
+ -- Gregor Hoffleit <flight@debian.org>  Thu, 10 May 2001 00:20:04 +0200
+
+python2 (2.0-7) unstable; urgency=low
+
+  * Rebuilt with recent tcl8.3-dev/tk8.3-dev in order to fix a
+    dependency problem with python2-tk (closes: #87793, #92962).
+  * Change postinst to create and update /usr/local/lib/python2.0 and
+    site-python with permissions and owner as mandated by policy:
+    2775 and root:staff (closes: #89047).
+  * Fix to compileall.py: A superfluous argument made compileall without
+    options fail (cf. #92990 for python).
+  * Move the distutils module into python2-dev. It needs Makefile.pre.in
+    in order to work (closes: #89900).
+  * Remove build-dependency on libgdbm2-dev (which isn't built anyway).
+  * Add a build-dependency on libdb2-dev (cf. #90220 for python).
+
+ -- Gregor Hoffleit <flight@debian.org>  Sat, 14 Apr 2001 21:07:51 +0200
+
+python2 (2.0-6) unstable; urgency=low
+
+  * Remove python-zlib package; merge it into python-base.
+  * Mark that README.python2 is not yet updated.
+
+ -- Gregor Hoffleit <flight@debian.org>  Wed, 21 Feb 2001 12:34:18 +0100
+
+python2 (2.0-5) unstable; urgency=low
+
+  * Recompile with tcl/tk8.3 (closes: #82088).
+  * Modifications to README.why-python2 (closes: #82116).
+  * Add menu hint to idle2 menu entry.
+  * idle2 is renamed idle-python2 and now build correctly (closes: #82218).
+  * Add build-dependency on autoconf (closes: #85339).
+  * Build bsddbmodule as shared module (Modules/Setup.config.in),
+    and link libpython2.so with -lm in Makefile (closes: #86027).
+  * various cleanups in debian/rules, e.g. removing dh_suidregister.
+  * Make pdb available as /usr/bin/pdb-python2 in python2-dev
+    (cf. #79870 in python-base).
+  * Remove libgmp3 from build-dependencies, since we currently can't
+    build the mpzmodule for Python2 due to license problems.
+
+ -- Gregor Hoffleit <flight@debian.org>  Sun, 18 Feb 2001 00:12:17 +0100
+
+python2 (2.0-4) unstable; urgency=low
+
+  * control: make python2-elisp conflict with python-elisp (it doesn't
+    make sense to have both of them installed, does it ?)
+  * include build-depend on libxmltok1-dev.
+  * again, build with tcl/tk8.0.
+
+ -- Gregor Hoffleit <flight@debian.org>  Wed, 10 Jan 2001 23:37:01 +0100
+
+python2 (2.0-3) unstable; urgency=low
+
+  * Modules/Setup.in: Added a missing \ that made _tkinter be built
+    incorrectly.
+  * rules: on the fly, change all '#!' python scripts to use python2.
+
+ -- Gregor Hoffleit <flight@debian.org>  Wed, 13 Dec 2000 20:07:24 +0100
+
+python2 (2.0-2) unstable; urgency=low
+
+  * Aaargh. Remove conflicts/provides/replaces on python-base to make
+    parallel installation of python-base and python2-base possible.
+  * Install examples into /usr/share/doc/python2 (not python) and fix
+    symlink to python2.0 (thanks to Rick Younie <younie@home.com> for
+    pointing out this).
+  * Rename man page to python2.1.
+
+ -- Gregor Hoffleit <flight@debian.org>  Wed, 13 Dec 2000 09:31:05 +0100
+
+python2 (2.0-1) unstable; urgency=low
+
+  * New upstream version. Initial release for python2.
+
+ -- Gregor Hoffleit <flight@debian.org>  Mon, 11 Dec 2000 22:39:46 +0100
diff --git a/changelog.shared b/changelog.shared
new file mode 100644 (file)
index 0000000..60a99df
--- /dev/null
@@ -0,0 +1,3 @@
+  * Link the interpreter against the shared runtime library. With
+    gcc-4.1 the difference in the pystones benchmark dropped from about
+    12% to about 5%.
diff --git a/compat b/compat
new file mode 100644 (file)
index 0000000..b4de394
--- /dev/null
+++ b/compat
@@ -0,0 +1 @@
+11
diff --git a/control b/control
new file mode 100644 (file)
index 0000000..3491bae
--- /dev/null
+++ b/control
@@ -0,0 +1,236 @@
+Source: python3.9
+Section: python
+Priority: optional
+Maintainer: Matthias Klose <doko@debian.org>
+Build-Depends: debhelper (>= 11), dpkg-dev (>= 1.17.11),
+  quilt, autoconf,
+  lsb-release, sharutils,
+  libreadline-dev, libncursesw5-dev (>= 5.3), 
+  zlib1g-dev, libbz2-dev, liblzma-dev,
+  libgdbm-dev, libdb-dev,
+  tk-dev, blt-dev (>= 2.4z), libssl-dev,
+  libexpat1-dev, libmpdec-dev (>= 2.5.1~),
+  libbluetooth-dev [linux-any] <!pkg.python3.9.nobluetooth>,
+  locales-all,
+  libsqlite3-dev, libffi-dev (>= 3.0.5) [!or1k !avr32],
+  libgpm2 [linux-any],
+  media-types | mime-support, netbase, bzip2, time, python3:any, python3.9:any <cross>,
+  net-tools, xvfb <!nocheck>, xauth <!nocheck>,
+  systemtap-sdt-dev
+Build-Depends-Indep: python3-sphinx, python3-docs-theme, texinfo
+Build-Conflicts: git
+Standards-Version: 4.5.1
+Vcs-Browser: https://salsa.debian.org/cpython-team/python3/tree/python3.9
+Vcs-Git: https://salsa.debian.org/cpython-team/python3.git -b python3.9
+XS-Testsuite: autopkgtest
+
+Package: python3.9
+Architecture: any
+Multi-Arch: allowed
+Priority: optional
+Depends: python3.9-minimal (= ${binary:Version}),
+ libpython3.9-stdlib (= ${binary:Version}),
+ media-types | mime-support,
+ ${shlibs:Depends}, ${misc:Depends}
+Suggests: python3.9-venv, python3.9-doc, binutils
+Breaks: python3-all (<< 3.6.5~rc1-1),
+  python3-dev (<< 3.6.5~rc1-1),
+  python3-venv (<< 3.6.5-2), ${python38:Breaks}
+Description: Interactive high-level object-oriented language (version 3.9)
+ Python is a high-level, interactive, object-oriented language. Its 3.9 version
+ includes an extensive class library with lots of goodies for
+ network programming, system administration, sounds and graphics.
+
+Package: python3.9-venv
+Architecture: any
+Multi-Arch: allowed
+Priority: optional
+Depends: python3.9 (= ${binary:Version}),
+ python-pip-whl (>= 8.1.0-2),
+ python3-distutils,
+ ${shlibs:Depends}, ${misc:Depends},
+Breaks: python3-pip (<< 1.5.6-4)
+Description: Interactive high-level object-oriented language (pyvenv binary, version 3.9)
+ Python is a high-level, interactive, object-oriented language. Its 3.9 version
+ includes an extensive class library with lots of goodies for
+ network programming, system administration, sounds and graphics.
+ .
+ This package contains the pyvenv-3.9 binary.
+
+Package: libpython3.9-stdlib
+Architecture: any
+Multi-Arch: same
+Priority: optional
+Pre-Depends: ${misc:Pre-Depends}
+Depends: libpython3.9-minimal (= ${binary:Version}),
+  media-types | mime-support,
+  tzdata,
+  ${shlibs:Depends}, ${misc:Depends}
+Recommends: ca-certificates
+Description: Interactive high-level object-oriented language (standard library, version 3.9)
+ Python is a high-level, interactive, object-oriented language. Its 3.9 version
+ includes an extensive class library with lots of goodies for
+ network programming, system administration, sounds and graphics.
+ .
+ This package contains Python 3.9's standard library. It is normally not
+ used on its own, but as a dependency of python3.9.
+
+Package: python3.9-minimal
+Architecture: any
+Multi-Arch: allowed
+Priority: optional
+Pre-Depends: ${shlibs:Pre-Depends}
+Depends: libpython3.9-minimal (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
+Recommends: python3.9
+Suggests: binfmt-support
+Conflicts: binfmt-support (<< 1.1.2)
+Description: Minimal subset of the Python language (version 3.9)
+ This package contains the interpreter and some essential modules.  It can
+ be used in the boot process for some basic tasks.
+ See /usr/share/doc/python3.9-minimal/README.Debian for a list of the modules
+ contained in this package.
+XB-Cnf-Visible-Pkgname: python3.9
+
+Package: libpython3.9-minimal
+Architecture: any
+Multi-Arch: same
+Priority: optional
+Pre-Depends: ${misc:Pre-Depends}
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Recommends: libpython3.9-stdlib
+Breaks: libpython3.9-stdlib (<< 3.9.0~rc1)
+Replaces: libpython3.9-stdlib (<< 3.9.0~rc1)
+Conflicts: binfmt-support (<< 1.1.2)
+Description: Minimal subset of the Python language (version 3.9)
+ This package contains some essential modules. It is normally not
+ used on it's own, but as a dependency of python3.9-minimal.
+
+Package: libpython3.9
+Architecture: any
+Multi-Arch: same
+Section: libs
+Priority: optional
+Pre-Depends: ${misc:Pre-Depends}
+Depends: libpython3.9-stdlib (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
+Description: Shared Python runtime library (version 3.9)
+ Python is a high-level, interactive, object-oriented language. Its 3.9 version
+ includes an extensive class library with lots of goodies for
+ network programming, system administration, sounds and graphics.
+ .
+ This package contains the shared runtime library, normally not needed
+ for programs using the statically linked interpreter.
+
+Package: python3.9-examples
+Architecture: all
+Depends: python3.9:any (>= ${source:Version}), ${misc:Depends}
+Description: Examples for the Python language (v3.9)
+ Examples, Demos and Tools for Python (v3.9). These are files included in
+ the upstream Python distribution (v3.9).
+
+Package: python3.9-dev
+Architecture: any
+Multi-Arch: allowed
+Depends: python3.9 (= ${binary:Version}),
+  libpython3.9-dev (= ${binary:Version}),
+  libpython3.9 (= ${binary:Version}),
+  libexpat1-dev, zlib1g-dev,
+  ${shlibs:Depends}, ${misc:Depends}
+Recommends: libc6-dev | libc-dev
+Description: Header files and a static library for Python (v3.9)
+ Header files, a static library and development tools for building
+ Python (v3.9) modules, extending the Python interpreter or embedding
+ Python (v3.9) in applications.
+ .
+ Maintainers of Python packages should read README.maintainers.
+
+Package: libpython3.9-dev
+Section: libdevel
+Architecture: any
+Multi-Arch: same
+Pre-Depends: ${misc:Pre-Depends}
+Depends: libpython3.9-stdlib (= ${binary:Version}), libpython3.9 (= ${binary:Version}), libexpat1-dev, ${shlibs:Depends}, ${misc:Depends}
+Recommends: libc6-dev | libc-dev
+Description: Header files and a static library for Python (v3.9)
+ Header files, a static library and development tools for building
+ Python (v3.9) modules, extending the Python interpreter or embedding
+ Python (v3.9) in applications.
+ .
+ Maintainers of Python packages should read README.maintainers.
+ .
+ This package contains development files. It is normally not
+ used on it's own, but as a dependency of python3.9-dev.
+
+Package: libpython3.9-testsuite
+Section: libdevel
+Architecture: all
+Depends: python3.9 (>= ${binary:Version}), ${misc:Depends}, net-tools
+Suggests: python3-gdbm, python3-tk
+Description: Testsuite for the Python standard library (v3.9)
+ The complete testsuite for the Python standard library.  Note that
+ a subset is found in the libpython3.9-stdlib package, which should
+ be enough for other packages to use (please do not build-depend
+ on this package, but file a bug report to include additional 
+ testsuite files in the libpython3.9-stdlib package).
+
+Package: idle-python3.9
+Architecture: all
+Depends: python3.9, python3-tk, python3.9-tk,
+  ${misc:Depends},
+  libjs-mathjax,
+Enhances: python3.9
+Description: IDE for Python (v3.9) using Tkinter
+ IDLE is an Integrated Development Environment for Python (v3.9).
+ IDLE is written using Tkinter and therefore quite platform-independent.
+
+Package: python3.9-doc
+Section: doc
+Architecture: all
+Multi-Arch: foreign
+Depends: libjs-jquery, libjs-underscore, ${misc:Depends}
+Suggests: python3.9
+Description: Documentation for the high-level object-oriented language Python (v3.9)
+ These is the official set of documentation for the interactive high-level
+ object-oriented language Python (v3.9). All documents are provided
+ in HTML format. The package consists of ten documents:
+ .
+   * What's New in Python3.9
+   * Tutorial
+   * Python Library Reference
+   * Macintosh Module Reference
+   * Python Language Reference
+   * Extending and Embedding Python
+   * Python/C API Reference
+   * Installing Python Modules
+   * Documenting Python
+   * Distributing Python Modules
+
+Package: python3.9-dbg
+Section: debug
+Architecture: any
+Multi-Arch: allowed
+Depends: python3.9 (= ${binary:Version}), libpython3.9-dbg (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
+Recommends: gdb
+Suggests: python3-gdbm-dbg, python3-tk-dbg
+Description: Debug Build of the Python Interpreter (version 3.9)
+ The package holds two things:
+ .
+ - A Python interpreter configured with --pydebug. Dynamically loaded modules
+   are searched as <foo>_d.so first. Third party extensions need a separate
+   build to be used by this interpreter.
+ - Debug information for standard python interpreter and extensions.
+ .
+ See the README.debug for more information.
+
+Package: libpython3.9-dbg
+Section: debug
+Architecture: any
+Multi-Arch: same
+Pre-Depends: ${misc:Pre-Depends}
+Depends: libpython3.9-stdlib (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
+Description: Debug Build of the Python Interpreter (version 3.9)
+ The package holds two things:
+ .
+ - Extensions for a Python interpreter configured with --pydebug.
+ - Debug information for standard python extensions.
+ .
+ See the README.debug for more information.
diff --git a/control.in b/control.in
new file mode 100644 (file)
index 0000000..d26c31b
--- /dev/null
@@ -0,0 +1,236 @@
+Source: @PVER@
+Section: python
+Priority: optional
+Maintainer: Matthias Klose <doko@debian.org>
+Build-Depends: debhelper (>= 11), @bd_dpkgdev@
+  quilt, autoconf,
+  lsb-release, sharutils,
+  libreadline-dev, libncursesw5-dev (>= 5.3), @bd_gcc@
+  zlib1g-dev, libbz2-dev, liblzma-dev,
+  libgdbm-dev, libdb-dev,
+  tk-dev, blt-dev (>= 2.4z), libssl-dev,
+  libexpat1-dev, libmpdec-dev (>= 2.5.1~),
+  libbluetooth-dev [linux-any] <!pkg.@PVER@.nobluetooth>,
+  locales-all,
+  libsqlite3-dev, libffi-dev (>= 3.0.5) [!or1k !avr32],
+  libgpm2 [linux-any],
+  media-types | mime-support, netbase, bzip2, time, python3@bd_qual@, @PVER@@bd_qual@ <cross>,
+  net-tools, xvfb <!nocheck>, xauth <!nocheck>,
+  systemtap-sdt-dev
+Build-Depends-Indep: python3-sphinx, python3-docs-theme, texinfo
+Build-Conflicts: git
+Standards-Version: 4.5.1
+Vcs-Browser: https://salsa.debian.org/cpython-team/python3/tree/python3.9
+Vcs-Git: https://salsa.debian.org/cpython-team/python3.git -b python3.9
+XS-Testsuite: autopkgtest
+
+Package: @PVER@
+Architecture: any
+Multi-Arch: allowed
+Priority: @PRIO@
+Depends: @PVER@-minimal (= ${binary:Version}),
+ lib@PVER@-stdlib (= ${binary:Version}),
+ media-types | mime-support,
+ ${shlibs:Depends}, ${misc:Depends}
+Suggests: @PVER@-venv, @PVER@-doc, binutils
+Breaks: python3-all (<< 3.6.5~rc1-1),
+  python3-dev (<< 3.6.5~rc1-1),
+  python3-venv (<< 3.6.5-2), ${python38:Breaks}
+Description: Interactive high-level object-oriented language (version @VER@)
+ Python is a high-level, interactive, object-oriented language. Its @VER@ version
+ includes an extensive class library with lots of goodies for
+ network programming, system administration, sounds and graphics.
+
+Package: @PVER@-venv
+Architecture: any
+Multi-Arch: allowed
+Priority: @PRIO@
+Depends: @PVER@ (= ${binary:Version}),
+ python-pip-whl (>= 8.1.0-2),
+ python3-distutils,
+ ${shlibs:Depends}, ${misc:Depends},
+Breaks: python3-pip (<< 1.5.6-4)
+Description: Interactive high-level object-oriented language (pyvenv binary, version @VER@)
+ Python is a high-level, interactive, object-oriented language. Its @VER@ version
+ includes an extensive class library with lots of goodies for
+ network programming, system administration, sounds and graphics.
+ .
+ This package contains the pyvenv-@VER@ binary.
+
+Package: lib@PVER@-stdlib
+Architecture: any
+Multi-Arch: same
+Priority: @PRIO@
+Pre-Depends: ${misc:Pre-Depends}
+Depends: lib@PVER@-minimal (= ${binary:Version}),
+  media-types | mime-support,
+  tzdata,
+  ${shlibs:Depends}, ${misc:Depends}
+Recommends: ca-certificates
+Description: Interactive high-level object-oriented language (standard library, version @VER@)
+ Python is a high-level, interactive, object-oriented language. Its @VER@ version
+ includes an extensive class library with lots of goodies for
+ network programming, system administration, sounds and graphics.
+ .
+ This package contains Python @VER@'s standard library. It is normally not
+ used on its own, but as a dependency of python@VER@.
+
+Package: @PVER@-minimal
+Architecture: any
+Multi-Arch: allowed
+Priority: @MINPRIO@
+Pre-Depends: ${shlibs:Pre-Depends}
+Depends: lib@PVER@-minimal (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
+Recommends: @PVER@
+Suggests: binfmt-support
+Conflicts: binfmt-support (<< 1.1.2)
+Description: Minimal subset of the Python language (version @VER@)
+ This package contains the interpreter and some essential modules.  It can
+ be used in the boot process for some basic tasks.
+ See /usr/share/doc/@PVER@-minimal/README.Debian for a list of the modules
+ contained in this package.
+XB-Cnf-Visible-Pkgname: @PVER@
+
+Package: lib@PVER@-minimal
+Architecture: any
+Multi-Arch: same
+Priority: @MINPRIO@
+Pre-Depends: ${misc:Pre-Depends}
+Depends: ${shlibs:Depends}, ${misc:Depends}
+Recommends: lib@PVER@-stdlib
+Breaks: lib@PVER@-stdlib (<< 3.9.0~rc1)
+Replaces: lib@PVER@-stdlib (<< 3.9.0~rc1)
+Conflicts: binfmt-support (<< 1.1.2)
+Description: Minimal subset of the Python language (version @VER@)
+ This package contains some essential modules. It is normally not
+ used on it's own, but as a dependency of @PVER@-minimal.
+
+Package: lib@PVER@
+Architecture: any
+Multi-Arch: same
+Section: libs
+Priority: @PRIO@
+Pre-Depends: ${misc:Pre-Depends}
+Depends: lib@PVER@-stdlib (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
+Description: Shared Python runtime library (version @VER@)
+ Python is a high-level, interactive, object-oriented language. Its @VER@ version
+ includes an extensive class library with lots of goodies for
+ network programming, system administration, sounds and graphics.
+ .
+ This package contains the shared runtime library, normally not needed
+ for programs using the statically linked interpreter.
+
+Package: @PVER@-examples
+Architecture: all
+Depends: @PVER@:any (>= ${source:Version}), ${misc:Depends}
+Description: Examples for the Python language (v@VER@)
+ Examples, Demos and Tools for Python (v@VER@). These are files included in
+ the upstream Python distribution (v@VER@).
+
+Package: @PVER@-dev
+Architecture: any
+Multi-Arch: allowed
+Depends: @PVER@ (= ${binary:Version}),
+  lib@PVER@-dev (= ${binary:Version}),
+  lib@PVER@ (= ${binary:Version}),
+  libexpat1-dev, zlib1g-dev,
+  ${shlibs:Depends}, ${misc:Depends}
+Recommends: libc6-dev | libc-dev
+Description: Header files and a static library for Python (v@VER@)
+ Header files, a static library and development tools for building
+ Python (v@VER@) modules, extending the Python interpreter or embedding
+ Python (v@VER@) in applications.
+ .
+ Maintainers of Python packages should read README.maintainers.
+
+Package: lib@PVER@-dev
+Section: libdevel
+Architecture: any
+Multi-Arch: same
+Pre-Depends: ${misc:Pre-Depends}
+Depends: lib@PVER@-stdlib (= ${binary:Version}), lib@PVER@ (= ${binary:Version}), libexpat1-dev, ${shlibs:Depends}, ${misc:Depends}
+Recommends: libc6-dev | libc-dev
+Description: Header files and a static library for Python (v@VER@)
+ Header files, a static library and development tools for building
+ Python (v@VER@) modules, extending the Python interpreter or embedding
+ Python (v@VER@) in applications.
+ .
+ Maintainers of Python packages should read README.maintainers.
+ .
+ This package contains development files. It is normally not
+ used on it's own, but as a dependency of @PVER@-dev.
+
+Package: lib@PVER@-testsuite
+Section: libdevel
+Architecture: all
+Depends: @PVER@ (>= ${binary:Version}), ${misc:Depends}, net-tools
+Suggests: python3-gdbm, python3-tk
+Description: Testsuite for the Python standard library (v@VER@)
+ The complete testsuite for the Python standard library.  Note that
+ a subset is found in the lib@PVER@-stdlib package, which should
+ be enough for other packages to use (please do not build-depend
+ on this package, but file a bug report to include additional 
+ testsuite files in the lib@PVER@-stdlib package).
+
+Package: idle-@PVER@
+Architecture: all
+Depends: @PVER@, python3-tk, @PVER@-tk,
+  ${misc:Depends},
+  libjs-mathjax,
+Enhances: @PVER@
+Description: IDE for Python (v@VER@) using Tkinter
+ IDLE is an Integrated Development Environment for Python (v@VER@).
+ IDLE is written using Tkinter and therefore quite platform-independent.
+
+Package: @PVER@-doc
+Section: doc
+Architecture: all
+Multi-Arch: foreign
+Depends: libjs-jquery, libjs-underscore, ${misc:Depends}
+Suggests: @PVER@
+Description: Documentation for the high-level object-oriented language Python (v@VER@)
+ These is the official set of documentation for the interactive high-level
+ object-oriented language Python (v@VER@). All documents are provided
+ in HTML format. The package consists of ten documents:
+ .
+   * What's New in Python@VER@
+   * Tutorial
+   * Python Library Reference
+   * Macintosh Module Reference
+   * Python Language Reference
+   * Extending and Embedding Python
+   * Python/C API Reference
+   * Installing Python Modules
+   * Documenting Python
+   * Distributing Python Modules
+
+Package: @PVER@-dbg
+Section: debug
+Architecture: any
+Multi-Arch: allowed
+Depends: @PVER@ (= ${binary:Version}), lib@PVER@-dbg (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
+Recommends: gdb
+Suggests: python3-gdbm-dbg, python3-tk-dbg
+Description: Debug Build of the Python Interpreter (version @VER@)
+ The package holds two things:
+ .
+ - A Python interpreter configured with --pydebug. Dynamically loaded modules
+   are searched as <foo>_d.so first. Third party extensions need a separate
+   build to be used by this interpreter.
+ - Debug information for standard python interpreter and extensions.
+ .
+ See the README.debug for more information.
+
+Package: lib@PVER@-dbg
+Section: debug
+Architecture: any
+Multi-Arch: same
+Pre-Depends: ${misc:Pre-Depends}
+Depends: lib@PVER@-stdlib (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends}
+Description: Debug Build of the Python Interpreter (version @VER@)
+ The package holds two things:
+ .
+ - Extensions for a Python interpreter configured with --pydebug.
+ - Debug information for standard python extensions.
+ .
+ See the README.debug for more information.
diff --git a/control.stdlib b/control.stdlib
new file mode 100644 (file)
index 0000000..fa1d444
--- /dev/null
@@ -0,0 +1,16 @@
+Package: @PVER@-tk
+Architecture: any
+Depends: @PVER@ (= ${Source-Version}), ${shlibs:Depends}
+Suggests: tix
+XB-Python-Version: @VER@
+Description: Tkinter - Writing Tk applications with Python (v@VER@)
+ A module for writing portable GUI applications with Python (v@VER@) using Tk.
+ Also known as Tkinter.
+
+Package: @PVER@-gdbm
+Architecture: any
+Depends: @PVER@ (= ${Source-Version}), ${shlibs:Depends}
+Description: GNU dbm database support for Python (v@VER@)
+ GNU dbm database module for Python. Install this if you want to
+ create or read GNU dbm database files with Python.
+
diff --git a/control.udeb b/control.udeb
new file mode 100644 (file)
index 0000000..3e1a351
--- /dev/null
@@ -0,0 +1,11 @@
+
+Package: @PVER@-udeb
+XC-Package-Type: udeb
+Section: debian-installer
+Architecture: any
+Depends: ${shlibs:Depends}, ${misc:Depends}
+XB-Python-Runtime: @PVER@
+XB-Python-Version: @VER@
+Description: A minimal subset of the Python language (version @VER@)
+ This package contains the interpreter and some essential modules, packaged
+ for use in the installer.
diff --git a/copyright b/copyright
new file mode 100644 (file)
index 0000000..1655fbe
--- /dev/null
+++ b/copyright
@@ -0,0 +1,995 @@
+This package was put together by Klee Dienes <klee@debian.org> from 
+sources from ftp.python.org:/pub/python, based on the Debianization by 
+the previous maintainers Bernd S. Brentrup <bsb@uni-muenster.de> and 
+Bruce Perens. Current maintainer is Matthias Klose <doko@debian.org>. 
+
+It was downloaded from http://python.org/
+
+Copyright:
+
+Upstream Author: Guido van Rossum <guido@cwi.nl> and others.
+
+License:
+
+The following text includes the Python license and licenses and
+acknowledgements for incorporated software. The licenses can be read
+in the HTML and texinfo versions of the documentation as well, after
+installing the pythonx.y-doc package. Licenses for files not licensed
+under the Python Licenses are found at the end of this file.
+
+
+Python License
+==============
+
+A. HISTORY OF THE SOFTWARE
+==========================
+
+Python was created in the early 1990s by Guido van Rossum at Stichting
+Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands
+as a successor of a language called ABC.  Guido remains Python's
+principal author, although it includes many contributions from others.
+
+In 1995, Guido continued his work on Python at the Corporation for
+National Research Initiatives (CNRI, see http://www.cnri.reston.va.us)
+in Reston, Virginia where he released several versions of the
+software.
+
+In May 2000, Guido and the Python core development team moved to
+BeOpen.com to form the BeOpen PythonLabs team.  In October of the same
+year, the PythonLabs team moved to Digital Creations (now Zope
+Corporation, see http://www.zope.com).  In 2001, the Python Software
+Foundation (PSF, see http://www.python.org/psf/) was formed, a
+non-profit organization created specifically to own Python-related
+Intellectual Property.  Zope Corporation is a sponsoring member of
+the PSF.
+
+All Python releases are Open Source (see http://www.opensource.org for
+the Open Source Definition).  Historically, most, but not all, Python
+releases have also been GPL-compatible; the table below summarizes
+the various releases.
+
+    Release         Derived     Year        Owner       GPL-
+                    from                                compatible? (1)
+
+    0.9.0 thru 1.2              1991-1995   CWI         yes
+    1.3 thru 1.5.2  1.2         1995-1999   CNRI        yes
+    1.6             1.5.2       2000        CNRI        no
+    2.0             1.6         2000        BeOpen.com  no
+    1.6.1           1.6         2001        CNRI        yes (2)
+    2.1             2.0+1.6.1   2001        PSF         no
+    2.0.1           2.0+1.6.1   2001        PSF         yes
+    2.1.1           2.1+2.0.1   2001        PSF         yes
+    2.2             2.1.1       2001        PSF         yes
+    2.1.2           2.1.1       2002        PSF         yes
+    2.1.3           2.1.2       2002        PSF         yes
+    2.2 and above   2.1.1       2001-now    PSF         yes
+
+Footnotes:
+
+(1) GPL-compatible doesn't mean that we're distributing Python under
+    the GPL.  All Python licenses, unlike the GPL, let you distribute
+    a modified version without making your changes open source.  The
+    GPL-compatible licenses make it possible to combine Python with
+    other software that is released under the GPL; the others don't.
+
+(2) According to Richard Stallman, 1.6.1 is not GPL-compatible,
+    because its license has a choice of law clause.  According to
+    CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1
+    is "not incompatible" with the GPL.
+
+Thanks to the many outside volunteers who have worked under Guido's
+direction to make these releases possible.
+
+
+B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON
+===============================================================
+
+PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
+--------------------------------------------
+
+1. This LICENSE AGREEMENT is between the Python Software Foundation
+("PSF"), and the Individual or Organization ("Licensee") accessing and
+otherwise using this software ("Python") in source or binary form and
+its associated documentation.
+
+2. Subject to the terms and conditions of this License Agreement, PSF
+hereby grants Licensee a nonexclusive, royalty-free, world-wide
+license to reproduce, analyze, test, perform and/or display publicly,
+prepare derivative works, distribute, and otherwise use Python alone
+or in any derivative version, provided, however, that PSF's License
+Agreement and PSF's notice of copyright, i.e., "Copyright (c) 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012,
+2013, 2014 Python Software Foundation; All Rights Reserved" are
+retained in Python alone or in any derivative version prepared by
+Licensee.
+
+3. In the event Licensee prepares a derivative work that is based on
+or incorporates Python or any part thereof, and wants to make
+the derivative work available to others as provided herein, then
+Licensee hereby agrees to include in any such work a brief summary of
+the changes made to Python.
+
+4. PSF is making Python available to Licensee on an "AS IS"
+basis.  PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
+FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
+A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
+OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+6. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+7. Nothing in this License Agreement shall be deemed to create any
+relationship of agency, partnership, or joint venture between PSF and
+Licensee.  This License Agreement does not grant permission to use PSF
+trademarks or trade name in a trademark sense to endorse or promote
+products or services of Licensee, or any third party.
+
+8. By copying, installing or otherwise using Python, Licensee
+agrees to be bound by the terms and conditions of this License
+Agreement.
+
+
+BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0
+-------------------------------------------
+
+BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1
+
+1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an
+office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the
+Individual or Organization ("Licensee") accessing and otherwise using
+this software in source or binary form and its associated
+documentation ("the Software").
+
+2. Subject to the terms and conditions of this BeOpen Python License
+Agreement, BeOpen hereby grants Licensee a non-exclusive,
+royalty-free, world-wide license to reproduce, analyze, test, perform
+and/or display publicly, prepare derivative works, distribute, and
+otherwise use the Software alone or in any derivative version,
+provided, however, that the BeOpen Python License is retained in the
+Software, alone or in any derivative version prepared by Licensee.
+
+3. BeOpen is making the Software available to Licensee on an "AS IS"
+basis.  BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE
+SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
+AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY
+DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+5. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+6. This License Agreement shall be governed by and interpreted in all
+respects by the law of the State of California, excluding conflict of
+law provisions.  Nothing in this License Agreement shall be deemed to
+create any relationship of agency, partnership, or joint venture
+between BeOpen and Licensee.  This License Agreement does not grant
+permission to use BeOpen trademarks or trade names in a trademark
+sense to endorse or promote products or services of Licensee, or any
+third party.  As an exception, the "BeOpen Python" logos available at
+http://www.pythonlabs.com/logos.html may be used according to the
+permissions granted on that web page.
+
+7. By copying, installing or otherwise using the software, Licensee
+agrees to be bound by the terms and conditions of this License
+Agreement.
+
+
+CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1
+---------------------------------------
+
+1. This LICENSE AGREEMENT is between the Corporation for National
+Research Initiatives, having an office at 1895 Preston White Drive,
+Reston, VA 20191 ("CNRI"), and the Individual or Organization
+("Licensee") accessing and otherwise using Python 1.6.1 software in
+source or binary form and its associated documentation.
+
+2. Subject to the terms and conditions of this License Agreement, CNRI
+hereby grants Licensee a nonexclusive, royalty-free, world-wide
+license to reproduce, analyze, test, perform and/or display publicly,
+prepare derivative works, distribute, and otherwise use Python 1.6.1
+alone or in any derivative version, provided, however, that CNRI's
+License Agreement and CNRI's notice of copyright, i.e., "Copyright (c)
+1995-2001 Corporation for National Research Initiatives; All Rights
+Reserved" are retained in Python 1.6.1 alone or in any derivative
+version prepared by Licensee.  Alternately, in lieu of CNRI's License
+Agreement, Licensee may substitute the following text (omitting the
+quotes): "Python 1.6.1 is made available subject to the terms and
+conditions in CNRI's License Agreement.  This Agreement together with
+Python 1.6.1 may be located on the Internet using the following
+unique, persistent identifier (known as a handle): 1895.22/1013.  This
+Agreement may also be obtained from a proxy server on the Internet
+using the following URL: http://hdl.handle.net/1895.22/1013".
+
+3. In the event Licensee prepares a derivative work that is based on
+or incorporates Python 1.6.1 or any part thereof, and wants to make
+the derivative work available to others as provided herein, then
+Licensee hereby agrees to include in any such work a brief summary of
+the changes made to Python 1.6.1.
+
+4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS"
+basis.  CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
+IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT
+INFRINGE ANY THIRD PARTY RIGHTS.
+
+5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
+1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
+A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,
+OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
+
+6. This License Agreement will automatically terminate upon a material
+breach of its terms and conditions.
+
+7. This License Agreement shall be governed by the federal
+intellectual property law of the United States, including without
+limitation the federal copyright law, and, to the extent such
+U.S. federal law does not apply, by the law of the Commonwealth of
+Virginia, excluding Virginia's conflict of law provisions.
+Notwithstanding the foregoing, with regard to derivative works based
+on Python 1.6.1 that incorporate non-separable material that was
+previously distributed under the GNU General Public License (GPL), the
+law of the Commonwealth of Virginia shall govern this License
+Agreement only as to issues arising under or with respect to
+Paragraphs 4, 5, and 7 of this License Agreement.  Nothing in this
+License Agreement shall be deemed to create any relationship of
+agency, partnership, or joint venture between CNRI and Licensee.  This
+License Agreement does not grant permission to use CNRI trademarks or
+trade name in a trademark sense to endorse or promote products or
+services of Licensee, or any third party.
+
+8. By clicking on the "ACCEPT" button where indicated, or by copying,
+installing or otherwise using Python 1.6.1, Licensee agrees to be
+bound by the terms and conditions of this License Agreement.
+
+        ACCEPT
+
+
+CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2
+--------------------------------------------------
+
+Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam,
+The Netherlands.  All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Stichting Mathematisch
+Centrum or CWI not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+
+Licenses and Acknowledgements for Incorporated Software
+=======================================================
+
+Mersenne Twister
+----------------
+
+The `_random' module includes code based on a download from
+`http://www.math.keio.ac.jp/~matumoto/MT2002/emt19937ar.html'.  The
+following are the verbatim comments from the original code:
+
+     A C-program for MT19937, with initialization improved 2002/1/26.
+     Coded by Takuji Nishimura and Makoto Matsumoto.
+
+     Before using, initialize the state by using init_genrand(seed)
+     or init_by_array(init_key, key_length).
+
+     Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
+     All rights reserved.
+
+     Redistribution and use in source and binary forms, with or without
+     modification, are permitted provided that the following conditions
+     are met:
+
+      1. Redistributions of source code must retain the above copyright
+         notice, this list of conditions and the following disclaimer.
+
+      2. Redistributions in binary form must reproduce the above copyright
+         notice, this list of conditions and the following disclaimer in the
+         documentation and/or other materials provided with the distribution.
+
+      3. The names of its contributors may not be used to endorse or promote
+         products derived from this software without specific prior written
+         permission.
+
+     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+     A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
+     OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+     TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+     PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+     LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+     NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+     Any feedback is very welcome.
+     http://www.math.keio.ac.jp/matumoto/emt.html
+     email: matumoto@math.keio.ac.jp
+
+
+Sockets
+-------
+
+The `socket' module uses the functions, `getaddrinfo', and
+`getnameinfo', which are coded in separate source files from the WIDE
+Project, `http://www.wide.ad.jp/about/index.html'.
+
+     Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+     All rights reserved.
+
+     Redistribution and use in source and binary forms, with or without
+     modification, are permitted provided that the following conditions
+     are met:
+     1. Redistributions of source code must retain the above copyright
+        notice, this list of conditions and the following disclaimer.
+     2. Redistributions in binary form must reproduce the above copyright
+        notice, this list of conditions and the following disclaimer in the
+        documentation and/or other materials provided with the distribution.
+     3. Neither the name of the project nor the names of its contributors
+        may be used to endorse or promote products derived from this software
+        without specific prior written permission.
+
+     THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+     GAI_ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+     ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+     FOR GAI_ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+     INTERRUPTION) HOWEVER CAUSED AND ON GAI_ANY THEORY OF LIABILITY, WHETHER
+     IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+     ARISING IN GAI_ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+     OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Floating point exception control
+--------------------------------
+
+The source for the `fpectl' module includes the following notice:
+
+     ---------------------------------------------------------------------  
+    /                       Copyright (c) 1996.                           \ 
+   |          The Regents of the University of California.                 |
+   |                        All rights reserved.                           |
+   |                                                                       |
+   |   Permission to use, copy, modify, and distribute this software for   |
+   |   any purpose without fee is hereby granted, provided that this en-   |
+   |   tire notice is included in all copies of any software which is or   |
+   |   includes  a  copy  or  modification  of  this software and in all   |
+   |   copies of the supporting documentation for such software.           |
+   |                                                                       |
+   |   This  work was produced at the University of California, Lawrence   |
+   |   Livermore National Laboratory under  contract  no.  W-7405-ENG-48   |
+   |   between  the  U.S.  Department  of  Energy and The Regents of the   |
+   |   University of California for the operation of UC LLNL.              |
+   |                                                                       |
+   |                              DISCLAIMER                               |
+   |                                                                       |
+   |   This  software was prepared as an account of work sponsored by an   |
+   |   agency of the United States Government. Neither the United States   |
+   |   Government  nor the University of California nor any of their em-   |
+   |   ployees, makes any warranty, express or implied, or  assumes  any   |
+   |   liability  or  responsibility  for the accuracy, completeness, or   |
+   |   usefulness of any information,  apparatus,  product,  or  process   |
+   |   disclosed,   or  represents  that  its  use  would  not  infringe   |
+   |   privately-owned rights. Reference herein to any specific  commer-   |
+   |   cial  products,  process,  or  service  by trade name, trademark,   |
+   |   manufacturer, or otherwise, does not  necessarily  constitute  or   |
+   |   imply  its endorsement, recommendation, or favoring by the United   |
+   |   States Government or the University of California. The views  and   |
+   |   opinions  of authors expressed herein do not necessarily state or   |
+   |   reflect those of the United States Government or  the  University   |
+   |   of  California,  and shall not be used for advertising or product   |
+    \  endorsement purposes.                                              / 
+     ---------------------------------------------------------------------
+
+
+Cookie management
+-----------------
+
+The `Cookie' module contains the following notice:
+
+      Copyright 2000 by Timothy O'Malley <timo@alum.mit.edu>
+
+                     All Rights Reserved
+
+      Permission to use, copy, modify, and distribute this software
+      and its documentation for any purpose and without fee is hereby
+      granted, provided that the above copyright notice appear in all
+      copies and that both that copyright notice and this permission
+      notice appear in supporting documentation, and that the name of
+      Timothy O'Malley  not be used in advertising or publicity
+      pertaining to distribution of the software without specific, written
+      prior permission.
+
+      Timothy O'Malley DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+      SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+      AND FITNESS, IN NO EVENT SHALL Timothy O'Malley BE LIABLE FOR
+      ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+      WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+      WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+      ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+      PERFORMANCE OF THIS SOFTWARE.
+
+
+Execution tracing
+-----------------
+
+The `trace' module contains the following notice:
+
+      portions copyright 2001, Autonomous Zones Industries, Inc., all rights...
+      err...  reserved and offered to the public under the terms of the
+      Python 2.2 license.
+      Author: Zooko O'Whielacronx
+      http://zooko.com/
+      mailto:zooko@zooko.com
+
+      Copyright 2000, Mojam Media, Inc., all rights reserved.
+      Author: Skip Montanaro
+
+      Copyright 1999, Bioreason, Inc., all rights reserved.
+      Author: Andrew Dalke
+
+      Copyright 1995-1997, Automatrix, Inc., all rights reserved.
+      Author: Skip Montanaro
+
+      Copyright 1991-1995, Stichting Mathematisch Centrum, all rights reserved.
+
+      Permission to use, copy, modify, and distribute this Python software and
+      its associated documentation for any purpose without fee is hereby
+      granted, provided that the above copyright notice appears in all copies,
+      and that both that copyright notice and this permission notice appear in
+      supporting documentation, and that the name of neither Automatrix,
+      Bioreason or Mojam Media be used in advertising or publicity pertaining
+      to distribution of the software without specific, written prior
+      permission.
+
+
+UUencode and UUdecode functions
+-------------------------------
+
+The `uu' module contains the following notice:
+
+      Copyright 1994 by Lance Ellinghouse
+      Cathedral City, California Republic, United States of America.
+                             All Rights Reserved
+      Permission to use, copy, modify, and distribute this software and its
+      documentation for any purpose and without fee is hereby granted,
+      provided that the above copyright notice appear in all copies and that
+      both that copyright notice and this permission notice appear in
+      supporting documentation, and that the name of Lance Ellinghouse
+      not be used in advertising or publicity pertaining to distribution
+      of the software without specific, written prior permission.
+      LANCE ELLINGHOUSE DISCLAIMS ALL WARRANTIES WITH REGARD TO
+      THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+      FITNESS, IN NO EVENT SHALL LANCE ELLINGHOUSE CENTRUM BE LIABLE
+      FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+      WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+      ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+      OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+      Modified by Jack Jansen, CWI, July 1995:
+      - Use binascii module to do the actual line-by-line conversion
+        between ascii and binary. This results in a 1000-fold speedup. The C
+        version is still 5 times faster, though.
+      - Arguments more compliant with python standard
+
+
+XML Remote Procedure Calls
+--------------------------
+
+The `xmlrpclib' module contains the following notice:
+
+          The XML-RPC client interface is
+
+      Copyright (c) 1999-2002 by Secret Labs AB
+      Copyright (c) 1999-2002 by Fredrik Lundh
+
+      By obtaining, using, and/or copying this software and/or its
+      associated documentation, you agree that you have read, understood,
+      and will comply with the following terms and conditions:
+
+      Permission to use, copy, modify, and distribute this software and
+      its associated documentation for any purpose and without fee is
+      hereby granted, provided that the above copyright notice appears in
+      all copies, and that both that copyright notice and this permission
+      notice appear in supporting documentation, and that the name of
+      Secret Labs AB or the author not be used in advertising or publicity
+      pertaining to distribution of the software without specific, written
+      prior permission.
+
+      SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+      TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+      ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+      BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+      DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+      WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+      ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+      OF THIS SOFTWARE.
+
+Licenses for Software linked to
+===============================
+
+Note that the choice of GPL compatibility outlined above doesn't extend
+to modules linked to particular libraries, since they change the
+effective License of the module binary.
+
+
+GNU Readline
+------------
+
+The 'readline' module makes use of GNU Readline.
+
+      The GNU Readline Library is free software; you can redistribute it
+      and/or modify it under the terms of the GNU General Public License as
+      published by the Free Software Foundation; either version 2, or (at
+      your option) any later version.
+
+      On Debian systems, you can find the complete statement in
+      /usr/share/doc/readline-common/copyright'. A copy of the GNU General
+      Public License is available in /usr/share/common-licenses/GPL-2'.
+
+
+OpenSSL
+-------
+
+The '_ssl' module makes use of OpenSSL.
+
+      The OpenSSL toolkit stays under a dual license, i.e. both the
+      conditions of the OpenSSL License and the original SSLeay license
+      apply to the toolkit. Actually both licenses are BSD-style Open
+      Source licenses. Note that both licenses are incompatible with
+      the GPL.
+
+      On Debian systems, you can find the complete license text in
+      /usr/share/doc/openssl/copyright'.
+
+
+Files with other licenses than the Python License
+-------------------------------------------------
+
+Files: Include/dynamic_annotations.h
+Files: Python/dynamic_annotations.c
+Copyright: (c) 2008-2009, Google Inc.
+License: Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are
+  met:
+      * Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+      * Neither the name of Google Inc. nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Files: Include/unicodeobject.h
+Copyright: (c) Corporation for National Research Initiatives.
+Copyright: (c) 1999 by Secret Labs AB.
+Copyright: (c) 1999 by Fredrik Lundh.
+License: By obtaining, using, and/or copying this software and/or its
+  associated documentation, you agree that you have read, understood,
+  and will comply with the following terms and conditions:
+  Permission to use, copy, modify, and distribute this software and its
+  associated documentation for any purpose and without fee is hereby
+  granted, provided that the above copyright notice appears in all
+  copies, and that both that copyright notice and this permission notice
+  appear in supporting documentation, and that the name of Secret Labs
+  AB or the author not be used in advertising or publicity pertaining to
+  distribution of the software without specific, written prior
+  permission.
+  SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO
+  THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR BE LIABLE FOR
+  ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+  OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Files: Lib/logging/*
+Copyright: 2001-2010 by Vinay Sajip. All Rights Reserved.
+License: Permission to use, copy, modify, and distribute this software and
+ its documentation for any purpose and without fee is hereby granted,
+ provided that the above copyright notice appear in all copies and that
+ both that copyright notice and this permission notice appear in
+ supporting documentation, and that the name of Vinay Sajip
+ not be used in advertising or publicity pertaining to distribution
+ of the software without specific, written prior permission.
+ VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+ IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Files: Lib/multiprocessing/*
+Files: Modules/_multiprocessing/*
+Copyright: (c) 2006-2008, R Oudkerk. All rights reserved.
+License: Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+ 3. Neither the name of author nor the names of any contributors may be
+    used to endorse or promote products derived from this software
+    without specific prior written permission.
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+
+Files: Lib/sqlite3/*
+Files: Modules/_sqlite/*
+Copyright: (C) 2004-2005 Gerhard Häring <gh@ghaering.de>
+License: This software is provided 'as-is', without any express or implied
+ warranty.  In no event will the authors be held liable for any damages
+ arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not
+    claim that you wrote the original software. If you use this software
+    in a product, an acknowledgment in the product documentation would be
+    appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+    misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+Files: Lib/async*
+Copyright: Copyright 1996 by Sam Rushing
+License: Permission to use, copy, modify, and distribute this software and
+ its documentation for any purpose and without fee is hereby
+ granted, provided that the above copyright notice appear in all
+ copies and that both that copyright notice and this permission
+ notice appear in supporting documentation, and that the name of Sam
+ Rushing not be used in advertising or publicity pertaining to
+ distribution of the software without specific, written prior
+ permission.
+ SAM RUSHING DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ NO EVENT SHALL SAM RUSHING BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Files: Lib/tarfile.py
+Copyright: (C) 2002 Lars Gustaebel <lars@gustaebel.de>
+License: Permission  is  hereby granted,  free  of charge,  to  any person
+ obtaining a  copy of  this software  and associated documentation
+ files  (the  "Software"),  to   deal  in  the  Software   without
+ restriction,  including  without limitation  the  rights to  use,
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies  of  the  Software,  and to  permit  persons  to  whom the
+ Software  is  furnished  to  do  so,  subject  to  the  following
+ conditions:
+ The above copyright  notice and this  permission notice shall  be
+ included in all copies or substantial portions of the Software.
+ THE SOFTWARE IS PROVIDED "AS  IS", WITHOUT WARRANTY OF ANY  KIND,
+ EXPRESS OR IMPLIED, INCLUDING  BUT NOT LIMITED TO  THE WARRANTIES
+ OF  MERCHANTABILITY,  FITNESS   FOR  A  PARTICULAR   PURPOSE  AND
+ NONINFRINGEMENT.  IN  NO  EVENT SHALL  THE  AUTHORS  OR COPYRIGHT
+ HOLDERS  BE LIABLE  FOR ANY  CLAIM, DAMAGES  OR OTHER  LIABILITY,
+ WHETHER  IN AN  ACTION OF  CONTRACT, TORT  OR OTHERWISE,  ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ OTHER DEALINGS IN THE SOFTWARE.
+
+Files: Lib/turtle.py
+Copyright: (C) 2006 - 2010  Gregor Lingl
+License: This software is provided 'as-is', without any express or implied
+ warranty.  In no event will the authors be held liable for any damages
+ arising from the use of this software.
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+ 1. The origin of this software must not be misrepresented; you must not
+    claim that you wrote the original software. If you use this software
+    in a product, an acknowledgment in the product documentation would be
+    appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+    misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ is copyright Gregor Lingl and licensed under a BSD-like license
+
+Files: Modules/_ctypes/libffi/*
+Copyright: Copyright (C) 1996-2011 Red Hat, Inc and others.
+    Copyright (C) 1996-2011 Anthony Green
+    Copyright (C) 1996-2010 Free Software Foundation, Inc
+    Copyright (c) 2003, 2004, 2006, 2007, 2008 Kaz Kojima
+    Copyright (c) 2010, 2011, Plausible Labs Cooperative , Inc.
+    Copyright (c) 2010 CodeSourcery
+    Copyright (c) 1998 Andreas Schwab
+    Copyright (c) 2000 Hewlett Packard Company
+    Copyright (c) 2009 Bradley Smith
+    Copyright (c) 2008 David Daney
+    Copyright (c) 2004 Simon Posnjak
+    Copyright (c) 2005 Axis Communications AB
+    Copyright (c) 1998 Cygnus Solutions
+    Copyright (c) 2004 Renesas Technology
+    Copyright (c) 2002, 2007  Bo Thorsen <bo@suse.de>
+    Copyright (c) 2002 Ranjit Mathew
+    Copyright (c) 2002 Roger Sayle
+    Copyright (c) 2000, 2007 Software AG
+    Copyright (c) 2003 Jakub Jelinek
+    Copyright (c) 2000, 2001 John Hornkvist
+    Copyright (c) 1998 Geoffrey Keating
+    Copyright (c) 2008 Björn König
+
+License: Permission is hereby granted, free of charge, to any person obtaining
+   a copy of this software and associated documentation files (the
+   ``Software''), to deal in the Software without restriction, including
+   without limitation the rights to use, copy, modify, merge, publish,
+   distribute, sublicense, and/or sell copies of the Software, and to
+   permit persons to whom the Software is furnished to do so, subject to
+   the following conditions:
+
+   The above copyright notice and this permission notice shall be included
+   in all copies or substantial portions of the Software.
+
+   THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
+   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+   NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+   DEALINGS IN THE SOFTWARE.
+
+   Documentation:
+   Permission is granted to copy, distribute and/or modify this document
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.  A copy of the license is included in the
+   section entitled ``GNU General Public License''.
+
+Files: Modules/_gestalt.c
+Copyright: 1991-1997 by Stichting Mathematisch Centrum, Amsterdam.
+License: Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose and without fee is hereby granted,
+ provided that the above copyright notice appear in all copies and that
+ both that copyright notice and this permission notice appear in
+ supporting documentation, and that the names of Stichting Mathematisch
+ Centrum or CWI not be used in advertising or publicity pertaining to
+ distribution of the software without specific, written prior permission.
+ STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
+ THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
+ FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Files: Modules/syslogmodule.c
+Copyright: 1994 by Lance Ellinghouse
+License: Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose and without fee is hereby granted,
+ provided that the above copyright notice appear in all copies and that
+ both that copyright notice and this permission notice appear in
+ supporting documentation, and that the name of Lance Ellinghouse
+ not be used in advertising or publicity pertaining to distribution
+ of the software without specific, written prior permission.
+ LANCE ELLINGHOUSE DISCLAIMS ALL WARRANTIES WITH REGARD TO
+ THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS, IN NO EVENT SHALL LANCE ELLINGHOUSE BE LIABLE FOR ANY SPECIAL,
+ INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Files: Modules/zlib/*
+Copyright: (C) 1995-2010 Jean-loup Gailly and Mark Adler
+License: This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  jloup@gzip.org          madler@alumni.caltech.edu
+
+ If you use the zlib library in a product, we would appreciate *not* receiving
+ lengthy legal documents to sign.  The sources are provided for free but without
+ warranty of any kind.  The library has been entirely written by Jean-loup
+ Gailly and Mark Adler; it does not include third-party code.
+
+Files: Modules/expat/*
+Copyright: Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+  and Clark Cooper
+  Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers
+License: Permission is hereby granted, free of charge, to any person obtaining
+  a copy of this software and associated documentation files (the
+  "Software"), to deal in the Software without restriction, including
+  without limitation the rights to use, copy, modify, merge, publish,
+  distribute, sublicense, and/or sell copies of the Software, and to
+  permit persons to whom the Software is furnished to do so, subject to
+  the following conditions:
+  The above copyright notice and this permission notice shall be included
+  in all copies or substantial portions of the Software.
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Files: Modules/_decimal/libmpdec/*
+Copyright: Copyright (c) 2008-2012 Stefan Krah. All rights reserved.
+License: Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ .
+ 1. Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+ .
+ 2. Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+ ,
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+
+Files: Misc/python-mode.el
+Copyright: Copyright (C) 1992,1993,1994  Tim Peters
+License: This software is provided as-is, without express or implied
+       warranty.  Permission to use, copy, modify, distribute or sell this
+       software, without fee, for any purpose and by any individual or
+       organization, is hereby granted, provided that the above copyright
+       notice and this paragraph appear in all copies.
+
+Files: Python/dtoa.c
+Copyright: (c) 1991, 2000, 2001 by Lucent Technologies.
+License: Permission to use, copy, modify, and distribute this software for any
+  purpose without fee is hereby granted, provided that this entire notice
+  is included in all copies of any software which is or includes a copy
+  or modification of this software and in all copies of the supporting
+  documentation for such software.
+  
+  THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
+  WARRANTY.  IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
+  REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
+  OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
+
+Files: Python/getopt.c
+Copyright: 1992-1994, David Gottner
+License: Permission to use, copy, modify, and distribute this software and its
+  documentation for any purpose and without fee is hereby granted,
+  provided that the above copyright notice, this permission notice and
+  the following disclaimer notice appear unmodified in all copies.
+  
+  I DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL I
+  BE LIABLE FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+  DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER
+  IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+  OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Files: PC/_subprocess.c
+Copyright: Copyright (c) 2004 by Fredrik Lundh <fredrik@pythonware.com>
+       Copyright (c) 2004 by Secret Labs AB, http://www.pythonware.com
+       Copyright (c) 2004 by Peter Astrand <astrand@lysator.liu.se>
+License:
+ * Permission to use, copy, modify, and distribute this software and
+ * its associated documentation for any purpose and without fee is
+ * hereby granted, provided that the above copyright notice appears in
+ * all copies, and that both that copyright notice and this permission
+ * notice appear in supporting documentation, and that the name of the
+ * authors not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission.
+ *
+ * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+Files: PC/winsound.c
+Copyright: Copyright (c) 1999 Toby Dickenson
+License:  * Permission to use this software in any way is granted without
+ * fee, provided that the copyright notice above appears in all
+ * copies. This software is provided "as is" without any warranty.
+ */
+
+/* Modified by Guido van Rossum */
+/* Beep added by Mark Hammond */
+/* Win9X Beep and platform identification added by Uncle Timmy */
+
+Files: Tools/pybench/*
+Copyright: (c), 1997-2006, Marc-Andre Lemburg (mal@lemburg.com)
+  (c), 2000-2006, eGenix.com Software GmbH (info@egenix.com)
+License: Permission to use, copy, modify, and distribute this software and its
+  documentation for any purpose and without fee or royalty is hereby
+  granted, provided that the above copyright notice appear in all copies
+  and that both that copyright notice and this permission notice appear
+  in supporting documentation or portions thereof, including
+  modifications, that you make.
+  
+  THE AUTHOR MARC-ANDRE LEMBURG DISCLAIMS ALL WARRANTIES WITH REGARD TO
+  THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+  FITNESS, IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
+  INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+  FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+  NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+  WITH THE USE OR PERFORMANCE OF THIS SOFTWARE !
diff --git a/depgraph.py b/depgraph.py
new file mode 100644 (file)
index 0000000..6b7ed13
--- /dev/null
@@ -0,0 +1,199 @@
+#! /usr/bin/python3
+
+# Copyright 2004 Toby Dickenson
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject
+# to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+import sys, getopt, colorsys, imp, hashlib
+
+class pydepgraphdot:
+
+    def main(self,argv):    
+        opts,args = getopt.getopt(argv,'',['mono'])
+        self.colored = 1
+        for o,v in opts:
+            if o=='--mono':
+                self.colored = 0
+        self.render()
+
+    def fix(self,s):
+        # Convert a module name to a syntactically correct node name
+        return s.replace('.','_')
+    
+    def render(self):
+        p,t = self.get_data()
+
+        # normalise our input data
+        for k,d in list(p.items()):
+            for v in list(d.keys()):
+                if v not in p:
+                    p[v] = {}
+                    
+        f = self.get_output_file()                    
+                    
+        f.write('digraph G {\n')
+        #f.write('concentrate = true;\n')
+        #f.write('ordering = out;\n')
+        f.write('ranksep=1.0;\n')
+        f.write('node [style=filled,fontname=Helvetica,fontsize=10];\n')
+        allkd = list(p.items())
+        allkd.sort()
+        for k,d in allkd:
+            tk = t.get(k)
+            if self.use(k,tk):
+                allv = list(d.keys())
+                allv.sort()
+                for v in allv:
+                    tv = t.get(v)
+                    if self.use(v,tv) and not self.toocommon(v,tv):
+                        f.write('%s -> %s' % ( self.fix(k),self.fix(v) ) )
+                        self.write_attributes(f,self.edge_attributes(k,v))
+                        f.write(';\n')
+                f.write(self.fix(k))
+                self.write_attributes(f,self.node_attributes(k,tk))
+                f.write(';\n')
+        f.write('}\n')
+
+    def write_attributes(self,f,a):
+        if a:
+            f.write(' [')
+            f.write(','.join(a))
+            f.write(']')
+
+    def node_attributes(self,k,type):
+        a = []
+        a.append('label="%s"' % self.label(k))
+        if self.colored:
+            a.append('fillcolor="%s"' % self.color(k,type))
+        else:
+            a.append('fillcolor=white')
+        if self.toocommon(k,type):
+            a.append('peripheries=2')
+        return a
+                
+    def edge_attributes(self,k,v):
+        a = []
+        weight = self.weight(k,v)
+        if weight!=1:
+            a.append('weight=%d' % weight)
+        length = self.alien(k,v)
+        if length:
+            a.append('minlen=%d' % length)
+        return a
+            
+    def get_data(self):
+        t = eval(sys.stdin.read())
+        return t['depgraph'],t['types']
+    
+    def get_output_file(self):
+        return sys.stdout
+
+    def use(self,s,type):
+        # Return true if this module is interesting and should be drawn. Return false
+        # if it should be completely omitted. This is a default policy - please override.
+        if s=='__main__':
+            return 0
+        #if s in ('os','sys','time','__future__','types','re','string'):
+        if s in ('sys'):
+            # nearly all modules use all of these... more or less. They add nothing to
+            # our diagram.
+            return 0
+        if s.startswith('encodings.'):
+            return 0
+        if self.toocommon(s,type):
+            # A module where we dont want to draw references _to_. Dot doesnt handle these
+            # well, so it is probably best to not draw them at all.
+            return 0
+        return 1
+
+    def toocommon(self,s,type):
+        # Return true if references to this module are uninteresting. Such references
+        # do not get drawn. This is a default policy - please override.
+        #
+        if s=='__main__':
+            # references *to* __main__ are never interesting. omitting them means
+            # that main floats to the top of the page
+            return 1
+        #if type==imp.PKG_DIRECTORY:
+        #    # dont draw references to packages.
+        #    return 1
+        return 0
+        
+    def weight(self,a,b):
+        # Return the weight of the dependency from a to b. Higher weights
+        # usually have shorter straighter edges. Return 1 if it has normal weight.
+        # A value of 4 is usually good for ensuring that a related pair of modules 
+        # are drawn next to each other. This is a default policy - please override.
+        #
+        if b.split('.')[-1].startswith('_'):
+            # A module that starts with an underscore. You need a special reason to
+            # import these (for example random imports _random), so draw them close
+            # together
+            return 4
+        return 1
+    
+    def alien(self,a,b):
+        # Return non-zero if references to this module are strange, and should be drawn
+        # extra-long. the value defines the length, in rank. This is also good for putting some
+        # vertical space between seperate subsystems. This is a default policy - please override.
+        #
+        return 0
+
+    def label(self,s):
+        # Convert a module name to a formatted node label. This is a default policy - please override.
+        #
+        return '\\.\\n'.join(s.split('.'))
+
+    def color(self,s,type):
+        # Return the node color for this module name. This is a default policy - please override.
+        #
+        # Calculate a color systematically based on the hash of the module name. Modules in the
+        # same package have the same color. Unpackaged modules are grey
+        t = self.normalise_module_name_for_hash_coloring(s,type)
+        return self.color_from_name(t)
+        
+    def normalise_module_name_for_hash_coloring(self,s,type):
+        if type==imp.PKG_DIRECTORY:
+            return s
+        else:
+            i = s.rfind('.')
+            if i<0:
+                return ''
+            else:
+                return s[:i]
+        
+    def color_from_name(self,name):
+        n = hashlib.md5(name.encode('utf-8')).digest()
+        hf = float(n[0]+n[1]*0xff)/0xffff
+        sf = float(n[2])/0xff
+        vf = float(n[3])/0xff
+        r,g,b = colorsys.hsv_to_rgb(hf, 0.3+0.6*sf, 0.8+0.2*vf)
+        return '#%02x%02x%02x' % (int(r*256),int(g*256),int(b*256))
+
+
+def main():
+    pydepgraphdot().main(sys.argv[1:])
+
+if __name__=='__main__':
+    main()
+
+
+
diff --git a/dh_doclink b/dh_doclink
new file mode 100644 (file)
index 0000000..99a3f2a
--- /dev/null
@@ -0,0 +1,28 @@
+#! /bin/sh
+
+pkg=`echo $1 | sed 's/^-p//'`
+target=$2
+
+ln -sf $target debian/$pkg/usr/share/doc/$pkg
+
+f=debian/$pkg.postinst.debhelper
+if [ ! -e $f ] || [ "`grep -c '^# dh_doclink' $f`" -eq 0 ]; then
+cat >> $f <<EOF
+# dh_doclink
+if [ "\$1" = "configure" ]; then
+  if [ -d /usr/doc -a ! -e /usr/doc/$pkg -a -d /usr/share/doc/$pkg ]; then
+    ln -sf ../share/doc/$pkg /usr/doc/$pkg
+  fi
+fi
+EOF
+fi
+
+f=debian/$pkg.prerm.debhelper
+if [ ! -e $f ] || [ "`grep -c '^# dh_doclink' $f`" -eq 0 ]; then
+cat >> $f <<EOF
+# dh_doclink
+if [ \( "\$1" = "upgrade" -o "\$1" = "remove" \) -a -L /usr/doc/$pkg ]; then
+  rm -f /usr/doc/$pkg
+fi
+EOF
+fi
diff --git a/idle-PVER.1.in b/idle-PVER.1.in
new file mode 100644 (file)
index 0000000..42c0b95
--- /dev/null
@@ -0,0 +1,104 @@
+.TH IDLE 1 "21 September 2004"
+.SH NAME
+\fBIDLE\fP \- An Integrated DeveLopment Environment for Python
+.SH SYNTAX
+.B idle [ \fI-dins\fP ] [ \fI-t title\fP ] [ \fIfile\fP ...]
+.PP
+.B idle [ \fI-dins\fP ] [ \fI-t title\fP ] ( \fI-c cmd\fP | \fI-r file\fP ) [ \fIarg\fP ...]
+.PP
+.B idle [ \fI-dins\fP ] [ \fI-t title\fP ] - [ \fIarg\fP ...]
+.SH DESCRIPTION
+This manual page documents briefly the
+.BR idle
+command.
+This manual page was written for Debian
+because the original program does not have a manual page.
+For more information, refer to IDLE's help menu.
+.PP
+.B IDLE
+is an Integrated DeveLopment Environment for Python. IDLE is based on
+Tkinter, Python's bindings to the Tk widget set. Features are 100% pure
+Python, multi-windows with multiple undo and Python colorizing, a Python
+shell window subclass, a debugger. IDLE is cross-platform, i.e. it works
+on all platforms where Tk is installed.
+.LP
+.SH OPTIONS
+.TP
+.B \-h
+.PD
+Print this help message and exit.
+.TP
+.B \-n
+.PD
+Run IDLE without a subprocess (see Help/IDLE Help for details).
+.PP
+The following options will override the IDLE 'settings' configuration:
+.TP
+.B \-e
+.PD
+Open an edit window.
+.TP
+.B \-i
+.PD
+Open a shell window.
+.PP
+The following options imply -i and will open a shell:
+.TP
+.B \-c cmd
+.PD
+Run the command in a shell, or
+.TP
+.B \-r file
+.PD
+Run script from file.
+.PP
+.TP
+.B \-d
+.PD
+Enable the debugger.
+.TP
+.B \-s
+.PD
+Run $IDLESTARTUP or $PYTHONSTARTUP before anything else.
+.TP
+.B \-t title
+.PD
+Set title of shell window.
+.PP
+A default edit window will be bypassed when -c, -r, or - are used.
+.PP
+[arg]* and [file]* are passed to the command (-c) or script (-r) in sys.argv[1:].
+.SH EXAMPLES
+.TP
+idle
+.PD
+Open an edit window or shell depending on IDLE's configuration.
+.TP
+idle foo.py foobar.py
+.PD
+Edit the files, also open a shell if configured to start with shell.
+.TP
+idle -est "Baz" foo.py
+.PD
+Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
+window with the title "Baz".
+.TP
+idle -c "import sys; print sys.argv" "foo"
+.PD
+Open a shell window and run the command, passing "-c" in sys.argv[0]
+and "foo" in sys.argv[1].
+.TP
+idle -d -s -r foo.py "Hello World"
+.PD
+Open a shell window, run a startup script, enable the debugger, and
+run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
+sys.argv[1].
+.TP
+echo "import sys; print sys.argv" | idle - "foobar"
+.PD
+Open a shell window, run the script piped in, passing '' in sys.argv[0]
+and "foobar" in sys.argv[1].
+.SH SEE ALSO
+python(1).
+.SH AUTHORS
+Various.
diff --git a/idle-PVER.overrides.in b/idle-PVER.overrides.in
new file mode 100644 (file)
index 0000000..58d77fa
--- /dev/null
@@ -0,0 +1,4 @@
+# icon in dependent package
+idle-@PVER@ binary: menu-icon-missing
+
+idle-@PVER@ binary: command-with-path-in-maintainer-script
diff --git a/idle-PVER.postinst.in b/idle-PVER.postinst.in
new file mode 100644 (file)
index 0000000..91b1902
--- /dev/null
@@ -0,0 +1,32 @@
+#! /bin/sh
+#
+# postinst script for the Debian idle-@PVER@ package.
+# Written 1998 by Gregor Hoffleit <flight@debian.org>.
+#
+
+set -e
+
+DIRLIST="/usr/lib/python@VER@/idlelib"
+
+case "$1" in
+    configure|abort-upgrade|abort-remove|abort-deconfigure)
+
+        for i in $DIRLIST ; do
+           /usr/bin/@PVER@ /usr/lib/@PVER@/compileall.py -q $i
+           if grep -sq '^byte-compile[^#]*optimize' /etc/python/debian_config
+           then
+               /usr/bin/@PVER@ -O /usr/lib/@PVER@/compileall.py -q $i
+           fi
+       done
+    ;;
+
+    *)
+       echo "postinst called with unknown argument \`$1'" >&2
+       exit 1
+    ;;
+
+esac
+
+#DEBHELPER#
+
+exit 0
diff --git a/idle-PVER.postrm.in b/idle-PVER.postrm.in
new file mode 100644 (file)
index 0000000..59742ee
--- /dev/null
@@ -0,0 +1,11 @@
+#! /bin/sh
+
+set -e
+
+if [ "$1" = "purge" ]; then
+    rm -rf /etc/idle-@PVER@
+fi
+
+#DEBHELPER#
+
+exit 0
diff --git a/idle-PVER.prerm.in b/idle-PVER.prerm.in
new file mode 100644 (file)
index 0000000..6fc9ca6
--- /dev/null
@@ -0,0 +1,33 @@
+#! /bin/sh
+
+set -e
+
+remove_bytecode()
+{
+    pkg=$1
+    max=$(LANG=C LC_ALL=C xargs --show-limits < /dev/null 2>&1 | awk '/Maximum length/ {print int($NF / 4)}')
+    dpkg -L $pkg \
+       | awk -F/ 'BEGIN {OFS="/"} /\.py$/ {$NF=sprintf("__pycache__/%s.*.py[co]", substr($NF,1,length($NF)-3)); print}' \
+       | xargs --max-chars=$max echo \
+       | while read files; do rm -f $files; done
+    find /usr/lib/@PVER@ -name dist-packages -prune -o -name __pycache__ -empty -print \
+       | xargs -r rm -rf
+}
+
+case "$1" in
+    remove|upgrade)
+       remove_bytecode idle-@PVER@
+        ;;
+    deconfigure)
+        ;;
+    failed-upgrade)
+        ;;
+    *)
+        echo "prerm called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+#DEBHELPER#
+
+exit 0
diff --git a/idle.desktop.in b/idle.desktop.in
new file mode 100644 (file)
index 0000000..bfeb47a
--- /dev/null
@@ -0,0 +1,9 @@
+[Desktop Entry]
+Name=IDLE (using Python-@VER@)
+Comment=Integrated Development Environment for Python (using Python-@VER@)
+Exec=/usr/bin/idle-@PVER@
+Icon=/usr/share/pixmaps/@PVER@.xpm
+Terminal=false
+Type=Application
+Categories=Application;Development;
+StartupNotify=true
diff --git a/libPVER-dbg.overrides.in b/libPVER-dbg.overrides.in
new file mode 100644 (file)
index 0000000..e5b9183
--- /dev/null
@@ -0,0 +1,17 @@
+lib@PVER@-dbg binary: package-name-doesnt-match-sonames
+lib@PVER@-dbg binary: non-dev-pkg-with-shlib-symlink
+
+# no, it's not unusual
+lib@PVER@-dbg binary: unusual-interpreter
+
+# just the gdb debug file
+lib@PVER@-dbg binary: python-script-but-no-python-dep
+
+# pointless lintian ...
+lib@PVER@-dbg binary: hardening-no-fortify-functions
+
+lib@PVER@-dbg binary: arch-dependent-file-not-in-arch-specific-directory
+
+# yes, some extensions don't have references to any external lib
+lib@PVER@-dbg binary: shared-lib-without-dependency-information
+lib@PVER@-dbg binary: library-not-linked-against-libc
diff --git a/libPVER-dbg.prerm.in b/libPVER-dbg.prerm.in
new file mode 100644 (file)
index 0000000..8f7e0e8
--- /dev/null
@@ -0,0 +1,23 @@
+#! /bin/sh
+
+set -e
+
+case "$1" in
+    remove)
+       dpkg -L lib@PVER@-dbg@HOST_QUAL@ \
+           | awk '/\.py$/ {print $0"c\n" $0"o"}' \
+           | xargs -r rm -f >&2
+        ;;
+    upgrade)
+        ;;
+    deconfigure)
+        ;;
+    failed-upgrade)
+        ;;
+    *)
+        echo "prerm called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+#DEBHELPER#
diff --git a/libPVER-dbg.symbols.i386.in b/libPVER-dbg.symbols.i386.in
new file mode 100644 (file)
index 0000000..e73cff3
--- /dev/null
@@ -0,0 +1,16 @@
+libpython@VER@d.so.1.0 libpython@VER@-dbg #MINVER#
+#include "libpython.symbols"
+ _Py_force_double@Base @SVER@
+ _Py_get_387controlword@Base @SVER@
+ _Py_set_387controlword@Base @SVER@
+ _PyObject_DebugMallocStats@Base @SVER@
+ _PySet_Dummy@Base @SVER@
+ _PyUnicode_CheckConsistency@Base @SVER@
+ _PyWideStringList_CheckConsistency@Base @SVER@
+ _Py_Dealloc@Base @SVER@
+ _Py_GetRefTotal@Base @SVER@
+ _Py_HashSecret_Initialized@Base @SVER@
+ _Py_NegativeRefcount@Base @SVER@
+ _Py_RefTotal@Base @SVER@
+ PyModule_Create2@Base @SVER@
+ PyModule_FromDefAndSpec2@Base @SVER@
diff --git a/libPVER-dbg.symbols.in b/libPVER-dbg.symbols.in
new file mode 100644 (file)
index 0000000..d9fc14a
--- /dev/null
@@ -0,0 +1,13 @@
+libpython@VER@d.so.1.0 libpython@VER@-dbg #MINVER#
+#include "libpython.symbols"
+ _PyObject_DebugMallocStats@Base @SVER@
+ _PySet_Dummy@Base @SVER@
+ _PyUnicode_CheckConsistency@Base @SVER@
+ _PyWideStringList_CheckConsistency@Base @SVER@
+ _Py_Dealloc@Base @SVER@
+ _Py_GetRefTotal@Base @SVER@
+ _Py_HashSecret_Initialized@Base @SVER@
+ _Py_NegativeRefcount@Base @SVER@
+ _Py_RefTotal@Base @SVER@
+ PyModule_Create2@Base @SVER@
+ PyModule_FromDefAndSpec2@Base @SVER@
diff --git a/libPVER-dev.overrides.in b/libPVER-dev.overrides.in
new file mode 100644 (file)
index 0000000..b94f6f7
--- /dev/null
@@ -0,0 +1,6 @@
+lib@PVER@-dev binary: python-script-but-no-python-dep
+
+lib@PVER@-dev binary: arch-dependent-file-not-in-arch-specific-directory
+
+# lintian needs an update for 3.8
+lib@PVER@-dev binary: package-contains-python-header-in-incorrect-directory
diff --git a/libPVER-minimal.overrides.in b/libPVER-minimal.overrides.in
new file mode 100644 (file)
index 0000000..4a8ebf5
--- /dev/null
@@ -0,0 +1,9 @@
+# intentional
+lib@PVER@-minimal binary: python-script-but-no-python-dep
+
+# lintian omission, multiarch string is encoded in the filename
+lib@PVER@-minimal binary: arch-dependent-file-not-in-arch-specific-directory
+
+# yes, some extensions don't have references to any external lib
+lib@PVER@-minimal binary: shared-lib-without-dependency-information
+lib@PVER@-minimal binary: library-not-linked-against-libc
diff --git a/libPVER-minimal.postinst.in b/libPVER-minimal.postinst.in
new file mode 100644 (file)
index 0000000..8cc1f11
--- /dev/null
@@ -0,0 +1,13 @@
+#! /bin/sh
+
+set -e
+
+if [ ! -f /etc/@PVER@/sitecustomize.py ]; then
+    cat <<-EOF
+       # Empty sitecustomize.py to avoid a dangling symlink
+EOF
+fi
+
+#DEBHELPER#
+
+exit 0
diff --git a/libPVER-minimal.postrm.in b/libPVER-minimal.postrm.in
new file mode 100644 (file)
index 0000000..e267ac4
--- /dev/null
@@ -0,0 +1,21 @@
+#! /bin/sh
+
+set -e
+
+if [ "$1" = "purge" ]; then
+    pc=$(dpkg-query -f '${db:Status-Abbrev} ${binary:Package}\n' -W lib@PVER@-minimal \
+       | grep -v '^.n' | wc -l)
+    if [ "$pc" -lt 1 ]; then
+       find /usr/lib/@PVER@ -depth -type d -name __pycache__ \
+           | xargs -r rm -rf
+       rm -f /etc/@PVER@/sitecustomize.py
+       rm -rf /etc/@PVER@/__pycache__
+       if [ -d /etc/@PVER@ ]; then
+           rmdir --ignore-fail-on-non-empty /etc/@PVER@
+       fi
+    fi
+fi
+
+#DEBHELPER#
+
+exit 0
diff --git a/libPVER-minimal.prerm.in b/libPVER-minimal.prerm.in
new file mode 100644 (file)
index 0000000..16aa084
--- /dev/null
@@ -0,0 +1,41 @@
+#! /bin/sh
+
+set -e
+
+remove_bytecode()
+{
+    pkg=$1
+    max=$(LANG=C LC_ALL=C xargs --show-limits < /dev/null 2>&1 | awk '/Maximum length/ {print int($NF / 4)}')
+    dpkg -L $pkg \
+       | awk -F/ 'BEGIN {OFS="/"} /\.py$/ {$NF=sprintf("__pycache__/%s.*.py[co]", substr($NF,1,length($NF)-3)); print}' \
+       | xargs --max-chars="$max" echo \
+       | while read files; do rm -f $files; done
+    find /usr/lib/python3 /usr/lib/@PVER@ \
+       \( -name dist-packages -prune \) -o \
+       \( -name __pycache__ -type d -empty -print \) \
+       | xargs -r rm -rf
+}
+
+case "$1" in
+    remove)
+       pc=$(dpkg-query -f '${db:Status-Abbrev} ${binary:Package}\n' -W lib@PVER@-minimal \
+            | grep -v '^.n' | wc -l)
+       if [ "$pc" -le 1 ]; then
+           remove_bytecode lib@PVER@-minimal@HOST_QUAL@
+       fi
+        ;;
+    upgrade)
+       remove_bytecode lib@PVER@-minimal@HOST_QUAL@
+       # byte compilation in @PVER@-minimal postinst, strict dependency
+        ;;
+    deconfigure)
+        ;;
+    failed-upgrade)
+        ;;
+    *)
+        echo "prerm called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+#DEBHELPER#
diff --git a/libPVER-stdlib.overrides.in b/libPVER-stdlib.overrides.in
new file mode 100644 (file)
index 0000000..402b1cb
--- /dev/null
@@ -0,0 +1,19 @@
+# idlelib images
+lib@PVER@-stdlib binary: image-file-in-usr-lib
+
+# license file referred by the standard library
+lib@PVER@-stdlib binary: extra-license-file
+
+# template files
+lib@PVER@-stdlib binary: interpreter-not-absolute usr/lib/@PVER@/venv/scripts/posix/pydoc #!__VENV_PYTHON__
+lib@PVER@-stdlib binary: unusual-interpreter usr/lib/@PVER@/venv/scripts/posix/pydoc #!__VENV_PYTHON__
+
+# the split is the reason for that
+lib@PVER@-stdlib binary: python-script-but-no-python-dep
+
+# lintian omission, multiarch string is encoded in the filename
+lib@PVER@-stdlib binary: arch-dependent-file-not-in-arch-specific-directory
+
+# yes, some extensions don't have references to any external lib
+lib@PVER@-stdlib binary: shared-lib-without-dependency-information
+lib@PVER@-stdlib binary: library-not-linked-against-libc
diff --git a/libPVER-stdlib.prerm.in b/libPVER-stdlib.prerm.in
new file mode 100644 (file)
index 0000000..4a5611b
--- /dev/null
@@ -0,0 +1,43 @@
+#! /bin/sh
+
+set -e
+
+remove_bytecode()
+{
+    pkg=$1
+    max=$(LANG=C LC_ALL=C xargs --show-limits < /dev/null 2>&1 | awk '/Maximum length/ {print int($NF / 4)}')
+    dpkg -L $pkg \
+       | awk -F/ 'BEGIN {OFS="/"} /\.py$/ {$NF=sprintf("__pycache__/%s.*.py[co]", substr($NF,1,length($NF)-3)); print}' \
+       | xargs --max-chars="$max" echo \
+       | while read files; do rm -f $files; done
+    # source and bytecode filename mismatch
+    rm -f /usr/lib/@PVER@/__pycache__/__phello__.cpython-*.py*
+    find /usr/lib/python3 /usr/lib/@PVER@ \
+       \( -name dist-packages -prune \) -o \
+       \( -name __pycache__ -type d -empty -print \) \
+       | xargs -r rm -rf
+}
+
+case "$1" in
+    remove)
+       pc=$(dpkg-query -f '${db:Status-Abbrev} ${binary:Package}\n' -W lib@PVER@-stdlib \
+            | grep -v '^.n' | wc -l)
+       if [ "$pc" -le 1 ]; then
+           remove_bytecode lib@PVER@-stdlib@HOST_QUAL@
+       fi
+        ;;
+    upgrade)
+       remove_bytecode lib@PVER@-stdlib@HOST_QUAL@
+       # byte compilation in @PVER@ postinst, strict dependency
+        ;;
+    deconfigure)
+        ;;
+    failed-upgrade)
+        ;;
+    *)
+        echo "prerm called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+#DEBHELPER#
diff --git a/libPVER-testsuite.overrides.in b/libPVER-testsuite.overrides.in
new file mode 100644 (file)
index 0000000..eebe34c
--- /dev/null
@@ -0,0 +1,5 @@
+lib@PVER@-testsuite binary: python-script-but-no-python-dep
+lib@PVER@-testsuite binary: image-file-in-usr-lib
+lib@PVER@-testsuite binary: privacy-breach-generic
+lib@PVER@-testsuite binary: command-with-path-in-maintainer-script
+lib@PVER@-testsuite binary: package-installs-python-egg
diff --git a/libPVER-testsuite.postinst.in b/libPVER-testsuite.postinst.in
new file mode 100644 (file)
index 0000000..05d587a
--- /dev/null
@@ -0,0 +1,20 @@
+#! /bin/sh
+
+set -e
+
+case "$1" in
+    configure)
+    files=$(dpkg -L lib@PVER@-testsuite | sed -n '/^\/usr\/lib\/@PVER@\/.*\.py$/p' | egrep -v '/lib2to3/tests/data|/test/bad')
+    if [ -n "$files" ]; then
+       /usr/bin/@PVER@ -E -S /usr/lib/@PVER@/py_compile.py $files
+       if grep -sq '^byte-compile[^#]*optimize' /etc/python/debian_config; then
+           /usr/bin/@PVER@ -E -S -O /usr/lib/@PVER@/py_compile.py $files
+       fi
+    else
+       echo >&2 "@PVER@: can't get files for byte-compilation"
+    fi
+esac
+
+#DEBHELPER#
+
+exit 0
diff --git a/libPVER-testsuite.prerm.in b/libPVER-testsuite.prerm.in
new file mode 100644 (file)
index 0000000..f003f91
--- /dev/null
@@ -0,0 +1,36 @@
+#! /bin/sh
+
+set -e
+
+remove_bytecode()
+{
+    pkg=$1
+    max=$(LANG=C LC_ALL=C xargs --show-limits < /dev/null 2>&1 | awk '/Maximum length/ {print int($NF / 4)}')
+    dpkg -L $pkg \
+       | awk -F/ 'BEGIN {OFS="/"} /\.py$/ {$NF=sprintf("__pycache__/%s.*.py[co]", substr($NF,1,length($NF)-3)); print}' \
+       | xargs --max-chars="$max" echo \
+       | while read files; do rm -f $files; done
+
+    find /usr/lib/@PVER@ \
+       -name __pycache__ -type d -empty -print \
+       | xargs -r rm -rf
+}
+
+case "$1" in
+    remove)
+       remove_bytecode lib@PVER@-testsuite
+        ;;
+    upgrade)
+       remove_bytecode lib@PVER@-testsuite
+        ;;
+    deconfigure)
+        ;;
+    failed-upgrade)
+        ;;
+    *)
+        echo "prerm called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+#DEBHELPER#
diff --git a/libPVER.overrides.in b/libPVER.overrides.in
new file mode 100644 (file)
index 0000000..9fc70c7
--- /dev/null
@@ -0,0 +1 @@
+lib@PVER@ binary: package-name-doesnt-match-sonames
diff --git a/libPVER.symbols.i386.in b/libPVER.symbols.i386.in
new file mode 100644 (file)
index 0000000..f9474e6
--- /dev/null
@@ -0,0 +1,7 @@
+libpython@VER@.so.1.0 libpython@VER@ #MINVER#
+#include "libpython.symbols"
+ PyModule_Create2@Base @SVER@
+ PyModule_FromDefAndSpec2@Base @SVER@
+ _Py_force_double@Base @SVER@
+ _Py_get_387controlword@Base @SVER@
+ _Py_set_387controlword@Base @SVER@
diff --git a/libPVER.symbols.in b/libPVER.symbols.in
new file mode 100644 (file)
index 0000000..6b55def
--- /dev/null
@@ -0,0 +1,4 @@
+libpython@VER@.so.1.0 libpython@VER@ #MINVER#
+#include "libpython.symbols"
+ PyModule_Create2@Base @SVER@
+ PyModule_FromDefAndSpec2@Base @SVER@
diff --git a/libpython.symbols.in b/libpython.symbols.in
new file mode 100644 (file)
index 0000000..2ba499d
--- /dev/null
@@ -0,0 +1,1698 @@
+ PyAST_CompileEx@Base @SVER@
+ PyAST_CompileObject@Base @SVER@
+ PyAST_FromNode@Base @SVER@
+ PyAST_FromNodeObject@Base @SVER@
+ PyAST_Validate@Base @SVER@
+ PyArena_AddPyObject@Base @SVER@
+ PyArena_Free@Base @SVER@
+ PyArena_Malloc@Base @SVER@
+ PyArena_New@Base @SVER@
+ PyArg_Parse@Base @SVER@
+ PyArg_ParseTuple@Base @SVER@
+ PyArg_ParseTupleAndKeywords@Base @SVER@
+ PyArg_UnpackTuple@Base @SVER@
+ PyArg_VaParse@Base @SVER@
+ PyArg_VaParseTupleAndKeywords@Base @SVER@
+ PyArg_ValidateKeywordArguments@Base @SVER@
+ PyAsyncGen_New@Base @SVER@
+ PyAsyncGen_Type@Base @SVER@
+ PyBaseObject_Type@Base @SVER@
+ PyBool_FromLong@Base @SVER@
+ PyBool_Type@Base @SVER@
+ PyBuffer_FillContiguousStrides@Base @SVER@
+ PyBuffer_FillInfo@Base @SVER@
+ PyBuffer_FromContiguous@Base @SVER@
+ PyBuffer_GetPointer@Base @SVER@
+ PyBuffer_IsContiguous@Base @SVER@
+ PyBuffer_Release@Base @SVER@
+ PyBuffer_SizeFromFormat@Base @SVER@
+ PyBuffer_ToContiguous@Base @SVER@
+ PyByteArrayIter_Type@Base @SVER@
+ PyByteArray_AsString@Base @SVER@
+ PyByteArray_Concat@Base @SVER@
+ PyByteArray_FromObject@Base @SVER@
+ PyByteArray_FromStringAndSize@Base @SVER@
+ PyByteArray_Resize@Base @SVER@
+ PyByteArray_Size@Base @SVER@
+ PyByteArray_Type@Base @SVER@
+ PyBytesIter_Type@Base @SVER@
+ PyBytes_AsString@Base @SVER@
+ PyBytes_AsStringAndSize@Base @SVER@
+ PyBytes_Concat@Base @SVER@
+ PyBytes_ConcatAndDel@Base @SVER@
+ PyBytes_DecodeEscape@Base @SVER@
+ PyBytes_FromFormat@Base @SVER@
+ PyBytes_FromFormatV@Base @SVER@
+ PyBytes_FromObject@Base @SVER@
+ PyBytes_FromString@Base @SVER@
+ PyBytes_FromStringAndSize@Base @SVER@
+ PyBytes_Repr@Base @SVER@
+ PyBytes_Size@Base @SVER@
+ PyBytes_Type@Base @SVER@
+ PyCFunction_Call@Base @SVER@
+ PyCFunction_GetFlags@Base @SVER@
+ PyCFunction_GetFunction@Base @SVER@
+ PyCFunction_GetSelf@Base @SVER@
+ PyCFunction_NewEx@Base @SVER@
+ PyCFunction_Type@Base @SVER@
+ PyCMethod_New@Base @SVER@
+ PyCMethod_Type@Base @SVER@
+ PyCallIter_New@Base @SVER@
+ PyCallIter_Type@Base @SVER@
+ PyCallable_Check@Base @SVER@
+ PyCapsule_GetContext@Base @SVER@
+ PyCapsule_GetDestructor@Base @SVER@
+ PyCapsule_GetName@Base @SVER@
+ PyCapsule_GetPointer@Base @SVER@
+ PyCapsule_Import@Base @SVER@
+ PyCapsule_IsValid@Base @SVER@
+ PyCapsule_New@Base @SVER@
+ PyCapsule_SetContext@Base @SVER@
+ PyCapsule_SetDestructor@Base @SVER@
+ PyCapsule_SetName@Base @SVER@
+ PyCapsule_SetPointer@Base @SVER@
+ PyCapsule_Type@Base @SVER@
+ PyCell_Get@Base @SVER@
+ PyCell_New@Base @SVER@
+ PyCell_Set@Base @SVER@
+ PyCell_Type@Base @SVER@
+ PyClassMethodDescr_Type@Base @SVER@
+ PyClassMethod_New@Base @SVER@
+ PyClassMethod_Type@Base @SVER@
+ PyCode_Addr2Line@Base @SVER@
+ PyCode_New@Base @SVER@
+ PyCode_NewEmpty@Base @SVER@
+ PyCode_NewWithPosOnlyArgs@Base @SVER@
+ PyCode_Optimize@Base @SVER@
+ PyCode_Type@Base @SVER@
+ PyCodec_BackslashReplaceErrors@Base @SVER@
+ PyCodec_Decode@Base @SVER@
+ PyCodec_Decoder@Base @SVER@
+ PyCodec_Encode@Base @SVER@
+ PyCodec_Encoder@Base @SVER@
+ PyCodec_IgnoreErrors@Base @SVER@
+ PyCodec_IncrementalDecoder@Base @SVER@
+ PyCodec_IncrementalEncoder@Base @SVER@
+ PyCodec_KnownEncoding@Base @SVER@
+ PyCodec_LookupError@Base @SVER@
+ PyCodec_NameReplaceErrors@Base @SVER@
+ PyCodec_Register@Base @SVER@
+ PyCodec_RegisterError@Base @SVER@
+ PyCodec_ReplaceErrors@Base @SVER@
+ PyCodec_StreamReader@Base @SVER@
+ PyCodec_StreamWriter@Base @SVER@
+ PyCodec_StrictErrors@Base @SVER@
+ PyCodec_XMLCharRefReplaceErrors@Base @SVER@
+ PyCompile_OpcodeStackEffect@Base @SVER@
+ PyCompile_OpcodeStackEffectWithJump@Base @SVER@
+ PyComplex_AsCComplex@Base @SVER@
+ PyComplex_FromCComplex@Base @SVER@
+ PyComplex_FromDoubles@Base @SVER@
+ PyComplex_ImagAsDouble@Base @SVER@
+ PyComplex_RealAsDouble@Base @SVER@
+ PyComplex_Type@Base @SVER@
+ PyConfig_Clear@Base @SVER@
+ PyConfig_InitIsolatedConfig@Base @SVER@
+ PyConfig_InitPythonConfig@Base @SVER@
+ PyConfig_Read@Base @SVER@
+ PyConfig_SetArgv@Base @SVER@
+ PyConfig_SetBytesArgv@Base @SVER@
+ PyConfig_SetBytesString@Base @SVER@
+ PyConfig_SetString@Base @SVER@
+ PyConfig_SetWideStringList@Base @SVER@
+ PyContextToken_Type@Base @SVER@
+ PyContextVar_Get@Base @SVER@
+ PyContextVar_New@Base @SVER@
+ PyContextVar_Reset@Base @SVER@
+ PyContextVar_Set@Base @SVER@
+ PyContextVar_Type@Base @SVER@
+ PyContext_Copy@Base @SVER@
+ PyContext_CopyCurrent@Base @SVER@
+ PyContext_Enter@Base @SVER@
+ PyContext_Exit@Base @SVER@
+ PyContext_New@Base @SVER@
+ PyContext_Type@Base @SVER@
+ PyCoro_New@Base @SVER@
+ PyCoro_Type@Base @SVER@
+ PyDescr_NewClassMethod@Base @SVER@
+ PyDescr_NewGetSet@Base @SVER@
+ PyDescr_NewMember@Base @SVER@
+ PyDescr_NewMethod@Base @SVER@
+ PyDescr_NewWrapper@Base @SVER@
+ PyDictItems_Type@Base @SVER@
+ PyDictIterItem_Type@Base @SVER@
+ PyDictIterKey_Type@Base @SVER@
+ PyDictIterValue_Type@Base @SVER@
+ PyDictKeys_Type@Base @SVER@
+ PyDictProxy_New@Base @SVER@
+ PyDictProxy_Type@Base @SVER@
+ PyDictRevIterItem_Type@Base @SVER@
+ PyDictRevIterKey_Type@Base @SVER@
+ PyDictRevIterValue_Type@Base @SVER@
+ PyDictValues_Type@Base @SVER@
+ PyDict_Clear@Base @SVER@
+ PyDict_Contains@Base @SVER@
+ PyDict_Copy@Base @SVER@
+ PyDict_DelItem@Base @SVER@
+ PyDict_DelItemString@Base @SVER@
+ PyDict_GetItem@Base @SVER@
+ PyDict_GetItemString@Base @SVER@
+ PyDict_GetItemWithError@Base @SVER@
+ PyDict_Items@Base @SVER@
+ PyDict_Keys@Base @SVER@
+ PyDict_Merge@Base @SVER@
+ PyDict_MergeFromSeq2@Base @SVER@
+ PyDict_New@Base @SVER@
+ PyDict_Next@Base @SVER@
+ PyDict_SetDefault@Base @SVER@
+ PyDict_SetItem@Base @SVER@
+ PyDict_SetItemString@Base @SVER@
+ PyDict_Size@Base @SVER@
+ PyDict_Type@Base @SVER@
+ PyDict_Update@Base @SVER@
+ PyDict_Values@Base @SVER@
+ PyEllipsis_Type@Base @SVER@
+ PyEnum_Type@Base @SVER@
+ PyErr_BadArgument@Base @SVER@
+ PyErr_BadInternalCall@Base @SVER@
+ PyErr_CheckSignals@Base @SVER@
+ PyErr_Clear@Base @SVER@
+ PyErr_Display@Base @SVER@
+ PyErr_ExceptionMatches@Base @SVER@
+ PyErr_Fetch@Base @SVER@
+ PyErr_Format@Base @SVER@
+ PyErr_FormatV@Base @SVER@
+ PyErr_GetExcInfo@Base @SVER@
+ PyErr_GivenExceptionMatches@Base @SVER@
+ PyErr_NewException@Base @SVER@
+ PyErr_NewExceptionWithDoc@Base @SVER@
+ PyErr_NoMemory@Base @SVER@
+ PyErr_NormalizeException@Base @SVER@
+ PyErr_Occurred@Base @SVER@
+ PyErr_Print@Base @SVER@
+ PyErr_PrintEx@Base @SVER@
+ PyErr_ProgramText@Base @SVER@
+ PyErr_ProgramTextObject@Base @SVER@
+ PyErr_ResourceWarning@Base @SVER@
+ PyErr_Restore@Base @SVER@
+ PyErr_SetExcInfo@Base @SVER@
+ PyErr_SetFromErrno@Base @SVER@
+ PyErr_SetFromErrnoWithFilename@Base @SVER@
+ PyErr_SetFromErrnoWithFilenameObject@Base @SVER@
+ PyErr_SetFromErrnoWithFilenameObjects@Base @SVER@
+ PyErr_SetImportError@Base @SVER@
+ PyErr_SetImportErrorSubclass@Base @SVER@
+ PyErr_SetInterrupt@Base @SVER@
+ PyErr_SetNone@Base @SVER@
+ PyErr_SetObject@Base @SVER@
+ PyErr_SetString@Base @SVER@
+ PyErr_SyntaxLocation@Base @SVER@
+ PyErr_SyntaxLocationEx@Base @SVER@
+ PyErr_SyntaxLocationObject@Base @SVER@
+ PyErr_WarnEx@Base @SVER@
+ PyErr_WarnExplicit@Base @SVER@
+ PyErr_WarnExplicitFormat@Base @SVER@
+ PyErr_WarnExplicitObject@Base @SVER@
+ PyErr_WarnFormat@Base @SVER@
+ PyErr_WriteUnraisable@Base @SVER@
+ PyEval_AcquireLock@Base @SVER@
+ PyEval_AcquireThread@Base @SVER@
+ PyEval_CallFunction@Base @SVER@
+ PyEval_CallMethod@Base @SVER@
+ PyEval_CallObjectWithKeywords@Base @SVER@
+ PyEval_EvalCode@Base @SVER@
+ PyEval_EvalCodeEx@Base @SVER@
+ PyEval_EvalFrame@Base @SVER@
+ PyEval_EvalFrameEx@Base @SVER@
+ PyEval_GetBuiltins@Base @SVER@
+ PyEval_GetFrame@Base @SVER@
+ PyEval_GetFuncDesc@Base @SVER@
+ PyEval_GetFuncName@Base @SVER@
+ PyEval_GetGlobals@Base @SVER@
+ PyEval_GetLocals@Base @SVER@
+ PyEval_InitThreads@Base @SVER@
+ PyEval_MergeCompilerFlags@Base @SVER@
+ PyEval_ReleaseLock@Base @SVER@
+ PyEval_ReleaseThread@Base @SVER@
+ PyEval_RestoreThread@Base @SVER@
+ PyEval_SaveThread@Base @SVER@
+ PyEval_SetProfile@Base @SVER@
+ PyEval_SetTrace@Base @SVER@
+ PyEval_ThreadsInitialized@Base @SVER@
+ PyExc_ArithmeticError@Base @SVER@
+ PyExc_AssertionError@Base @SVER@
+ PyExc_AttributeError@Base @SVER@
+ PyExc_BaseException@Base @SVER@
+ PyExc_BlockingIOError@Base @SVER@
+ PyExc_BrokenPipeError@Base @SVER@
+ PyExc_BufferError@Base @SVER@
+ PyExc_BytesWarning@Base @SVER@
+ PyExc_ChildProcessError@Base @SVER@
+ PyExc_ConnectionAbortedError@Base @SVER@
+ PyExc_ConnectionError@Base @SVER@
+ PyExc_ConnectionRefusedError@Base @SVER@
+ PyExc_ConnectionResetError@Base @SVER@
+ PyExc_DeprecationWarning@Base @SVER@
+ PyExc_EOFError@Base @SVER@
+ PyExc_EnvironmentError@Base @SVER@
+ PyExc_Exception@Base @SVER@
+ PyExc_FileExistsError@Base @SVER@
+ PyExc_FileNotFoundError@Base @SVER@
+ PyExc_FloatingPointError@Base @SVER@
+ PyExc_FutureWarning@Base @SVER@
+ PyExc_GeneratorExit@Base @SVER@
+ PyExc_IOError@Base @SVER@
+ PyExc_ImportError@Base @SVER@
+ PyExc_ImportWarning@Base @SVER@
+ PyExc_IndentationError@Base @SVER@
+ PyExc_IndexError@Base @SVER@
+ PyExc_InterruptedError@Base @SVER@
+ PyExc_IsADirectoryError@Base @SVER@
+ PyExc_KeyError@Base @SVER@
+ PyExc_KeyboardInterrupt@Base @SVER@
+ PyExc_LookupError@Base @SVER@
+ PyExc_MemoryError@Base @SVER@
+ PyExc_ModuleNotFoundError@Base @SVER@
+ PyExc_NameError@Base @SVER@
+ PyExc_NotADirectoryError@Base @SVER@
+ PyExc_NotImplementedError@Base @SVER@
+ PyExc_OSError@Base @SVER@
+ PyExc_OverflowError@Base @SVER@
+ PyExc_PendingDeprecationWarning@Base @SVER@
+ PyExc_PermissionError@Base @SVER@
+ PyExc_ProcessLookupError@Base @SVER@
+ PyExc_RecursionError@Base @SVER@
+ PyExc_ReferenceError@Base @SVER@
+ PyExc_ResourceWarning@Base @SVER@
+ PyExc_RuntimeError@Base @SVER@
+ PyExc_RuntimeWarning@Base @SVER@
+ PyExc_StopAsyncIteration@Base @SVER@
+ PyExc_StopIteration@Base @SVER@
+ PyExc_SyntaxError@Base @SVER@
+ PyExc_SyntaxWarning@Base @SVER@
+ PyExc_SystemError@Base @SVER@
+ PyExc_SystemExit@Base @SVER@
+ PyExc_TabError@Base @SVER@
+ PyExc_TimeoutError@Base @SVER@
+ PyExc_TypeError@Base @SVER@
+ PyExc_UnboundLocalError@Base @SVER@
+ PyExc_UnicodeDecodeError@Base @SVER@
+ PyExc_UnicodeEncodeError@Base @SVER@
+ PyExc_UnicodeError@Base @SVER@
+ PyExc_UnicodeTranslateError@Base @SVER@
+ PyExc_UnicodeWarning@Base @SVER@
+ PyExc_UserWarning@Base @SVER@
+ PyExc_ValueError@Base @SVER@
+ PyExc_Warning@Base @SVER@
+ PyExc_ZeroDivisionError@Base @SVER@
+ PyExceptionClass_Name@Base @SVER@
+ PyException_GetCause@Base @SVER@
+ PyException_GetContext@Base @SVER@
+ PyException_GetTraceback@Base @SVER@
+ PyException_SetCause@Base @SVER@
+ PyException_SetContext@Base @SVER@
+ PyException_SetTraceback@Base @SVER@
+ PyFile_FromFd@Base @SVER@
+ PyFile_GetLine@Base @SVER@
+ PyFile_NewStdPrinter@Base @SVER@
+ PyFile_OpenCode@Base @SVER@
+ PyFile_OpenCodeObject@Base @SVER@
+ PyFile_SetOpenCodeHook@Base @SVER@
+ PyFile_WriteObject@Base @SVER@
+ PyFile_WriteString@Base @SVER@
+ PyFilter_Type@Base @SVER@
+ PyFloat_AsDouble@Base @SVER@
+ PyFloat_FromDouble@Base @SVER@
+ PyFloat_FromString@Base @SVER@
+ PyFloat_GetInfo@Base @SVER@
+ PyFloat_GetMax@Base @SVER@
+ PyFloat_GetMin@Base @SVER@
+ PyFloat_Type@Base @SVER@
+ PyFrame_BlockPop@Base @SVER@
+ PyFrame_BlockSetup@Base @SVER@
+ PyFrame_FastToLocals@Base @SVER@
+ PyFrame_FastToLocalsWithError@Base @SVER@
+ PyFrame_GetBack@Base @SVER@
+ PyFrame_GetCode@Base @SVER@
+ PyFrame_GetLineNumber@Base @SVER@
+ PyFrame_LocalsToFast@Base @SVER@
+ PyFrame_New@Base @SVER@
+ PyFrame_Type@Base @SVER@
+ PyFrozenSet_New@Base @SVER@
+ PyFrozenSet_Type@Base @SVER@
+ PyFunction_GetAnnotations@Base @SVER@
+ PyFunction_GetClosure@Base @SVER@
+ PyFunction_GetCode@Base @SVER@
+ PyFunction_GetDefaults@Base @SVER@
+ PyFunction_GetGlobals@Base @SVER@
+ PyFunction_GetKwDefaults@Base @SVER@
+ PyFunction_GetModule@Base @SVER@
+ PyFunction_New@Base @SVER@
+ PyFunction_NewWithQualName@Base @SVER@
+ PyFunction_SetAnnotations@Base @SVER@
+ PyFunction_SetClosure@Base @SVER@
+ PyFunction_SetDefaults@Base @SVER@
+ PyFunction_SetKwDefaults@Base @SVER@
+ PyFunction_Type@Base @SVER@
+ PyFuture_FromAST@Base @SVER@
+ PyFuture_FromASTObject@Base @SVER@
+ PyGC_Collect@Base @SVER@
+ PyGILState_Check@Base @SVER@
+ PyGILState_Ensure@Base @SVER@
+ PyGILState_GetThisThreadState@Base @SVER@
+ PyGILState_Release@Base @SVER@
+ PyGen_New@Base @SVER@
+ PyGen_NewWithQualName@Base @SVER@
+ PyGen_Type@Base @SVER@
+ PyGetSetDescr_Type@Base @SVER@
+ PyHash_GetFuncDef@Base @SVER@
+ PyImport_AddModule@Base @SVER@
+ PyImport_AddModuleObject@Base @SVER@
+ PyImport_AppendInittab@Base @SVER@
+ PyImport_ExecCodeModule@Base @SVER@
+ PyImport_ExecCodeModuleEx@Base @SVER@
+ PyImport_ExecCodeModuleObject@Base @SVER@
+ PyImport_ExecCodeModuleWithPathnames@Base @SVER@
+ PyImport_ExtendInittab@Base @SVER@
+ PyImport_FrozenModules@Base @SVER@
+ PyImport_GetImporter@Base @SVER@
+ PyImport_GetMagicNumber@Base @SVER@
+ PyImport_GetMagicTag@Base @SVER@
+ PyImport_GetModule@Base @SVER@
+ PyImport_GetModuleDict@Base @SVER@
+ PyImport_Import@Base @SVER@
+ PyImport_ImportFrozenModule@Base @SVER@
+ PyImport_ImportFrozenModuleObject@Base @SVER@
+ PyImport_ImportModule@Base @SVER@
+ PyImport_ImportModuleLevel@Base @SVER@
+ PyImport_ImportModuleLevelObject@Base @SVER@
+ PyImport_ImportModuleNoBlock@Base @SVER@
+ PyImport_Inittab@Base @SVER@
+ PyImport_ReloadModule@Base @SVER@
+ PyIndex_Check@Base @SVER@
+ PyInit__abc@Base @SVER@
+ PyInit__ast@Base @SVER@
+ PyInit__bisect@Base @SVER@
+ PyInit__blake2@Base @SVER@
+ PyInit__codecs@Base @SVER@
+ PyInit__collections@Base @SVER@
+ PyInit__datetime@Base @SVER@
+ PyInit__elementtree@Base @SVER@
+ PyInit__functools@Base @SVER@
+ PyInit__heapq@Base @SVER@
+ PyInit__imp@Base @SVER@
+ PyInit__io@Base @SVER@
+ PyInit__locale@Base @SVER@
+ PyInit__md5@Base @SVER@
+ PyInit__operator@Base @SVER@
+ PyInit__pickle@Base @SVER@
+ PyInit__posixsubprocess@Base @SVER@
+ PyInit__random@Base @SVER@
+ PyInit__sha1@Base @SVER@
+ PyInit__sha256@Base @SVER@
+ PyInit__sha3@Base @SVER@
+ PyInit__sha512@Base @SVER@
+ PyInit__signal@Base @SVER@
+ PyInit__socket@Base @SVER@
+ PyInit__sre@Base @SVER@
+ PyInit__stat@Base @SVER@
+ PyInit__string@Base @SVER@
+ PyInit__struct@Base @SVER@
+ PyInit__symtable@Base @SVER@
+ PyInit__thread@Base @SVER@
+ PyInit__tracemalloc@Base @SVER@
+ PyInit__weakref@Base @SVER@
+ PyInit_array@Base @SVER@
+ PyInit_atexit@Base @SVER@
+ PyInit_binascii@Base @SVER@
+ PyInit_cmath@Base @SVER@
+ PyInit_errno@Base @SVER@
+ PyInit_faulthandler@Base @SVER@
+ PyInit_fcntl@Base @SVER@
+ PyInit_gc@Base @SVER@
+ PyInit_grp@Base @SVER@
+ PyInit_itertools@Base @SVER@
+ PyInit_math@Base @SVER@
+ PyInit_posix@Base @SVER@
+ PyInit_pwd@Base @SVER@
+ PyInit_pyexpat@Base @SVER@
+ PyInit_select@Base @SVER@
+ PyInit_spwd@Base @SVER@
+ PyInit_syslog@Base @SVER@
+ PyInit_time@Base @SVER@
+ PyInit_unicodedata@Base @SVER@
+ PyInit_xxsubtype@Base @SVER@
+ PyInit_zlib@Base @SVER@
+ PyInstanceMethod_Function@Base @SVER@
+ PyInstanceMethod_New@Base @SVER@
+ PyInstanceMethod_Type@Base @SVER@
+ PyInterpreterState_Clear@Base @SVER@
+ PyInterpreterState_Delete@Base @SVER@
+ PyInterpreterState_Get@Base @SVER@
+ PyInterpreterState_GetDict@Base @SVER@
+ PyInterpreterState_GetID@Base @SVER@
+ PyInterpreterState_Head@Base @SVER@
+ PyInterpreterState_Main@Base @SVER@
+ PyInterpreterState_New@Base @SVER@
+ PyInterpreterState_Next@Base @SVER@
+ PyInterpreterState_ThreadHead@Base @SVER@
+ PyIter_Check@Base @SVER@
+ PyIter_Next@Base @SVER@
+ PyListIter_Type@Base @SVER@
+ PyListRevIter_Type@Base @SVER@
+ PyList_Append@Base @SVER@
+ PyList_AsTuple@Base @SVER@
+ PyList_GetItem@Base @SVER@
+ PyList_GetSlice@Base @SVER@
+ PyList_Insert@Base @SVER@
+ PyList_New@Base @SVER@
+ PyList_Reverse@Base @SVER@
+ PyList_SetItem@Base @SVER@
+ PyList_SetSlice@Base @SVER@
+ PyList_Size@Base @SVER@
+ PyList_Sort@Base @SVER@
+ PyList_Type@Base @SVER@
+ PyLongRangeIter_Type@Base @SVER@
+ PyLong_AsDouble@Base @SVER@
+ PyLong_AsLong@Base @SVER@
+ PyLong_AsLongAndOverflow@Base @SVER@
+ PyLong_AsLongLong@Base @SVER@
+ PyLong_AsLongLongAndOverflow@Base @SVER@
+ PyLong_AsSize_t@Base @SVER@
+ PyLong_AsSsize_t@Base @SVER@
+ PyLong_AsUnsignedLong@Base @SVER@
+ PyLong_AsUnsignedLongLong@Base @SVER@
+ PyLong_AsUnsignedLongLongMask@Base @SVER@
+ PyLong_AsUnsignedLongMask@Base @SVER@
+ PyLong_AsVoidPtr@Base @SVER@
+ PyLong_FromDouble@Base @SVER@
+ PyLong_FromLong@Base @SVER@
+ PyLong_FromLongLong@Base @SVER@
+ PyLong_FromSize_t@Base @SVER@
+ PyLong_FromSsize_t@Base @SVER@
+ PyLong_FromString@Base @SVER@
+ PyLong_FromUnicode@Base @SVER@
+ PyLong_FromUnicodeObject@Base @SVER@
+ PyLong_FromUnsignedLong@Base @SVER@
+ PyLong_FromUnsignedLongLong@Base @SVER@
+ PyLong_FromVoidPtr@Base @SVER@
+ PyLong_GetInfo@Base @SVER@
+ PyLong_Type@Base @SVER@
+ PyMap_Type@Base @SVER@
+ PyMapping_Check@Base @SVER@
+ PyMapping_GetItemString@Base @SVER@
+ PyMapping_HasKey@Base @SVER@
+ PyMapping_HasKeyString@Base @SVER@
+ PyMapping_Items@Base @SVER@
+ PyMapping_Keys@Base @SVER@
+ PyMapping_Length@Base @SVER@
+ PyMapping_SetItemString@Base @SVER@
+ PyMapping_Size@Base @SVER@
+ PyMapping_Values@Base @SVER@
+ PyMarshal_Init@Base @SVER@
+ PyMarshal_ReadLastObjectFromFile@Base @SVER@
+ PyMarshal_ReadLongFromFile@Base @SVER@
+ PyMarshal_ReadObjectFromFile@Base @SVER@
+ PyMarshal_ReadObjectFromString@Base @SVER@
+ PyMarshal_ReadShortFromFile@Base @SVER@
+ PyMarshal_WriteLongToFile@Base @SVER@
+ PyMarshal_WriteObjectToFile@Base @SVER@
+ PyMarshal_WriteObjectToString@Base @SVER@
+ PyMem_Calloc@Base @SVER@
+ PyMem_Free@Base @SVER@
+ PyMem_GetAllocator@Base @SVER@
+ PyMem_Malloc@Base @SVER@
+ PyMem_RawCalloc@Base @SVER@
+ PyMem_RawFree@Base @SVER@
+ PyMem_RawMalloc@Base @SVER@
+ PyMem_RawRealloc@Base @SVER@
+ PyMem_Realloc@Base @SVER@
+ PyMem_SetAllocator@Base @SVER@
+ PyMem_SetupDebugHooks@Base @SVER@
+ PyMemberDescr_Type@Base @SVER@
+ PyMember_GetOne@Base @SVER@
+ PyMember_SetOne@Base @SVER@
+ PyMemoryView_FromBuffer@Base @SVER@
+ PyMemoryView_FromMemory@Base @SVER@
+ PyMemoryView_FromObject@Base @SVER@
+ PyMemoryView_GetContiguous@Base @SVER@
+ PyMemoryView_Type@Base @SVER@
+ PyMethodDescr_Type@Base @SVER@
+ PyMethod_Function@Base @SVER@
+ PyMethod_New@Base @SVER@
+ PyMethod_Self@Base @SVER@
+ PyMethod_Type@Base @SVER@
+ PyModuleDef_Init@Base @SVER@
+ PyModuleDef_Type@Base @SVER@
+ PyModule_AddFunctions@Base @SVER@
+ PyModule_AddIntConstant@Base @SVER@
+ PyModule_AddObject@Base @SVER@
+ PyModule_AddStringConstant@Base @SVER@
+ PyModule_AddType@Base @SVER@
+ PyModule_ExecDef@Base @SVER@
+ PyModule_GetDef@Base @SVER@
+ PyModule_GetDict@Base @SVER@
+ PyModule_GetFilename@Base @SVER@
+ PyModule_GetFilenameObject@Base @SVER@
+ PyModule_GetName@Base @SVER@
+ PyModule_GetNameObject@Base @SVER@
+ PyModule_GetState@Base @SVER@
+ PyModule_New@Base @SVER@
+ PyModule_NewObject@Base @SVER@
+ PyModule_SetDocString@Base @SVER@
+ PyModule_Type@Base @SVER@
+ PyNode_AddChild@Base @SVER@
+ PyNode_Compile@Base @SVER@
+ PyNode_Free@Base @SVER@
+ PyNode_ListTree@Base @SVER@
+ PyNode_New@Base @SVER@
+ PyNumber_Absolute@Base @SVER@
+ PyNumber_Add@Base @SVER@
+ PyNumber_And@Base @SVER@
+ PyNumber_AsSsize_t@Base @SVER@
+ PyNumber_Check@Base @SVER@
+ PyNumber_Divmod@Base @SVER@
+ PyNumber_Float@Base @SVER@
+ PyNumber_FloorDivide@Base @SVER@
+ PyNumber_InPlaceAdd@Base @SVER@
+ PyNumber_InPlaceAnd@Base @SVER@
+ PyNumber_InPlaceFloorDivide@Base @SVER@
+ PyNumber_InPlaceLshift@Base @SVER@
+ PyNumber_InPlaceMatrixMultiply@Base @SVER@
+ PyNumber_InPlaceMultiply@Base @SVER@
+ PyNumber_InPlaceOr@Base @SVER@
+ PyNumber_InPlacePower@Base @SVER@
+ PyNumber_InPlaceRemainder@Base @SVER@
+ PyNumber_InPlaceRshift@Base @SVER@
+ PyNumber_InPlaceSubtract@Base @SVER@
+ PyNumber_InPlaceTrueDivide@Base @SVER@
+ PyNumber_InPlaceXor@Base @SVER@
+ PyNumber_Index@Base @SVER@
+ PyNumber_Invert@Base @SVER@
+ PyNumber_Long@Base @SVER@
+ PyNumber_Lshift@Base @SVER@
+ PyNumber_MatrixMultiply@Base @SVER@
+ PyNumber_Multiply@Base @SVER@
+ PyNumber_Negative@Base @SVER@
+ PyNumber_Or@Base @SVER@
+ PyNumber_Positive@Base @SVER@
+ PyNumber_Power@Base @SVER@
+ PyNumber_Remainder@Base @SVER@
+ PyNumber_Rshift@Base @SVER@
+ PyNumber_Subtract@Base @SVER@
+ PyNumber_ToBase@Base @SVER@
+ PyNumber_TrueDivide@Base @SVER@
+ PyNumber_Xor@Base @SVER@
+ PyODictItems_Type@Base @SVER@
+ PyODictIter_Type@Base @SVER@
+ PyODictKeys_Type@Base @SVER@
+ PyODictValues_Type@Base @SVER@
+ PyODict_DelItem@Base @SVER@
+ PyODict_New@Base @SVER@
+ PyODict_SetItem@Base @SVER@
+ PyODict_Type@Base @SVER@
+ PyOS_AfterFork@Base @SVER@
+ PyOS_AfterFork_Child@Base @SVER@
+ PyOS_AfterFork_Parent@Base @SVER@
+ PyOS_BeforeFork@Base @SVER@
+ PyOS_FSPath@Base @SVER@
+ PyOS_InitInterrupts@Base @SVER@
+ PyOS_InputHook@Base @SVER@
+ PyOS_InterruptOccurred@Base @SVER@
+ PyOS_Readline@Base @SVER@
+ PyOS_ReadlineFunctionPointer@Base @SVER@
+ PyOS_double_to_string@Base @SVER@
+ PyOS_getsig@Base @SVER@
+ PyOS_mystricmp@Base @SVER@
+ PyOS_mystrnicmp@Base @SVER@
+ PyOS_setsig@Base @SVER@
+ PyOS_snprintf@Base @SVER@
+ PyOS_string_to_double@Base @SVER@
+ PyOS_strtol@Base @SVER@
+ PyOS_strtoul@Base @SVER@
+ PyOS_vsnprintf@Base @SVER@
+ PyObject_ASCII@Base @SVER@
+ PyObject_AsCharBuffer@Base @SVER@
+ PyObject_AsFileDescriptor@Base @SVER@
+ PyObject_AsReadBuffer@Base @SVER@
+ PyObject_AsWriteBuffer@Base @SVER@
+ PyObject_Bytes@Base @SVER@
+ PyObject_Call@Base @SVER@
+ PyObject_CallFinalizer@Base @SVER@
+ PyObject_CallFinalizerFromDealloc@Base @SVER@
+ PyObject_CallFunction@Base @SVER@
+ PyObject_CallFunctionObjArgs@Base @SVER@
+ PyObject_CallMethod@Base @SVER@
+ PyObject_CallMethodObjArgs@Base @SVER@
+ PyObject_CallNoArgs@Base @SVER@
+ PyObject_CallObject@Base @SVER@
+ PyObject_Calloc@Base @SVER@
+ PyObject_CheckBuffer@Base @SVER@
+ PyObject_CheckReadBuffer@Base @SVER@
+ PyObject_ClearWeakRefs@Base @SVER@
+ PyObject_CopyData@Base @SVER@
+ PyObject_DelItem@Base @SVER@
+ PyObject_DelItemString@Base @SVER@
+ PyObject_Dir@Base @SVER@
+ PyObject_Format@Base @SVER@
+ PyObject_Free@Base @SVER@
+ PyObject_GC_Del@Base @SVER@
+ PyObject_GC_IsFinalized@Base @SVER@
+ PyObject_GC_IsTracked@Base @SVER@
+ PyObject_GC_Track@Base @SVER@
+ PyObject_GC_UnTrack@Base @SVER@
+ PyObject_GET_WEAKREFS_LISTPTR@Base @SVER@
+ PyObject_GenericGetAttr@Base @SVER@
+ PyObject_GenericGetDict@Base @SVER@
+ PyObject_GenericSetAttr@Base @SVER@
+ PyObject_GenericSetDict@Base @SVER@
+ PyObject_GetArenaAllocator@Base @SVER@
+ PyObject_GetAttr@Base @SVER@
+ PyObject_GetAttrString@Base @SVER@
+ PyObject_GetBuffer@Base @SVER@
+ PyObject_GetItem@Base @SVER@
+ PyObject_GetIter@Base @SVER@
+ PyObject_HasAttr@Base @SVER@
+ PyObject_HasAttrString@Base @SVER@
+ PyObject_Hash@Base @SVER@
+ PyObject_HashNotImplemented@Base @SVER@
+ PyObject_IS_GC@Base @SVER@
+ PyObject_Init@Base @SVER@
+ PyObject_InitVar@Base @SVER@
+ PyObject_IsInstance@Base @SVER@
+ PyObject_IsSubclass@Base @SVER@
+ PyObject_IsTrue@Base @SVER@
+ PyObject_Length@Base @SVER@
+ PyObject_LengthHint@Base @SVER@
+ PyObject_Malloc@Base @SVER@
+ PyObject_Not@Base @SVER@
+ PyObject_Print@Base @SVER@
+ PyObject_Realloc@Base @SVER@
+ PyObject_Repr@Base @SVER@
+ PyObject_RichCompare@Base @SVER@
+ PyObject_RichCompareBool@Base @SVER@
+ PyObject_SelfIter@Base @SVER@
+ PyObject_SetArenaAllocator@Base @SVER@
+ PyObject_SetAttr@Base @SVER@
+ PyObject_SetAttrString@Base @SVER@
+ PyObject_SetItem@Base @SVER@
+ PyObject_Size@Base @SVER@
+ PyObject_Str@Base @SVER@
+ PyObject_Type@Base @SVER@
+ PyObject_VectorcallDict@Base @SVER@
+ PyObject_VectorcallMethod@Base @SVER@
+ PyParser_ASTFromFile@Base @SVER@
+ PyParser_ASTFromFileObject@Base @SVER@
+ PyParser_ASTFromString@Base @SVER@
+ PyParser_ASTFromStringObject@Base @SVER@
+ PyParser_ClearError@Base @SVER@
+ PyParser_ParseFile@Base @SVER@
+ PyParser_ParseFileFlags@Base @SVER@
+ PyParser_ParseFileFlagsEx@Base @SVER@
+ PyParser_ParseFileObject@Base @SVER@
+ PyParser_ParseString@Base @SVER@
+ PyParser_ParseStringFlags@Base @SVER@
+ PyParser_ParseStringFlagsFilename@Base @SVER@
+ PyParser_ParseStringFlagsFilenameEx@Base @SVER@
+ PyParser_ParseStringObject@Base @SVER@
+ PyParser_SetError@Base @SVER@
+ PyParser_SimpleParseFile@Base @SVER@
+ PyParser_SimpleParseFileFlags@Base @SVER@
+ PyParser_SimpleParseString@Base @SVER@
+ PyParser_SimpleParseStringFlags@Base @SVER@
+ PyParser_SimpleParseStringFlagsFilename@Base @SVER@
+ PyPegen_ASTFromFileObject@Base @SVER@
+ PyPegen_ASTFromFilename@Base @SVER@
+ PyPegen_ASTFromString@Base @SVER@
+ PyPegen_ASTFromStringObject@Base @SVER@
+ PyPickleBuffer_FromObject@Base @SVER@
+ PyPickleBuffer_GetBuffer@Base @SVER@
+ PyPickleBuffer_Release@Base @SVER@
+ PyPickleBuffer_Type@Base @SVER@
+ PyPreConfig_InitIsolatedConfig@Base @SVER@
+ PyPreConfig_InitPythonConfig@Base @SVER@
+ PyProperty_Type@Base @SVER@
+ PyRangeIter_Type@Base @SVER@
+ PyRange_Type@Base @SVER@
+ PyReversed_Type@Base @SVER@
+ PyRun_AnyFile@Base @SVER@
+ PyRun_AnyFileEx@Base @SVER@
+ PyRun_AnyFileExFlags@Base @SVER@
+ PyRun_AnyFileFlags@Base @SVER@
+ PyRun_File@Base @SVER@
+ PyRun_FileEx@Base @SVER@
+ PyRun_FileExFlags@Base @SVER@
+ PyRun_FileFlags@Base @SVER@
+ PyRun_InteractiveLoop@Base @SVER@
+ PyRun_InteractiveLoopFlags@Base @SVER@
+ PyRun_InteractiveOne@Base @SVER@
+ PyRun_InteractiveOneFlags@Base @SVER@
+ PyRun_InteractiveOneObject@Base @SVER@
+ PyRun_SimpleFile@Base @SVER@
+ PyRun_SimpleFileEx@Base @SVER@
+ PyRun_SimpleFileExFlags@Base @SVER@
+ PyRun_SimpleString@Base @SVER@
+ PyRun_SimpleStringFlags@Base @SVER@
+ PyRun_String@Base @SVER@
+ PyRun_StringFlags@Base @SVER@
+ PySTEntry_Type@Base @SVER@
+ PyST_GetScope@Base @SVER@
+ PySeqIter_New@Base @SVER@
+ PySeqIter_Type@Base @SVER@
+ PySequence_Check@Base @SVER@
+ PySequence_Concat@Base @SVER@
+ PySequence_Contains@Base @SVER@
+ PySequence_Count@Base @SVER@
+ PySequence_DelItem@Base @SVER@
+ PySequence_DelSlice@Base @SVER@
+ PySequence_Fast@Base @SVER@
+ PySequence_GetItem@Base @SVER@
+ PySequence_GetSlice@Base @SVER@
+ PySequence_In@Base @SVER@
+ PySequence_InPlaceConcat@Base @SVER@
+ PySequence_InPlaceRepeat@Base @SVER@
+ PySequence_Index@Base @SVER@
+ PySequence_Length@Base @SVER@
+ PySequence_List@Base @SVER@
+ PySequence_Repeat@Base @SVER@
+ PySequence_SetItem@Base @SVER@
+ PySequence_SetSlice@Base @SVER@
+ PySequence_Size@Base @SVER@
+ PySequence_Tuple@Base @SVER@
+ PySetIter_Type@Base @SVER@
+ PySet_Add@Base @SVER@
+ PySet_Clear@Base @SVER@
+ PySet_Contains@Base @SVER@
+ PySet_Discard@Base @SVER@
+ PySet_New@Base @SVER@
+ PySet_Pop@Base @SVER@
+ PySet_Size@Base @SVER@
+ PySet_Type@Base @SVER@
+ PySlice_AdjustIndices@Base @SVER@
+ PySlice_GetIndices@Base @SVER@
+ PySlice_GetIndicesEx@Base @SVER@
+ PySlice_New@Base @SVER@
+ PySlice_Type@Base @SVER@
+ PySlice_Unpack@Base @SVER@
+ PyState_AddModule@Base @SVER@
+ PyState_FindModule@Base @SVER@
+ PyState_RemoveModule@Base @SVER@
+ PyStaticMethod_New@Base @SVER@
+ PyStaticMethod_Type@Base @SVER@
+ PyStatus_Error@Base @SVER@
+ PyStatus_Exception@Base @SVER@
+ PyStatus_Exit@Base @SVER@
+ PyStatus_IsError@Base @SVER@
+ PyStatus_IsExit@Base @SVER@
+ PyStatus_NoMemory@Base @SVER@
+ PyStatus_Ok@Base @SVER@
+ PyStdPrinter_Type@Base @SVER@
+ PyStructSequence_GetItem@Base @SVER@
+ PyStructSequence_InitType2@Base @SVER@
+ PyStructSequence_InitType@Base @SVER@
+ PyStructSequence_New@Base @SVER@
+ PyStructSequence_NewType@Base @SVER@
+ PyStructSequence_SetItem@Base @SVER@
+ PySuper_Type@Base @SVER@
+ PySymtable_Build@Base @SVER@
+ PySymtable_BuildObject@Base @SVER@
+ PySymtable_Free@Base @SVER@
+ PySymtable_Lookup@Base @SVER@
+ PySys_AddAuditHook@Base @SVER@
+ PySys_AddWarnOption@Base @SVER@
+ PySys_AddWarnOptionUnicode@Base @SVER@
+ PySys_AddXOption@Base @SVER@
+ PySys_Audit@Base @SVER@
+ PySys_FormatStderr@Base @SVER@
+ PySys_FormatStdout@Base @SVER@
+ PySys_GetObject@Base @SVER@
+ PySys_GetXOptions@Base @SVER@
+ PySys_HasWarnOptions@Base @SVER@
+ PySys_ResetWarnOptions@Base @SVER@
+ PySys_SetArgv@Base @SVER@
+ PySys_SetArgvEx@Base @SVER@
+ PySys_SetObject@Base @SVER@
+ PySys_SetPath@Base @SVER@
+ PySys_WriteStderr@Base @SVER@
+ PySys_WriteStdout@Base @SVER@
+ PyThreadState_Clear@Base @SVER@
+ PyThreadState_Delete@Base @SVER@
+ PyThreadState_DeleteCurrent@Base @SVER@
+ PyThreadState_Get@Base @SVER@
+ PyThreadState_GetDict@Base @SVER@
+ PyThreadState_GetFrame@Base @SVER@
+ PyThreadState_GetID@Base @SVER@
+ PyThreadState_GetInterpreter@Base @SVER@
+ PyThreadState_New@Base @SVER@
+ PyThreadState_Next@Base @SVER@
+ PyThreadState_SetAsyncExc@Base @SVER@
+ PyThreadState_Swap@Base @SVER@
+ PyThread_GetInfo@Base @SVER@
+ PyThread_ReInitTLS@Base @SVER@
+ PyThread_acquire_lock@Base @SVER@
+ PyThread_acquire_lock_timed@Base @SVER@
+ PyThread_allocate_lock@Base @SVER@
+ PyThread_create_key@Base @SVER@
+ PyThread_delete_key@Base @SVER@
+ PyThread_delete_key_value@Base @SVER@
+ PyThread_exit_thread@Base @SVER@
+ PyThread_free_lock@Base @SVER@
+ PyThread_get_key_value@Base @SVER@
+ PyThread_get_stacksize@Base @SVER@
+ PyThread_get_thread_ident@Base @SVER@
+ (arch=linux-any hurd-any)PyThread_get_thread_native_id@Base @SVER@
+ PyThread_init_thread@Base @SVER@
+ PyThread_release_lock@Base @SVER@
+ PyThread_set_key_value@Base @SVER@
+ PyThread_set_stacksize@Base @SVER@
+ PyThread_start_new_thread@Base @SVER@
+ PyThread_tss_alloc@Base @SVER@
+ PyThread_tss_create@Base @SVER@
+ PyThread_tss_delete@Base @SVER@
+ PyThread_tss_free@Base @SVER@
+ PyThread_tss_get@Base @SVER@
+ PyThread_tss_is_created@Base @SVER@
+ PyThread_tss_set@Base @SVER@
+ PyToken_OneChar@Base @SVER@
+ PyToken_ThreeChars@Base @SVER@
+ PyToken_TwoChars@Base @SVER@
+ PyTraceBack_Here@Base @SVER@
+ PyTraceBack_Print@Base @SVER@
+ PyTraceBack_Type@Base @SVER@
+ PyTraceMalloc_Track@Base @SVER@
+ PyTraceMalloc_Untrack@Base @SVER@
+ PyTupleIter_Type@Base @SVER@
+ PyTuple_GetItem@Base @SVER@
+ PyTuple_GetSlice@Base @SVER@
+ PyTuple_New@Base @SVER@
+ PyTuple_Pack@Base @SVER@
+ PyTuple_SetItem@Base @SVER@
+ PyTuple_Size@Base @SVER@
+ PyTuple_Type@Base @SVER@
+ PyType_ClearCache@Base @SVER@
+ PyType_FromModuleAndSpec@Base @SVER@
+ PyType_FromSpec@Base @SVER@
+ PyType_FromSpecWithBases@Base @SVER@
+ PyType_GenericAlloc@Base @SVER@
+ PyType_GenericNew@Base @SVER@
+ PyType_GetFlags@Base @SVER@
+ PyType_GetModule@Base @SVER@
+ PyType_GetModuleState@Base @SVER@
+ PyType_GetSlot@Base @SVER@
+ PyType_IsSubtype@Base @SVER@
+ PyType_Modified@Base @SVER@
+ PyType_Ready@Base @SVER@
+ PyType_Type@Base @SVER@
+ PyUnicodeDecodeError_Create@Base @SVER@
+ PyUnicodeDecodeError_GetEncoding@Base @SVER@
+ PyUnicodeDecodeError_GetEnd@Base @SVER@
+ PyUnicodeDecodeError_GetObject@Base @SVER@
+ PyUnicodeDecodeError_GetReason@Base @SVER@
+ PyUnicodeDecodeError_GetStart@Base @SVER@
+ PyUnicodeDecodeError_SetEnd@Base @SVER@
+ PyUnicodeDecodeError_SetReason@Base @SVER@
+ PyUnicodeDecodeError_SetStart@Base @SVER@
+ PyUnicodeEncodeError_Create@Base @SVER@
+ PyUnicodeEncodeError_GetEncoding@Base @SVER@
+ PyUnicodeEncodeError_GetEnd@Base @SVER@
+ PyUnicodeEncodeError_GetObject@Base @SVER@
+ PyUnicodeEncodeError_GetReason@Base @SVER@
+ PyUnicodeEncodeError_GetStart@Base @SVER@
+ PyUnicodeEncodeError_SetEnd@Base @SVER@
+ PyUnicodeEncodeError_SetReason@Base @SVER@
+ PyUnicodeEncodeError_SetStart@Base @SVER@
+ PyUnicodeIter_Type@Base @SVER@
+ PyUnicodeTranslateError_Create@Base @SVER@
+ PyUnicodeTranslateError_GetEnd@Base @SVER@
+ PyUnicodeTranslateError_GetObject@Base @SVER@
+ PyUnicodeTranslateError_GetReason@Base @SVER@
+ PyUnicodeTranslateError_GetStart@Base @SVER@
+ PyUnicodeTranslateError_SetEnd@Base @SVER@
+ PyUnicodeTranslateError_SetReason@Base @SVER@
+ PyUnicodeTranslateError_SetStart@Base @SVER@
+ PyUnicode_Append@Base @SVER@
+ PyUnicode_AppendAndDel@Base @SVER@
+ PyUnicode_AsASCIIString@Base @SVER@
+ PyUnicode_AsCharmapString@Base @SVER@
+ PyUnicode_AsDecodedObject@Base @SVER@
+ PyUnicode_AsDecodedUnicode@Base @SVER@
+ PyUnicode_AsEncodedObject@Base @SVER@
+ PyUnicode_AsEncodedString@Base @SVER@
+ PyUnicode_AsEncodedUnicode@Base @SVER@
+ PyUnicode_AsLatin1String@Base @SVER@
+ PyUnicode_AsRawUnicodeEscapeString@Base @SVER@
+ PyUnicode_AsUCS4@Base @SVER@
+ PyUnicode_AsUCS4Copy@Base @SVER@
+ PyUnicode_AsUTF16String@Base @SVER@
+ PyUnicode_AsUTF32String@Base @SVER@
+ PyUnicode_AsUTF8@Base @SVER@
+ PyUnicode_AsUTF8AndSize@Base @SVER@
+ PyUnicode_AsUTF8String@Base @SVER@
+ PyUnicode_AsUnicode@Base @SVER@
+ PyUnicode_AsUnicodeAndSize@Base @SVER@
+ PyUnicode_AsUnicodeCopy@Base @SVER@
+ PyUnicode_AsUnicodeEscapeString@Base @SVER@
+ PyUnicode_AsWideChar@Base @SVER@
+ PyUnicode_AsWideCharString@Base @SVER@
+ PyUnicode_BuildEncodingMap@Base @SVER@
+ PyUnicode_Compare@Base @SVER@
+ PyUnicode_CompareWithASCIIString@Base @SVER@
+ PyUnicode_Concat@Base @SVER@
+ PyUnicode_Contains@Base @SVER@
+ PyUnicode_CopyCharacters@Base @SVER@
+ PyUnicode_Count@Base @SVER@
+ PyUnicode_Decode@Base @SVER@
+ PyUnicode_DecodeASCII@Base @SVER@
+ PyUnicode_DecodeCharmap@Base @SVER@
+ PyUnicode_DecodeFSDefault@Base @SVER@
+ PyUnicode_DecodeFSDefaultAndSize@Base @SVER@
+ PyUnicode_DecodeLatin1@Base @SVER@
+ PyUnicode_DecodeLocale@Base @SVER@
+ PyUnicode_DecodeLocaleAndSize@Base @SVER@
+ PyUnicode_DecodeRawUnicodeEscape@Base @SVER@
+ PyUnicode_DecodeUTF16@Base @SVER@
+ PyUnicode_DecodeUTF16Stateful@Base @SVER@
+ PyUnicode_DecodeUTF32@Base @SVER@
+ PyUnicode_DecodeUTF32Stateful@Base @SVER@
+ PyUnicode_DecodeUTF7@Base @SVER@
+ PyUnicode_DecodeUTF7Stateful@Base @SVER@
+ PyUnicode_DecodeUTF8@Base @SVER@
+ PyUnicode_DecodeUTF8Stateful@Base @SVER@
+ PyUnicode_DecodeUnicodeEscape@Base @SVER@
+ PyUnicode_Encode@Base @SVER@
+ PyUnicode_EncodeASCII@Base @SVER@
+ PyUnicode_EncodeCharmap@Base @SVER@
+ PyUnicode_EncodeDecimal@Base @SVER@
+ PyUnicode_EncodeFSDefault@Base @SVER@
+ PyUnicode_EncodeLatin1@Base @SVER@
+ PyUnicode_EncodeLocale@Base @SVER@
+ PyUnicode_EncodeRawUnicodeEscape@Base @SVER@
+ PyUnicode_EncodeUTF16@Base @SVER@
+ PyUnicode_EncodeUTF32@Base @SVER@
+ PyUnicode_EncodeUTF7@Base @SVER@
+ PyUnicode_EncodeUTF8@Base @SVER@
+ PyUnicode_EncodeUnicodeEscape@Base @SVER@
+ PyUnicode_FSConverter@Base @SVER@
+ PyUnicode_FSDecoder@Base @SVER@
+ PyUnicode_Fill@Base @SVER@
+ PyUnicode_Find@Base @SVER@
+ PyUnicode_FindChar@Base @SVER@
+ PyUnicode_Format@Base @SVER@
+ PyUnicode_FromEncodedObject@Base @SVER@
+ PyUnicode_FromFormat@Base @SVER@
+ PyUnicode_FromFormatV@Base @SVER@
+ PyUnicode_FromKindAndData@Base @SVER@
+ PyUnicode_FromObject@Base @SVER@
+ PyUnicode_FromOrdinal@Base @SVER@
+ PyUnicode_FromString@Base @SVER@
+ PyUnicode_FromStringAndSize@Base @SVER@
+ PyUnicode_FromUnicode@Base @SVER@
+ PyUnicode_FromWideChar@Base @SVER@
+ PyUnicode_GetDefaultEncoding@Base @SVER@
+ PyUnicode_GetLength@Base @SVER@
+ PyUnicode_GetMax@Base @SVER@
+ PyUnicode_GetSize@Base @SVER@
+ PyUnicode_InternFromString@Base @SVER@
+ PyUnicode_InternImmortal@Base @SVER@
+ PyUnicode_InternInPlace@Base @SVER@
+ PyUnicode_IsIdentifier@Base @SVER@
+ PyUnicode_Join@Base @SVER@
+ PyUnicode_New@Base @SVER@
+ PyUnicode_Partition@Base @SVER@
+ PyUnicode_RPartition@Base @SVER@
+ PyUnicode_RSplit@Base @SVER@
+ PyUnicode_ReadChar@Base @SVER@
+ PyUnicode_Replace@Base @SVER@
+ PyUnicode_Resize@Base @SVER@
+ PyUnicode_RichCompare@Base @SVER@
+ PyUnicode_Split@Base @SVER@
+ PyUnicode_Splitlines@Base @SVER@
+ PyUnicode_Substring@Base @SVER@
+ PyUnicode_Tailmatch@Base @SVER@
+ PyUnicode_TransformDecimalToASCII@Base @SVER@
+ PyUnicode_Translate@Base @SVER@
+ PyUnicode_TranslateCharmap@Base @SVER@
+ PyUnicode_Type@Base @SVER@
+ PyUnicode_WriteChar@Base @SVER@
+ PyVectorcall_Call@Base @SVER@
+ PyWeakref_GetObject@Base @SVER@
+ PyWeakref_NewProxy@Base @SVER@
+ PyWeakref_NewRef@Base @SVER@
+ PyWideStringList_Append@Base @SVER@
+ PyWideStringList_Insert@Base @SVER@
+ PyWrapperDescr_Type@Base @SVER@
+ PyWrapper_New@Base @SVER@
+ PyZip_Type@Base @SVER@
+ Py_AddPendingCall@Base @SVER@
+ Py_AtExit@Base @SVER@
+ Py_BuildValue@Base @SVER@
+ Py_BytesMain@Base @SVER@
+ Py_BytesWarningFlag@Base @SVER@
+ Py_CompileString@Base @SVER@
+ Py_CompileStringExFlags@Base @SVER@
+ Py_CompileStringFlags@Base @SVER@
+ Py_CompileStringObject@Base @SVER@
+ Py_DebugFlag@Base @SVER@
+ Py_DecRef@Base @SVER@
+ Py_DecodeLocale@Base @SVER@
+ Py_DontWriteBytecodeFlag@Base @SVER@
+ Py_EncodeLocale@Base @SVER@
+ Py_EndInterpreter@Base @SVER@
+ Py_EnterRecursiveCall@Base @SVER@
+ Py_Exit@Base @SVER@
+ Py_ExitStatusException@Base @SVER@
+ Py_FatalError@Base @SVER@
+ Py_FdIsInteractive@Base @SVER@
+ Py_FileSystemDefaultEncodeErrors@Base @SVER@
+ Py_FileSystemDefaultEncoding@Base @SVER@
+ Py_Finalize@Base @SVER@
+ Py_FinalizeEx@Base @SVER@
+ Py_FrozenFlag@Base @SVER@
+ Py_FrozenMain@Base @SVER@
+ Py_GenericAlias@Base @SVER@
+ Py_GenericAliasType@Base @SVER@
+ Py_GetArgcArgv@Base @SVER@
+ Py_GetBuildInfo@Base @SVER@
+ Py_GetCompiler@Base @SVER@
+ Py_GetCopyright@Base @SVER@
+ Py_GetExecPrefix@Base @SVER@
+ Py_GetPath@Base @SVER@
+ Py_GetPlatform@Base @SVER@
+ Py_GetPrefix@Base @SVER@
+ Py_GetProgramFullPath@Base @SVER@
+ Py_GetProgramName@Base @SVER@
+ Py_GetPythonHome@Base @SVER@
+ Py_GetRecursionLimit@Base @SVER@
+ Py_GetVersion@Base @SVER@
+ Py_HasFileSystemDefaultEncoding@Base @SVER@
+ Py_HashRandomizationFlag@Base @SVER@
+ Py_IgnoreEnvironmentFlag@Base @SVER@
+ Py_IncRef@Base @SVER@
+ Py_Initialize@Base @SVER@
+ Py_InitializeEx@Base @SVER@
+ Py_InitializeFromConfig@Base @SVER@
+ Py_InspectFlag@Base @SVER@
+ Py_InteractiveFlag@Base @SVER@
+ Py_IsInitialized@Base @SVER@
+ Py_IsolatedFlag@Base @SVER@
+ Py_LeaveRecursiveCall@Base @SVER@
+ Py_Main@Base @SVER@
+ Py_MakePendingCalls@Base @SVER@
+ Py_NewInterpreter@Base @SVER@
+ Py_NoSiteFlag@Base @SVER@
+ Py_NoUserSiteDirectory@Base @SVER@
+ Py_OptimizeFlag@Base @SVER@
+ Py_PreInitialize@Base @SVER@
+ Py_PreInitializeFromArgs@Base @SVER@
+ Py_PreInitializeFromBytesArgs@Base @SVER@
+ Py_QuietFlag@Base @SVER@
+ Py_ReprEnter@Base @SVER@
+ Py_ReprLeave@Base @SVER@
+ Py_RunMain@Base @SVER@
+ Py_SetPath@Base @SVER@
+ Py_SetProgramName@Base @SVER@
+ Py_SetPythonHome@Base @SVER@
+ Py_SetRecursionLimit@Base @SVER@
+ Py_SetStandardStreamEncoding@Base @SVER@
+ Py_SymtableString@Base @SVER@
+ Py_SymtableStringObject@Base @SVER@
+ Py_UNICODE_strcat@Base @SVER@
+ Py_UNICODE_strchr@Base @SVER@
+ Py_UNICODE_strcmp@Base @SVER@
+ Py_UNICODE_strcpy@Base @SVER@
+ Py_UNICODE_strlen@Base @SVER@
+ Py_UNICODE_strncmp@Base @SVER@
+ Py_UNICODE_strncpy@Base @SVER@
+ Py_UNICODE_strrchr@Base @SVER@
+ Py_UTF8Mode@Base @SVER@
+ Py_UnbufferedStdioFlag@Base @SVER@
+ Py_UniversalNewlineFgets@Base @SVER@
+ Py_VaBuildValue@Base @SVER@
+ Py_VerboseFlag@Base @SVER@
+ Py_hexdigits@Base @SVER@
+ _PyAST_GetDocString@Base @SVER@
+ _PyAST_Optimize@Base @SVER@
+ _PyAccu_Accumulate@Base @SVER@
+ _PyAccu_Destroy@Base @SVER@
+ _PyAccu_Finish@Base @SVER@
+ _PyAccu_FinishAsList@Base @SVER@
+ _PyAccu_Init@Base @SVER@
+ _PyArg_BadArgument@Base @SVER@
+ _PyArg_CheckPositional@Base @SVER@
+ _PyArg_NoKeywords@Base @SVER@
+ _PyArg_NoKwnames@Base @SVER@
+ _PyArg_NoPositional@Base @SVER@
+ _PyArg_ParseStack@Base @SVER@
+ _PyArg_ParseStackAndKeywords@Base @SVER@
+ _PyArg_ParseStackAndKeywords_SizeT@Base @SVER@
+ _PyArg_ParseStack_SizeT@Base @SVER@
+ _PyArg_ParseTupleAndKeywordsFast@Base @SVER@
+ _PyArg_ParseTupleAndKeywordsFast_SizeT@Base @SVER@
+ _PyArg_ParseTupleAndKeywords_SizeT@Base @SVER@
+ _PyArg_ParseTuple_SizeT@Base @SVER@
+ _PyArg_Parse_SizeT@Base @SVER@
+ _PyArg_UnpackKeywords@Base @SVER@
+ _PyArg_UnpackStack@Base @SVER@
+ _PyArg_VaParseTupleAndKeywordsFast@Base @SVER@
+ _PyArg_VaParseTupleAndKeywordsFast_SizeT@Base @SVER@
+ _PyArg_VaParseTupleAndKeywords_SizeT@Base @SVER@
+ _PyArg_VaParse_SizeT@Base @SVER@
+ _PyArgv_AsWstrList@Base @SVER@
+ _PyAsyncGenASend_Type@Base @SVER@
+ _PyAsyncGenAThrow_Type@Base @SVER@
+ _PyAsyncGenWrappedValue_Type@Base @SVER@
+ _PyByteArray_empty_string@Base @SVER@
+ _PyBytesIOBuffer_Type@Base @SVER@
+ _PyBytesWriter_Alloc@Base @SVER@
+ _PyBytesWriter_Dealloc@Base @SVER@
+ _PyBytesWriter_Finish@Base @SVER@
+ _PyBytesWriter_Init@Base @SVER@
+ _PyBytesWriter_Prepare@Base @SVER@
+ _PyBytesWriter_Resize@Base @SVER@
+ _PyBytesWriter_WriteBytes@Base @SVER@
+ _PyBytes_DecodeEscape@Base @SVER@
+ _PyBytes_FormatEx@Base @SVER@
+ _PyBytes_FromHex@Base @SVER@
+ _PyBytes_Join@Base @SVER@
+ _PyBytes_Resize@Base @SVER@
+ _PyCode_CheckLineNumber@Base @SVER@
+ _PyCode_ConstantKey@Base @SVER@
+ _PyCode_GetExtra@Base @SVER@
+ _PyCode_SetExtra@Base @SVER@
+ _PyCodecInfo_GetIncrementalDecoder@Base @SVER@
+ _PyCodecInfo_GetIncrementalEncoder@Base @SVER@
+ _PyCodec_DecodeText@Base @SVER@
+ _PyCodec_EncodeText@Base @SVER@
+ _PyCodec_Forget@Base @SVER@
+ _PyCodec_Lookup@Base @SVER@
+ _PyCodec_LookupTextEncoding@Base @SVER@
+ _PyComplex_FormatAdvancedWriter@Base @SVER@
+ _PyConfig_InitCompatConfig@Base @SVER@
+ _PyContext_NewHamtForTests@Base @SVER@
+ _PyCoroWrapper_Type@Base @SVER@
+ _PyCrossInterpreterData_Lookup@Base @SVER@
+ _PyCrossInterpreterData_NewObject@Base @SVER@
+ _PyCrossInterpreterData_RegisterClass@Base @SVER@
+ _PyCrossInterpreterData_Release@Base @SVER@
+ _PyDebugAllocatorStats@Base @SVER@
+ _PyDictView_Intersect@Base @SVER@
+ _PyDictView_New@Base @SVER@
+ _PyDict_CheckConsistency@Base @SVER@
+ _PyDict_Contains@Base @SVER@
+ _PyDict_DebugMallocStats@Base @SVER@
+ _PyDict_DelItemId@Base @SVER@
+ _PyDict_DelItemIf@Base @SVER@
+ _PyDict_DelItem_KnownHash@Base @SVER@
+ _PyDict_GetItemId@Base @SVER@
+ _PyDict_GetItemIdWithError@Base @SVER@
+ _PyDict_GetItemStringWithError@Base @SVER@
+ _PyDict_GetItem_KnownHash@Base @SVER@
+ _PyDict_HasOnlyStringKeys@Base @SVER@
+ _PyDict_MaybeUntrack@Base @SVER@
+ _PyDict_MergeEx@Base @SVER@
+ _PyDict_NewPresized@Base @SVER@
+ _PyDict_Next@Base @SVER@
+ _PyDict_Pop@Base @SVER@
+ _PyDict_SetItemId@Base @SVER@
+ _PyDict_SetItem_KnownHash@Base @SVER@
+ _PyDict_SizeOf@Base @SVER@
+ _PyErr_BadInternalCall@Base @SVER@
+ _PyErr_ChainExceptions@Base @SVER@
+ _PyErr_ChainStackItem@Base @SVER@
+ _PyErr_CheckSignals@Base @SVER@
+ _PyErr_CheckSignalsTstate@Base @SVER@
+ _PyErr_Clear@Base @SVER@
+ _PyErr_Display@Base @SVER@
+ _PyErr_ExceptionMatches@Base @SVER@
+ _PyErr_Fetch@Base @SVER@
+ _PyErr_Format@Base @SVER@
+ _PyErr_FormatFromCause@Base @SVER@
+ _PyErr_FormatFromCauseTstate@Base @SVER@
+ _PyErr_GetExcInfo@Base @SVER@
+ _PyErr_GetTopmostException@Base @SVER@
+ _PyErr_NoMemory@Base @SVER@
+ _PyErr_NormalizeException@Base @SVER@
+ _PyErr_Print@Base @SVER@
+ _PyErr_Restore@Base @SVER@
+ _PyErr_SetKeyError@Base @SVER@
+ _PyErr_SetNone@Base @SVER@
+ _PyErr_SetObject@Base @SVER@
+ _PyErr_SetString@Base @SVER@
+ _PyErr_TrySetFromCause@Base @SVER@
+ _PyErr_WriteUnraisableMsg@Base @SVER@
+ _PyEval_AddPendingCall@Base @SVER@
+ _PyEval_CallTracing@Base @SVER@
+ _PyEval_EvalCodeWithName@Base @SVER@
+ _PyEval_EvalFrameDefault@Base @SVER@
+ _PyEval_GetAsyncGenFinalizer@Base @SVER@
+ _PyEval_GetAsyncGenFirstiter@Base @SVER@
+ _PyEval_GetBuiltinId@Base @SVER@
+ _PyEval_GetCoroutineOriginTrackingDepth@Base @SVER@
+ _PyEval_GetSwitchInterval@Base @SVER@
+ _PyEval_RequestCodeExtraIndex@Base @SVER@
+ _PyEval_SetAsyncGenFinalizer@Base @SVER@
+ _PyEval_SetAsyncGenFirstiter@Base @SVER@
+ _PyEval_SetCoroutineOriginTrackingDepth@Base @SVER@
+ _PyEval_SetProfile@Base @SVER@
+ _PyEval_SetSwitchInterval@Base @SVER@
+ _PyEval_SetTrace@Base @SVER@
+ _PyEval_SignalAsyncExc@Base @SVER@
+ _PyEval_SignalReceived@Base @SVER@
+ _PyEval_SliceIndex@Base @SVER@
+ _PyEval_SliceIndexNotNone@Base @SVER@
+ _PyFloat_DebugMallocStats@Base @SVER@
+ _PyFloat_FormatAdvancedWriter@Base @SVER@
+ _PyFloat_Pack2@Base @SVER@
+ _PyFloat_Pack4@Base @SVER@
+ _PyFloat_Pack8@Base @SVER@
+ _PyFloat_Unpack2@Base @SVER@
+ _PyFloat_Unpack4@Base @SVER@
+ _PyFloat_Unpack8@Base @SVER@
+ _PyFrame_DebugMallocStats@Base @SVER@
+ _PyFunction_Vectorcall@Base @SVER@
+ _PyGC_CollectIfEnabled@Base @SVER@
+ _PyGC_CollectNoFail@Base @SVER@
+ _PyGC_InitState@Base @SVER@
+ _PyGILState_GetInterpreterStateUnsafe@Base @SVER@
+ _PyGILState_Reinit@Base @SVER@
+ _PyGen_FetchStopIterationValue@Base @SVER@
+ _PyGen_Finalize@Base @SVER@
+ _PyGen_Send@Base @SVER@
+ _PyGen_SetStopIterationValue@Base @SVER@
+ _PyHamtItems_Type@Base @SVER@
+ _PyHamtKeys_Type@Base @SVER@
+ _PyHamtValues_Type@Base @SVER@
+ _PyHamt_ArrayNode_Type@Base @SVER@
+ _PyHamt_BitmapNode_Type@Base @SVER@
+ _PyHamt_CollisionNode_Type@Base @SVER@
+ _PyHamt_Type@Base @SVER@
+ _PyImport_AcquireLock@Base @SVER@
+ _PyImport_FindExtensionObject@Base @SVER@
+ _PyImport_FixupBuiltin@Base @SVER@
+ _PyImport_FixupExtensionObject@Base @SVER@
+ _PyImport_GetModuleId@Base @SVER@
+ _PyImport_IsInitialized@Base @SVER@
+ _PyImport_ReleaseLock@Base @SVER@
+ _PyImport_SetModule@Base @SVER@
+ _PyImport_SetModuleString@Base @SVER@
+ _PyInterpreterID_LookUp@Base @SVER@
+ _PyInterpreterID_New@Base @SVER@
+ _PyInterpreterID_Type@Base @SVER@
+ _PyInterpreterState_DeleteExceptMain@Base @SVER@
+ _PyInterpreterState_Enable@Base @SVER@
+ _PyInterpreterState_GetConfig@Base @SVER@
+ _PyInterpreterState_GetEvalFrameFunc@Base @SVER@
+ _PyInterpreterState_GetIDObject@Base @SVER@
+ _PyInterpreterState_GetMainModule@Base @SVER@
+ _PyInterpreterState_IDDecref@Base @SVER@
+ _PyInterpreterState_IDIncref@Base @SVER@
+ _PyInterpreterState_IDInitref@Base @SVER@
+ _PyInterpreterState_LookUpID@Base @SVER@
+ _PyInterpreterState_RequireIDRef@Base @SVER@
+ _PyInterpreterState_RequiresIDRef@Base @SVER@
+ _PyInterpreterState_SetEvalFrameFunc@Base @SVER@
+ _PyList_DebugMallocStats@Base @SVER@
+ _PyList_Extend@Base @SVER@
+ _PyLong_AsByteArray@Base @SVER@
+ _PyLong_AsInt@Base @SVER@
+ _PyLong_AsTime_t@Base @SVER@
+ _PyLong_Copy@Base @SVER@
+ _PyLong_DigitValue@Base @SVER@
+ _PyLong_DivmodNear@Base @SVER@
+ _PyLong_Format@Base @SVER@
+ _PyLong_FormatAdvancedWriter@Base @SVER@
+ _PyLong_FormatBytesWriter@Base @SVER@
+ _PyLong_FormatWriter@Base @SVER@
+ _PyLong_Frexp@Base @SVER@
+ _PyLong_FromByteArray@Base @SVER@
+ _PyLong_FromBytes@Base @SVER@
+ _PyLong_FromGid@Base @SVER@
+ _PyLong_FromNbIndexOrNbInt@Base @SVER@
+ _PyLong_FromNbInt@Base @SVER@
+ _PyLong_FromTime_t@Base @SVER@
+ _PyLong_FromUid@Base @SVER@
+ _PyLong_GCD@Base @SVER@
+ _PyLong_Lshift@Base @SVER@
+ _PyLong_New@Base @SVER@
+ _PyLong_NumBits@Base @SVER@
+ _PyLong_One@Base @SVER@
+ _PyLong_Rshift@Base @SVER@
+ _PyLong_Sign@Base @SVER@
+ _PyLong_Size_t_Converter@Base @SVER@
+ _PyLong_UnsignedInt_Converter@Base @SVER@
+ _PyLong_UnsignedLongLong_Converter@Base @SVER@
+ _PyLong_UnsignedLong_Converter@Base @SVER@
+ _PyLong_UnsignedShort_Converter@Base @SVER@
+ _PyLong_Zero@Base @SVER@
+ _PyManagedBuffer_Type@Base @SVER@
+ _PyMem_GetAllocatorName@Base @SVER@
+ _PyMem_GetCurrentAllocatorName@Base @SVER@
+ _PyMem_RawStrdup@Base @SVER@
+ _PyMem_RawWcsdup@Base @SVER@
+ _PyMem_SetDefaultAllocator@Base @SVER@
+ _PyMem_SetupAllocators@Base @SVER@
+ _PyMem_Strdup@Base @SVER@
+ _PyMethodWrapper_Type@Base @SVER@
+ _PyModuleSpec_IsInitializing@Base @SVER@
+ _PyModule_Clear@Base @SVER@
+ _PyModule_ClearDict@Base @SVER@
+ _PyModule_CreateInitialized@Base @SVER@
+ _PyNamespace_New@Base @SVER@
+ _PyNamespace_Type@Base @SVER@
+ _PyNode_SizeOf@Base @SVER@
+ _PyNone_Type@Base @SVER@
+ _PyNotImplemented_Type@Base @SVER@
+ _PyOS_InterruptOccurred@Base @SVER@
+ _PyOS_IsMainThread@Base @SVER@
+ _PyOS_ReadlineTState@Base @SVER@
+ _PyOS_URandom@Base @SVER@
+ _PyOS_URandomNonblock@Base @SVER@
+ _PyObject_AssertFailed@Base @SVER@
+ _PyObject_Call@Base @SVER@
+ _PyObject_CallFunction_SizeT@Base @SVER@
+ _PyObject_CallMethodId@Base @SVER@
+ _PyObject_CallMethodIdObjArgs@Base @SVER@
+ _PyObject_CallMethodId_SizeT@Base @SVER@
+ _PyObject_CallMethod_SizeT@Base @SVER@
+ _PyObject_Call_Prepend@Base @SVER@
+ _PyObject_CheckConsistency@Base @SVER@
+ _PyObject_CheckCrossInterpreterData@Base @SVER@
+ _PyObject_DebugMallocStats@Base @SVER@
+ _PyObject_DebugTypeStats@Base @SVER@
+ _PyObject_Dump@Base @SVER@
+ _PyObject_FastCallDictTstate@Base @SVER@
+ _PyObject_FunctionStr@Base @SVER@
+ _PyObject_GC_Calloc@Base @SVER@
+ _PyObject_GC_Malloc@Base @SVER@
+ _PyObject_GC_New@Base @SVER@
+ _PyObject_GC_NewVar@Base @SVER@
+ _PyObject_GC_Resize@Base @SVER@
+ _PyObject_GenericGetAttrWithDict@Base @SVER@
+ _PyObject_GenericSetAttrWithDict@Base @SVER@
+ _PyObject_GetAttrId@Base @SVER@
+ _PyObject_GetCrossInterpreterData@Base @SVER@
+ _PyObject_GetDictPtr@Base @SVER@
+ _PyObject_GetMethod@Base @SVER@
+ _PyObject_HasAttrId@Base @SVER@
+ _PyObject_HasLen@Base @SVER@
+ _PyObject_IsAbstract@Base @SVER@
+ _PyObject_IsFreed@Base @SVER@
+ _PyObject_LookupAttr@Base @SVER@
+ _PyObject_LookupAttrId@Base @SVER@
+ _PyObject_LookupSpecial@Base @SVER@
+ _PyObject_MakeTpCall@Base @SVER@
+ _PyObject_New@Base @SVER@
+ _PyObject_NewVar@Base @SVER@
+ _PyObject_NextNotImplemented@Base @SVER@
+ _PyObject_RealIsInstance@Base @SVER@
+ _PyObject_RealIsSubclass@Base @SVER@
+ _PyObject_SetAttrId@Base @SVER@
+ _PyParser_Grammar@Base @SVER@
+ _PyParser_TokenNames@Base @SVER@
+ _PyPreConfig_InitCompatConfig@Base @SVER@
+ _PyRuntime@Base @SVER@
+ _PyRuntimeState_Fini@Base @SVER@
+ _PyRuntimeState_Init@Base @SVER@
+ _PyRuntimeState_ReInitThreads@Base @SVER@
+ _PyRuntime_Finalize@Base @SVER@
+ _PyRuntime_Initialize@Base @SVER@
+ _PySequence_BytesToCharpArray@Base @SVER@
+ _PySequence_IterSearch@Base @SVER@
+ _PySet_Dummy@Base @SVER@
+ _PySet_NextEntry@Base @SVER@
+ _PySet_Update@Base @SVER@
+ _PySignal_AfterFork@Base @SVER@
+ _PySlice_FromIndices@Base @SVER@
+ _PySlice_GetLongIndices@Base @SVER@
+ _PyStack_AsDict@Base @SVER@
+ _PyState_AddModule@Base @SVER@
+ _PySys_GetObjectId@Base @SVER@
+ _PySys_GetSizeOf@Base @SVER@
+ _PySys_SetObjectId@Base @SVER@
+ _PyThreadState_DeleteCurrent@Base @SVER@
+ _PyThreadState_DeleteExcept@Base @SVER@
+ _PyThreadState_GetDict@Base @SVER@
+ _PyThreadState_Init@Base @SVER@
+ _PyThreadState_Prealloc@Base @SVER@
+ _PyThreadState_Swap@Base @SVER@
+ _PyThreadState_UncheckedGet@Base @SVER@
+ _PyThread_CurrentFrames@Base @SVER@
+ _PyThread_at_fork_reinit@Base @SVER@
+ _PyTime_AsMicroseconds@Base @SVER@
+ _PyTime_AsMilliseconds@Base @SVER@
+ _PyTime_AsNanosecondsObject@Base @SVER@
+ _PyTime_AsSecondsDouble@Base @SVER@
+ _PyTime_AsTimespec@Base @SVER@
+ _PyTime_AsTimeval@Base @SVER@
+ _PyTime_AsTimevalTime_t@Base @SVER@
+ _PyTime_AsTimeval_noraise@Base @SVER@
+ _PyTime_FromMillisecondsObject@Base @SVER@
+ _PyTime_FromNanoseconds@Base @SVER@
+ _PyTime_FromNanosecondsObject@Base @SVER@
+ _PyTime_FromSeconds@Base @SVER@
+ _PyTime_FromSecondsObject@Base @SVER@
+ _PyTime_FromTimespec@Base @SVER@
+ _PyTime_FromTimeval@Base @SVER@
+ _PyTime_GetMonotonicClock@Base @SVER@
+ _PyTime_GetMonotonicClockWithInfo@Base @SVER@
+ _PyTime_GetPerfCounter@Base @SVER@
+ _PyTime_GetPerfCounterWithInfo@Base @SVER@
+ _PyTime_GetSystemClock@Base @SVER@
+ _PyTime_GetSystemClockWithInfo@Base @SVER@
+ _PyTime_Init@Base @SVER@
+ _PyTime_MulDiv@Base @SVER@
+ _PyTime_ObjectToTime_t@Base @SVER@
+ _PyTime_ObjectToTimespec@Base @SVER@
+ _PyTime_ObjectToTimeval@Base @SVER@
+ _PyTime_gmtime@Base @SVER@
+ _PyTime_localtime@Base @SVER@
+ _PyTraceMalloc_GetTraceback@Base @SVER@
+ _PyTraceMalloc_NewReference@Base @SVER@
+ _PyTraceback_Add@Base @SVER@
+ _PyTrash_begin@Base @SVER@
+ _PyTrash_deposit_object@Base @SVER@
+ _PyTrash_destroy_chain@Base @SVER@
+ _PyTrash_end@Base @SVER@
+ _PyTrash_thread_deposit_object@Base @SVER@
+ _PyTrash_thread_destroy_chain@Base @SVER@
+ _PyTuple_DebugMallocStats@Base @SVER@
+ _PyTuple_MaybeUntrack@Base @SVER@
+ _PyTuple_Resize@Base @SVER@
+ _PyType_CalculateMetaclass@Base @SVER@
+ _PyType_CheckConsistency@Base @SVER@
+ _PyType_GetDocFromInternalDoc@Base @SVER@
+ _PyType_GetTextSignatureFromInternalDoc@Base @SVER@
+ _PyType_Lookup@Base @SVER@
+ _PyType_LookupId@Base @SVER@
+ _PyType_Name@Base @SVER@
+ _PyUnicodeTranslateError_Create@Base @SVER@
+ _PyUnicodeWriter_Dealloc@Base @SVER@
+ _PyUnicodeWriter_Finish@Base @SVER@
+ _PyUnicodeWriter_Init@Base @SVER@
+ _PyUnicodeWriter_PrepareInternal@Base @SVER@
+ _PyUnicodeWriter_PrepareKindInternal@Base @SVER@
+ _PyUnicodeWriter_WriteASCIIString@Base @SVER@
+ _PyUnicodeWriter_WriteChar@Base @SVER@
+ _PyUnicodeWriter_WriteLatin1String@Base @SVER@
+ _PyUnicodeWriter_WriteStr@Base @SVER@
+ _PyUnicodeWriter_WriteSubstring@Base @SVER@
+ _PyUnicode_AsASCIIString@Base @SVER@
+ _PyUnicode_AsLatin1String@Base @SVER@
+ _PyUnicode_AsUTF8String@Base @SVER@
+ _PyUnicode_AsUnicode@Base @SVER@
+ _PyUnicode_CheckConsistency@Base @SVER@
+ _PyUnicode_Copy@Base @SVER@
+ _PyUnicode_DecodeUnicodeEscape@Base @SVER@
+ _PyUnicode_EQ@Base @SVER@
+ _PyUnicode_EncodeCharmap@Base @SVER@
+ _PyUnicode_EncodeUTF16@Base @SVER@
+ _PyUnicode_EncodeUTF32@Base @SVER@
+ _PyUnicode_EncodeUTF7@Base @SVER@
+ _PyUnicode_EqualToASCIIId@Base @SVER@
+ _PyUnicode_EqualToASCIIString@Base @SVER@
+ _PyUnicode_FastCopyCharacters@Base @SVER@
+ _PyUnicode_FastFill@Base @SVER@
+ _PyUnicode_FindMaxChar@Base @SVER@
+ _PyUnicode_FormatAdvancedWriter@Base @SVER@
+ _PyUnicode_FormatLong@Base @SVER@
+ _PyUnicode_FromASCII@Base @SVER@
+ _PyUnicode_FromId@Base @SVER@
+ _PyUnicode_InsertThousandsGrouping@Base @SVER@
+ _PyUnicode_IsAlpha@Base @SVER@
+ _PyUnicode_IsCaseIgnorable@Base @SVER@
+ _PyUnicode_IsCased@Base @SVER@
+ _PyUnicode_IsDecimalDigit@Base @SVER@
+ _PyUnicode_IsDigit@Base @SVER@
+ _PyUnicode_IsLinebreak@Base @SVER@
+ _PyUnicode_IsLowercase@Base @SVER@
+ _PyUnicode_IsNumeric@Base @SVER@
+ _PyUnicode_IsPrintable@Base @SVER@
+ _PyUnicode_IsTitlecase@Base @SVER@
+ _PyUnicode_IsUppercase@Base @SVER@
+ _PyUnicode_IsWhitespace@Base @SVER@
+ _PyUnicode_IsXidContinue@Base @SVER@
+ _PyUnicode_IsXidStart@Base @SVER@
+ _PyUnicode_JoinArray@Base @SVER@
+ _PyUnicode_Ready@Base @SVER@
+ _PyUnicode_ScanIdentifier@Base @SVER@
+ _PyUnicode_ToDecimalDigit@Base @SVER@
+ _PyUnicode_ToDigit@Base @SVER@
+ _PyUnicode_ToFoldedFull@Base @SVER@
+ _PyUnicode_ToLowerFull@Base @SVER@
+ _PyUnicode_ToLowercase@Base @SVER@
+ _PyUnicode_ToNumeric@Base @SVER@
+ _PyUnicode_ToTitleFull@Base @SVER@
+ _PyUnicode_ToTitlecase@Base @SVER@
+ _PyUnicode_ToUpperFull@Base @SVER@
+ _PyUnicode_ToUppercase@Base @SVER@
+ _PyUnicode_TransformDecimalAndSpaceToASCII@Base @SVER@
+ _PyUnicode_XStrip@Base @SVER@
+ _PyWarnings_Init@Base @SVER@
+ _PyWeakref_CallableProxyType@Base @SVER@
+ _PyWeakref_ClearRef@Base @SVER@
+ _PyWeakref_GetWeakrefCount@Base @SVER@
+ _PyWeakref_ProxyType@Base @SVER@
+ _PyWeakref_RefType@Base @SVER@
+ _PyWideStringList_AsList@Base @SVER@
+ _PyWideStringList_Clear@Base @SVER@
+ _PyWideStringList_Copy@Base @SVER@
+ _PyWideStringList_Extend@Base @SVER@
+ _Py_BreakPoint@Base @SVER@
+ _Py_BuildValue_SizeT@Base @SVER@
+ _Py_CheckFunctionResult@Base @SVER@
+ _Py_CheckRecursionLimit@Base @SVER@
+ _Py_CheckRecursiveCall@Base @SVER@
+ _Py_ClearArgcArgv@Base @SVER@
+ _Py_ClearStandardStreamEncoding@Base @SVER@
+ _Py_CoerceLegacyLocale@Base @SVER@
+ _Py_Dealloc@Base @SVER@
+ _Py_DecodeLocaleEx@Base @SVER@
+ _Py_DecodeUTF8Ex@Base @SVER@
+ _Py_DecodeUTF8_surrogateescape@Base @SVER@
+ _Py_DisplaySourceLine@Base @SVER@
+ _Py_EllipsisObject@Base @SVER@
+ _Py_EncodeLocaleEx@Base @SVER@
+ _Py_EncodeLocaleRaw@Base @SVER@
+ _Py_EncodeUTF8Ex@Base @SVER@
+ _Py_FalseStruct@Base @SVER@
+ _Py_FatalErrorFormat@Base @SVER@
+ _Py_FatalErrorFunc@Base @SVER@
+ _Py_FatalError_TstateNULL@Base @SVER@
+ _Py_FreeCharPArray@Base @SVER@
+ _Py_GetAllocatedBlocks@Base @SVER@
+ _Py_GetConfig@Base @SVER@
+ _Py_GetConfigsAsDict@Base @SVER@
+ _Py_GetEnv@Base @SVER@
+ _Py_GetErrorHandler@Base @SVER@
+ _Py_GetForceASCII@Base @SVER@
+ _Py_GetLocaleconvNumeric@Base @SVER@
+ _Py_Gid_Converter@Base @SVER@
+ _Py_HandleSystemExit@Base @SVER@
+ _Py_HashBytes@Base @SVER@
+ _Py_HashDouble@Base @SVER@
+ _Py_HashPointer@Base @SVER@
+ _Py_HashPointerRaw@Base @SVER@
+ _Py_HashSecret@Base @SVER@
+ _Py_InitializeMain@Base @SVER@
+ _Py_IsCoreInitialized@Base @SVER@
+ _Py_IsFinalizing@Base @SVER@
+ _Py_IsLocaleCoercionTarget@Base @SVER@
+ _Py_LegacyLocaleDetected@Base @SVER@
+ _Py_Mangle@Base @SVER@
+ _Py_NewInterpreter@Base @SVER@
+ _Py_NewReference@Base @SVER@
+ _Py_NoneStruct@Base @SVER@
+ _Py_NotImplementedStruct@Base @SVER@
+ _Py_PackageContext@Base @SVER@
+ _Py_PreInitializeFromConfig@Base @SVER@
+ _Py_PreInitializeFromPyArgv@Base @SVER@
+ _Py_PyAtExit@Base @SVER@
+ _Py_ResetForceASCII@Base @SVER@
+ _Py_RestoreSignals@Base @SVER@
+ _Py_SetLocaleFromEnv@Base @SVER@
+ _Py_SetProgramFullPath@Base @SVER@
+ _Py_Sigset_Converter@Base @SVER@
+ _Py_SourceAsString@Base @SVER@
+ _Py_SwappedOp@Base @SVER@
+ _Py_SymtableStringObjectFlags@Base @SVER@
+ _Py_TrueStruct@Base @SVER@
+ _Py_Uid_Converter@Base @SVER@
+ _Py_UnhandledKeyboardInterrupt@Base @SVER@
+ _Py_VaBuildStack@Base @SVER@
+ _Py_VaBuildStack_SizeT@Base @SVER@
+ _Py_VaBuildValue_SizeT@Base @SVER@
+ _Py_abspath@Base @SVER@
+ _Py_add_one_to_index_C@Base @SVER@
+ _Py_add_one_to_index_F@Base @SVER@
+ _Py_ascii_whitespace@Base @SVER@
+ _Py_bit_length@Base @SVER@
+ _Py_c_abs@Base @SVER@
+ _Py_c_diff@Base @SVER@
+ _Py_c_neg@Base @SVER@
+ _Py_c_pow@Base @SVER@
+ _Py_c_prod@Base @SVER@
+ _Py_c_quot@Base @SVER@
+ _Py_c_sum@Base @SVER@
+ _Py_convert_optional_to_ssize_t@Base @SVER@
+ _Py_ctype_table@Base @SVER@
+ _Py_ctype_tolower@Base @SVER@
+ _Py_ctype_toupper@Base @SVER@
+ _Py_device_encoding@Base @SVER@
+ (arch=!m68k)_Py_dg_dtoa@Base @SVER@
+ (arch=!m68k)_Py_dg_freedtoa@Base @SVER@
+ (arch=!m68k)_Py_dg_infinity@Base @SVER@
+ (arch=!m68k)_Py_dg_stdnan@Base @SVER@
+ (arch=!m68k)_Py_dg_strtod@Base @SVER@
+ _Py_dup@Base @SVER@
+ _Py_fopen@Base @SVER@
+ _Py_fopen_obj@Base @SVER@
+ _Py_fstat@Base @SVER@
+ _Py_fstat_noraise@Base @SVER@
+ _Py_get_blocking@Base @SVER@
+ _Py_get_env_flag@Base @SVER@
+ _Py_get_inheritable@Base @SVER@
+ _Py_get_xoption@Base @SVER@
+ _Py_gitidentifier@Base @SVER@
+ _Py_gitversion@Base @SVER@
+ _Py_hashtable_clear@Base @SVER@
+ _Py_hashtable_compare_direct@Base @SVER@
+ _Py_hashtable_destroy@Base @SVER@
+ _Py_hashtable_foreach@Base @SVER@
+ _Py_hashtable_get@Base @SVER@
+ _Py_hashtable_hash_ptr@Base @SVER@
+ _Py_hashtable_new@Base @SVER@
+ _Py_hashtable_new_full@Base @SVER@
+ _Py_hashtable_set@Base @SVER@
+ _Py_hashtable_size@Base @SVER@
+ _Py_hashtable_steal@Base @SVER@
+ _Py_isabs@Base @SVER@
+ _Py_open@Base @SVER@
+ _Py_open_noraise@Base @SVER@
+ _Py_parse_inf_or_nan@Base @SVER@
+ _Py_path_config@Base @SVER@
+ _Py_read@Base @SVER@
+ _Py_set_blocking@Base @SVER@
+ _Py_set_inheritable@Base @SVER@
+ _Py_set_inheritable_async_safe@Base @SVER@
+ _Py_stat@Base @SVER@
+ _Py_str_to_int@Base @SVER@
+ _Py_strhex@Base @SVER@
+ _Py_strhex_bytes@Base @SVER@
+ _Py_strhex_bytes_with_sep@Base @SVER@
+ _Py_strhex_with_sep@Base @SVER@
+ _Py_string_to_number_with_underscores@Base @SVER@
+ _Py_tracemalloc_config@Base @SVER@
+ _Py_wfopen@Base @SVER@
+ _Py_wgetcwd@Base @SVER@
+ _Py_wreadlink@Base @SVER@
+ _Py_wrealpath@Base @SVER@
+ _Py_write@Base @SVER@
+ _Py_write_noraise@Base @SVER@
+
+ (arch=i386 hurd-i386 kfreebsd-i386 m68k)_Py_force_double@Base @SVER@
+ (arch=amd64 i386 hurd-i386 kfreebsd-i386)_Py_get_387controlword@Base @SVER@
+ (arch=amd64 i386 hurd-i386 kfreebsd-i386)_Py_set_387controlword@Base @SVER@
+
+ (optional|regex)"^_ctypes_.*@Base$" @SVER@
+
+ (optional|regex)"^PyInit_.*@Base$" @SVER@
diff --git a/locale-gen b/locale-gen
new file mode 100644 (file)
index 0000000..285cd1f
--- /dev/null
@@ -0,0 +1,31 @@
+#!/bin/sh
+
+LOCPATH=`pwd`/locales
+export LOCPATH
+
+[ -d $LOCPATH ] || mkdir -p $LOCPATH
+
+umask 022
+
+echo "Generating locales..."
+while read locale charset; do
+       case $locale in \#*) continue;; esac
+       [ -n "$locale" -a -n "$charset" ] || continue
+       echo -n "  `echo $locale | sed 's/\([^.\@]*\).*/\1/'`"
+       echo -n ".$charset"
+       echo -n `echo $locale | sed 's/\([^\@]*\)\(\@.*\)*/\2/'`
+       echo -n '...'
+        if [ -f $LOCPATH/$locale ]; then
+           input=$locale
+       else
+            input=`echo $locale | sed 's/\([^.]*\)[^@]*\(.*\)/\1\2/'`
+       fi
+       localedef -i $input -c -f $charset $LOCPATH/$locale #-A /etc/locale.alias
+       echo ' done'; \
+done <<EOF
+# This file lists locales that the python testsuite depends on
+en_US                  ISO-8859-1
+en_US.UTF-8            UTF-8
+EOF
+
+echo "Generation complete."
diff --git a/mincheck.py b/mincheck.py
new file mode 100644 (file)
index 0000000..5d29586
--- /dev/null
@@ -0,0 +1,41 @@
+
+import sys
+
+def get_listed(fn):
+    modules = set()
+    for line in open(fn).readlines():
+        modules.add(line.split()[1])
+    return modules
+
+def get_dependencies(fn):
+    t = eval(open(fn).read())
+    modules = set()
+    depgraph = t['depgraph']
+    for mod, deps in list(depgraph.items()):
+        if mod != '__main__':
+            modules.add(mod)
+        modules.update(list(deps.keys()))
+    return depgraph, modules
+
+def main():
+    mods = get_listed(sys.argv[1])
+    depgraph, deps = get_dependencies(sys.argv[2])
+    print(("Listed modules:", sorted(mods)))
+    print("")
+    print(("Dependent modules:", sorted(deps)))
+    print("")
+
+    missing = deps.difference(mods)
+    if missing:
+        print("Missing modules in python-minimal:")
+        print(missing)
+    for m in missing:
+        users = []
+        for caller, callees in list(depgraph.items()):
+            if m in callees:
+                users.append(caller)
+        print((m, "used in: ", users))
+    sys.exit(len(missing))
+
+main()
+
diff --git a/mkbinfmt.py b/mkbinfmt.py
new file mode 100644 (file)
index 0000000..0cf45e7
--- /dev/null
@@ -0,0 +1,18 @@
+# mkbinfmt.py
+import imp, sys, os.path
+
+magic = "".join(["\\x%.2x" % c for c in imp.get_magic()])
+
+name = sys.argv[1]
+binfmt = '''\
+package %s
+interpreter /usr/bin/%s
+magic %s\
+''' % (name, name, magic)
+
+#filename = '/usr/share/binfmts/' + name
+#open(filename,'w+').write(binfmt)
+
+sys.stdout.write(binfmt)
+sys.stdout.write('\n')
diff --git a/multiarch.h.in b/multiarch.h.in
new file mode 100644 (file)
index 0000000..bc579db
--- /dev/null
@@ -0,0 +1,105 @@
+#if defined(__linux__)
+# if defined(__x86_64__) && defined(__LP64__)
+#  include <x86_64-linux-gnu/@subdir@/@header@>
+# elif defined(__x86_64__) && defined(__ILP32__)
+#  include <x86_64-linux-gnux32/@subdir@/@header@>
+# elif defined(__i386__)
+#  include <i386-linux-gnu/@subdir@/@header@>
+# elif defined(__aarch64__) && defined(__AARCH64EL__)
+#  include <aarch64-linux-gnu/@subdir@/@header@>
+# elif defined(__alpha__)
+#  include <alpha-linux-gnu/@subdir@/@header@>
+# elif defined(__ARM_EABI__) && defined(__ARM_PCS_VFP)
+#  include <arm-linux-gnueabihf/@subdir@/@header@>
+# elif defined(__ARM_EABI__) && !defined(__ARM_PCS_VFP)
+#  include <arm-linux-gnueabi/@subdir@/@header@>
+# elif defined(__hppa__)
+#  include <hppa-linux-gnu/@subdir@/@header@>
+# elif defined(__ia64__)
+#  include <ia64-linux-gnu/@subdir@/@header@>
+# elif defined(__m68k__) && !defined(__mcoldfire__)
+#  include <m68k-linux-gnu/@subdir@/@header@>
+# elif defined(__mips_hard_float) && defined(__mips_isa_rev) && (__mips_isa_rev >=6) && defined(_MIPSEL)
+#  if _MIPS_SIM == _ABIO32
+#   include <mipsisa32r6el-linux-gnu/@subdir@/@header@>
+#  elif _MIPS_SIM == _ABIN32
+#   include <mipsisa64r6el-linux-gnuabin32/@subdir@/@header@>
+#  elif _MIPS_SIM == _ABI64
+#   include <mipsisa64r6el-linux-gnuabi64/@subdir@/@header@>
+#  else
+#   error unknown multiarch location for @header@
+#  endif
+# elif defined(__mips_hard_float) && defined(__mips_isa_rev) && (__mips_isa_rev >=6)
+#  if _MIPS_SIM == _ABIO32
+#   include <mipsisa32r6-linux-gnu/@subdir@/@header@>
+#  elif _MIPS_SIM == _ABIN32
+#   include <mipsisa64r6-linux-gnuabin32/@subdir@/@header@>
+#  elif _MIPS_SIM == _ABI64
+#   include <mipsisa64r6-linux-gnuabi64/@subdir@/@header@>
+#  else
+#   error unknown multiarch location for @header@
+#  endif
+# elif defined(__mips_hard_float) && defined(_MIPSEL)
+#  if _MIPS_SIM == _ABIO32
+#   include <mipsel-linux-gnu/@subdir@/@header@>
+#  elif _MIPS_SIM == _ABIN32
+#   include <mips64el-linux-gnuabin32/@subdir@/@header@>
+#  elif _MIPS_SIM == _ABI64
+#   include <mips64el-linux-gnuabi64/@subdir@/@header@>
+#  else
+#   error unknown multiarch location for @header@
+#  endif
+# elif defined(__mips_hard_float)
+#  if _MIPS_SIM == _ABIO32
+#   include <mips-linux-gnu/@subdir@/@header@>
+#  elif _MIPS_SIM == _ABIN32
+#   include <mips64-linux-gnuabin32/@subdir@/@header@>
+#  elif _MIPS_SIM == _ABI64
+#   include <mips64-linux-gnuabi64/@subdir@/@header@>
+#  else
+#   error unknown multiarch location for @header@
+#  endif
+# elif defined(__or1k__)
+#  include <or1k-linux-gnu/@subdir@/@header@>
+# elif defined(__powerpc__) && defined(__SPE__)
+#  include <powerpc-linux-gnuspe/@subdir@/@header@>
+# elif defined(__powerpc64__)
+#  if defined(__LITTLE_ENDIAN__)
+#    include <powerpc64le-linux-gnu/@subdir@/@header@>
+#  else
+#    include <powerpc64-linux-gnu/@subdir@/@header@>
+#  endif
+# elif defined(__powerpc__)
+#  include <powerpc-linux-gnu/@subdir@/@header@>
+# elif defined(__s390x__)
+#  include <s390x-linux-gnu/@subdir@/@header@>
+# elif defined(__s390__)
+#  include <s390-linux-gnu/@subdir@/@header@>
+# elif defined(__sh__) && defined(__LITTLE_ENDIAN__)
+#  include <sh4-linux-gnu/@subdir@/@header@>
+# elif defined(__sparc__) && defined(__arch64__)
+#  include <sparc64-linux-gnu/@subdir@/@header@>
+# elif defined(__sparc__)
+#  include <sparc-linux-gnu/@subdir@/@header@>
+# elif defined(__riscv)
+#  if __riscv_xlen == 64
+#    include <riscv64-linux-gnu/@subdir@/@header@>
+#  else
+#    include <riscv32-linux-gnu/@subdir@/@header@>
+#  endif
+# else
+#   error unknown multiarch location for @header@
+# endif
+#elif defined(__FreeBSD_kernel__)
+# if defined(__LP64__)
+#  include <x86_64-kfreebsd-gnu/@subdir@/@header@>
+# elif defined(__i386__)
+#  include <i386-kfreebsd-gnu/@subdir@/@header@>
+# else
+#   error unknown multiarch location for @header@
+# endif
+#elif defined(__gnu_hurd__)
+# include <i386-gnu/@subdir@/@header@>
+#else
+# error unknown multiarch location for @header@
+#endif
diff --git a/openssl.cnf b/openssl.cnf
new file mode 100644 (file)
index 0000000..a4d9923
--- /dev/null
@@ -0,0 +1,7 @@
+openssl_conf = default_conf
+[default_conf]
+ssl_conf = ssl_sect
+[ssl_sect]
+system_default = system_default_sect
+[system_default_sect]
+CipherString = DEFAULT@SECLEVEL=1
diff --git a/patches/argparse-no-shutil.diff b/patches/argparse-no-shutil.diff
new file mode 100644 (file)
index 0000000..917debd
--- /dev/null
@@ -0,0 +1,18 @@
+--- a/Lib/argparse.py
++++ b/Lib/argparse.py
+@@ -175,9 +175,12 @@ class HelpFormatter(object):
+         # default setting for width
+         if width is None:
+-            import shutil
+-            width = shutil.get_terminal_size().columns
+-            width -= 2
++            try:
++                import shutil as _shutil
++                width = _shutil.get_terminal_size().columns
++                width -= 2
++            except ImportError:
++                width = 70
+         self._prog = prog
+         self._indent_increment = indent_increment
diff --git a/patches/arm-alignment.diff b/patches/arm-alignment.diff
new file mode 100644 (file)
index 0000000..15d28b8
--- /dev/null
@@ -0,0 +1,17 @@
+Author: Dave Jones <dave.jones@canonical.com>
+Description: Use aligned access for _sha3 module on ARM.
+--- a/Modules/_sha3/sha3module.c
++++ b/Modules/_sha3/sha3module.c
+@@ -64,6 +64,12 @@
+ #define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
+ #endif
++/* Bus error on 32-bit ARM due to un-aligned memory accesses; 64-bit ARM
++ * doesn't complain but un-aligned memory accesses are sub-optimal */
++#if defined(__arm__) || defined(__aarch64__)
++#define NO_MISALIGNED_ACCESSES 1
++#endif
++
+ /* mangle names */
+ #define KeccakF1600_FastLoop_Absorb _PySHA3_KeccakF1600_FastLoop_Absorb
+ #define Keccak_HashFinal _PySHA3_Keccak_HashFinal
diff --git a/patches/bdist-wininst-notfound.diff b/patches/bdist-wininst-notfound.diff
new file mode 100644 (file)
index 0000000..29a857d
--- /dev/null
@@ -0,0 +1,16 @@
+# DP: suggest installation of the pythonX.Y-dev package, if bdist_wininst
+# DP: cannot find the wininst-* files.
+
+--- a/Lib/distutils/command/bdist_wininst.py
++++ b/Lib/distutils/command/bdist_wininst.py
+@@ -372,6 +372,10 @@ class bdist_wininst(Command):
+         filename = os.path.join(directory, "wininst-%s%s.exe" % (bv, sfix))
+         f = open(filename, "rb")
+         try:
++            f = open(filename, "rb")
++        except IOError as e:
++            raise DistutilsFileError(str(e) + ', %s not included in the Debian packages.' % filename)
++        try:
+             return f.read()
+         finally:
+             f.close()
diff --git a/patches/build-math-object.diff b/patches/build-math-object.diff
new file mode 100644 (file)
index 0000000..8f7c54c
--- /dev/null
@@ -0,0 +1,23 @@
+--- a/Makefile.pre.in
++++ b/Makefile.pre.in
+@@ -22,7 +22,8 @@
+ MODBUILT_NAMES=    _MODBUILT_NAMES_
+ MODDISABLED_NAMES= _MODDISABLED_NAMES_
+-MODOBJS=           _MODOBJS_
++# filter out duplicate object files (_math.o)
++MODOBJS=           $(sort _MODOBJS_)
+ MODLIBS=           _MODLIBS_
+ # === Variables set by configure
+@@ -619,8 +620,9 @@ pybuilddir.txt: $(BUILDPYTHON)
+       fi
+ # This is shared by the math and cmath modules
++# don't build with -fPIC when building as math and cmath as builtins
+ Modules/_math.o: Modules/_math.c Modules/_math.h
+-      $(CC) -c $(CCSHARED) $(PY_CORE_CFLAGS) -o $@ $<
++      $(CC) -c $(if $(findstring _math.o, $(MODOBJS)),,$(CCSHARED)) $(PY_CORE_CFLAGS) -o $@ $<
+ # blake2s is auto-generated from blake2b
+ $(srcdir)/Modules/_blake2/blake2s_impl.c: $(srcdir)/Modules/_blake2/blake2b_impl.c $(srcdir)/Modules/_blake2/blake2b2s.py
diff --git a/patches/ctypes-arm.diff b/patches/ctypes-arm.diff
new file mode 100644 (file)
index 0000000..129ff8a
--- /dev/null
@@ -0,0 +1,32 @@
+--- a/Lib/ctypes/util.py
++++ b/Lib/ctypes/util.py
+@@ -269,16 +269,27 @@ elif os.name == "posix":
+         def _findSoname_ldconfig(name):
+             import struct
++            # XXX this code assumes that we know all unames and that a single
++            # ABI is supported per uname; instead we should find what the
++            # ABI is (e.g. check ABI of current process) or simply ask libc
++            # to load the library for us
++            uname = os.uname()
++            # ARM has a variety of unames, e.g. armv7l
++            if uname.machine.startswith("arm"):
++                machine = "arm"
+             if struct.calcsize('l') == 4:
+-                machine = os.uname().machine + '-32'
++                machine = uname.machine + '-32'
+             else:
+-                machine = os.uname().machine + '-64'
++                machine = uname.machine + '-64'
+             mach_map = {
+                 'x86_64-64': 'libc6,x86-64',
+                 'ppc64-64': 'libc6,64bit',
+                 'sparc64-64': 'libc6,64bit',
+                 's390x-64': 'libc6,64bit',
+                 'ia64-64': 'libc6,IA-64',
++                # this actually breaks on biarch or multiarch as the first
++                # library wins; uname doesn't tell us which ABI we're using
++                'arm-32': 'libc6(,hard-float)?',
+                 }
+             abi_type = mach_map.get(machine, 'libc6')
diff --git a/patches/deb-locations.diff b/patches/deb-locations.diff
new file mode 100644 (file)
index 0000000..ac7805f
--- /dev/null
@@ -0,0 +1,26 @@
+# DP: adjust locations of directories to debian policy
+
+--- a/Lib/pydoc.py
++++ b/Lib/pydoc.py
+@@ -31,6 +31,10 @@ to a file named "<name>.html".
+ Module docs for core modules are assumed to be in
++    /usr/share/doc/pythonX.Y/html/library
++
++if the pythonX.Y-doc package is installed or in
++
+     https://docs.python.org/X.Y/library/
+ This can be overridden by setting the PYTHONDOCS environment variable
+--- a/Misc/python.man
++++ b/Misc/python.man
+@@ -371,7 +371,7 @@ exception).  Error messages are written
+ These are subject to difference depending on local installation
+ conventions; ${prefix} and ${exec_prefix} are installation-dependent
+ and should be interpreted as for GNU software; they may be the same.
+-The default for both is \fI/usr/local\fP.
++On Debian GNU/{Hurd,Linux} the default for both is \fI/usr\fP.
+ .IP \fI${exec_prefix}/bin/python\fP
+ Recommended location of the interpreter.
+ .PP
diff --git a/patches/deb-setup.diff b/patches/deb-setup.diff
new file mode 100644 (file)
index 0000000..01a8c69
--- /dev/null
@@ -0,0 +1,31 @@
+# DP: Don't include /usr/local/include and /usr/local/lib as gcc search paths
+
+--- a/setup.py
++++ b/setup.py
+@@ -452,8 +452,10 @@ class PyBuildExt(build_ext):
+         # unfortunately, distutils doesn't let us provide separate C and C++
+         # compilers
+         if compiler is not None:
+-            (ccshared,cflags) = sysconfig.get_config_vars('CCSHARED','CFLAGS')
+-            args['compiler_so'] = compiler + ' ' + ccshared + ' ' + cflags
++            (ccshared, cppflags, cflags) = \
++                sysconfig.get_config_vars('CCSHARED', 'CPPFLAGS', 'CFLAGS')
++            cppflags = ' '.join([f for f in cppflags.split() if not f.startswith('-I')])
++            args['compiler_so'] = compiler + ' ' + ccshared + ' ' + cppflags + ' ' + cflags
+         self.compiler.set_executables(**args)
+     def build_extensions(self):
+@@ -740,12 +742,7 @@ class PyBuildExt(build_ext):
+                         add_dir_to_list(dir_list, directory)
+     def configure_compiler(self):
+-        # Ensure that /usr/local is always used, but the local build
+-        # directories (i.e. '.' and 'Include') must be first.  See issue
+-        # 10520.
+-        if not CROSS_COMPILING:
+-            add_dir_to_list(self.compiler.library_dirs, '/usr/local/lib')
+-            add_dir_to_list(self.compiler.include_dirs, '/usr/local/include')
++        # On Debian /usr/local is always used, so we don't include it twice
+         # only change this for cross builds for 3.3, issues on Mageia
+         if CROSS_COMPILING:
+             self.add_cross_compiling_paths()
diff --git a/patches/disable-sem-check.diff b/patches/disable-sem-check.diff
new file mode 100644 (file)
index 0000000..9a93ce6
--- /dev/null
@@ -0,0 +1,36 @@
+# DP: Assume working semaphores, don't rely on running kernel for the check.
+
+--- a/configure.ac
++++ b/configure.ac
+@@ -4605,8 +4605,13 @@ int main(void) {
+ AC_MSG_RESULT($ac_cv_posix_semaphores_enabled)
+ if test $ac_cv_posix_semaphores_enabled = no
+ then
+-  AC_DEFINE(POSIX_SEMAPHORES_NOT_ENABLED, 1,
+-            [Define if POSIX semaphores aren't enabled on your system])
++  case $ac_sys_system in
++    Linux*) # assume yes, see https://launchpad.net/bugs/630511
++      ;;
++    *)
++      AC_DEFINE(POSIX_SEMAPHORES_NOT_ENABLED, 1,
++                [Define if POSIX semaphores aren't enabled on your system])
++  esac
+ fi
+ # Multiprocessing check for broken sem_getvalue
+@@ -4641,8 +4646,13 @@ int main(void){
+ AC_MSG_RESULT($ac_cv_broken_sem_getvalue)
+ if test $ac_cv_broken_sem_getvalue = yes
+ then
+-  AC_DEFINE(HAVE_BROKEN_SEM_GETVALUE, 1,
+-  [define to 1 if your sem_getvalue is broken.])
++  case $ac_sys_system in
++    Linux*) # assume yes, see https://launchpad.net/bugs/630511
++      ;;
++    *)
++      AC_DEFINE(HAVE_BROKEN_SEM_GETVALUE, 1,
++      [define to 1 if your sem_getvalue is broken.])
++  esac
+ fi
+ AC_CHECK_DECLS([RTLD_LAZY, RTLD_NOW, RTLD_GLOBAL, RTLD_LOCAL, RTLD_NODELETE, RTLD_NOLOAD, RTLD_DEEPBIND, RTLD_MEMBER], [], [], [[#include <dlfcn.h>]])
diff --git a/patches/disable-some-tests.diff b/patches/disable-some-tests.diff
new file mode 100644 (file)
index 0000000..28b72ec
--- /dev/null
@@ -0,0 +1,14 @@
+# DP: Disable some failing tests we are not interested in
+
+Index: b/Lib/distutils/tests/test_build_ext.py
+===================================================================
+--- a/Lib/distutils/tests/test_build_ext.py
++++ b/Lib/distutils/tests/test_build_ext.py
+@@ -111,6 +111,7 @@ class BuildExtTestCase(TempdirManager,
+         """)
+         assert_python_ok('-c', code)
++    @unittest.skip('Skipping failing Solaris test')
+     def test_solaris_enable_shared(self):
+         dist = Distribution({'name': 'xx'})
+         cmd = self.build_ext(dist)
diff --git a/patches/distutils-install-layout.diff b/patches/distutils-install-layout.diff
new file mode 100644 (file)
index 0000000..9e4f68c
--- /dev/null
@@ -0,0 +1,263 @@
+# DP: distutils: Add an option --install-layout=deb, which
+# DP: - installs into $prefix/dist-packages instead of $prefix/site-packages.
+# DP: - doesn't encode the python version into the egg name.
+
+--- a/Lib/distutils/command/install_egg_info.py
++++ b/Lib/distutils/command/install_egg_info.py
+@@ -14,18 +14,38 @@ class install_egg_info(Command):
+     description = "Install package's PKG-INFO metadata as an .egg-info file"
+     user_options = [
+         ('install-dir=', 'd', "directory to install to"),
++        ('install-layout', None, "custom installation layout"),
+     ]
+     def initialize_options(self):
+         self.install_dir = None
++        self.install_layout = None
++        self.prefix_option = None
+     def finalize_options(self):
+         self.set_undefined_options('install_lib',('install_dir','install_dir'))
+-        basename = "%s-%s-py%d.%d.egg-info" % (
+-            to_filename(safe_name(self.distribution.get_name())),
+-            to_filename(safe_version(self.distribution.get_version())),
+-            *sys.version_info[:2]
+-        )
++        self.set_undefined_options('install',('install_layout','install_layout'))
++        self.set_undefined_options('install',('prefix_option','prefix_option'))
++        if self.install_layout:
++            if not self.install_layout.lower() in ['deb', 'unix']:
++                raise DistutilsOptionError(
++                    "unknown value for --install-layout")
++            no_pyver = (self.install_layout.lower() == 'deb')
++        elif self.prefix_option:
++            no_pyver = False
++        else:
++            no_pyver = True
++        if no_pyver:
++            basename = "%s-%s.egg-info" % (
++                to_filename(safe_name(self.distribution.get_name())),
++                to_filename(safe_version(self.distribution.get_version()))
++                )
++        else:
++            basename = "%s-%s-py%d.%d.egg-info" % (
++                to_filename(safe_name(self.distribution.get_name())),
++                to_filename(safe_version(self.distribution.get_version())),
++                *sys.version_info[:2]
++            )
+         self.target = os.path.join(self.install_dir, basename)
+         self.outputs = [self.target]
+--- a/Lib/distutils/command/install.py
++++ b/Lib/distutils/command/install.py
+@@ -35,6 +35,20 @@ INSTALL_SCHEMES = {
+         'scripts': '$base/bin',
+         'data'   : '$base',
+         },
++    'unix_local': {
++        'purelib': '$base/local/lib/python$py_version_short/dist-packages',
++        'platlib': '$platbase/local/lib/python$py_version_short/dist-packages',
++        'headers': '$base/local/include/python$py_version_short/$dist_name',
++        'scripts': '$base/local/bin',
++        'data'   : '$base/local',
++        },
++    'deb_system': {
++        'purelib': '$base/lib/python3/dist-packages',
++        'platlib': '$platbase/lib/python3/dist-packages',
++        'headers': '$base/include/python$py_version_short/$dist_name',
++        'scripts': '$base/bin',
++        'data'   : '$base',
++        },
+     'unix_home': {
+         'purelib': '$base/lib/python',
+         'platlib': '$base/$platlibdir/python',
+@@ -131,6 +145,9 @@ class install(Command):
+         ('record=', None,
+          "filename in which to record list of installed files"),
++
++        ('install-layout=', None,
++         "installation layout to choose (known values: deb, unix)"),
+         ]
+     boolean_options = ['compile', 'force', 'skip-build']
+@@ -151,6 +168,7 @@ class install(Command):
+         self.exec_prefix = None
+         self.home = None
+         self.user = 0
++        self.prefix_option = None
+         # These select only the installation base; it's up to the user to
+         # specify the installation scheme (currently, that means supplying
+@@ -172,6 +190,9 @@ class install(Command):
+         self.install_userbase = USER_BASE
+         self.install_usersite = USER_SITE
++        # enable custom installation, known values: deb
++        self.install_layout = None
++        
+         self.compile = None
+         self.optimize = None
+@@ -414,6 +435,7 @@ class install(Command):
+             self.install_base = self.install_platbase = self.home
+             self.select_scheme("unix_home")
+         else:
++            self.prefix_option = self.prefix
+             if self.prefix is None:
+                 if self.exec_prefix is not None:
+                     raise DistutilsOptionError(
+@@ -428,7 +450,26 @@ class install(Command):
+             self.install_base = self.prefix
+             self.install_platbase = self.exec_prefix
+-            self.select_scheme("unix_prefix")
++            if self.install_layout:
++                if self.install_layout.lower() in ['deb']:
++                    self.select_scheme("deb_system")
++                elif self.install_layout.lower() in ['unix']:
++                    self.select_scheme("unix_prefix")
++                else:
++                    raise DistutilsOptionError(
++                        "unknown value for --install-layout")
++            elif ((self.prefix_option and
++                   os.path.normpath(self.prefix) != '/usr/local')
++                  or sys.base_prefix != sys.prefix
++                  or 'PYTHONUSERBASE' in os.environ
++                  or 'VIRTUAL_ENV' in os.environ
++                  or 'real_prefix' in sys.__dict__):
++                self.select_scheme("unix_prefix")
++            else:
++                if os.path.normpath(self.prefix) == '/usr/local':
++                    self.prefix = self.exec_prefix = '/usr'
++                    self.install_base = self.install_platbase = '/usr'
++                self.select_scheme("unix_local")
+     def finalize_other(self):
+         """Finalizes options for non-posix platforms"""
+--- a/Lib/distutils/sysconfig.py
++++ b/Lib/distutils/sysconfig.py
+@@ -138,6 +138,7 @@ def get_python_lib(plat_specific=0, stan
+     If 'prefix' is supplied, use it instead of sys.base_prefix or
+     sys.base_exec_prefix -- i.e., ignore 'plat_specific'.
+     """
++    is_default_prefix = not prefix or os.path.normpath(prefix) in ('/usr', '/usr/local')
+     if prefix is None:
+         if standard_lib:
+             prefix = plat_specific and BASE_EXEC_PREFIX or BASE_PREFIX
+@@ -156,6 +157,12 @@ def get_python_lib(plat_specific=0, stan
+                                  "python" + get_python_version())
+         if standard_lib:
+             return libpython
++        elif (is_default_prefix and
++              'PYTHONUSERBASE' not in os.environ and
++              'VIRTUAL_ENV' not in os.environ and
++              'real_prefix' not in sys.__dict__ and
++              sys.prefix == sys.base_prefix):
++            return os.path.join(prefix, "lib", "python3", "dist-packages")
+         else:
+             return os.path.join(libpython, "site-packages")
+     elif os.name == "nt":
+--- a/Lib/site.py
++++ b/Lib/site.py
+@@ -7,12 +7,18 @@
+ This will append site-specific paths to the module search path.  On
+ Unix (including Mac OSX), it starts with sys.prefix and
+ sys.exec_prefix (if different) and appends
+-lib/python<version>/site-packages.
++lib/python3/dist-packages.
+ On other platforms (such as Windows), it tries each of the
+ prefixes directly, as well as with lib/site-packages appended.  The
+ resulting directories, if they exist, are appended to sys.path, and
+ also inspected for path configuration files.
++For Debian and derivatives, this sys.path is augmented with directories
++for packages distributed within the distribution. Local addons go
++into /usr/local/lib/python<version>/dist-packages, Debian addons
++install into /usr/lib/python3/dist-packages.
++/usr/lib/python<version>/site-packages is not used.
++
+ If a file named "pyvenv.cfg" exists one directory above sys.executable,
+ sys.prefix and sys.exec_prefix are set to that directory and
+ it is also checked for site-packages (sys.base_prefix and
+@@ -339,10 +345,21 @@ def getsitepackages(prefixes=None):
+             libdirs.append("lib")
+         if os.sep == '/':
++            if 'VIRTUAL_ENV' in os.environ or sys.base_prefix != sys.prefix:
++                sitepackages.append(os.path.join(prefix, "lib",
++                                                 "python" + sys.version[:3],
++                                                 "site-packages"))
++            sitepackages.append(os.path.join(prefix, "local/lib",
++                                             "python" + sys.version[:3],
++                                             "dist-packages"))
++            sitepackages.append(os.path.join(prefix, "lib",
++                                             "python3",
++                                             "dist-packages"))
++            # this one is deprecated for Debian
+             for libdir in libdirs:
+                 path = os.path.join(prefix, libdir,
+-                                    "python%d.%d" % sys.version_info[:2],
+-                                    "site-packages")
++                                    "python" + sys.version[:3],
++                                    "dist-packages")
+                 sitepackages.append(path)
+         else:
+             sitepackages.append(prefix)
+--- a/Lib/test/test_site.py
++++ b/Lib/test/test_site.py
+@@ -269,10 +269,10 @@ class HelperFunctionsTests(unittest.Test
+         if os.sep == '/':
+             # OS X, Linux, FreeBSD, etc
+             if sys.platlibdir != "lib":
+-                self.assertEqual(len(dirs), 2)
+-                wanted = os.path.join('xoxo', sys.platlibdir,
++                self.assertEqual(len(dirs), 3)
++                wanted = os.path.join('xoxo', 'local', 'lib',
+                                       'python%d.%d' % sys.version_info[:2],
+-                                      'site-packages')
++                                      'dist-packages')
+                 self.assertEqual(dirs[0], wanted)
+             else:
+                 self.assertEqual(len(dirs), 1)
+--- a/Lib/distutils/tests/test_bdist_dumb.py
++++ b/Lib/distutils/tests/test_bdist_dumb.py
+@@ -85,7 +85,7 @@ class BuildDumbTestCase(support.TempdirM
+             fp.close()
+         contents = sorted(filter(None, map(os.path.basename, contents)))
+-        wanted = ['foo-0.1-py%s.%s.egg-info' % sys.version_info[:2], 'foo.py']
++        wanted = ['foo-0.1.egg-info', 'foo.py']
+         if not sys.dont_write_bytecode:
+             wanted.append('foo.%s.pyc' % sys.implementation.cache_tag)
+         self.assertEqual(contents, sorted(wanted))
+--- a/Lib/distutils/tests/test_install.py
++++ b/Lib/distutils/tests/test_install.py
+@@ -194,7 +194,7 @@ class InstallTestCase(support.TempdirMan
+         found = [os.path.basename(line) for line in content.splitlines()]
+         expected = ['hello.py', 'hello.%s.pyc' % sys.implementation.cache_tag,
+                     'sayhi',
+-                    'UNKNOWN-0.0.0-py%s.%s.egg-info' % sys.version_info[:2]]
++                    'UNKNOWN-0.0.0.egg-info']
+         self.assertEqual(found, expected)
+     def test_record_extensions(self):
+@@ -227,7 +227,7 @@ class InstallTestCase(support.TempdirMan
+         found = [os.path.basename(line) for line in content.splitlines()]
+         expected = [_make_ext_name('xx'),
+-                    'UNKNOWN-0.0.0-py%s.%s.egg-info' % sys.version_info[:2]]
++                    'UNKNOWN-0.0.0.egg-info']
+         self.assertEqual(found, expected)
+     def test_debug_mode(self):
+--- a/Lib/pydoc.py
++++ b/Lib/pydoc.py
+@@ -505,6 +505,7 @@ class Doc:
+                                  'marshal', 'posix', 'signal', 'sys',
+                                  '_thread', 'zipimport') or
+              (file.startswith(basedir) and
++              not file.startswith(os.path.join(basedir, 'dist-packages')) and
+               not file.startswith(os.path.join(basedir, 'site-packages')))) and
+             object.__name__ not in ('xml.etree', 'test.pydoc_mod')):
+             if docloc.startswith(("http://", "https://")):
diff --git a/patches/distutils-link.diff b/patches/distutils-link.diff
new file mode 100644 (file)
index 0000000..b8ad3cf
--- /dev/null
@@ -0,0 +1,24 @@
+# DP: Don't add standard library dirs to library_dirs and runtime_library_dirs.
+
+Index: b/Lib/distutils/unixccompiler.py
+===================================================================
+--- a/Lib/distutils/unixccompiler.py
++++ b/Lib/distutils/unixccompiler.py
+@@ -155,6 +155,17 @@ class UnixCCompiler(CCompiler):
+                                         runtime_library_dirs)
+         libraries, library_dirs, runtime_library_dirs = fixed_args
++        # filter out standard library paths, which are not explicitely needed
++        # for linking
++        system_libdirs = ['/lib', '/lib64', '/usr/lib', '/usr/lib64']
++        multiarch = sysconfig.get_config_var("MULTIARCH")
++        if multiarch:
++            system_libdirs.extend(['/lib/%s' % multiarch, '/usr/lib/%s' % multiarch])
++        library_dirs = [dir for dir in library_dirs
++                        if not dir in system_libdirs]
++        runtime_library_dirs = [dir for dir in runtime_library_dirs
++                                if not dir in system_libdirs]
++
+         lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs,
+                                    libraries)
+         if not isinstance(output_dir, (str, type(None))):
diff --git a/patches/distutils-sysconfig.diff b/patches/distutils-sysconfig.diff
new file mode 100644 (file)
index 0000000..02a9ab7
--- /dev/null
@@ -0,0 +1,52 @@
+# DP: Get CONFIGURE_CFLAGS, CONFIGURE_CPPFLAGS, CONFIGURE_LDFLAGS from
+# DP: the python build, when CFLAGS, CPPFLAGS, LDSHARED) are not set
+# DP: in the environment.
+
+--- a/Lib/distutils/sysconfig.py
++++ b/Lib/distutils/sysconfig.py
+@@ -200,9 +200,11 @@ def customize_compiler(compiler):
+                 _osx_support.customize_compiler(_config_vars)
+                 _config_vars['CUSTOMIZED_OSX_COMPILER'] = 'True'
+-        (cc, cxx, cflags, ccshared, ldshared, shlib_suffix, ar, ar_flags) = \
++        (cc, cxx, cflags, ccshared, ldshared, shlib_suffix, ar, ar_flags,
++         configure_cppflags, configure_cflags, configure_ldflags) = \
+             get_config_vars('CC', 'CXX', 'CFLAGS',
+-                            'CCSHARED', 'LDSHARED', 'SHLIB_SUFFIX', 'AR', 'ARFLAGS')
++                            'CCSHARED', 'LDSHARED', 'SHLIB_SUFFIX', 'AR', 'ARFLAGS',
++                            'CONFIGURE_CPPFLAGS', 'CONFIGURE_CFLAGS', 'CONFIGURE_LDFLAGS')
+         if 'CC' in os.environ:
+             newcc = os.environ['CC']
+@@ -223,13 +225,22 @@ def customize_compiler(compiler):
+             cpp = cc + " -E"           # not always
+         if 'LDFLAGS' in os.environ:
+             ldshared = ldshared + ' ' + os.environ['LDFLAGS']
++        elif configure_ldflags:
++            ldshared = ldshared + ' ' + configure_ldflags
+         if 'CFLAGS' in os.environ:
+             cflags = cflags + ' ' + os.environ['CFLAGS']
+             ldshared = ldshared + ' ' + os.environ['CFLAGS']
++        elif configure_cflags:
++            cflags = cflags + ' ' + configure_cflags
++            ldshared = ldshared + ' ' + configure_cflags
+         if 'CPPFLAGS' in os.environ:
+             cpp = cpp + ' ' + os.environ['CPPFLAGS']
+             cflags = cflags + ' ' + os.environ['CPPFLAGS']
+             ldshared = ldshared + ' ' + os.environ['CPPFLAGS']
++        elif configure_cppflags:
++            cpp = cpp + ' ' + configure_cppflags
++            cflags = cflags + ' ' + configure_cppflags
++            ldshared = ldshared + ' ' + configure_cppflags
+         if 'AR' in os.environ:
+             ar = os.environ['AR']
+         if 'ARFLAGS' in os.environ:
+@@ -243,7 +254,7 @@ def customize_compiler(compiler):
+             compiler=cc_cmd,
+             compiler_so=cc_cmd + ' ' + ccshared,
+             compiler_cxx=cxx,
+-            linker_so=ldshared,
++            linker_so=ldshared + ' ' + ccshared,
+             linker_exe=cc,
+             archiver=archiver)
diff --git a/patches/doc-build-texinfo.diff b/patches/doc-build-texinfo.diff
new file mode 100644 (file)
index 0000000..338db82
--- /dev/null
@@ -0,0 +1,27 @@
+Description: Add the option to build Texinfo-format documentation.
+Author: Benjamin Moody <benjamin@physionet.org>
+Bug-Debian: https://bugs.debian.org/881959
+Last-Update: 2017-11-27
+
+--- a/Doc/Makefile
++++ b/Doc/Makefile
+@@ -32,6 +32,7 @@ help:
+       @echo "  htmlview   to open the index page built by the html target in your browser"
+       @echo "  htmlhelp   to make HTML files and a HTML help project"
+       @echo "  latex      to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
++      @echo "  texinfo    to make Texinfo files"
+       @echo "  text       to make plain text files"
+       @echo "  texinfo    to make Texinfo file"
+       @echo "  epub       to make EPUB files"
+@@ -86,6 +87,11 @@ latex: build
+       @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
+             "run these through (pdf)latex."
++texinfo: BUILDER = texinfo
++texinfo: build
++      @echo "Build finished; the Texinfo files are in build/texinfo."
++      @echo "Run \`make\' in that directory to run these through makeinfo."
++
+ text: BUILDER = text
+ text: build
+       @echo "Build finished; the text files are in build/text."
diff --git a/patches/ensurepip-disabled.diff b/patches/ensurepip-disabled.diff
new file mode 100644 (file)
index 0000000..631a0c2
--- /dev/null
@@ -0,0 +1,83 @@
+# DP: Disable ensurepip for the system installation, only enable it for virtual environments.
+
+--- a/Lib/ensurepip/__init__.py
++++ b/Lib/ensurepip/__init__.py
+@@ -11,6 +11,34 @@ from importlib import resources
+ __all__ = ["version", "bootstrap"]
++def _ensurepip_is_disabled_in_debian_for_system():
++    # Detect if ensurepip is being executed inside of a python-virtualenv
++    # environment and return early if so.
++    if hasattr(sys, 'real_prefix'):
++        return
++
++    # Detect if ensurepip is being executed inside of a stdlib venv
++    # environment and return early if so.
++    if sys.prefix != getattr(sys, "base_prefix", sys.prefix):
++        return
++
++    # If we've gotten here, then we are running inside of the system Python
++    # and we don't want to use ensurepip to install into the system Python
++    # so instead we'll redirect the user to using dpkg and apt-get.
++    print('''\
++ensurepip is disabled in Debian/Ubuntu for the system python.
++
++Python modules for the system python are usually handled by dpkg and apt-get.
++
++    apt-get install python-<module name>
++
++Install the python-pip package to use pip itself.  Using pip together
++with the system python might have unexpected results for any system installed
++module, so use it on your own risk, or make sure to only use it in virtual
++environments.
++''')
++    sys.exit(1)
++
+ _PROJECTS = [
+     "setuptools",
+@@ -78,6 +106,11 @@ def _bootstrap(*, root=None, upgrade=Fal
+     Note that calling this function will alter both sys.path and os.environ.
+     """
++
++    # Ensure that we are only running this inside of a virtual environment
++    # of some kind.
++    _ensurepip_is_disabled_in_debian_for_system()
++
+     if altinstall and default_pip:
+         raise ValueError("Cannot use altinstall and default_pip together")
+--- a/Lib/venv/__init__.py
++++ b/Lib/venv/__init__.py
+@@ -295,7 +295,28 @@ class EnvBuilder:
+         # intended for the global Python environment
+         cmd = [context.env_exe, '-Im', 'ensurepip', '--upgrade',
+                                                     '--default-pip']
+-        subprocess.check_output(cmd, stderr=subprocess.STDOUT)
++        # Debian 2015-09-18 barry@debian.org: <python>-venv is a separate
++        # binary package which might not be installed.  In that case, the
++        # following command will produce an unhelpful error.  Let's make it
++        # more user friendly.
++        try:
++            subprocess.check_output(
++                cmd, stderr=subprocess.STDOUT,
++                universal_newlines=True)
++        except subprocess.CalledProcessError:
++            print("""\
++The virtual environment was not created successfully because ensurepip is not
++available.  On Debian/Ubuntu systems, you need to install the python3-venv
++package using the following command.
++
++    apt-get install python3-venv
++
++You may need to use sudo with that command.  After installing the python3-venv
++package, recreate your virtual environment.
++
++Failing command: {}
++""".format(cmd))
++            sys.exit(1)
+     def setup_scripts(self, context):
+         """
diff --git a/patches/ensurepip-wheels.diff b/patches/ensurepip-wheels.diff
new file mode 100644 (file)
index 0000000..25854d2
--- /dev/null
@@ -0,0 +1,125 @@
+--- a/Lib/ensurepip/__init__.py
++++ b/Lib/ensurepip/__init__.py
+@@ -1,3 +1,4 @@
++import glob
+ import os
+ import os.path
+ import sys
+@@ -6,20 +7,15 @@ import tempfile
+ import subprocess
+ from importlib import resources
+-from . import _bundled
+-
+ __all__ = ["version", "bootstrap"]
+-_SETUPTOOLS_VERSION = "49.2.1"
+-
+-_PIP_VERSION = "20.2.3"
+-
+ _PROJECTS = [
+-    ("setuptools", _SETUPTOOLS_VERSION, "py3"),
+-    ("pip", _PIP_VERSION, "py2.py3"),
++    "setuptools",
++    "pip",
++    "pkg_resources",
+ ]
+@@ -42,7 +38,9 @@ def version():
+     """
+     Returns a string specifying the bundled version of pip.
+     """
+-    return _PIP_VERSION
++    wheel_names = glob.glob('/usr/share/python-wheels/pip-*.whl')
++    assert len(wheel_names) == 1, wheel_names
++    return os.path.basename(wheel_names[0]).split('-')[1]
+ def _disable_pip_configuration_settings():
+     # We deliberately ignore all pip environment variables
+@@ -100,20 +98,44 @@ def _bootstrap(*, root=None, upgrade=Fal
+         # omit pip and easy_install
+         os.environ["ENSUREPIP_OPTIONS"] = "install"
++    # Debian: The bundled wheels are useless to us because we must use ones
++    # crafted from source code in the archive.  As we build the virtual
++    # environment, copy the wheels from the system location into the virtual
++    # environment, and place those wheels on sys.path.
++    def copy_wheels(wheels, destdir, paths):
++        for project in wheels:
++            wheel_names = glob.glob(
++                '/usr/share/python-wheels/{}-*.whl'.format(project))
++            if len(wheel_names) == 0:
++                raise RuntimeError('missing dependency wheel %s' % project)
++            assert len(wheel_names) == 1, wheel_names
++            wheel_name = os.path.basename(wheel_names[0])
++            path = os.path.join('/usr/share/python-wheels', wheel_name)
++            with open(path, 'rb') as fp:
++                whl = fp.read()
++            dest = os.path.join(destdir, wheel_name)
++            with open(dest, 'wb') as fp:
++                fp.write(whl)
++            paths.append(dest)
++
+     with tempfile.TemporaryDirectory() as tmpdir:
++        # This directory is a "well known directory" which Debian has patched
++        # pip to look in when attempting to locate wheels to use to satisfy
++        # the dependencies that pip normally bundles but Debian has debundled.
++        # This is critically important and if this directory changes then both
++        # python-pip and python-virtualenv needs updated to match.
++        venv_wheel_dir = os.path.join(sys.prefix, 'share', 'python-wheels')
++        os.makedirs(venv_wheel_dir, exist_ok=True)
++        dependencies = [
++            os.path.basename(whl).split('-')[0]
++            for whl in glob.glob('/usr/share/python-wheels/*.whl')
++            ]
++        copy_wheels(dependencies, venv_wheel_dir, sys.path)
++
+         # Put our bundled wheels into a temporary directory and construct the
+         # additional paths that need added to sys.path
+         additional_paths = []
+-        for project, version, py_tag in _PROJECTS:
+-            wheel_name = "{}-{}-{}-none-any.whl".format(project, version, py_tag)
+-            whl = resources.read_binary(
+-                _bundled,
+-                wheel_name,
+-            )
+-            with open(os.path.join(tmpdir, wheel_name), "wb") as fp:
+-                fp.write(whl)
+-
+-            additional_paths.append(os.path.join(tmpdir, wheel_name))
++        copy_wheels(_PROJECTS, tmpdir, additional_paths)
+         # Construct the arguments to be passed to the pip command
+         args = ["install", "--no-cache-dir", "--no-index", "--find-links", tmpdir]
+@@ -126,7 +148,7 @@ def _bootstrap(*, root=None, upgrade=Fal
+         if verbosity:
+             args += ["-" + "v" * verbosity]
+-        return _run_pip(args + [p[0] for p in _PROJECTS], additional_paths)
++        return _run_pip(args + _PROJECTS, additional_paths)
+ def _uninstall_helper(*, verbosity=0):
+     """Helper to support a clean default uninstall process on Windows
+@@ -140,7 +162,8 @@ def _uninstall_helper(*, verbosity=0):
+         return
+     # If the pip version doesn't match the bundled one, leave it alone
+-    if pip.__version__ != _PIP_VERSION:
++    # Disabled for Debian, always using the version from the python3-pip package.
++    if False and pip.__version__ != _PIP_VERSION:
+         msg = ("ensurepip will only uninstall a matching version "
+                "({!r} installed, {!r} bundled)")
+         print(msg.format(pip.__version__, _PIP_VERSION), file=sys.stderr)
+@@ -153,7 +176,7 @@ def _uninstall_helper(*, verbosity=0):
+     if verbosity:
+         args += ["-" + "v" * verbosity]
+-    return _run_pip(args + [p[0] for p in reversed(_PROJECTS)])
++    return _run_pip(args + reversed(_PROJECTS))
+ def _main(argv=None):
diff --git a/patches/ext-no-libpython-link.diff b/patches/ext-no-libpython-link.diff
new file mode 100644 (file)
index 0000000..00700fb
--- /dev/null
@@ -0,0 +1,22 @@
+# DP: Don't link extensions with the shared libpython library.
+
+--- a/Lib/distutils/command/build_ext.py
++++ b/Lib/distutils/command/build_ext.py
+@@ -231,7 +231,7 @@ class build_ext(Command):
+         # For building extensions with a shared Python library,
+         # Python's library directory must be appended to library_dirs
+         # See Issues: #1600860, #4366
+-        if (sysconfig.get_config_var('Py_ENABLE_SHARED')):
++        if False and (sysconfig.get_config_var('Py_ENABLE_SHARED')):
+             if not sysconfig.python_build:
+                 # building third party extensions
+                 self.library_dirs.append(sysconfig.get_config_var('LIBDIR'))
+@@ -734,7 +734,7 @@ class build_ext(Command):
+             # shared libraries are resolved at link time.
+             from distutils.sysconfig import get_config_var
+             link_libpython = False
+-            if get_config_var('Py_ENABLE_SHARED'):
++            if False and get_config_var('Py_ENABLE_SHARED'):
+                 # A native build on an Android device or on Cygwin
+                 if hasattr(sys, 'getandroidapilevel'):
+                     link_libpython = True
diff --git a/patches/gdbm-import.diff b/patches/gdbm-import.diff
new file mode 100644 (file)
index 0000000..2be2934
--- /dev/null
@@ -0,0 +1,12 @@
+# DP: suggest installation of python3-gdbm package on failing _gdbm import
+
+--- a/Lib/dbm/gnu.py
++++ b/Lib/dbm/gnu.py
+@@ -1,3 +1,6 @@
+ """Provide the _gdbm module as a dbm submodule."""
+-from _gdbm import *
++try:
++    from _gdbm import *
++except ImportError as msg:
++    raise ImportError(str(msg) + ', please install the python3-gdbm package')
diff --git a/patches/git-updates.diff b/patches/git-updates.diff
new file mode 100644 (file)
index 0000000..6d2b7af
--- /dev/null
@@ -0,0 +1,16869 @@
+# DP: updates from the 3.9 branch (until 2021-02-04).
+
+# git diff --no-renames 1e5d33e9b9b8631b36f061103a30208b206fd03a b0b01811bb28d3d6c70846e47fa2f6ba03ed03f1 | filterdiff -x ?/.hgignore -x ?/.hgeol -x ?/.hgtags -x ?/.hgtouch -x ?/.gitignore -x ?/.gitattributes -x '?/.github/*' -x '?/.git*' -x ?/.codecov.yml -x ?/.travis.yml -x ?/configure --remove-timestamps
+
+diff --git a/Doc/c-api/bool.rst b/Doc/c-api/bool.rst
+index ce8de6e22f..c197d447e9 100644
+--- a/Doc/c-api/bool.rst
++++ b/Doc/c-api/bool.rst
+@@ -13,7 +13,8 @@ are available, however.
+ .. c:function:: int PyBool_Check(PyObject *o)
+-   Return true if *o* is of type :c:data:`PyBool_Type`.
++   Return true if *o* is of type :c:data:`PyBool_Type`.  This function always
++   succeeds.
+ .. c:var:: PyObject* Py_False
+diff --git a/Doc/c-api/bytearray.rst b/Doc/c-api/bytearray.rst
+index b2f409c15a..30bcfc7cf9 100644
+--- a/Doc/c-api/bytearray.rst
++++ b/Doc/c-api/bytearray.rst
+@@ -25,13 +25,13 @@ Type check macros
+ .. c:function:: int PyByteArray_Check(PyObject *o)
+    Return true if the object *o* is a bytearray object or an instance of a
+-   subtype of the bytearray type.
++   subtype of the bytearray type.  This function always succeeds.
+ .. c:function:: int PyByteArray_CheckExact(PyObject *o)
+    Return true if the object *o* is a bytearray object, but not an instance of a
+-   subtype of the bytearray type.
++   subtype of the bytearray type.  This function always succeeds.
+ Direct API functions
+diff --git a/Doc/c-api/bytes.rst b/Doc/c-api/bytes.rst
+index 0e33ed2c7c..de65701037 100644
+--- a/Doc/c-api/bytes.rst
++++ b/Doc/c-api/bytes.rst
+@@ -25,13 +25,13 @@ called with a non-bytes parameter.
+ .. c:function:: int PyBytes_Check(PyObject *o)
+    Return true if the object *o* is a bytes object or an instance of a subtype
+-   of the bytes type.
++   of the bytes type.  This function always succeeds.
+ .. c:function:: int PyBytes_CheckExact(PyObject *o)
+    Return true if the object *o* is a bytes object, but not an instance of a
+-   subtype of the bytes type.
++   subtype of the bytes type.  This function always succeeds.
+ .. c:function:: PyObject* PyBytes_FromString(const char *v)
+diff --git a/Doc/c-api/capsule.rst b/Doc/c-api/capsule.rst
+index 5eb313c89b..908e92653d 100644
+--- a/Doc/c-api/capsule.rst
++++ b/Doc/c-api/capsule.rst
+@@ -34,7 +34,8 @@ Refer to :ref:`using-capsules` for more information on using these objects.
+ .. c:function:: int PyCapsule_CheckExact(PyObject *p)
+-   Return true if its argument is a :c:type:`PyCapsule`.
++   Return true if its argument is a :c:type:`PyCapsule`.  This function always
++   succeeds.
+ .. c:function:: PyObject* PyCapsule_New(void *pointer, const char *name, PyCapsule_Destructor destructor)
+diff --git a/Doc/c-api/cell.rst b/Doc/c-api/cell.rst
+index 8408f7e398..ac4ef5adc5 100644
+--- a/Doc/c-api/cell.rst
++++ b/Doc/c-api/cell.rst
+@@ -27,7 +27,8 @@ Cell objects are not likely to be useful elsewhere.
+ .. c:function:: int PyCell_Check(ob)
+-   Return true if *ob* is a cell object; *ob* must not be ``NULL``.
++   Return true if *ob* is a cell object; *ob* must not be ``NULL``.  This
++   function always succeeds.
+ .. c:function:: PyObject* PyCell_New(PyObject *ob)
+diff --git a/Doc/c-api/code.rst b/Doc/c-api/code.rst
+index 6f8c41ccbf..b3a17f1898 100644
+--- a/Doc/c-api/code.rst
++++ b/Doc/c-api/code.rst
+@@ -27,7 +27,7 @@ bound into a function.
+ .. c:function:: int PyCode_Check(PyObject *co)
+-   Return true if *co* is a :class:`code` object.
++   Return true if *co* is a :class:`code` object.  This function always succeeds.
+ .. c:function:: int PyCode_GetNumFree(PyCodeObject *co)
+diff --git a/Doc/c-api/complex.rst b/Doc/c-api/complex.rst
+index 06dbb25727..e2ea766b3a 100644
+--- a/Doc/c-api/complex.rst
++++ b/Doc/c-api/complex.rst
+@@ -94,13 +94,13 @@ Complex Numbers as Python Objects
+ .. c:function:: int PyComplex_Check(PyObject *p)
+    Return true if its argument is a :c:type:`PyComplexObject` or a subtype of
+-   :c:type:`PyComplexObject`.
++   :c:type:`PyComplexObject`.  This function always succeeds.
+ .. c:function:: int PyComplex_CheckExact(PyObject *p)
+    Return true if its argument is a :c:type:`PyComplexObject`, but not a subtype of
+-   :c:type:`PyComplexObject`.
++   :c:type:`PyComplexObject`.  This function always succeeds.
+ .. c:function:: PyObject* PyComplex_FromCComplex(Py_complex v)
+diff --git a/Doc/c-api/coro.rst b/Doc/c-api/coro.rst
+index 2260944a9a..caa855a10d 100644
+--- a/Doc/c-api/coro.rst
++++ b/Doc/c-api/coro.rst
+@@ -24,6 +24,7 @@ return.
+ .. c:function:: int PyCoro_CheckExact(PyObject *ob)
+    Return true if *ob*'s type is :c:type:`PyCoro_Type`; *ob* must not be ``NULL``.
++   This function always succeeds.
+ .. c:function:: PyObject* PyCoro_New(PyFrameObject *frame, PyObject *name, PyObject *qualname)
+diff --git a/Doc/c-api/datetime.rst b/Doc/c-api/datetime.rst
+index bd4f1ff446..66f148df28 100644
+--- a/Doc/c-api/datetime.rst
++++ b/Doc/c-api/datetime.rst
+@@ -28,61 +28,66 @@ Type-check macros:
+ .. c:function:: int PyDate_Check(PyObject *ob)
+    Return true if *ob* is of type :c:data:`PyDateTime_DateType` or a subtype of
+-   :c:data:`PyDateTime_DateType`.  *ob* must not be ``NULL``.
++   :c:data:`PyDateTime_DateType`.  *ob* must not be ``NULL``.  This function always
++   succeeds.
+ .. c:function:: int PyDate_CheckExact(PyObject *ob)
+    Return true if *ob* is of type :c:data:`PyDateTime_DateType`. *ob* must not be
+-   ``NULL``.
++   ``NULL``.  This function always succeeds.
+ .. c:function:: int PyDateTime_Check(PyObject *ob)
+    Return true if *ob* is of type :c:data:`PyDateTime_DateTimeType` or a subtype of
+-   :c:data:`PyDateTime_DateTimeType`.  *ob* must not be ``NULL``.
++   :c:data:`PyDateTime_DateTimeType`.  *ob* must not be ``NULL``.  This function always
++   succeeds.
+ .. c:function:: int PyDateTime_CheckExact(PyObject *ob)
+    Return true if *ob* is of type :c:data:`PyDateTime_DateTimeType`. *ob* must not
+-   be ``NULL``.
++   be ``NULL``.  This function always succeeds.
+ .. c:function:: int PyTime_Check(PyObject *ob)
+    Return true if *ob* is of type :c:data:`PyDateTime_TimeType` or a subtype of
+-   :c:data:`PyDateTime_TimeType`.  *ob* must not be ``NULL``.
++   :c:data:`PyDateTime_TimeType`.  *ob* must not be ``NULL``.  This function always
++   succeeds.
+ .. c:function:: int PyTime_CheckExact(PyObject *ob)
+    Return true if *ob* is of type :c:data:`PyDateTime_TimeType`. *ob* must not be
+-   ``NULL``.
++   ``NULL``.  This function always succeeds.
+ .. c:function:: int PyDelta_Check(PyObject *ob)
+    Return true if *ob* is of type :c:data:`PyDateTime_DeltaType` or a subtype of
+-   :c:data:`PyDateTime_DeltaType`.  *ob* must not be ``NULL``.
++   :c:data:`PyDateTime_DeltaType`.  *ob* must not be ``NULL``.  This function always
++   succeeds.
+ .. c:function:: int PyDelta_CheckExact(PyObject *ob)
+    Return true if *ob* is of type :c:data:`PyDateTime_DeltaType`. *ob* must not be
+-   ``NULL``.
++   ``NULL``.  This function always succeeds.
+ .. c:function:: int PyTZInfo_Check(PyObject *ob)
+    Return true if *ob* is of type :c:data:`PyDateTime_TZInfoType` or a subtype of
+-   :c:data:`PyDateTime_TZInfoType`.  *ob* must not be ``NULL``.
++   :c:data:`PyDateTime_TZInfoType`.  *ob* must not be ``NULL``.  This function always
++   succeeds.
+ .. c:function:: int PyTZInfo_CheckExact(PyObject *ob)
+    Return true if *ob* is of type :c:data:`PyDateTime_TZInfoType`. *ob* must not be
+-   ``NULL``.
++   ``NULL``.  This function always succeeds.
+ Macros to create objects:
+diff --git a/Doc/c-api/dict.rst b/Doc/c-api/dict.rst
+index 8c626c7d4a..5803ac2ad9 100644
+--- a/Doc/c-api/dict.rst
++++ b/Doc/c-api/dict.rst
+@@ -22,13 +22,13 @@ Dictionary Objects
+ .. c:function:: int PyDict_Check(PyObject *p)
+    Return true if *p* is a dict object or an instance of a subtype of the dict
+-   type.
++   type.  This function always succeeds.
+ .. c:function:: int PyDict_CheckExact(PyObject *p)
+    Return true if *p* is a dict object, but not an instance of a subtype of
+-   the dict type.
++   the dict type.  This function always succeeds.
+ .. c:function:: PyObject* PyDict_New()
+diff --git a/Doc/c-api/float.rst b/Doc/c-api/float.rst
+index b29937dbec..c107243a88 100644
+--- a/Doc/c-api/float.rst
++++ b/Doc/c-api/float.rst
+@@ -22,13 +22,13 @@ Floating Point Objects
+ .. c:function:: int PyFloat_Check(PyObject *p)
+    Return true if its argument is a :c:type:`PyFloatObject` or a subtype of
+-   :c:type:`PyFloatObject`.
++   :c:type:`PyFloatObject`.  This function always succeeds.
+ .. c:function:: int PyFloat_CheckExact(PyObject *p)
+    Return true if its argument is a :c:type:`PyFloatObject`, but not a subtype of
+-   :c:type:`PyFloatObject`.
++   :c:type:`PyFloatObject`.  This function always succeeds.
+ .. c:function:: PyObject* PyFloat_FromString(PyObject *str)
+diff --git a/Doc/c-api/function.rst b/Doc/c-api/function.rst
+index bb416f4bb6..20968828e0 100644
+--- a/Doc/c-api/function.rst
++++ b/Doc/c-api/function.rst
+@@ -26,7 +26,7 @@ There are a few functions specific to Python functions.
+ .. c:function:: int PyFunction_Check(PyObject *o)
+    Return true if *o* is a function object (has type :c:data:`PyFunction_Type`).
+-   The parameter must not be ``NULL``.
++   The parameter must not be ``NULL``.  This function always succeeds.
+ .. c:function:: PyObject* PyFunction_New(PyObject *code, PyObject *globals)
+diff --git a/Doc/c-api/gen.rst b/Doc/c-api/gen.rst
+index 74410927bf..0eb5922f6d 100644
+--- a/Doc/c-api/gen.rst
++++ b/Doc/c-api/gen.rst
+@@ -22,12 +22,14 @@ than explicitly calling :c:func:`PyGen_New` or :c:func:`PyGen_NewWithQualName`.
+ .. c:function:: int PyGen_Check(PyObject *ob)
+-   Return true if *ob* is a generator object; *ob* must not be ``NULL``.
++   Return true if *ob* is a generator object; *ob* must not be ``NULL``.  This
++   function always succeeds.
+ .. c:function:: int PyGen_CheckExact(PyObject *ob)
+-   Return true if *ob*'s type is :c:type:`PyGen_Type`; *ob* must not be ``NULL``.
++   Return true if *ob*'s type is :c:type:`PyGen_Type`; *ob* must not be
++   ``NULL``.  This function always succeeds.
+ .. c:function:: PyObject* PyGen_New(PyFrameObject *frame)
+diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst
+index 7f06648bcb..eb0bd14587 100644
+--- a/Doc/c-api/init.rst
++++ b/Doc/c-api/init.rst
+@@ -1155,7 +1155,7 @@ All of the following functions must be called after :c:func:`Py_Initialize`.
+    .. versionadded:: 3.9
+-.. c:function:: void _PyInterpreterState_SetEvalFrameFunc(PyInterpreterState *interp, _PyFrameEvalFunction eval_frame);
++.. c:function:: void _PyInterpreterState_SetEvalFrameFunc(PyInterpreterState *interp, _PyFrameEvalFunction eval_frame)
+    Set the frame evaluation function.
+diff --git a/Doc/c-api/iter.rst b/Doc/c-api/iter.rst
+index a2992b3452..189f80b9b8 100644
+--- a/Doc/c-api/iter.rst
++++ b/Doc/c-api/iter.rst
+@@ -9,7 +9,8 @@ There are two functions specifically for working with iterators.
+ .. c:function:: int PyIter_Check(PyObject *o)
+-   Return true if the object *o* supports the iterator protocol.
++   Return true if the object *o* supports the iterator protocol.  This
++   function always succeeds.
+ .. c:function:: PyObject* PyIter_Next(PyObject *o)
+diff --git a/Doc/c-api/iterator.rst b/Doc/c-api/iterator.rst
+index 4d91e4a224..3fcf099134 100644
+--- a/Doc/c-api/iterator.rst
++++ b/Doc/c-api/iterator.rst
+@@ -21,7 +21,8 @@ sentinel value is returned.
+ .. c:function:: int PySeqIter_Check(op)
+-   Return true if the type of *op* is :c:data:`PySeqIter_Type`.
++   Return true if the type of *op* is :c:data:`PySeqIter_Type`.  This function
++   always succeeds.
+ .. c:function:: PyObject* PySeqIter_New(PyObject *seq)
+@@ -39,7 +40,8 @@ sentinel value is returned.
+ .. c:function:: int PyCallIter_Check(op)
+-   Return true if the type of *op* is :c:data:`PyCallIter_Type`.
++   Return true if the type of *op* is :c:data:`PyCallIter_Type`.  This
++   function always succeeds.
+ .. c:function:: PyObject* PyCallIter_New(PyObject *callable, PyObject *sentinel)
+diff --git a/Doc/c-api/list.rst b/Doc/c-api/list.rst
+index 0bc0785f20..f338e2ae06 100644
+--- a/Doc/c-api/list.rst
++++ b/Doc/c-api/list.rst
+@@ -22,13 +22,13 @@ List Objects
+ .. c:function:: int PyList_Check(PyObject *p)
+    Return true if *p* is a list object or an instance of a subtype of the list
+-   type.
++   type.  This function always succeeds.
+ .. c:function:: int PyList_CheckExact(PyObject *p)
+    Return true if *p* is a list object, but not an instance of a subtype of
+-   the list type.
++   the list type.  This function always succeeds.
+ .. c:function:: PyObject* PyList_New(Py_ssize_t len)
+diff --git a/Doc/c-api/long.rst b/Doc/c-api/long.rst
+index 22e59ce1e5..60e1791df9 100644
+--- a/Doc/c-api/long.rst
++++ b/Doc/c-api/long.rst
+@@ -27,13 +27,13 @@ distinguished from a number.  Use :c:func:`PyErr_Occurred` to disambiguate.
+ .. c:function:: int PyLong_Check(PyObject *p)
+    Return true if its argument is a :c:type:`PyLongObject` or a subtype of
+-   :c:type:`PyLongObject`.
++   :c:type:`PyLongObject`.  This function always succeeds.
+ .. c:function:: int PyLong_CheckExact(PyObject *p)
+    Return true if its argument is a :c:type:`PyLongObject`, but not a subtype of
+-   :c:type:`PyLongObject`.
++   :c:type:`PyLongObject`.  This function always succeeds.
+ .. c:function:: PyObject* PyLong_FromLong(long v)
+diff --git a/Doc/c-api/memoryview.rst b/Doc/c-api/memoryview.rst
+index de429e5c11..24f8c93530 100644
+--- a/Doc/c-api/memoryview.rst
++++ b/Doc/c-api/memoryview.rst
+@@ -45,7 +45,8 @@ any other object.
+ .. c:function:: int PyMemoryView_Check(PyObject *obj)
+    Return true if the object *obj* is a memoryview object.  It is not
+-   currently allowed to create subclasses of :class:`memoryview`.
++   currently allowed to create subclasses of :class:`memoryview`.  This
++   function always succeeds.
+ .. c:function:: Py_buffer *PyMemoryView_GET_BUFFER(PyObject *mview)
+diff --git a/Doc/c-api/method.rst b/Doc/c-api/method.rst
+index 0a5341cbbd..23852251df 100644
+--- a/Doc/c-api/method.rst
++++ b/Doc/c-api/method.rst
+@@ -22,6 +22,7 @@ to bind a :c:data:`PyCFunction` to a class object. It replaces the former call
+    Return true if *o* is an instance method object (has type
+    :c:data:`PyInstanceMethod_Type`).  The parameter must not be ``NULL``.
++   This function always succeeds.
+ .. c:function:: PyObject* PyInstanceMethod_New(PyObject *func)
+@@ -64,7 +65,7 @@ no longer available.
+ .. c:function:: int PyMethod_Check(PyObject *o)
+    Return true if *o* is a method object (has type :c:data:`PyMethod_Type`).  The
+-   parameter must not be ``NULL``.
++   parameter must not be ``NULL``.  This function always succeeds.
+ .. c:function:: PyObject* PyMethod_New(PyObject *func, PyObject *self)
+diff --git a/Doc/c-api/module.rst b/Doc/c-api/module.rst
+index 6e9474bfa4..90766dca78 100644
+--- a/Doc/c-api/module.rst
++++ b/Doc/c-api/module.rst
+@@ -19,12 +19,13 @@ Module Objects
+ .. c:function:: int PyModule_Check(PyObject *p)
+    Return true if *p* is a module object, or a subtype of a module object.
++   This function always succeeds.
+ .. c:function:: int PyModule_CheckExact(PyObject *p)
+    Return true if *p* is a module object, but not a subtype of
+-   :c:data:`PyModule_Type`.
++   :c:data:`PyModule_Type`.  This function always succeeds.
+ .. c:function:: PyObject* PyModule_NewObject(PyObject *name)
+diff --git a/Doc/c-api/set.rst b/Doc/c-api/set.rst
+index 879f394d96..84f34e7dae 100644
+--- a/Doc/c-api/set.rst
++++ b/Doc/c-api/set.rst
+@@ -53,28 +53,29 @@ the constructor functions work with any iterable Python object.
+ .. c:function:: int PySet_Check(PyObject *p)
+    Return true if *p* is a :class:`set` object or an instance of a subtype.
++   This function always succeeds.
+ .. c:function:: int PyFrozenSet_Check(PyObject *p)
+    Return true if *p* is a :class:`frozenset` object or an instance of a
+-   subtype.
++   subtype.  This function always succeeds.
+ .. c:function:: int PyAnySet_Check(PyObject *p)
+    Return true if *p* is a :class:`set` object, a :class:`frozenset` object, or an
+-   instance of a subtype.
++   instance of a subtype.  This function always succeeds.
+ .. c:function:: int PyAnySet_CheckExact(PyObject *p)
+    Return true if *p* is a :class:`set` object or a :class:`frozenset` object but
+-   not an instance of a subtype.
++   not an instance of a subtype.  This function always succeeds.
+ .. c:function:: int PyFrozenSet_CheckExact(PyObject *p)
+    Return true if *p* is a :class:`frozenset` object but not an instance of a
+-   subtype.
++   subtype.  This function always succeeds.
+ .. c:function:: PyObject* PySet_New(PyObject *iterable)
+diff --git a/Doc/c-api/slice.rst b/Doc/c-api/slice.rst
+index 48a58c6c6f..8271d9acfb 100644
+--- a/Doc/c-api/slice.rst
++++ b/Doc/c-api/slice.rst
+@@ -14,7 +14,8 @@ Slice Objects
+ .. c:function:: int PySlice_Check(PyObject *ob)
+-   Return true if *ob* is a slice object; *ob* must not be ``NULL``.
++   Return true if *ob* is a slice object; *ob* must not be ``NULL``.  This
++   function always succeeds.
+ .. c:function:: PyObject* PySlice_New(PyObject *start, PyObject *stop, PyObject *step)
+diff --git a/Doc/c-api/tuple.rst b/Doc/c-api/tuple.rst
+index bf751e44ac..1dbf7dbb67 100644
+--- a/Doc/c-api/tuple.rst
++++ b/Doc/c-api/tuple.rst
+@@ -21,14 +21,14 @@ Tuple Objects
+ .. c:function:: int PyTuple_Check(PyObject *p)
+-   Return true if *p* is a tuple object or an instance of a subtype of the tuple
+-   type.
++   Return true if *p* is a tuple object or an instance of a subtype of the
++   tuple type.  This function always succeeds.
+ .. c:function:: int PyTuple_CheckExact(PyObject *p)
+    Return true if *p* is a tuple object, but not an instance of a subtype of the
+-   tuple type.
++   tuple type.  This function always succeeds.
+ .. c:function:: PyObject* PyTuple_New(Py_ssize_t len)
+diff --git a/Doc/c-api/type.rst b/Doc/c-api/type.rst
+index 822360e061..ee76f52289 100644
+--- a/Doc/c-api/type.rst
++++ b/Doc/c-api/type.rst
+@@ -23,12 +23,14 @@ Type Objects
+    Return non-zero if the object *o* is a type object, including instances of
+    types derived from the standard type object.  Return 0 in all other cases.
++   This function always succeeds.
+ .. c:function:: int PyType_CheckExact(PyObject *o)
+-   Return non-zero if the object *o* is a type object, but not a subtype of the
+-   standard type object.  Return 0 in all other cases.
++   Return non-zero if the object *o* is a type object, but not a subtype of
++   the standard type object.  Return 0 in all other cases.  This function
++   always succeeds.
+ .. c:function:: unsigned int PyType_ClearCache()
+diff --git a/Doc/c-api/unicode.rst b/Doc/c-api/unicode.rst
+index 8a312ae90e..62295b4c52 100644
+--- a/Doc/c-api/unicode.rst
++++ b/Doc/c-api/unicode.rst
+@@ -91,13 +91,13 @@ access internal read-only data of Unicode objects:
+ .. c:function:: int PyUnicode_Check(PyObject *o)
+    Return true if the object *o* is a Unicode object or an instance of a Unicode
+-   subtype.
++   subtype.  This function always succeeds.
+ .. c:function:: int PyUnicode_CheckExact(PyObject *o)
+    Return true if the object *o* is a Unicode object, but not an instance of a
+-   subtype.
++   subtype.  This function always succeeds.
+ .. c:function:: int PyUnicode_READY(PyObject *o)
+diff --git a/Doc/c-api/weakref.rst b/Doc/c-api/weakref.rst
+index e3a9bda54d..67698de77f 100644
+--- a/Doc/c-api/weakref.rst
++++ b/Doc/c-api/weakref.rst
+@@ -13,17 +13,18 @@ as much as it can.
+ .. c:function:: int PyWeakref_Check(ob)
+-   Return true if *ob* is either a reference or proxy object.
++   Return true if *ob* is either a reference or proxy object.  This function
++   always succeeds.
+ .. c:function:: int PyWeakref_CheckRef(ob)
+-   Return true if *ob* is a reference object.
++   Return true if *ob* is a reference object.  This function always succeeds.
+ .. c:function:: int PyWeakref_CheckProxy(ob)
+-   Return true if *ob* is a proxy object.
++   Return true if *ob* is a proxy object.  This function always succeeds.
+ .. c:function:: PyObject* PyWeakref_NewRef(PyObject *ob, PyObject *callback)
+diff --git a/Doc/copyright.rst b/Doc/copyright.rst
+index 1b90d9f172..4191c0bb63 100644
+--- a/Doc/copyright.rst
++++ b/Doc/copyright.rst
+@@ -4,7 +4,7 @@ Copyright
+ Python and this documentation is:
+-Copyright Â© 2001-2020 Python Software Foundation. All rights reserved.
++Copyright Â© 2001-2021 Python Software Foundation. All rights reserved.
+ Copyright Â© 2000 BeOpen.com. All rights reserved.
+diff --git a/Doc/howto/descriptor.rst b/Doc/howto/descriptor.rst
+index ab5a573c6a..0f999c9559 100644
+--- a/Doc/howto/descriptor.rst
++++ b/Doc/howto/descriptor.rst
+@@ -497,7 +497,7 @@ Definition and introduction
+ In general, a descriptor is an attribute value that has one of the methods in
+ the descriptor protocol.  Those methods are :meth:`__get__`, :meth:`__set__`,
+-and :meth:`__delete__`.  If any of those methods are defined for an the
++and :meth:`__delete__`.  If any of those methods are defined for an
+ attribute, it is said to be a :term:`descriptor`.
+ The default behavior for attribute access is to get, set, or delete the
+diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst
+index 02cd70f4f7..4542961d78 100644
+--- a/Doc/library/argparse.rst
++++ b/Doc/library/argparse.rst
+@@ -1050,63 +1050,70 @@ command-line argument was not present::
+ type
+ ^^^^
+-By default, :class:`ArgumentParser` objects read command-line arguments in as simple
++By default, the parser reads command-line arguments in as simple
+ strings. However, quite often the command-line string should instead be
+-interpreted as another type, like a :class:`float` or :class:`int`.  The
+-``type`` keyword argument of :meth:`~ArgumentParser.add_argument` allows any
+-necessary type-checking and type conversions to be performed.  Common built-in
+-types and functions can be used directly as the value of the ``type`` argument::
++interpreted as another type, such as a :class:`float` or :class:`int`.  The
++``type`` keyword for :meth:`~ArgumentParser.add_argument` allows any
++necessary type-checking and type conversions to be performed.
+-   >>> parser = argparse.ArgumentParser()
+-   >>> parser.add_argument('foo', type=int)
+-   >>> parser.add_argument('bar', type=open)
+-   >>> parser.parse_args('2 temp.txt'.split())
+-   Namespace(bar=<_io.TextIOWrapper name='temp.txt' encoding='UTF-8'>, foo=2)
++If the type_ keyword is used with the default_ keyword, the type converter
++is only applied if the default is a string.
+-See the section on the default_ keyword argument for information on when the
+-``type`` argument is applied to default arguments.
++The argument to ``type`` can be any callable that accepts a single string.
++If the function raises :exc:`ArgumentTypeError`, :exc:`TypeError`, or
++:exc:`ValueError`, the exception is caught and a nicely formatted error
++message is displayed.  No other exception types are handled.
+-To ease the use of various types of files, the argparse module provides the
+-factory FileType which takes the ``mode=``, ``bufsize=``, ``encoding=`` and
+-``errors=`` arguments of the :func:`open` function.  For example,
+-``FileType('w')`` can be used to create a writable file::
++Common built-in types and functions can be used as type converters:
+-   >>> parser = argparse.ArgumentParser()
+-   >>> parser.add_argument('bar', type=argparse.FileType('w'))
+-   >>> parser.parse_args(['out.txt'])
+-   Namespace(bar=<_io.TextIOWrapper name='out.txt' encoding='UTF-8'>)
+-
+-``type=`` can take any callable that takes a single string argument and returns
+-the converted value::
+-
+-   >>> def perfect_square(string):
+-   ...     value = int(string)
+-   ...     sqrt = math.sqrt(value)
+-   ...     if sqrt != int(sqrt):
+-   ...         msg = "%r is not a perfect square" % string
+-   ...         raise argparse.ArgumentTypeError(msg)
+-   ...     return value
++.. testcode::
++
++   import argparse
++   import pathlib
++
++   parser = argparse.ArgumentParser()
++   parser.add_argument('count', type=int)
++   parser.add_argument('distance', type=float)
++   parser.add_argument('street', type=ascii)
++   parser.add_argument('code_point', type=ord)
++   parser.add_argument('source_file', type=open)
++   parser.add_argument('dest_file', type=argparse.FileType('w', encoding='latin-1'))
++   parser.add_argument('datapath', type=pathlib.Path)
++
++User defined functions can be used as well:
++
++.. doctest::
++
++   >>> def hyphenated(string):
++   ...     return '-'.join([word[:4] for word in string.casefold().split()])
+    ...
+-   >>> parser = argparse.ArgumentParser(prog='PROG')
+-   >>> parser.add_argument('foo', type=perfect_square)
+-   >>> parser.parse_args(['9'])
+-   Namespace(foo=9)
+-   >>> parser.parse_args(['7'])
+-   usage: PROG [-h] foo
+-   PROG: error: argument foo: '7' is not a perfect square
++   >>> parser = argparse.ArgumentParser()
++   >>> _ = parser.add_argument('short_title', type=hyphenated)
++   >>> parser.parse_args(['"The Tale of Two Cities"'])
++   Namespace(short_title='"the-tale-of-two-citi')
+-The choices_ keyword argument may be more convenient for type checkers that
+-simply check against a range of values::
++The :func:`bool` function is not recommended as a type converter.  All it does
++is convert empty strings to ``False`` and non-empty strings to ``True``.
++This is usually not what is desired.
+-   >>> parser = argparse.ArgumentParser(prog='PROG')
+-   >>> parser.add_argument('foo', type=int, choices=range(5, 10))
+-   >>> parser.parse_args(['7'])
+-   Namespace(foo=7)
+-   >>> parser.parse_args(['11'])
+-   usage: PROG [-h] {5,6,7,8,9}
+-   PROG: error: argument foo: invalid choice: 11 (choose from 5, 6, 7, 8, 9)
++In general, the ``type`` keyword is a convenience that should only be used for
++simple conversions that can only raise one of the three supported exceptions.
++Anything with more interesting error-handling or resource management should be
++done downstream after the arguments are parsed.
+-See the choices_ section for more details.
++For example, JSON or YAML conversions have complex error cases that require
++better reporting than can be given by the ``type`` keyword.  An
++:exc:`~json.JSONDecodeError` would not be well formatted and a
++:exc:`FileNotFound` exception would not be handled at all.
++
++Even :class:`~argparse.FileType` has its limitations for use with the ``type``
++keyword.  If one argument uses *FileType* and then a subsequent argument fails,
++an error is reported but the file is not automatically closed.  In this case, it
++would be better to wait until after the parser has run and then use the
++:keyword:`with`-statement to manage the files.
++
++For type checkers that simply check against a fixed set of values, consider
++using the choices_ keyword instead.
+ choices
+@@ -1145,6 +1152,11 @@ Any container can be passed as the *choices* value, so :class:`list` objects,
+ Use of :class:`enum.Enum` is not recommended because it is difficult to
+ control its appearance in usage, help, and error messages.
++Formatted choices overrides the default *metavar* which is normally derived
++from *dest*.  This is usually what you want because the user never sees the
++*dest* parameter.  If this display isn't desirable (perhaps because there are
++many choices), just specify an explicit metavar_.
++
+ required
+ ^^^^^^^^
+diff --git a/Doc/library/asyncio-eventloop.rst b/Doc/library/asyncio-eventloop.rst
+index b1e73189a7..be43ca4aeb 100644
+--- a/Doc/library/asyncio-eventloop.rst
++++ b/Doc/library/asyncio-eventloop.rst
+@@ -321,7 +321,7 @@ Creating Futures and Tasks
+    .. versionadded:: 3.5.2
+-.. method:: loop.create_task(coro, \*, name=None)
++.. method:: loop.create_task(coro, *, name=None)
+    Schedule the execution of a :ref:`coroutine`.
+    Return a :class:`Task` object.
+@@ -356,7 +356,7 @@ Opening network connections
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ .. coroutinemethod:: loop.create_connection(protocol_factory, \
+-                          host=None, port=None, \*, ssl=None, \
++                          host=None, port=None, *, ssl=None, \
+                           family=0, proto=0, flags=0, sock=None, \
+                           local_addr=None, server_hostname=None, \
+                           ssl_handshake_timeout=None, \
+@@ -482,7 +482,7 @@ Opening network connections
+       that can be used directly in async/await code.
+ .. coroutinemethod:: loop.create_datagram_endpoint(protocol_factory, \
+-                        local_addr=None, remote_addr=None, \*, \
++                        local_addr=None, remote_addr=None, *, \
+                         family=0, proto=0, flags=0, \
+                         reuse_address=None, reuse_port=None, \
+                         allow_broadcast=None, sock=None)
+@@ -559,7 +559,7 @@ Opening network connections
+       Added support for Windows.
+ .. coroutinemethod:: loop.create_unix_connection(protocol_factory, \
+-                        path=None, \*, ssl=None, sock=None, \
++                        path=None, *, ssl=None, sock=None, \
+                         server_hostname=None, ssl_handshake_timeout=None)
+    Create a Unix connection.
+@@ -592,7 +592,7 @@ Creating network servers
+ ^^^^^^^^^^^^^^^^^^^^^^^^
+ .. coroutinemethod:: loop.create_server(protocol_factory, \
+-                        host=None, port=None, \*, \
++                        host=None, port=None, *, \
+                         family=socket.AF_UNSPEC, \
+                         flags=socket.AI_PASSIVE, \
+                         sock=None, backlog=100, ssl=None, \
+@@ -683,7 +683,7 @@ Creating network servers
+ .. coroutinemethod:: loop.create_unix_server(protocol_factory, path=None, \
+-                          \*, sock=None, backlog=100, ssl=None, \
++                          *, sock=None, backlog=100, ssl=None, \
+                           ssl_handshake_timeout=None, start_serving=True)
+    Similar to :meth:`loop.create_server` but works with the
+@@ -708,7 +708,7 @@ Creating network servers
+       The *path* parameter can now be a :class:`~pathlib.Path` object.
+ .. coroutinemethod:: loop.connect_accepted_socket(protocol_factory, \
+-                        sock, \*, ssl=None, ssl_handshake_timeout=None)
++                        sock, *, ssl=None, ssl_handshake_timeout=None)
+    Wrap an already accepted connection into a transport/protocol pair.
+@@ -773,7 +773,7 @@ TLS Upgrade
+ ^^^^^^^^^^^
+ .. coroutinemethod:: loop.start_tls(transport, protocol, \
+-                        sslcontext, \*, server_side=False, \
++                        sslcontext, *, server_side=False, \
+                         server_hostname=None, ssl_handshake_timeout=None)
+    Upgrade an existing transport-based connection to TLS.
+@@ -806,7 +806,7 @@ TLS Upgrade
+ Watching file descriptors
+ ^^^^^^^^^^^^^^^^^^^^^^^^^
+-.. method:: loop.add_reader(fd, callback, \*args)
++.. method:: loop.add_reader(fd, callback, *args)
+    Start monitoring the *fd* file descriptor for read availability and
+    invoke *callback* with the specified arguments once *fd* is available for
+@@ -816,7 +816,7 @@ Watching file descriptors
+    Stop monitoring the *fd* file descriptor for read availability.
+-.. method:: loop.add_writer(fd, callback, \*args)
++.. method:: loop.add_writer(fd, callback, *args)
+    Start monitoring the *fd* file descriptor for write availability and
+    invoke *callback* with the specified arguments once *fd* is available for
+@@ -930,7 +930,7 @@ convenient.
+       :meth:`loop.create_server` and :func:`start_server`.
+ .. coroutinemethod:: loop.sock_sendfile(sock, file, offset=0, count=None, \
+-                                        \*, fallback=True)
++                                        *, fallback=True)
+    Send a file using high-performance :mod:`os.sendfile` if possible.
+    Return the total number of bytes sent.
+@@ -964,7 +964,7 @@ convenient.
+ DNS
+ ^^^
+-.. coroutinemethod:: loop.getaddrinfo(host, port, \*, family=0, \
++.. coroutinemethod:: loop.getaddrinfo(host, port, *, family=0, \
+                         type=0, proto=0, flags=0)
+    Asynchronous version of :meth:`socket.getaddrinfo`.
+@@ -1029,7 +1029,7 @@ Working with pipes
+ Unix signals
+ ^^^^^^^^^^^^
+-.. method:: loop.add_signal_handler(signum, callback, \*args)
++.. method:: loop.add_signal_handler(signum, callback, *args)
+    Set *callback* as the handler for the *signum* signal.
+@@ -1064,7 +1064,7 @@ Unix signals
+ Executing code in thread or process pools
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+-.. awaitablemethod:: loop.run_in_executor(executor, func, \*args)
++.. awaitablemethod:: loop.run_in_executor(executor, func, *args)
+    Arrange for *func* to be called in the specified executor.
+@@ -1234,9 +1234,9 @@ async/await code consider using the high-level
+    subprocesses. See :ref:`Subprocess Support on Windows
+    <asyncio-windows-subprocess>` for details.
+-.. coroutinemethod:: loop.subprocess_exec(protocol_factory, \*args, \
++.. coroutinemethod:: loop.subprocess_exec(protocol_factory, *args, \
+                       stdin=subprocess.PIPE, stdout=subprocess.PIPE, \
+-                      stderr=subprocess.PIPE, \*\*kwargs)
++                      stderr=subprocess.PIPE, **kwargs)
+    Create a subprocess from one or more string arguments specified by
+    *args*.
+@@ -1316,9 +1316,9 @@ async/await code consider using the high-level
+    conforms to the :class:`asyncio.SubprocessTransport` base class and
+    *protocol* is an object instantiated by the *protocol_factory*.
+-.. coroutinemethod:: loop.subprocess_shell(protocol_factory, cmd, \*, \
++.. coroutinemethod:: loop.subprocess_shell(protocol_factory, cmd, *, \
+                         stdin=subprocess.PIPE, stdout=subprocess.PIPE, \
+-                        stderr=subprocess.PIPE, \*\*kwargs)
++                        stderr=subprocess.PIPE, **kwargs)
+    Create a subprocess from *cmd*, which can be a :class:`str` or a
+    :class:`bytes` string encoded to the
+diff --git a/Doc/library/asyncio-future.rst b/Doc/library/asyncio-future.rst
+index e1ac18eaf0..939d4c1a84 100644
+--- a/Doc/library/asyncio-future.rst
++++ b/Doc/library/asyncio-future.rst
+@@ -31,7 +31,7 @@ Future Functions
+    .. versionadded:: 3.5
+-.. function:: ensure_future(obj, \*, loop=None)
++.. function:: ensure_future(obj, *, loop=None)
+    Return:
+@@ -58,7 +58,7 @@ Future Functions
+       The function accepts any :term:`awaitable` object.
+-.. function:: wrap_future(future, \*, loop=None)
++.. function:: wrap_future(future, *, loop=None)
+    Wrap a :class:`concurrent.futures.Future` object in a
+    :class:`asyncio.Future` object.
+@@ -67,7 +67,7 @@ Future Functions
+ Future Object
+ =============
+-.. class:: Future(\*, loop=None)
++.. class:: Future(*, loop=None)
+    A Future represents an eventual result of an asynchronous
+    operation.  Not thread-safe.
+diff --git a/Doc/library/asyncio-policy.rst b/Doc/library/asyncio-policy.rst
+index 5e69525e90..ef6a058850 100644
+--- a/Doc/library/asyncio-policy.rst
++++ b/Doc/library/asyncio-policy.rst
+@@ -159,7 +159,7 @@ implementation used by the asyncio event loop:
+ .. class:: AbstractChildWatcher
+-   .. method:: add_child_handler(pid, callback, \*args)
++   .. method:: add_child_handler(pid, callback, *args)
+       Register a new child handler.
+diff --git a/Doc/library/asyncio-stream.rst b/Doc/library/asyncio-stream.rst
+index b76ed379c7..714de8d41a 100644
+--- a/Doc/library/asyncio-stream.rst
++++ b/Doc/library/asyncio-stream.rst
+@@ -48,7 +48,7 @@ The following top-level asyncio functions can be used to create
+ and work with streams:
+-.. coroutinefunction:: open_connection(host=None, port=None, \*, \
++.. coroutinefunction:: open_connection(host=None, port=None, *, \
+                           loop=None, limit=None, ssl=None, family=0, \
+                           proto=0, flags=0, sock=None, local_addr=None, \
+                           server_hostname=None, ssl_handshake_timeout=None)
+@@ -74,7 +74,7 @@ and work with streams:
+       The *ssl_handshake_timeout* parameter.
+ .. coroutinefunction:: start_server(client_connected_cb, host=None, \
+-                          port=None, \*, loop=None, limit=None, \
++                          port=None, *, loop=None, limit=None, \
+                           family=socket.AF_UNSPEC, \
+                           flags=socket.AI_PASSIVE, sock=None, \
+                           backlog=100, ssl=None, reuse_address=None, \
+@@ -109,7 +109,7 @@ and work with streams:
+ .. rubric:: Unix Sockets
+-.. coroutinefunction:: open_unix_connection(path=None, \*, loop=None, \
++.. coroutinefunction:: open_unix_connection(path=None, *, loop=None, \
+                         limit=None, ssl=None, sock=None, \
+                         server_hostname=None, ssl_handshake_timeout=None)
+@@ -132,7 +132,7 @@ and work with streams:
+ .. coroutinefunction:: start_unix_server(client_connected_cb, path=None, \
+-                          \*, loop=None, limit=None, sock=None, \
++                          *, loop=None, limit=None, sock=None, \
+                           backlog=100, ssl=None, ssl_handshake_timeout=None, \
+                           start_serving=True)
+diff --git a/Doc/library/asyncio-subprocess.rst b/Doc/library/asyncio-subprocess.rst
+index b0330349df..fb98552c86 100644
+--- a/Doc/library/asyncio-subprocess.rst
++++ b/Doc/library/asyncio-subprocess.rst
+@@ -61,9 +61,9 @@ See also the `Examples`_ subsection.
+ Creating Subprocesses
+ =====================
+-.. coroutinefunction:: create_subprocess_exec(program, \*args, stdin=None, \
++.. coroutinefunction:: create_subprocess_exec(program, *args, stdin=None, \
+                           stdout=None, stderr=None, loop=None, \
+-                          limit=None, \*\*kwds)
++                          limit=None, **kwds)
+    Create a subprocess.
+@@ -82,7 +82,7 @@ Creating Subprocesses
+ .. coroutinefunction:: create_subprocess_shell(cmd, stdin=None, \
+                           stdout=None, stderr=None, loop=None, \
+-                          limit=None, \*\*kwds)
++                          limit=None, **kwds)
+    Run the *cmd* shell command.
+diff --git a/Doc/library/asyncio-sync.rst b/Doc/library/asyncio-sync.rst
+index 84a52cb2d5..f62ce670fc 100644
+--- a/Doc/library/asyncio-sync.rst
++++ b/Doc/library/asyncio-sync.rst
+@@ -104,8 +104,8 @@ Event
+    that some event has happened.
+    An Event object manages an internal flag that can be set to *true*
+-   with the :meth:`set` method and reset to *false* with the
+-   :meth:`clear` method.  The :meth:`wait` method blocks until the
++   with the :meth:`~Event.set` method and reset to *false* with the
++   :meth:`clear` method.  The :meth:`~Event.wait` method blocks until the
+    flag is set to *true*.  The flag is set to *false* initially.
+@@ -142,7 +142,7 @@ Event
+       Wait until the event is set.
+       If the event is set, return ``True`` immediately.
+-      Otherwise block until another task calls :meth:`set`.
++      Otherwise block until another task calls :meth:`~Event.set`.
+    .. method:: set()
+@@ -155,8 +155,8 @@ Event
+       Clear (unset) the event.
+-      Tasks awaiting on :meth:`wait` will now block until the
+-      :meth:`set` method is called again.
++      Tasks awaiting on :meth:`~Event.wait` will now block until the
++      :meth:`~Event.set` method is called again.
+    .. method:: is_set()
+diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst
+index c638f1263f..201678b0a3 100644
+--- a/Doc/library/asyncio-task.rst
++++ b/Doc/library/asyncio-task.rst
+@@ -210,7 +210,7 @@ is :meth:`loop.run_in_executor`.
+ Running an asyncio Program
+ ==========================
+-.. function:: run(coro, \*, debug=False)
++.. function:: run(coro, *, debug=False)
+     Execute the :term:`coroutine` *coro* and return the result.
+@@ -247,7 +247,7 @@ Running an asyncio Program
+ Creating Tasks
+ ==============
+-.. function:: create_task(coro, \*, name=None)
++.. function:: create_task(coro, *, name=None)
+    Wrap the *coro* :ref:`coroutine <coroutine>` into a :class:`Task`
+    and schedule its execution.  Return the Task object.
+@@ -283,7 +283,7 @@ Creating Tasks
+ Sleeping
+ ========
+-.. coroutinefunction:: sleep(delay, result=None, \*, loop=None)
++.. coroutinefunction:: sleep(delay, result=None, *, loop=None)
+    Block for *delay* seconds.
+@@ -319,7 +319,7 @@ Sleeping
+ Running Tasks Concurrently
+ ==========================
+-.. awaitablefunction:: gather(\*aws, loop=None, return_exceptions=False)
++.. awaitablefunction:: gather(*aws, loop=None, return_exceptions=False)
+    Run :ref:`awaitable objects <asyncio-awaitables>` in the *aws*
+    sequence *concurrently*.
+@@ -403,7 +403,7 @@ Running Tasks Concurrently
+ Shielding From Cancellation
+ ===========================
+-.. awaitablefunction:: shield(aw, \*, loop=None)
++.. awaitablefunction:: shield(aw, *, loop=None)
+    Protect an :ref:`awaitable object <asyncio-awaitables>`
+    from being :meth:`cancelled <Task.cancel>`.
+@@ -443,7 +443,7 @@ Shielding From Cancellation
+ Timeouts
+ ========
+-.. coroutinefunction:: wait_for(aw, timeout, \*, loop=None)
++.. coroutinefunction:: wait_for(aw, timeout, *, loop=None)
+    Wait for the *aw* :ref:`awaitable <asyncio-awaitables>`
+    to complete with a timeout.
+@@ -500,7 +500,7 @@ Timeouts
+ Waiting Primitives
+ ==================
+-.. coroutinefunction:: wait(aws, \*, loop=None, timeout=None,\
++.. coroutinefunction:: wait(aws, *, loop=None, timeout=None,\
+                             return_when=ALL_COMPLETED)
+    Run :ref:`awaitable objects <asyncio-awaitables>` in the *aws*
+@@ -590,7 +590,7 @@ Waiting Primitives
+       deprecated.
+-.. function:: as_completed(aws, \*, loop=None, timeout=None)
++.. function:: as_completed(aws, *, loop=None, timeout=None)
+    Run :ref:`awaitable objects <asyncio-awaitables>` in the *aws*
+    iterable concurrently.  Return an iterator of coroutines.
+@@ -613,7 +613,7 @@ Waiting Primitives
+ Running in Threads
+ ==================
+-.. coroutinefunction:: to_thread(func, /, \*args, \*\*kwargs)
++.. coroutinefunction:: to_thread(func, /, *args, **kwargs)
+    Asynchronously run function *func* in a separate thread.
+@@ -743,7 +743,7 @@ Introspection
+ Task Object
+ ===========
+-.. class:: Task(coro, \*, loop=None, name=None)
++.. class:: Task(coro, *, loop=None, name=None)
+    A :class:`Future-like <Future>` object that runs a Python
+    :ref:`coroutine <coroutine>`.  Not thread-safe.
+@@ -909,7 +909,7 @@ Task Object
+       See the documentation of :meth:`Future.remove_done_callback`
+       for more details.
+-   .. method:: get_stack(\*, limit=None)
++   .. method:: get_stack(*, limit=None)
+       Return the list of stack frames for this Task.
+@@ -930,7 +930,7 @@ Task Object
+       stack are returned, but the oldest frames of a traceback are
+       returned.  (This matches the behavior of the traceback module.)
+-   .. method:: print_stack(\*, limit=None, file=None)
++   .. method:: print_stack(*, limit=None, file=None)
+       Print the stack or traceback for this Task.
+diff --git a/Doc/library/codecs.rst b/Doc/library/codecs.rst
+index f071057293..6eb907afce 100644
+--- a/Doc/library/codecs.rst
++++ b/Doc/library/codecs.rst
+@@ -694,7 +694,7 @@ compatible with the Python codec registry.
+    .. method:: reset()
+-      Flushes and resets the codec buffers used for keeping state.
++      Resets the codec buffers used for keeping internal state.
+       Calling this method should ensure that the data on the output is put into
+       a clean state that allows appending of new fresh data without having to
+@@ -789,7 +789,7 @@ compatible with the Python codec registry.
+    .. method:: reset()
+-      Resets the codec buffers used for keeping state.
++      Resets the codec buffers used for keeping internal state.
+       Note that no stream repositioning should take place. This method is
+       primarily intended to be able to recover from decoding errors.
+diff --git a/Doc/library/compileall.rst b/Doc/library/compileall.rst
+index 9b914b1f0d..5c6e68f930 100644
+--- a/Doc/library/compileall.rst
++++ b/Doc/library/compileall.rst
+@@ -148,7 +148,7 @@ runtime.
+ Public functions
+ ----------------
+-.. function:: compile_dir(dir, maxlevels=sys.getrecursionlimit(), ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=-1, workers=1, invalidation_mode=None, \*, stripdir=None, prependdir=None, limit_sl_dest=None, hardlink_dupes=False)
++.. function:: compile_dir(dir, maxlevels=sys.getrecursionlimit(), ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=-1, workers=1, invalidation_mode=None, *, stripdir=None, prependdir=None, limit_sl_dest=None, hardlink_dupes=False)
+    Recursively descend the directory tree named by *dir*, compiling all :file:`.py`
+    files along the way. Return a true value if all the files compiled successfully,
+@@ -231,7 +231,7 @@ Public functions
+       Added *stripdir*, *prependdir*, *limit_sl_dest* and *hardlink_dupes* arguments.
+       Default value of *maxlevels* was changed from ``10`` to ``sys.getrecursionlimit()``
+-.. function:: compile_file(fullname, ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=-1, invalidation_mode=None, \*, stripdir=None, prependdir=None, limit_sl_dest=None, hardlink_dupes=False)
++.. function:: compile_file(fullname, ddir=None, force=False, rx=None, quiet=0, legacy=False, optimize=-1, invalidation_mode=None, *, stripdir=None, prependdir=None, limit_sl_dest=None, hardlink_dupes=False)
+    Compile the file with path *fullname*. Return a true value if the file
+    compiled successfully, and a false value otherwise.
+diff --git a/Doc/library/concurrent.futures.rst b/Doc/library/concurrent.futures.rst
+index 61d6c1143c..d57f8ce23d 100644
+--- a/Doc/library/concurrent.futures.rst
++++ b/Doc/library/concurrent.futures.rst
+@@ -67,7 +67,7 @@ Executor Objects
+        .. versionchanged:: 3.5
+           Added the *chunksize* argument.
+-    .. method:: shutdown(wait=True, \*, cancel_futures=False)
++    .. method:: shutdown(wait=True, *, cancel_futures=False)
+        Signal the executor that it should free any resources that it is using
+        when the currently pending futures are done executing.  Calls to
+diff --git a/Doc/library/contextvars.rst b/Doc/library/contextvars.rst
+index 8805661c45..14ac47f4c9 100644
+--- a/Doc/library/contextvars.rst
++++ b/Doc/library/contextvars.rst
+@@ -26,7 +26,7 @@ See also :pep:`567` for additional details.
+ Context Variables
+ -----------------
+-.. class:: ContextVar(name, [\*, default])
++.. class:: ContextVar(name, [*, default])
+    This class is used to declare a new Context Variable, e.g.::
+@@ -146,7 +146,7 @@ Manual Context Management
+    Context implements the :class:`collections.abc.Mapping` interface.
+-   .. method:: run(callable, \*args, \*\*kwargs)
++   .. method:: run(callable, *args, **kwargs)
+       Execute ``callable(*args, **kwargs)`` code in the context object
+       the *run* method is called on.  Return the result of the execution
+diff --git a/Doc/library/ctypes.rst b/Doc/library/ctypes.rst
+index bf32d3e549..7313148721 100644
+--- a/Doc/library/ctypes.rst
++++ b/Doc/library/ctypes.rst
+@@ -2508,7 +2508,7 @@ other data types containing pointer type fields.
+ Arrays and pointers
+ ^^^^^^^^^^^^^^^^^^^
+-.. class:: Array(\*args)
++.. class:: Array(*args)
+    Abstract base class for arrays.
+diff --git a/Doc/library/curses.rst b/Doc/library/curses.rst
+index 7a13295f48..c72840a07c 100644
+--- a/Doc/library/curses.rst
++++ b/Doc/library/curses.rst
+@@ -112,14 +112,15 @@ The module :mod:`curses` defines the following functions:
+ .. function:: color_content(color_number)
+    Return the intensity of the red, green, and blue (RGB) components in the color
+-   *color_number*, which must be between ``0`` and :const:`COLORS`.  Return a 3-tuple,
++   *color_number*, which must be between ``0`` and ``COLORS - 1``.  Return a 3-tuple,
+    containing the R,G,B values for the given color, which will be between
+    ``0`` (no component) and ``1000`` (maximum amount of component).
+-.. function:: color_pair(color_number)
++.. function:: color_pair(pair_number)
+-   Return the attribute value for displaying text in the specified color.  This
++   Return the attribute value for displaying text in the specified color pair.
++   Only the first 256 color pairs are supported. This
+    attribute value can be combined with :const:`A_STANDOUT`, :const:`A_REVERSE`,
+    and the other :const:`A_\*` attributes.  :func:`pair_number` is the counterpart
+    to this function.
+@@ -278,7 +279,7 @@ The module :mod:`curses` defines the following functions:
+    Change the definition of a color, taking the number of the color to be changed
+    followed by three RGB values (for the amounts of red, green, and blue
+    components).  The value of *color_number* must be between ``0`` and
+-   :const:`COLORS`.  Each of *r*, *g*, *b*, must be a value between ``0`` and
++   `COLORS - 1`.  Each of *r*, *g*, *b*, must be a value between ``0`` and
+    ``1000``.  When :func:`init_color` is used, all occurrences of that color on the
+    screen immediately change to the new definition.  This function is a no-op on
+    most terminals; it is active only if :func:`can_change_color` returns ``True``.
+@@ -291,7 +292,8 @@ The module :mod:`curses` defines the following functions:
+    color number.  The value of *pair_number* must be between ``1`` and
+    ``COLOR_PAIRS - 1`` (the ``0`` color pair is wired to white on black and cannot
+    be changed).  The value of *fg* and *bg* arguments must be between ``0`` and
+-   :const:`COLORS`.  If the color-pair was previously initialized, the screen is
++   ``COLORS - 1``, or, after calling :func:`use_default_colors`, ``-1``.
++   If the color-pair was previously initialized, the screen is
+    refreshed and all occurrences of that color-pair are changed to the new
+    definition.
+@@ -441,7 +443,7 @@ The module :mod:`curses` defines the following functions:
+ .. function:: pair_content(pair_number)
+    Return a tuple ``(fg, bg)`` containing the colors for the requested color pair.
+-   The value of *pair_number* must be between ``1`` and ``COLOR_PAIRS - 1``.
++   The value of *pair_number* must be between ``0`` and ``COLOR_PAIRS - 1``.
+ .. function:: pair_number(attr)
+diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst
+index 508bc88e7f..dae0dd7aa5 100644
+--- a/Doc/library/datetime.rst
++++ b/Doc/library/datetime.rst
+@@ -1219,7 +1219,7 @@ Instance methods:
+ .. method:: datetime.replace(year=self.year, month=self.month, day=self.day, \
+    hour=self.hour, minute=self.minute, second=self.second, microsecond=self.microsecond, \
+-   tzinfo=self.tzinfo, * fold=0)
++   tzinfo=self.tzinfo, *, fold=0)
+    Return a datetime with the same attributes, except for those attributes given
+    new values by whichever keyword arguments are specified. Note that
+@@ -1783,7 +1783,7 @@ Other constructor:
+ Instance methods:
+ .. method:: time.replace(hour=self.hour, minute=self.minute, second=self.second, \
+-   microsecond=self.microsecond, tzinfo=self.tzinfo, * fold=0)
++   microsecond=self.microsecond, tzinfo=self.tzinfo, *, fold=0)
+    Return a :class:`.time` with the same value, except for those attributes given
+    new values by whichever keyword arguments are specified. Note that
+diff --git a/Doc/library/dialog.rst b/Doc/library/dialog.rst
+index dc82a974ce..53f98c1018 100644
+--- a/Doc/library/dialog.rst
++++ b/Doc/library/dialog.rst
+@@ -198,7 +198,7 @@ These do not emulate the native look-and-feel of the platform.
+    A subclass of FileDialog that creates a dialog window for selecting a
+    destination file.
+-    .. method:: ok_command()
++   .. method:: ok_command()
+       Test whether or not the selection points to a valid file that is not a
+       directory. Confirmation is required if an already existing file is
+diff --git a/Doc/library/email.contentmanager.rst b/Doc/library/email.contentmanager.rst
+index e09c7c0e40..918fc55677 100644
+--- a/Doc/library/email.contentmanager.rst
++++ b/Doc/library/email.contentmanager.rst
+@@ -116,7 +116,7 @@ Currently the email package provides only one concrete content manager,
+       decoding the payload to unicode.  The default error handler is
+       ``replace``.
+-   .. method:: set_content(msg, <'str'>, subtype="plain", charset='utf-8' \
++   .. method:: set_content(msg, <'str'>, subtype="plain", charset='utf-8', \
+                            cte=None, \
+                            disposition=None, filename=None, cid=None, \
+                            params=None, headers=None)
+diff --git a/Doc/library/email.headerregistry.rst b/Doc/library/email.headerregistry.rst
+index 9376da2b8d..3e1d97a032 100644
+--- a/Doc/library/email.headerregistry.rst
++++ b/Doc/library/email.headerregistry.rst
+@@ -289,7 +289,7 @@ variant, :attr:`~.BaseHeader.max_count` is set to 1.
+     A :class:`ParameterizedMIMEHeader` class that handles the
+     :mailheader:`Content-Disposition` header.
+-    .. attribute:: content-disposition
++    .. attribute:: content_disposition
+        ``inline`` and ``attachment`` are the only valid values in common use.
+diff --git a/Doc/library/email.policy.rst b/Doc/library/email.policy.rst
+index 8e70762598..bf53b9520f 100644
+--- a/Doc/library/email.policy.rst
++++ b/Doc/library/email.policy.rst
+@@ -210,7 +210,7 @@ added matters.  To illustrate::
+       :meth:`register_defect` method.
+-   .. attribute:: mangle_from\_
++   .. attribute:: mangle_from_
+       If :const:`True`, lines starting with *"From "* in the body are
+       escaped by putting a ``>`` in front of them. This parameter is used when
+diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst
+index a3c5165557..8836b24912 100644
+--- a/Doc/library/enum.rst
++++ b/Doc/library/enum.rst
+@@ -56,7 +56,7 @@ helper, :class:`auto`.
+     the bitwise operations without losing their :class:`Flag` membership.
+ .. function:: unique
+-   :noindex:
++    :noindex:
+     Enum class decorator that ensures only one name is bound to any one value.
+@@ -1121,6 +1121,15 @@ and raise an error if the two do not match::
+     In Python 2 code the :attr:`_order_` attribute is necessary as definition
+     order is lost before it can be recorded.
++
++_Private__names
++"""""""""""""""
++
++Private names will be normal attributes in Python 3.10 instead of either an error
++or a member (depending on if the name ends with an underscore). Using these names
++in 3.9 will issue a :exc:`DeprecationWarning`.
++
++
+ ``Enum`` member type
+ """"""""""""""""""""
+diff --git a/Doc/library/fnmatch.rst b/Doc/library/fnmatch.rst
+index ce07d326b3..925f08e914 100644
+--- a/Doc/library/fnmatch.rst
++++ b/Doc/library/fnmatch.rst
+@@ -75,7 +75,7 @@ patterns.
+ .. function:: filter(names, pattern)
+-   Return the subset of the list of *names* that match *pattern*. It is the same as
++   Construct a list from those elements of the iterable *names* that match *pattern*. It is the same as
+    ``[n for n in names if fnmatch(n, pattern)]``, but implemented more efficiently.
+diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst
+index 9c12b6c48d..9d13967c04 100644
+--- a/Doc/library/functions.rst
++++ b/Doc/library/functions.rst
+@@ -1687,18 +1687,19 @@ are always available.  They are listed here in alphabetical order.
+    With three arguments, return a new type object.  This is essentially a
+-   dynamic form of the :keyword:`class` statement. The *name* string is the
+-   class name and becomes the :attr:`~definition.__name__` attribute; the *bases*
+-   tuple itemizes the base classes and becomes the :attr:`~class.__bases__`
+-   attribute; and the *dict* dictionary is the namespace containing definitions
+-   for class body and is copied to a standard dictionary to become the
+-   :attr:`~object.__dict__` attribute.  For example, the following two
+-   statements create identical :class:`type` objects:
++   dynamic form of the :keyword:`class` statement. The *name* string is
++   the class name and becomes the :attr:`~definition.__name__` attribute.
++   The *bases* tuple contains the base classes and becomes the
++   :attr:`~class.__bases__` attribute; if empty, :class:`object`, the
++   ultimate base of all classes, is added.  The *dict* dictionary contains
++   attribute and method definitions for the class body; it may be copied
++   or wrapped before becoming the :attr:`~object.__dict__` attribute.
++   The following two statements create identical :class:`type` objects:
+       >>> class X:
+       ...     a = 1
+       ...
+-      >>> X = type('X', (object,), dict(a=1))
++      >>> X = type('X', (), dict(a=1))
+    See also :ref:`bltin-type-objects`.
+diff --git a/Doc/library/functools.rst b/Doc/library/functools.rst
+index 4869b67cb9..85d4e74698 100644
+--- a/Doc/library/functools.rst
++++ b/Doc/library/functools.rst
+@@ -62,16 +62,26 @@ The :mod:`functools` module defines the following functions:
+    Example::
+        class DataSet:
++
+            def __init__(self, sequence_of_numbers):
+-               self._data = sequence_of_numbers
++               self._data = tuple(sequence_of_numbers)
+            @cached_property
+            def stdev(self):
+                return statistics.stdev(self._data)
+-           @cached_property
+-           def variance(self):
+-               return statistics.variance(self._data)
++   The mechanics of :func:`cached_property` are somewhat different from
++   :func:`property`.  A regular property blocks attribute writes unless a
++   setter is defined. In contrast, a *cached_property* allows writes.
++
++   The *cached_property* decorator only runs on lookups and only when an
++   attribute of the same name doesn't exist.  When it does run, the
++   *cached_property* writes to the attribute with the same name. Subsequent
++   attribute reads and writes take precedence over the *cached_property*
++   method and it works like a normal attribute.
++
++   The cached value can be cleared by deleting the attribute.  This
++   allows the *cached_property* method to run again.
+    Note, this decorator interferes with the operation of :pep:`412`
+    key-sharing dictionaries.  This means that instance dictionaries
+diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst
+index a59a5d3a46..e7eaabd8bf 100644
+--- a/Doc/library/idle.rst
++++ b/Doc/library/idle.rst
+@@ -250,7 +250,7 @@ View Last Restart
+   Scroll the shell window to the last Shell restart.
+ Restart Shell
+-  Restart the shell to clean the environment.
++  Restart the shell to clean the environment and reset display and exception handling.
+ Previous History
+   Cycle through earlier commands in history which match the current entry.
+diff --git a/Doc/library/importlib.metadata.rst b/Doc/library/importlib.metadata.rst
+index 21da143f3b..0dd3daaa54 100644
+--- a/Doc/library/importlib.metadata.rst
++++ b/Doc/library/importlib.metadata.rst
+@@ -206,9 +206,9 @@ Thus, an alternative way to get the version number is through the
+ There are all kinds of additional metadata available on the ``Distribution``
+ instance::
+-    >>> d.metadata['Requires-Python']  # doctest: +SKIP
++    >>> dist.metadata['Requires-Python']  # doctest: +SKIP
+     '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*'
+-    >>> d.metadata['License']  # doctest: +SKIP
++    >>> dist.metadata['License']  # doctest: +SKIP
+     'MIT'
+ The full set of available metadata is not described here.  See :pep:`566`
+diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst
+index 9027ba58ac..cb2a5686a9 100644
+--- a/Doc/library/importlib.rst
++++ b/Doc/library/importlib.rst
+@@ -1135,7 +1135,7 @@ find and load modules.
+       directory for ``''`` (i.e. the empty string).
+-.. class:: FileFinder(path, \*loader_details)
++.. class:: FileFinder(path, *loader_details)
+    A concrete implementation of :class:`importlib.abc.PathEntryFinder` which
+    caches results from the file system.
+@@ -1178,7 +1178,7 @@ find and load modules.
+       Clear out the internal cache.
+-   .. classmethod:: path_hook(\*loader_details)
++   .. classmethod:: path_hook(*loader_details)
+       A class method which returns a closure for use on :attr:`sys.path_hooks`.
+       An instance of :class:`FileFinder` is returned by the closure using the
+@@ -1473,7 +1473,7 @@ an :term:`importer`.
+    If  **name** has no leading dots, then **name** is simply returned. This
+    allows for usage such as
+-   ``importlib.util.resolve_name('sys', __package__)`` without doing a
++   ``importlib.util.resolve_name('sys', __spec__.parent)`` without doing a
+    check to see if the **package** argument is needed.
+    :exc:`ImportError` is raised if **name** is a relative module name but
+diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst
+index d00a30ff00..b53a9421fb 100644
+--- a/Doc/library/inspect.rst
++++ b/Doc/library/inspect.rst
+@@ -556,7 +556,7 @@ The Signature object represents the call signature of a callable object and its
+ return annotation.  To retrieve a Signature object, use the :func:`signature`
+ function.
+-.. function:: signature(callable, \*, follow_wrapped=True)
++.. function:: signature(callable, *, follow_wrapped=True)
+    Return a :class:`Signature` object for the given ``callable``::
+@@ -597,7 +597,7 @@ function.
+       C provide no metadata about their arguments.
+-.. class:: Signature(parameters=None, \*, return_annotation=Signature.empty)
++.. class:: Signature(parameters=None, *, return_annotation=Signature.empty)
+    A Signature object represents the call signature of a function and its return
+    annotation.  For each parameter accepted by the function it stores a
+@@ -668,7 +668,7 @@ function.
+          >>> str(new_sig)
+          "(a, b) -> 'new return anno'"
+-   .. classmethod:: Signature.from_callable(obj, \*, follow_wrapped=True)
++   .. classmethod:: Signature.from_callable(obj, *, follow_wrapped=True)
+        Return a :class:`Signature` (or its subclass) object for a given callable
+        ``obj``.  Pass ``follow_wrapped=False`` to get a signature of ``obj``
+@@ -684,7 +684,7 @@ function.
+        .. versionadded:: 3.5
+-.. class:: Parameter(name, kind, \*, default=Parameter.empty, annotation=Parameter.empty)
++.. class:: Parameter(name, kind, *, default=Parameter.empty, annotation=Parameter.empty)
+    Parameter objects are *immutable*.  Instead of modifying a Parameter object,
+    you can use :meth:`Parameter.replace` to create a modified copy.
+diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst
+index 3de66c9349..ff5b60d70f 100644
+--- a/Doc/library/itertools.rst
++++ b/Doc/library/itertools.rst
+@@ -565,7 +565,7 @@ loops that truncate the stream.
+    Before :func:`product` runs, it completely consumes the input iterables,
+    keeping pools of values in memory to generate the products.  Accordingly,
+-   it only useful with finite inputs.
++   it is only useful with finite inputs.
+ .. function:: repeat(object[, times])
+@@ -769,6 +769,18 @@ which incur interpreter overhead.
+    def dotproduct(vec1, vec2):
+        return sum(map(operator.mul, vec1, vec2))
++   def convolve(signal, kernel):
++       # See:  https://betterexplained.com/articles/intuitive-convolution/
++       # convolve(data, [0.25, 0.25, 0.25, 0.25]) --> Moving average (blur)
++       # convolve(data, [1, -1]) --> 1st finite difference (1st derivative)
++       # convolve(data, [1, -2, 1]) --> 2nd finite difference (2nd derivative)
++       kernel = list(reversed(kernel))
++       n = len(kernel)
++       window = collections.deque([0] * n, maxlen=n)
++       for x in chain(signal, repeat(0, n-1)):
++           window.append(x)
++           yield sum(map(operator.mul, kernel, window))
++
+    def flatten(list_of_lists):
+        "Flatten one level of nesting"
+        return chain.from_iterable(list_of_lists)
+diff --git a/Doc/library/logging.config.rst b/Doc/library/logging.config.rst
+index 683d6ed5e8..0b5e2fc2a6 100644
+--- a/Doc/library/logging.config.rst
++++ b/Doc/library/logging.config.rst
+@@ -35,45 +35,45 @@ in :mod:`logging` itself) and defining handlers which are declared either in
+ .. function:: dictConfig(config)
+-    Takes the logging configuration from a dictionary.  The contents of
+-    this dictionary are described in :ref:`logging-config-dictschema`
+-    below.
+-
+-    If an error is encountered during configuration, this function will
+-    raise a :exc:`ValueError`, :exc:`TypeError`, :exc:`AttributeError`
+-    or :exc:`ImportError` with a suitably descriptive message.  The
+-    following is a (possibly incomplete) list of conditions which will
+-    raise an error:
+-
+-    * A ``level`` which is not a string or which is a string not
+-      corresponding to an actual logging level.
+-    * A ``propagate`` value which is not a boolean.
+-    * An id which does not have a corresponding destination.
+-    * A non-existent handler id found during an incremental call.
+-    * An invalid logger name.
+-    * Inability to resolve to an internal or external object.
+-
+-    Parsing is performed by the :class:`DictConfigurator` class, whose
+-    constructor is passed the dictionary used for configuration, and
+-    has a :meth:`configure` method.  The :mod:`logging.config` module
+-    has a callable attribute :attr:`dictConfigClass`
+-    which is initially set to :class:`DictConfigurator`.
+-    You can replace the value of :attr:`dictConfigClass` with a
+-    suitable implementation of your own.
+-
+-    :func:`dictConfig` calls :attr:`dictConfigClass` passing
+-    the specified dictionary, and then calls the :meth:`configure` method on
+-    the returned object to put the configuration into effect::
+-
+-          def dictConfig(config):
+-              dictConfigClass(config).configure()
+-
+-    For example, a subclass of :class:`DictConfigurator` could call
+-    ``DictConfigurator.__init__()`` in its own :meth:`__init__()`, then
+-    set up custom prefixes which would be usable in the subsequent
+-    :meth:`configure` call. :attr:`dictConfigClass` would be bound to
+-    this new subclass, and then :func:`dictConfig` could be called exactly as
+-    in the default, uncustomized state.
++   Takes the logging configuration from a dictionary.  The contents of
++   this dictionary are described in :ref:`logging-config-dictschema`
++   below.
++
++   If an error is encountered during configuration, this function will
++   raise a :exc:`ValueError`, :exc:`TypeError`, :exc:`AttributeError`
++   or :exc:`ImportError` with a suitably descriptive message.  The
++   following is a (possibly incomplete) list of conditions which will
++   raise an error:
++
++   * A ``level`` which is not a string or which is a string not
++     corresponding to an actual logging level.
++   * A ``propagate`` value which is not a boolean.
++   * An id which does not have a corresponding destination.
++   * A non-existent handler id found during an incremental call.
++   * An invalid logger name.
++   * Inability to resolve to an internal or external object.
++
++   Parsing is performed by the :class:`DictConfigurator` class, whose
++   constructor is passed the dictionary used for configuration, and
++   has a :meth:`configure` method.  The :mod:`logging.config` module
++   has a callable attribute :attr:`dictConfigClass`
++   which is initially set to :class:`DictConfigurator`.
++   You can replace the value of :attr:`dictConfigClass` with a
++   suitable implementation of your own.
++
++   :func:`dictConfig` calls :attr:`dictConfigClass` passing
++   the specified dictionary, and then calls the :meth:`configure` method on
++   the returned object to put the configuration into effect::
++
++         def dictConfig(config):
++             dictConfigClass(config).configure()
++
++   For example, a subclass of :class:`DictConfigurator` could call
++   ``DictConfigurator.__init__()`` in its own :meth:`__init__()`, then
++   set up custom prefixes which would be usable in the subsequent
++   :meth:`configure` call. :attr:`dictConfigClass` would be bound to
++   this new subclass, and then :func:`dictConfig` could be called exactly as
++   in the default, uncustomized state.
+    .. versionadded:: 3.2
+diff --git a/Doc/library/logging.rst b/Doc/library/logging.rst
+index 7267f812cc..e63475d3b5 100644
+--- a/Doc/library/logging.rst
++++ b/Doc/library/logging.rst
+@@ -1089,8 +1089,8 @@ functions.
+    suitable value.
+    .. versionchanged:: 3.7
+-      The *level* parameter was defaulted to level ``CRITICAL``. See Issue
+-      #28524 for more information about this change.
++      The *level* parameter was defaulted to level ``CRITICAL``. See
++      :issue:`28524` for more information about this change.
+ .. function:: addLevelName(level, levelName)
+diff --git a/Doc/library/lzma.rst b/Doc/library/lzma.rst
+index 4bfff9c614..633c87873c 100644
+--- a/Doc/library/lzma.rst
++++ b/Doc/library/lzma.rst
+@@ -33,7 +33,7 @@ from multiple threads, it is necessary to protect it with a lock.
+ Reading and writing compressed files
+ ------------------------------------
+-.. function:: open(filename, mode="rb", \*, format=None, check=-1, preset=None, filters=None, encoding=None, errors=None, newline=None)
++.. function:: open(filename, mode="rb", *, format=None, check=-1, preset=None, filters=None, encoding=None, errors=None, newline=None)
+    Open an LZMA-compressed file in binary or text mode, returning a :term:`file
+    object`.
+@@ -69,7 +69,7 @@ Reading and writing compressed files
+       Accepts a :term:`path-like object`.
+-.. class:: LZMAFile(filename=None, mode="r", \*, format=None, check=-1, preset=None, filters=None)
++.. class:: LZMAFile(filename=None, mode="r", *, format=None, check=-1, preset=None, filters=None)
+    Open an LZMA-compressed file in binary mode.
+diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst
+index ab84d39ed0..352f48f513 100644
+--- a/Doc/library/multiprocessing.rst
++++ b/Doc/library/multiprocessing.rst
+@@ -2661,6 +2661,46 @@ The :mod:`multiprocessing.dummy` module
+ :mod:`multiprocessing.dummy` replicates the API of :mod:`multiprocessing` but is
+ no more than a wrapper around the :mod:`threading` module.
++.. currentmodule:: multiprocessing.pool
++
++In particular, the ``Pool`` function provided by :mod:`multiprocessing.dummy`
++returns an instance of :class:`ThreadPool`, which is a subclass of
++:class:`Pool` that supports all the same method calls but uses a pool of
++worker threads rather than worker processes.
++
++
++.. class:: ThreadPool([processes[, initializer[, initargs]]])
++
++   A thread pool object which controls a pool of worker threads to which jobs
++   can be submitted.  :class:`ThreadPool` instances are fully interface
++   compatible with :class:`Pool` instances, and their resources must also be
++   properly managed, either by using the pool as a context manager or by
++   calling :meth:`~multiprocessing.pool.Pool.close` and
++   :meth:`~multiprocessing.pool.Pool.terminate` manually.
++
++   *processes* is the number of worker threads to use.  If *processes* is
++   ``None`` then the number returned by :func:`os.cpu_count` is used.
++
++   If *initializer* is not ``None`` then each worker process will call
++   ``initializer(*initargs)`` when it starts.
++
++   Unlike :class:`Pool`, *maxtasksperchild* and *context* cannot be provided.
++
++    .. note::
++
++        A :class:`ThreadPool` shares the same interface as :class:`Pool`, which
++        is designed around a pool of processes and predates the introduction of
++        the :class:`concurrent.futures` module.  As such, it inherits some
++        operations that don't make sense for a pool backed by threads, and it
++        has its own type for representing the status of asynchronous jobs,
++        :class:`AsyncResult`, that is not understood by any other libraries.
++
++        Users should generally prefer to use
++        :class:`concurrent.futures.ThreadPoolExecutor`, which has a simpler
++        interface that was designed around threads from the start, and which
++        returns :class:`concurrent.futures.Future` instances that are
++        compatible with many other libraries, including :mod:`asyncio`.
++
+ .. _multiprocessing-programming:
+diff --git a/Doc/library/os.rst b/Doc/library/os.rst
+index 6e287abb6f..9d206f46ae 100644
+--- a/Doc/library/os.rst
++++ b/Doc/library/os.rst
+@@ -1869,7 +1869,7 @@ features:
+       Accepts a :term:`path-like object`.
+-.. function:: lstat(path, \*, dir_fd=None)
++.. function:: lstat(path, *, dir_fd=None)
+    Perform the equivalent of an :c:func:`lstat` system call on the given path.
+    Similar to :func:`~os.stat`, but does not follow symbolic links. Return a
+@@ -2376,7 +2376,7 @@ features:
+       On the first, uncached call, a system call is required on Windows but
+       not on Unix.
+-   .. method:: is_dir(\*, follow_symlinks=True)
++   .. method:: is_dir(*, follow_symlinks=True)
+       Return ``True`` if this entry is a directory or a symbolic link pointing
+       to a directory; return ``False`` if the entry is or points to any other
+@@ -2400,7 +2400,7 @@ features:
+       This method can raise :exc:`OSError`, such as :exc:`PermissionError`,
+       but :exc:`FileNotFoundError` is caught and not raised.
+-   .. method:: is_file(\*, follow_symlinks=True)
++   .. method:: is_file(*, follow_symlinks=True)
+       Return ``True`` if this entry is a file or a symbolic link pointing to a
+       file; return ``False`` if the entry is or points to a directory or other
+@@ -2430,7 +2430,7 @@ features:
+       This method can raise :exc:`OSError`, such as :exc:`PermissionError`,
+       but :exc:`FileNotFoundError` is caught and not raised.
+-   .. method:: stat(\*, follow_symlinks=True)
++   .. method:: stat(*, follow_symlinks=True)
+       Return a :class:`stat_result` object for this entry. This method
+       follows symbolic links by default; to stat a symbolic link add the
+@@ -2462,7 +2462,7 @@ features:
+       for :class:`bytes` paths on Windows.
+-.. function:: stat(path, \*, dir_fd=None, follow_symlinks=True)
++.. function:: stat(path, *, dir_fd=None, follow_symlinks=True)
+    Get the status of a file or a file descriptor. Perform the equivalent of a
+    :c:func:`stat` system call on the given path. *path* may be specified as
+diff --git a/Doc/library/pickle.rst b/Doc/library/pickle.rst
+index b7c3452771..be48561ed1 100644
+--- a/Doc/library/pickle.rst
++++ b/Doc/library/pickle.rst
+@@ -213,7 +213,7 @@ The :mod:`pickle` module provides the following constants:
+ The :mod:`pickle` module provides the following functions to make the pickling
+ process more convenient:
+-.. function:: dump(obj, file, protocol=None, \*, fix_imports=True, buffer_callback=None)
++.. function:: dump(obj, file, protocol=None, *, fix_imports=True, buffer_callback=None)
+    Write the pickled representation of the object *obj* to the open
+    :term:`file object` *file*.  This is equivalent to
+@@ -225,7 +225,7 @@ process more convenient:
+    .. versionchanged:: 3.8
+       The *buffer_callback* argument was added.
+-.. function:: dumps(obj, protocol=None, \*, fix_imports=True, buffer_callback=None)
++.. function:: dumps(obj, protocol=None, *, fix_imports=True, buffer_callback=None)
+    Return the pickled representation of the object *obj* as a :class:`bytes` object,
+    instead of writing it to a file.
+@@ -236,7 +236,7 @@ process more convenient:
+    .. versionchanged:: 3.8
+       The *buffer_callback* argument was added.
+-.. function:: load(file, \*, fix_imports=True, encoding="ASCII", errors="strict", buffers=None)
++.. function:: load(file, *, fix_imports=True, encoding="ASCII", errors="strict", buffers=None)
+    Read the pickled representation of an object from the open :term:`file object`
+    *file* and return the reconstituted object hierarchy specified therein.
+@@ -252,7 +252,7 @@ process more convenient:
+    .. versionchanged:: 3.8
+       The *buffers* argument was added.
+-.. function:: loads(data, /, \*, fix_imports=True, encoding="ASCII", errors="strict", buffers=None)
++.. function:: loads(data, /, *, fix_imports=True, encoding="ASCII", errors="strict", buffers=None)
+    Return the reconstituted object hierarchy of the pickled representation
+    *data* of an object. *data* must be a :term:`bytes-like object`.
+@@ -296,7 +296,7 @@ The :mod:`pickle` module defines three exceptions:
+ The :mod:`pickle` module exports three classes, :class:`Pickler`,
+ :class:`Unpickler` and :class:`PickleBuffer`:
+-.. class:: Pickler(file, protocol=None, \*, fix_imports=True, buffer_callback=None)
++.. class:: Pickler(file, protocol=None, *, fix_imports=True, buffer_callback=None)
+    This takes a binary file for writing a pickle data stream.
+@@ -391,7 +391,7 @@ The :mod:`pickle` module exports three classes, :class:`Pickler`,
+       Use :func:`pickletools.optimize` if you need more compact pickles.
+-.. class:: Unpickler(file, \*, fix_imports=True, encoding="ASCII", errors="strict", buffers=None)
++.. class:: Unpickler(file, *, fix_imports=True, encoding="ASCII", errors="strict", buffers=None)
+    This takes a binary file for reading a pickle data stream.
+diff --git a/Doc/library/plistlib.rst b/Doc/library/plistlib.rst
+index 6def72b373..ce6d4a85bf 100644
+--- a/Doc/library/plistlib.rst
++++ b/Doc/library/plistlib.rst
+@@ -52,7 +52,7 @@ or :class:`datetime.datetime` objects.
+ This module defines the following functions:
+-.. function:: load(fp, \*, fmt=None, dict_type=dict)
++.. function:: load(fp, *, fmt=None, dict_type=dict)
+    Read a plist file. *fp* should be a readable and binary file object.
+    Return the unpacked root object (which usually is a
+@@ -80,7 +80,7 @@ This module defines the following functions:
+    .. versionadded:: 3.4
+-.. function:: loads(data, \*, fmt=None, dict_type=dict)
++.. function:: loads(data, *, fmt=None, dict_type=dict)
+    Load a plist from a bytes object. See :func:`load` for an explanation of
+    the keyword arguments.
+@@ -88,7 +88,7 @@ This module defines the following functions:
+    .. versionadded:: 3.4
+-.. function:: dump(value, fp, \*, fmt=FMT_XML, sort_keys=True, skipkeys=False)
++.. function:: dump(value, fp, *, fmt=FMT_XML, sort_keys=True, skipkeys=False)
+    Write *value* to a plist file. *Fp* should be a writable, binary
+    file object.
+@@ -116,7 +116,7 @@ This module defines the following functions:
+    .. versionadded:: 3.4
+-.. function:: dumps(value, \*, fmt=FMT_XML, sort_keys=True, skipkeys=False)
++.. function:: dumps(value, *, fmt=FMT_XML, sort_keys=True, skipkeys=False)
+    Return *value* as a plist-formatted bytes object. See
+    the documentation for :func:`dump` for an explanation of the keyword
+diff --git a/Doc/library/profile.rst b/Doc/library/profile.rst
+index 34525a96f5..774d46d0e9 100644
+--- a/Doc/library/profile.rst
++++ b/Doc/library/profile.rst
+@@ -525,16 +525,16 @@ Analysis of the profiler data is done using the :class:`~pstats.Stats` class.
+       ordering are identical to the :meth:`~pstats.Stats.print_callers` method.
+-    .. method:: get_stats_profile()
++   .. method:: get_stats_profile()
+       This method returns an instance of StatsProfile, which contains a mapping
+       of function names to instances of FunctionProfile. Each FunctionProfile
+       instance holds information related to the function's profile such as how
+       long the function took to run, how many times it was called, etc...
+-       .. versionadded:: 3.9
+-          Added the following dataclasses: StatsProfile, FunctionProfile.
+-          Added the following function: get_stats_profile.
++      .. versionadded:: 3.9
++         Added the following dataclasses: StatsProfile, FunctionProfile.
++         Added the following function: get_stats_profile.
+ .. _deterministic-profiling:
+diff --git a/Doc/library/pyexpat.rst b/Doc/library/pyexpat.rst
+index e43b9aecd8..034e579315 100644
+--- a/Doc/library/pyexpat.rst
++++ b/Doc/library/pyexpat.rst
+@@ -665,14 +665,14 @@ The ``errors`` module has the following attributes:
+ .. data:: codes
+-   A dictionary mapping numeric error codes to their string descriptions.
++   A dictionary mapping string descriptions to their error codes.
+    .. versionadded:: 3.2
+ .. data:: messages
+-   A dictionary mapping string descriptions to their error codes.
++   A dictionary mapping numeric error codes to their string descriptions.
+    .. versionadded:: 3.2
+diff --git a/Doc/library/random.rst b/Doc/library/random.rst
+index 8154dfc18c..0e70325125 100644
+--- a/Doc/library/random.rst
++++ b/Doc/library/random.rst
+@@ -142,10 +142,11 @@ Functions for integers
+ .. function:: getrandbits(k)
+-   Returns a Python integer with *k* random bits. This method is supplied with
+-   the MersenneTwister generator and some other generators may also provide it
+-   as an optional part of the API. When available, :meth:`getrandbits` enables
+-   :meth:`randrange` to handle arbitrarily large ranges.
++   Returns a non-negative Python integer with *k* random bits. This method
++   is supplied with the MersenneTwister generator and some other generators
++   may also provide it as an optional part of the API. When available,
++   :meth:`getrandbits` enables :meth:`randrange` to handle arbitrarily large
++   ranges.
+    .. versionchanged:: 3.9
+       This method now accepts zero for *k*.
+diff --git a/Doc/library/shutil.rst b/Doc/library/shutil.rst
+index 3f5122760e..435787c276 100644
+--- a/Doc/library/shutil.rst
++++ b/Doc/library/shutil.rst
+@@ -218,7 +218,7 @@ Directory and files operations
+       copy the file more efficiently. See
+       :ref:`shutil-platform-dependent-efficient-copy-operations` section.
+-.. function:: ignore_patterns(\*patterns)
++.. function:: ignore_patterns(*patterns)
+    This factory function creates a function that can be used as a callable for
+    :func:`copytree`\'s *ignore* argument, ignoring files and directories that
+diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst
+index faf8a76251..2fc170a0bc 100755
+--- a/Doc/library/socket.rst
++++ b/Doc/library/socket.rst
+@@ -56,12 +56,12 @@ created.  Socket addresses are represented as follows:
+   bytes-like object can be used for either type of address when
+   passing it as an argument.
+-   .. versionchanged:: 3.3
+-      Previously, :const:`AF_UNIX` socket paths were assumed to use UTF-8
+-      encoding.
++  .. versionchanged:: 3.3
++     Previously, :const:`AF_UNIX` socket paths were assumed to use UTF-8
++     encoding.
+-   .. versionchanged:: 3.5
+-      Writable :term:`bytes-like object` is now accepted.
++  .. versionchanged:: 3.5
++     Writable :term:`bytes-like object` is now accepted.
+ .. _host_port:
+diff --git a/Doc/library/sqlite3.rst b/Doc/library/sqlite3.rst
+index ccb82278bd..2e2e5e9cda 100644
+--- a/Doc/library/sqlite3.rst
++++ b/Doc/library/sqlite3.rst
+@@ -99,10 +99,6 @@ This example uses the iterator form::
+ .. seealso::
+-   https://github.com/ghaering/pysqlite
+-      The pysqlite web page -- sqlite3 is developed externally under the name
+-      "pysqlite".
+-
+    https://www.sqlite.org
+       The SQLite web page; the documentation describes the syntax and the
+       available data types for the supported SQL dialect.
+@@ -197,7 +193,9 @@ Module functions and constants
+    *detect_types* defaults to 0 (i. e. off, no type detection), you can set it to
+    any combination of :const:`PARSE_DECLTYPES` and :const:`PARSE_COLNAMES` to turn
+-   type detection on.
++   type detection on. Due to SQLite behaviour, types can't be detected for generated
++   fields (for example ``max(data)``), even when *detect_types* parameter is set. In
++   such case, the returned type is :class:`str`.
+    By default, *check_same_thread* is :const:`True` and only the creating thread may
+    use the connection. If set :const:`False`, the returned connection may be shared
+@@ -543,7 +541,7 @@ Connection Objects
+          con.close()
+-   .. method:: backup(target, *, pages=0, progress=None, name="main", sleep=0.250)
++   .. method:: backup(target, *, pages=-1, progress=None, name="main", sleep=0.250)
+       This method makes a backup of a SQLite database even while it's being accessed
+       by other clients, or concurrently by the same connection.  The copy will be
+@@ -1091,19 +1089,6 @@ committed:
+ .. literalinclude:: ../includes/sqlite3/ctx_manager.py
+-Common issues
+--------------
+-
+-Multithreading
+-^^^^^^^^^^^^^^
+-
+-Older SQLite versions had issues with sharing connections between threads.
+-That's why the Python module disallows sharing connections and cursors between
+-threads. If you still try to do so, you will get an exception at runtime.
+-
+-The only exception is calling the :meth:`~Connection.interrupt` method, which
+-only makes sense to call from a different thread.
+-
+ .. rubric:: Footnotes
+ .. [#f1] The sqlite3 module is not built with loadable extension support by
+diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst
+index a48cfa1327..0667a60157 100644
+--- a/Doc/library/stdtypes.rst
++++ b/Doc/library/stdtypes.rst
+@@ -478,7 +478,7 @@ class`. In addition, it provides a few more methods:
+     .. versionadded:: 3.1
+-.. method:: int.to_bytes(length, byteorder, \*, signed=False)
++.. method:: int.to_bytes(length, byteorder, *, signed=False)
+     Return an array of bytes representing an integer.
+@@ -510,7 +510,7 @@ class`. In addition, it provides a few more methods:
+     .. versionadded:: 3.2
+-.. classmethod:: int.from_bytes(bytes, byteorder, \*, signed=False)
++.. classmethod:: int.from_bytes(bytes, byteorder, *, signed=False)
+     Return the integer represented by the given array of bytes.
+@@ -5196,8 +5196,8 @@ types, where they are relevant.  Some of these are not reported by the
+ .. method:: class.__subclasses__
+    Each class keeps a list of weak references to its immediate subclasses.  This
+-   method returns a list of all those references still alive.
+-   Example::
++   method returns a list of all those references still alive.  The list is in
++   definition order.  Example::
+       >>> int.__subclasses__()
+       [<class 'bool'>]
+diff --git a/Doc/library/string.rst b/Doc/library/string.rst
+index 5542e9b727..54786d0c2a 100644
+--- a/Doc/library/string.rst
++++ b/Doc/library/string.rst
+@@ -514,6 +514,8 @@ The available presentation types for :class:`float` and
+    |         | this rounds the number to ``p`` significant digits and   |
+    |         | then formats the result in either fixed-point format     |
+    |         | or in scientific notation, depending on its magnitude.   |
++   |         | A precision of ``0`` is treated as equivalent to a       |
++   |         | precision of ``1``.                                      |
+    |         |                                                          |
+    |         | The precise rules are as follows: suppose that the       |
+    |         | result formatted with presentation type ``'e'`` and      |
+@@ -528,16 +530,19 @@ The available presentation types for :class:`float` and
+    |         | removed if there are no remaining digits following it,   |
+    |         | unless the ``'#'`` option is used.                       |
+    |         |                                                          |
++   |         | With no precision given, uses a precision of ``6``       |
++   |         | significant digits for :class:`float`. For               |
++   |         | :class:`~decimal.Decimal`, the coefficient of the result |
++   |         | is formed from the coefficient digits of the value;      |
++   |         | scientific notation is used for values smaller than      |
++   |         | ``1e-6`` in absolute value and values where the place    |
++   |         | value of the least significant digit is larger than 1,   |
++   |         | and fixed-point notation is used otherwise.              |
++   |         |                                                          |
+    |         | Positive and negative infinity, positive and negative    |
+    |         | zero, and nans, are formatted as ``inf``, ``-inf``,      |
+    |         | ``0``, ``-0`` and ``nan`` respectively, regardless of    |
+    |         | the precision.                                           |
+-   |         |                                                          |
+-   |         | A precision of ``0`` is treated as equivalent to a       |
+-   |         | precision of ``1``. With no precision given, uses a      |
+-   |         | precision of ``6`` significant digits for                |
+-   |         | :class:`float`, and shows all coefficient digits         |
+-   |         | for :class:`~decimal.Decimal`.                           |
+    +---------+----------------------------------------------------------+
+    | ``'G'`` | General format. Same as ``'g'`` except switches to       |
+    |         | ``'E'`` if the number gets too large. The                |
+@@ -550,12 +555,18 @@ The available presentation types for :class:`float` and
+    | ``'%'`` | Percentage. Multiplies the number by 100 and displays    |
+    |         | in fixed (``'f'``) format, followed by a percent sign.   |
+    +---------+----------------------------------------------------------+
+-   | None    | Similar to ``'g'``, except that fixed-point notation,    |
+-   |         | when used, has at least one digit past the decimal point.|
+-   |         | The default precision is as high as needed to represent  |
+-   |         | the particular value. The overall effect is to match the |
+-   |         | output of :func:`str` as altered by the other format     |
+-   |         | modifiers.                                               |
++   | None    | For :class:`float` this is the same as ``'g'``, except   |
++   |         | that when fixed-point notation is used to format the     |
++   |         | result, it always includes at least one digit past the   |
++   |         | decimal point. The precision used is as large as needed  |
++   |         | to represent the given value faithfully.                 |
++   |         |                                                          |
++   |         | For :class:`~decimal.Decimal`, this is the same as       |
++   |         | either ``'g'`` or ``'G'`` depending on the value of      |
++   |         | ``context.capitals`` for the current decimal context.    |
++   |         |                                                          |
++   |         | The overall effect is to match the output of :func:`str` |
++   |         | as altered by the other format modifiers.                |
+    +---------+----------------------------------------------------------+
+diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst
+index e37cc980e9..3150aa6070 100644
+--- a/Doc/library/subprocess.rst
++++ b/Doc/library/subprocess.rst
+@@ -339,7 +339,7 @@ functions.
+                  stderr=None, preexec_fn=None, close_fds=True, shell=False, \
+                  cwd=None, env=None, universal_newlines=None, \
+                  startupinfo=None, creationflags=0, restore_signals=True, \
+-                 start_new_session=False, pass_fds=(), \*, group=None, \
++                 start_new_session=False, pass_fds=(), *, group=None, \
+                  extra_groups=None, user=None, umask=-1, \
+                  encoding=None, errors=None, text=None)
+@@ -1163,8 +1163,9 @@ calls these functions.
+    The arguments shown above are merely some common ones.
+    The full function signature is largely the same as that of :func:`run` -
+    most arguments are passed directly through to that interface.
+-   However, explicitly passing ``input=None`` to inherit the parent's
+-   standard input file handle is not supported.
++   One API deviation from :func:`run` behavior exists: passing ``input=None``
++   will behave the same as ``input=b''`` (or ``input=''``, depending on other
++   arguments) rather than using the parent's standard input file handle.
+    By default, this function will return the data as encoded bytes. The actual
+    encoding of the output data may depend on the command being invoked, so the
+diff --git a/Doc/library/symtable.rst b/Doc/library/symtable.rst
+index 3efdecb5af..e364232247 100644
+--- a/Doc/library/symtable.rst
++++ b/Doc/library/symtable.rst
+@@ -156,6 +156,12 @@ Examining Symbol Tables
+       Return ``True`` if the symbol is local to its block.
++   .. method:: is_annotated()
++
++      Return ``True`` if the symbol is annotated.
++
++      .. versionadded:: 3.6
++
+    .. method:: is_free()
+       Return ``True`` if the symbol is referenced in its block, but not assigned
+diff --git a/Doc/library/sysconfig.rst b/Doc/library/sysconfig.rst
+index 78a1dfce9a..c9306e9bf9 100644
+--- a/Doc/library/sysconfig.rst
++++ b/Doc/library/sysconfig.rst
+@@ -32,7 +32,7 @@ can be accessed using :func:`get_config_vars` or :func:`get_config_var`.
+ Notice that on Windows, it's a much smaller set.
+-.. function:: get_config_vars(\*args)
++.. function:: get_config_vars(*args)
+    With no arguments, return a dictionary of all configuration variables
+    relevant for the current platform.
+diff --git a/Doc/library/tarfile.rst b/Doc/library/tarfile.rst
+index 7a114fdf5d..13088a10d7 100644
+--- a/Doc/library/tarfile.rst
++++ b/Doc/library/tarfile.rst
+@@ -37,7 +37,7 @@ Some facts and figures:
+    Added support for :mod:`lzma` compression.
+-.. function:: open(name=None, mode='r', fileobj=None, bufsize=10240, \*\*kwargs)
++.. function:: open(name=None, mode='r', fileobj=None, bufsize=10240, **kwargs)
+    Return a :class:`TarFile` object for the pathname *name*. For detailed
+    information on :class:`TarFile` objects and the keyword arguments that are
+diff --git a/Doc/library/test.rst b/Doc/library/test.rst
+index e24f69cda8..bb1bd29bf6 100644
+--- a/Doc/library/test.rst
++++ b/Doc/library/test.rst
+@@ -546,7 +546,7 @@ The :mod:`test.support` module defines the following functions:
+    Define match test with regular expression *patterns*.
+-.. function:: run_unittest(\*classes)
++.. function:: run_unittest(*classes)
+    Execute :class:`unittest.TestCase` subclasses passed to the function. The
+    function scans the classes for methods starting with the prefix ``test_``
+diff --git a/Doc/library/trace.rst b/Doc/library/trace.rst
+index c2732d900b..40cf198f12 100644
+--- a/Doc/library/trace.rst
++++ b/Doc/library/trace.rst
+@@ -153,47 +153,47 @@ Programmatic Interface
+    count information.  *timing* enables a timestamp relative to when tracing was
+    started to be displayed.
+-    .. method:: run(cmd)
++   .. method:: run(cmd)
+-       Execute the command and gather statistics from the execution with
+-       the current tracing parameters.  *cmd* must be a string or code object,
+-       suitable for passing into :func:`exec`.
++      Execute the command and gather statistics from the execution with
++      the current tracing parameters.  *cmd* must be a string or code object,
++      suitable for passing into :func:`exec`.
+-    .. method:: runctx(cmd, globals=None, locals=None)
++   .. method:: runctx(cmd, globals=None, locals=None)
+-       Execute the command and gather statistics from the execution with the
+-       current tracing parameters, in the defined global and local
+-       environments.  If not defined, *globals* and *locals* default to empty
+-       dictionaries.
++      Execute the command and gather statistics from the execution with the
++      current tracing parameters, in the defined global and local
++      environments.  If not defined, *globals* and *locals* default to empty
++      dictionaries.
+-    .. method:: runfunc(func, /, *args, **kwds)
++   .. method:: runfunc(func, /, *args, **kwds)
+-       Call *func* with the given arguments under control of the :class:`Trace`
+-       object with the current tracing parameters.
++      Call *func* with the given arguments under control of the :class:`Trace`
++      object with the current tracing parameters.
+-    .. method:: results()
++   .. method:: results()
+-       Return a :class:`CoverageResults` object that contains the cumulative
+-       results of all previous calls to ``run``, ``runctx`` and ``runfunc``
+-       for the given :class:`Trace` instance.  Does not reset the accumulated
+-       trace results.
++      Return a :class:`CoverageResults` object that contains the cumulative
++      results of all previous calls to ``run``, ``runctx`` and ``runfunc``
++      for the given :class:`Trace` instance.  Does not reset the accumulated
++      trace results.
+ .. class:: CoverageResults
+    A container for coverage results, created by :meth:`Trace.results`.  Should
+    not be created directly by the user.
+-    .. method:: update(other)
++   .. method:: update(other)
+-       Merge in data from another :class:`CoverageResults` object.
++      Merge in data from another :class:`CoverageResults` object.
+-    .. method:: write_results(show_missing=True, summary=False, coverdir=None)
++   .. method:: write_results(show_missing=True, summary=False, coverdir=None)
+-       Write coverage results.  Set *show_missing* to show lines that had no
+-       hits.  Set *summary* to include in the output the coverage summary per
+-       module.  *coverdir* specifies the directory into which the coverage
+-       result files will be output.  If ``None``, the results for each source
+-       file are placed in its directory.
++      Write coverage results.  Set *show_missing* to show lines that had no
++      hits.  Set *summary* to include in the output the coverage summary per
++      module.  *coverdir* specifies the directory into which the coverage
++      result files will be output.  If ``None``, the results for each source
++      file are placed in its directory.
+ A simple example demonstrating the use of the programmatic interface::
+diff --git a/Doc/library/turtle.rst b/Doc/library/turtle.rst
+index d3487537df..6a9d61916a 100644
+--- a/Doc/library/turtle.rst
++++ b/Doc/library/turtle.rst
+@@ -662,7 +662,7 @@ Tell Turtle's state
+    Return the angle between the line from turtle position to position specified
+    by (x,y), the vector or the other turtle.  This depends on the turtle's start
+-   orientation which depends on the mode - "standard"/"world" or "logo").
++   orientation which depends on the mode - "standard"/"world" or "logo".
+    .. doctest::
+       :skipif: _tkinter is None
+@@ -913,8 +913,8 @@ Color control
+       Set pencolor to the RGB color represented by *r*, *g*, and *b*.  Each of
+       *r*, *g*, and *b* must be in the range 0..colormode.
+-    If turtleshape is a polygon, the outline of that polygon is drawn with the
+-    newly set pencolor.
++   If turtleshape is a polygon, the outline of that polygon is drawn with the
++   newly set pencolor.
+    .. doctest::
+       :skipif: _tkinter is None
+@@ -962,8 +962,8 @@ Color control
+       Set fillcolor to the RGB color represented by *r*, *g*, and *b*.  Each of
+       *r*, *g*, and *b* must be in the range 0..colormode.
+-    If turtleshape is a polygon, the interior of that polygon is drawn
+-    with the newly set fillcolor.
++   If turtleshape is a polygon, the interior of that polygon is drawn
++   with the newly set fillcolor.
+    .. doctest::
+       :skipif: _tkinter is None
+@@ -1001,8 +1001,8 @@ Color control
+       Equivalent to ``pencolor(colorstring1)`` and ``fillcolor(colorstring2)``
+       and analogously if the other input format is used.
+-    If turtleshape is a polygon, outline and interior of that polygon is drawn
+-    with the newly set colors.
++   If turtleshape is a polygon, outline and interior of that polygon is drawn
++   with the newly set colors.
+    .. doctest::
+       :skipif: _tkinter is None
+@@ -1105,7 +1105,7 @@ More drawing control
+    :param font: a triple (fontname, fontsize, fonttype)
+    Write text - the string representation of *arg* - at the current turtle
+-   position according to *align* ("left", "center" or right") and with the given
++   position according to *align* ("left", "center" or "right") and with the given
+    font.  If *move* is true, the pen is moved to the bottom-right corner of the
+    text.  By default, *move* is ``False``.
+@@ -1192,7 +1192,7 @@ Appearance
+      :func:`shapesize`.
+    - "noresize": no adaption of the turtle's appearance takes place.
+-   resizemode("user") is called by :func:`shapesize` when used with arguments.
++   ``resizemode("user")`` is called by :func:`shapesize` when used with arguments.
+    .. doctest::
+       :skipif: _tkinter is None
+@@ -1330,7 +1330,7 @@ Appearance
+    matrix as a tuple of 4 elements.
+    Otherwise set the given elements and transform the turtleshape
+    according to the matrix consisting of first row t11, t12 and
+-   second row t21, 22. The determinant t11 * t22 - t12 * t21 must not be
++   second row t21, t22. The determinant t11 * t22 - t12 * t21 must not be
+    zero, otherwise an error is raised.
+    Modify stretchfactor, shearfactor and tiltangle according to the
+    given matrix.
+@@ -1513,7 +1513,7 @@ Special Turtle methods
+    :param size: an integer or ``None``
+-   Set or disable undobuffer.  If *size* is an integer an empty undobuffer of
++   Set or disable undobuffer.  If *size* is an integer, an empty undobuffer of
+    given size is installed.  *size* gives the maximum number of turtle actions
+    that can be undone by the :func:`undo` method/function.  If *size* is
+    ``None``, the undobuffer is disabled.
+@@ -1821,7 +1821,7 @@ Using screen events
+    existing bindings are removed.
+    Example for a TurtleScreen instance named ``screen`` and a Turtle instance
+-   named turtle:
++   named ``turtle``:
+    .. doctest::
+       :skipif: _tkinter is None
+@@ -2048,7 +2048,7 @@ Methods specific to Screen, not inherited from TurtleScreen
+ .. function:: exitonclick()
+-   Bind bye() method to mouse clicks on the Screen.
++   Bind ``bye()`` method to mouse clicks on the Screen.
+    If the value "using_IDLE" in the configuration dictionary is ``False``
+diff --git a/Doc/library/types.rst b/Doc/library/types.rst
+index 0fe3822fa5..d83d9667ba 100644
+--- a/Doc/library/types.rst
++++ b/Doc/library/types.rst
+@@ -260,6 +260,9 @@ Standard names are defined for the following types:
+    .. versionadded:: 3.9
++   .. versionchanged:: 3.9.2
++      This type can now be subclassed.
++
+ .. class:: TracebackType(tb_next, tb_frame, tb_lasti, tb_lineno)
+diff --git a/Doc/library/warnings.rst b/Doc/library/warnings.rst
+index a481a3509d..9c1743cad2 100644
+--- a/Doc/library/warnings.rst
++++ b/Doc/library/warnings.rst
+@@ -491,7 +491,7 @@ Available Functions
+ Available Context Managers
+ --------------------------
+-.. class:: catch_warnings(\*, record=False, module=None)
++.. class:: catch_warnings(*, record=False, module=None)
+     A context manager that copies and, upon exit, restores the warnings filter
+     and the :func:`showwarning` function.
+diff --git a/Doc/library/winreg.rst b/Doc/library/winreg.rst
+index dccb7db27e..487856a3ac 100644
+--- a/Doc/library/winreg.rst
++++ b/Doc/library/winreg.rst
+@@ -791,7 +791,7 @@ integer handle, and also disconnect the Windows handle from the handle object.
+ .. method:: PyHKEY.__enter__()
+-            PyHKEY.__exit__(\*exc_info)
++            PyHKEY.__exit__(*exc_info)
+    The HKEY object implements :meth:`~object.__enter__` and
+    :meth:`~object.__exit__` and thus supports the context protocol for the
+diff --git a/Doc/license.rst b/Doc/license.rst
+index 4030825bbd..f487d98b2b 100644
+--- a/Doc/license.rst
++++ b/Doc/license.rst
+@@ -100,7 +100,7 @@ PSF LICENSE AGREEMENT FOR PYTHON |release|
+       analyze, test, perform and/or display publicly, prepare derivative works,
+       distribute, and otherwise use Python |release| alone or in any derivative
+       version, provided, however, that PSF's License Agreement and PSF's notice of
+-      copyright, i.e., "Copyright Â© 2001-2020 Python Software Foundation; All Rights
++      copyright, i.e., "Copyright Â© 2001-2021 Python Software Foundation; All Rights
+       Reserved" are retained in Python |release| alone or in any derivative version
+       prepared by Licensee.
+diff --git a/Doc/reference/compound_stmts.rst b/Doc/reference/compound_stmts.rst
+index b4e06e5b10..7e666351b1 100644
+--- a/Doc/reference/compound_stmts.rst
++++ b/Doc/reference/compound_stmts.rst
+@@ -254,7 +254,8 @@ present, must be last; it matches any exception.  For an except clause with an
+ expression, that expression is evaluated, and the clause matches the exception
+ if the resulting object is "compatible" with the exception.  An object is
+ compatible with an exception if it is the class or a base class of the exception
+-object or a tuple containing an item compatible with the exception.
++object, or a tuple containing an item that is the class or a base class of
++the exception object.
+ If no except clause matches the exception, the search for an exception handler
+ continues in the surrounding code and on the invocation stack.  [#]_
+@@ -799,12 +800,12 @@ The :keyword:`!async for` statement
+ .. productionlist:: python-grammar
+    async_for_stmt: "async" `for_stmt`
+-An :term:`asynchronous iterable` is able to call asynchronous code in its
+-*iter* implementation, and :term:`asynchronous iterator` can call asynchronous
+-code in its *next* method.
++An :term:`asynchronous iterable` provides an ``__aiter__`` method that directly
++returns an :term:`asynchronous iterator`, which can call asynchronous code in
++its ``__anext__`` method.
+ The ``async for`` statement allows convenient iteration over asynchronous
+-iterators.
++iterables.
+ The following code::
+diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst
+index 89063876cc..3b3bd5524e 100644
+--- a/Doc/reference/datamodel.rst
++++ b/Doc/reference/datamodel.rst
+@@ -217,7 +217,6 @@ Ellipsis
+       There are two types of integers:
+       Integers (:class:`int`)
+-
+          These represent numbers in an unlimited range, subject to available (virtual)
+          memory only.  For the purpose of shift and mask operations, a binary
+          representation is assumed, and negative numbers are represented in a variant of
+diff --git a/Doc/using/venv-create.inc b/Doc/using/venv-create.inc
+index 5e724cd579..ddb36f9466 100644
+--- a/Doc/using/venv-create.inc
++++ b/Doc/using/venv-create.inc
+@@ -126,6 +126,10 @@ directory containing the virtual environment):
+ |             | PowerShell      | PS C:\\> <venv>\\Scripts\\Activate.ps1  |
+ +-------------+-----------------+-----------------------------------------+
++When a virtual environment is active, the :envvar:`VIRTUAL_ENV` environment
++variable is set to the path of the virtual environment. This can be used to
++check if one is running inside a virtual environment.
++
+ You don't specifically *need* to activate an environment; activation just
+ prepends the virtual environment's binary directory to your path, so that
+ "python" invokes the virtual environment's Python interpreter and you can run
+diff --git a/Doc/using/windows.rst b/Doc/using/windows.rst
+index d0c342e1da..857308e77d 100644
+--- a/Doc/using/windows.rst
++++ b/Doc/using/windows.rst
+@@ -339,6 +339,11 @@ full write access to shared locations such as ``TEMP`` and the registry.
+ Instead, it will write to a private copy. If your scripts must modify the
+ shared locations, you will need to install the full installer.
++For more detail on the technical basis for these limitations, please consult
++Microsoft's documentation on packaged full-trust apps, currently available at
++`docs.microsoft.com/en-us/windows/msix/desktop/desktop-to-uwp-behind-the-scenes
++<https://docs.microsoft.com/en-us/windows/msix/desktop/desktop-to-uwp-behind-the-scenes>`_
++
+ .. _windows-nuget:
+diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst
+index f8f421bdda..68b1e504da 100644
+--- a/Doc/whatsnew/3.9.rst
++++ b/Doc/whatsnew/3.9.rst
+@@ -1497,3 +1497,22 @@ functions and options conditionally available based on the operating system
+ version in use at runtime ("weaklinking").
+ (Contributed by Ronald Oussoren and Lawrence D'Anna in :issue:`41100`.)
++
++Notable changes in Python 3.9.2
++===============================
++
++collections.abc
++---------------
++
++:class:`collections.abc.Callable` generic now flattens type parameters, similar
++to what :data:`typing.Callable` currently does.  This means that
++``collections.abc.Callable[[int, str], str]`` will have ``__args__`` of
++``(int, str, str)``; previously this was ``([int, str], str)``.  To allow this
++change, :class:`types.GenericAlias` can now be subclassed, and a subclass will
++be returned when subscripting the :class:`collections.abc.Callable` type.
++Code which accesses the arguments via :func:`typing.get_args` or ``__args__``
++need to account for this change.  A :exc:`DeprecationWarning` may be emitted for
++invalid forms of parameterizing :class:`collections.abc.Callable` which may have
++passed silently in Python 3.9.1.  This :exc:`DeprecationWarning` will
++become a :exc:`TypeError` in Python 3.10.
++(Contributed by Ken Jin in :issue:`42195`.)
+diff --git a/Grammar/python.gram b/Grammar/python.gram
+index ce78397196..64e205e7fd 100644
+--- a/Grammar/python.gram
++++ b/Grammar/python.gram
+@@ -563,18 +563,23 @@ star_targets[expr_ty]:
+     | a=star_target !',' { a }
+     | a=star_target b=(',' c=star_target { c })* [','] {
+         _Py_Tuple(CHECK(_PyPegen_seq_insert_in_front(p, a, b)), Store, EXTRA) }
+-star_targets_seq[asdl_seq*]: a=','.star_target+ [','] { a }
++star_targets_list_seq[asdl_seq*]: a=','.star_target+ [','] { a }
++star_targets_tuple_seq[asdl_seq*]:
++    | a=star_target b=(',' c=star_target { c })+ [','] { _PyPegen_seq_insert_in_front(p, a, b) }
++    | a=star_target ',' { _PyPegen_singleton_seq(p, a) }
+ star_target[expr_ty] (memo):
+     | '*' a=(!'*' star_target) {
+         _Py_Starred(CHECK(_PyPegen_set_expr_context(p, a, Store)), Store, EXTRA) }
++    | target_with_star_atom
++target_with_star_atom[expr_ty] (memo):
+     | a=t_primary '.' b=NAME !t_lookahead { _Py_Attribute(a, b->v.Name.id, Store, EXTRA) }
+     | a=t_primary '[' b=slices ']' !t_lookahead { _Py_Subscript(a, b, Store, EXTRA) }
+     | star_atom
+ star_atom[expr_ty]:
+     | a=NAME { _PyPegen_set_expr_context(p, a, Store) }
+-    | '(' a=star_target ')' { _PyPegen_set_expr_context(p, a, Store) }
+-    | '(' a=[star_targets_seq] ')' { _Py_Tuple(a, Store, EXTRA) }
+-    | '[' a=[star_targets_seq] ']' { _Py_List(a, Store, EXTRA) }
++    | '(' a=target_with_star_atom ')' { _PyPegen_set_expr_context(p, a, Store) }
++    | '(' a=[star_targets_tuple_seq] ')' { _Py_Tuple(a, Store, EXTRA) }
++    | '[' a=[star_targets_list_seq] ']' { _Py_List(a, Store, EXTRA) }
+ single_target[expr_ty]:
+     | single_subscript_attribute_target
+diff --git a/Include/cpython/abstract.h b/Include/cpython/abstract.h
+index 7bc80833a7..0f1304d26a 100644
+--- a/Include/cpython/abstract.h
++++ b/Include/cpython/abstract.h
+@@ -67,7 +67,7 @@ PyVectorcall_Function(PyObject *callable)
+ {
+     PyTypeObject *tp;
+     Py_ssize_t offset;
+-    vectorcallfunc *ptr;
++    vectorcallfunc ptr;
+     assert(callable != NULL);
+     tp = Py_TYPE(callable);
+@@ -77,8 +77,8 @@ PyVectorcall_Function(PyObject *callable)
+     assert(PyCallable_Check(callable));
+     offset = tp->tp_vectorcall_offset;
+     assert(offset > 0);
+-    ptr = (vectorcallfunc *)(((char *)callable) + offset);
+-    return *ptr;
++    memcpy(&ptr, (char *) callable + offset, sizeof(ptr));
++    return ptr;
+ }
+ /* Call the callable object 'callable' with the "vectorcall" calling
+diff --git a/Include/cpython/unicodeobject.h b/Include/cpython/unicodeobject.h
+index 1fc732abeb..17db79cffb 100644
+--- a/Include/cpython/unicodeobject.h
++++ b/Include/cpython/unicodeobject.h
+@@ -22,7 +22,7 @@ extern "C" {
+  */
+ #define Py_UNICODE_ISSPACE(ch) \
+-    ((ch) < 128U ? _Py_ascii_whitespace[(ch)] : _PyUnicode_IsWhitespace(ch))
++    ((Py_UCS4)(ch) < 128U ? _Py_ascii_whitespace[(ch)] : _PyUnicode_IsWhitespace(ch))
+ #define Py_UNICODE_ISLOWER(ch) _PyUnicode_IsLowercase(ch)
+ #define Py_UNICODE_ISUPPER(ch) _PyUnicode_IsUppercase(ch)
+@@ -760,13 +760,6 @@ PyAPI_FUNC(const char *) PyUnicode_AsUTF8AndSize(
+    Use of this API is DEPRECATED since no size information can be
+    extracted from the returned data.
+-
+-   *** This API is for interpreter INTERNAL USE ONLY and will likely
+-   *** be removed or changed for Python 3.1.
+-
+-   *** If you need to access the Unicode object as UTF-8 bytes string,
+-   *** please use PyUnicode_AsUTF8String() instead.
+-
+ */
+ PyAPI_FUNC(const char *) PyUnicode_AsUTF8(PyObject *unicode);
+diff --git a/Include/patchlevel.h b/Include/patchlevel.h
+index 0b5d280bd4..253421378b 100644
+--- a/Include/patchlevel.h
++++ b/Include/patchlevel.h
+@@ -23,7 +23,7 @@
+ #define PY_RELEASE_SERIAL       0
+ /* Version as a string */
+-#define PY_VERSION              "3.9.1"
++#define PY_VERSION              "3.9.1+"
+ /*--end constants--*/
+ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2.
+diff --git a/Include/pylifecycle.h b/Include/pylifecycle.h
+index c5368b3c5e..783fcb455e 100644
+--- a/Include/pylifecycle.h
++++ b/Include/pylifecycle.h
+@@ -32,6 +32,8 @@ PyAPI_FUNC(void) _Py_NO_RETURN Py_Exit(int);
+ /* Bootstrap __main__ (defined in Modules/main.c) */
+ PyAPI_FUNC(int) Py_Main(int argc, wchar_t **argv);
++PyAPI_FUNC(int) Py_FrozenMain(int argc, char **argv);
++
+ PyAPI_FUNC(int) Py_BytesMain(int argc, char **argv);
+ /* In pathconfig.c */
+diff --git a/LICENSE b/LICENSE
+index f42f8adbed..473861da1b 100644
+--- a/LICENSE
++++ b/LICENSE
+@@ -84,7 +84,7 @@ analyze, test, perform and/or display publicly, prepare derivative works,
+ distribute, and otherwise use Python alone or in any derivative version,
+ provided, however, that PSF's License Agreement and PSF's notice of copyright,
+ i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+-2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Python Software Foundation;
++2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Python Software Foundation;
+ All Rights Reserved" are retained in Python alone or in any derivative version
+ prepared by Licensee.
+diff --git a/Lib/_collections_abc.py b/Lib/_collections_abc.py
+index 36cd993000..b6ecf8eac6 100644
+--- a/Lib/_collections_abc.py
++++ b/Lib/_collections_abc.py
+@@ -10,6 +10,10 @@ from abc import ABCMeta, abstractmethod
+ import sys
+ GenericAlias = type(list[int])
++EllipsisType = type(...)
++def _f(): pass
++FunctionType = type(_f)
++del _f
+ __all__ = ["Awaitable", "Coroutine",
+            "AsyncIterable", "AsyncIterator", "AsyncGenerator",
+@@ -409,6 +413,86 @@ class Collection(Sized, Iterable, Container):
+         return NotImplemented
++class _CallableGenericAlias(GenericAlias):
++    """ Represent `Callable[argtypes, resulttype]`.
++
++    This sets ``__args__`` to a tuple containing the flattened``argtypes``
++    followed by ``resulttype``.
++
++    Example: ``Callable[[int, str], float]`` sets ``__args__`` to
++    ``(int, str, float)``.
++    """
++
++    __slots__ = ()
++
++    def __new__(cls, origin, args):
++        try:
++            return cls.__create_ga(origin, args)
++        except TypeError as exc:
++            import warnings
++            warnings.warn(f'{str(exc)} '
++                          f'(This will raise a TypeError in Python 3.10.)',
++                          DeprecationWarning)
++            return GenericAlias(origin, args)
++
++    @classmethod
++    def __create_ga(cls, origin, args):
++        if not isinstance(args, tuple) or len(args) != 2:
++            raise TypeError(
++                "Callable must be used as Callable[[arg, ...], result].")
++        t_args, t_result = args
++        if isinstance(t_args, (list, tuple)):
++            ga_args = tuple(t_args) + (t_result,)
++        # This relaxes what t_args can be on purpose to allow things like
++        # PEP 612 ParamSpec.  Responsibility for whether a user is using
++        # Callable[...] properly is deferred to static type checkers.
++        else:
++            ga_args = args
++        return super().__new__(cls, origin, ga_args)
++
++    def __repr__(self):
++        if len(self.__args__) == 2 and self.__args__[0] is Ellipsis:
++            return super().__repr__()
++        return (f'collections.abc.Callable'
++                f'[[{", ".join([_type_repr(a) for a in self.__args__[:-1]])}], '
++                f'{_type_repr(self.__args__[-1])}]')
++
++    def __reduce__(self):
++        args = self.__args__
++        if not (len(args) == 2 and args[0] is Ellipsis):
++            args = list(args[:-1]), args[-1]
++        return _CallableGenericAlias, (Callable, args)
++
++    def __getitem__(self, item):
++        # Called during TypeVar substitution, returns the custom subclass
++        # rather than the default types.GenericAlias object.
++        ga = super().__getitem__(item)
++        args = ga.__args__
++        t_result = args[-1]
++        t_args = args[:-1]
++        args = (t_args, t_result)
++        return _CallableGenericAlias(Callable, args)
++
++
++def _type_repr(obj):
++    """Return the repr() of an object, special-casing types (internal helper).
++
++    Copied from :mod:`typing` since collections.abc
++    shouldn't depend on that module.
++    """
++    if isinstance(obj, GenericAlias):
++        return repr(obj)
++    if isinstance(obj, type):
++        if obj.__module__ == 'builtins':
++            return obj.__qualname__
++        return f'{obj.__module__}.{obj.__qualname__}'
++    if obj is Ellipsis:
++        return '...'
++    if isinstance(obj, FunctionType):
++        return obj.__name__
++    return repr(obj)
++
++
+ class Callable(metaclass=ABCMeta):
+     __slots__ = ()
+@@ -423,7 +507,7 @@ class Callable(metaclass=ABCMeta):
+             return _check_methods(C, "__call__")
+         return NotImplemented
+-    __class_getitem__ = classmethod(GenericAlias)
++    __class_getitem__ = classmethod(_CallableGenericAlias)
+ ### SETS ###
+diff --git a/Lib/asyncio/tasks.py b/Lib/asyncio/tasks.py
+index f486b67229..d6262ae75e 100644
+--- a/Lib/asyncio/tasks.py
++++ b/Lib/asyncio/tasks.py
+@@ -471,7 +471,10 @@ async def wait_for(fut, timeout, *, loop=None):
+                 return fut.result()
+             else:
+                 fut.remove_done_callback(cb)
+-                fut.cancel()
++                # We must ensure that the task is not running
++                # after wait_for() returns.
++                # See https://bugs.python.org/issue32751
++                await _cancel_and_wait(fut, loop=loop)
+                 raise
+         if fut.done():
+diff --git a/Lib/asyncio/unix_events.py b/Lib/asyncio/unix_events.py
+index f34a5b4b44..3efa6698b8 100644
+--- a/Lib/asyncio/unix_events.py
++++ b/Lib/asyncio/unix_events.py
+@@ -1230,13 +1230,15 @@ class MultiLoopChildWatcher(AbstractChildWatcher):
+     def close(self):
+         self._callbacks.clear()
+-        if self._saved_sighandler is not None:
+-            handler = signal.getsignal(signal.SIGCHLD)
+-            if handler != self._sig_chld:
+-                logger.warning("SIGCHLD handler was changed by outside code")
+-            else:
+-                signal.signal(signal.SIGCHLD, self._saved_sighandler)
+-            self._saved_sighandler = None
++        if self._saved_sighandler is None:
++            return
++
++        handler = signal.getsignal(signal.SIGCHLD)
++        if handler != self._sig_chld:
++            logger.warning("SIGCHLD handler was changed by outside code")
++        else:
++            signal.signal(signal.SIGCHLD, self._saved_sighandler)
++        self._saved_sighandler = None
+     def __enter__(self):
+         return self
+@@ -1263,15 +1265,17 @@ class MultiLoopChildWatcher(AbstractChildWatcher):
+         # The reason to do it here is that attach_loop() is called from
+         # unix policy only for the main thread.
+         # Main thread is required for subscription on SIGCHLD signal
++        if self._saved_sighandler is not None:
++            return
++
++        self._saved_sighandler = signal.signal(signal.SIGCHLD, self._sig_chld)
+         if self._saved_sighandler is None:
+-            self._saved_sighandler = signal.signal(signal.SIGCHLD, self._sig_chld)
+-            if self._saved_sighandler is None:
+-                logger.warning("Previous SIGCHLD handler was set by non-Python code, "
+-                               "restore to default handler on watcher close.")
+-                self._saved_sighandler = signal.SIG_DFL
++            logger.warning("Previous SIGCHLD handler was set by non-Python code, "
++                           "restore to default handler on watcher close.")
++            self._saved_sighandler = signal.SIG_DFL
+-            # Set SA_RESTART to limit EINTR occurrences.
+-            signal.siginterrupt(signal.SIGCHLD, False)
++        # Set SA_RESTART to limit EINTR occurrences.
++        signal.siginterrupt(signal.SIGCHLD, False)
+     def _do_waitpid_all(self):
+         for pid in list(self._callbacks):
+diff --git a/Lib/base64.py b/Lib/base64.py
+index a28109f8a7..ec3823b724 100755
+--- a/Lib/base64.py
++++ b/Lib/base64.py
+@@ -320,7 +320,7 @@ def a85encode(b, *, foldspaces=False, wrapcol=0, pad=False, adobe=False):
+     global _a85chars, _a85chars2
+     # Delay the initialization of tables to not waste memory
+     # if the function is never called
+-    if _a85chars is None:
++    if _a85chars2 is None:
+         _a85chars = [bytes((i,)) for i in range(33, 118)]
+         _a85chars2 = [(a + b) for a in _a85chars for b in _a85chars]
+@@ -428,7 +428,7 @@ def b85encode(b, pad=False):
+     global _b85chars, _b85chars2
+     # Delay the initialization of tables to not waste memory
+     # if the function is never called
+-    if _b85chars is None:
++    if _b85chars2 is None:
+         _b85chars = [bytes((i,)) for i in _b85alphabet]
+         _b85chars2 = [(a + b) for a in _b85chars for b in _b85chars]
+     return _85encode(b, _b85chars, _b85chars2, pad)
+diff --git a/Lib/cProfile.py b/Lib/cProfile.py
+index 59b4699feb..22a7d0aade 100755
+--- a/Lib/cProfile.py
++++ b/Lib/cProfile.py
+@@ -175,7 +175,12 @@ def main():
+                 '__package__': None,
+                 '__cached__': None,
+             }
+-        runctx(code, globs, None, options.outfile, options.sort)
++        try:
++            runctx(code, globs, None, options.outfile, options.sort)
++        except BrokenPipeError as exc:
++            # Prevent "Exception ignored" during interpreter shutdown.
++            sys.stdout = None
++            sys.exit(exc.errno)
+     else:
+         parser.print_usage()
+     return parser
+diff --git a/Lib/codecs.py b/Lib/codecs.py
+index 7f23e9775d..d2edd148a2 100644
+--- a/Lib/codecs.py
++++ b/Lib/codecs.py
+@@ -386,7 +386,7 @@ class StreamWriter(Codec):
+     def reset(self):
+-        """ Flushes and resets the codec buffers used for keeping state.
++        """ Resets the codec buffers used for keeping internal state.
+             Calling this method should ensure that the data on the
+             output is put into a clean state, that allows appending
+@@ -620,7 +620,7 @@ class StreamReader(Codec):
+     def reset(self):
+-        """ Resets the codec buffers used for keeping state.
++        """ Resets the codec buffers used for keeping internal state.
+             Note that no stream repositioning should take place.
+             This method is primarily intended to be able to recover
+diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py
+index bc69a6757f..5bdd3b3516 100644
+--- a/Lib/collections/__init__.py
++++ b/Lib/collections/__init__.py
+@@ -424,7 +424,7 @@ def namedtuple(typename, field_names, *, rename=False, defaults=None, module=Non
+     namespace = {
+         '_tuple_new': tuple_new,
+-        '__builtins__': None,
++        '__builtins__': {},
+         '__name__': f'namedtuple_{typename}',
+     }
+     code = f'lambda _cls, {arg_list}: _tuple_new(_cls, ({arg_list}))'
+diff --git a/Lib/collections/abc.py b/Lib/collections/abc.py
+index 891600d16b..86ca8b8a84 100644
+--- a/Lib/collections/abc.py
++++ b/Lib/collections/abc.py
+@@ -1,2 +1,3 @@
+ from _collections_abc import *
+ from _collections_abc import __all__
++from _collections_abc import _CallableGenericAlias
+diff --git a/Lib/ctypes/test/test_parameters.py b/Lib/ctypes/test/test_parameters.py
+index e4c25fd880..38af7ac13d 100644
+--- a/Lib/ctypes/test/test_parameters.py
++++ b/Lib/ctypes/test/test_parameters.py
+@@ -201,6 +201,49 @@ class SimpleTypesTestCase(unittest.TestCase):
+         with self.assertRaises(ZeroDivisionError):
+             WorseStruct().__setstate__({}, b'foo')
++    def test_parameter_repr(self):
++        from ctypes import (
++            c_bool,
++            c_char,
++            c_wchar,
++            c_byte,
++            c_ubyte,
++            c_short,
++            c_ushort,
++            c_int,
++            c_uint,
++            c_long,
++            c_ulong,
++            c_longlong,
++            c_ulonglong,
++            c_float,
++            c_double,
++            c_longdouble,
++            c_char_p,
++            c_wchar_p,
++            c_void_p,
++        )
++        self.assertRegex(repr(c_bool.from_param(True)), r"^<cparam '\?' at 0x[A-Fa-f0-9]+>$")
++        self.assertEqual(repr(c_char.from_param(97)), "<cparam 'c' ('a')>")
++        self.assertRegex(repr(c_wchar.from_param('a')), r"^<cparam 'u' at 0x[A-Fa-f0-9]+>$")
++        self.assertEqual(repr(c_byte.from_param(98)), "<cparam 'b' (98)>")
++        self.assertEqual(repr(c_ubyte.from_param(98)), "<cparam 'B' (98)>")
++        self.assertEqual(repr(c_short.from_param(511)), "<cparam 'h' (511)>")
++        self.assertEqual(repr(c_ushort.from_param(511)), "<cparam 'H' (511)>")
++        self.assertRegex(repr(c_int.from_param(20000)), r"^<cparam '[li]' \(20000\)>$")
++        self.assertRegex(repr(c_uint.from_param(20000)), r"^<cparam '[LI]' \(20000\)>$")
++        self.assertRegex(repr(c_long.from_param(20000)), r"^<cparam '[li]' \(20000\)>$")
++        self.assertRegex(repr(c_ulong.from_param(20000)), r"^<cparam '[LI]' \(20000\)>$")
++        self.assertRegex(repr(c_longlong.from_param(20000)), r"^<cparam '[liq]' \(20000\)>$")
++        self.assertRegex(repr(c_ulonglong.from_param(20000)), r"^<cparam '[LIQ]' \(20000\)>$")
++        self.assertEqual(repr(c_float.from_param(1.5)), "<cparam 'f' (1.5)>")
++        self.assertEqual(repr(c_double.from_param(1.5)), "<cparam 'd' (1.5)>")
++        self.assertEqual(repr(c_double.from_param(1e300)), "<cparam 'd' (1e+300)>")
++        self.assertRegex(repr(c_longdouble.from_param(1.5)), r"^<cparam ('d' \(1.5\)|'g' at 0x[A-Fa-f0-9]+)>$")
++        self.assertRegex(repr(c_char_p.from_param(b'hihi')), r"^<cparam 'z' \(0x[A-Fa-f0-9]+\)>$")
++        self.assertRegex(repr(c_wchar_p.from_param('hihi')), r"^<cparam 'Z' \(0x[A-Fa-f0-9]+\)>$")
++        self.assertRegex(repr(c_void_p.from_param(0x12)), r"^<cparam 'P' \(0x0*12\)>$")
++
+ ################################################################
+ if __name__ == '__main__':
+diff --git a/Lib/datetime.py b/Lib/datetime.py
+index e508d996fb..23d2bf0918 100644
+--- a/Lib/datetime.py
++++ b/Lib/datetime.py
+@@ -2358,7 +2358,7 @@ _EPOCH = datetime(1970, 1, 1, tzinfo=timezone.utc)
+ #    This is again a requirement for a sane tzinfo class.
+ #
+ # 4. (x+k).s = x.s
+-#    This follows from #2, and that datimetimetz+timedelta preserves tzinfo.
++#    This follows from #2, and that datetime.timetz+timedelta preserves tzinfo.
+ #
+ # 5. (x+k).n = x.n + k
+ #    Again follows from how arithmetic is defined.
+diff --git a/Lib/distutils/spawn.py b/Lib/distutils/spawn.py
+index f50edd2da9..0d1bd0391e 100644
+--- a/Lib/distutils/spawn.py
++++ b/Lib/distutils/spawn.py
+@@ -54,8 +54,8 @@ def spawn(cmd, search_path=1, verbose=0, dry_run=0):
+         global _cfg_target, _cfg_target_split
+         if _cfg_target is None:
+             from distutils import sysconfig
+-            _cfg_target = str(sysconfig.get_config_var(
+-                                  'MACOSX_DEPLOYMENT_TARGET') or '')
++            _cfg_target = sysconfig.get_config_var(
++                                  'MACOSX_DEPLOYMENT_TARGET') or ''
+             if _cfg_target:
+                 _cfg_target_split = [int(x) for x in _cfg_target.split('.')]
+         if _cfg_target:
+diff --git a/Lib/distutils/tests/test_build_ext.py b/Lib/distutils/tests/test_build_ext.py
+index 1b034c9302..808c0dc287 100644
+--- a/Lib/distutils/tests/test_build_ext.py
++++ b/Lib/distutils/tests/test_build_ext.py
+@@ -455,7 +455,7 @@ class BuildExtTestCase(TempdirManager,
+         deptarget = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
+         if deptarget:
+             # increment the minor version number (i.e. 10.6 -> 10.7)
+-            deptarget = [int(x) for x in str(deptarget).split('.')]
++            deptarget = [int(x) for x in deptarget.split('.')]
+             deptarget[-1] += 1
+             deptarget = '.'.join(str(i) for i in deptarget)
+             self._try_compile_deployment_target('<', deptarget)
+@@ -488,7 +488,7 @@ class BuildExtTestCase(TempdirManager,
+         # get the deployment target that the interpreter was built with
+         target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
+-        target = tuple(map(int, str(target).split('.')[0:2]))
++        target = tuple(map(int, target.split('.')[0:2]))
+         # format the target value as defined in the Apple
+         # Availability Macros.  We can't use the macro names since
+         # at least one value we test with will not exist yet.
+diff --git a/Lib/enum.py b/Lib/enum.py
+index ebadd9f662..1fddb1c75e 100644
+--- a/Lib/enum.py
++++ b/Lib/enum.py
+@@ -10,31 +10,54 @@ __all__ = [
+ def _is_descriptor(obj):
+-    """Returns True if obj is a descriptor, False otherwise."""
++    """
++    Returns True if obj is a descriptor, False otherwise.
++    """
+     return (
+             hasattr(obj, '__get__') or
+             hasattr(obj, '__set__') or
+-            hasattr(obj, '__delete__'))
+-
++            hasattr(obj, '__delete__')
++            )
+ def _is_dunder(name):
+-    """Returns True if a __dunder__ name, False otherwise."""
+-    return (len(name) > 4 and
++    """
++    Returns True if a __dunder__ name, False otherwise.
++    """
++    return (
++            len(name) > 4 and
+             name[:2] == name[-2:] == '__' and
+             name[2] != '_' and
+-            name[-3] != '_')
+-
++            name[-3] != '_'
++            )
+ def _is_sunder(name):
+-    """Returns True if a _sunder_ name, False otherwise."""
+-    return (len(name) > 2 and
++    """
++    Returns True if a _sunder_ name, False otherwise.
++    """
++    return (
++            len(name) > 2 and
+             name[0] == name[-1] == '_' and
+             name[1:2] != '_' and
+-            name[-2:-1] != '_')
+-
++            name[-2:-1] != '_'
++            )
++
++def _is_private(cls_name, name):
++    # do not use `re` as `re` imports `enum`
++    pattern = '_%s__' % (cls_name, )
++    if (
++            len(name) >= 5
++            and name.startswith(pattern)
++            and name[len(pattern)] != '_'
++            and (name[-1] != '_' or name[-2] != '_')
++        ):
++        return True
++    else:
++        return False
+ def _make_class_unpicklable(cls):
+-    """Make the given class un-picklable."""
++    """
++    Make the given class un-picklable.
++    """
+     def _break_on_call_reduce(self, proto):
+         raise TypeError('%r cannot be pickled' % self)
+     cls.__reduce_ex__ = _break_on_call_reduce
+@@ -49,11 +72,11 @@ class auto:
+ class _EnumDict(dict):
+-    """Track enum member order and ensure member names are not reused.
++    """
++    Track enum member order and ensure member names are not reused.
+     EnumMeta will use the names found in self._member_names as the
+     enumeration member names.
+-
+     """
+     def __init__(self):
+         super().__init__()
+@@ -63,14 +86,22 @@ class _EnumDict(dict):
+         self._auto_called = False
+     def __setitem__(self, key, value):
+-        """Changes anything not dundered or not a descriptor.
++        """
++        Changes anything not dundered or not a descriptor.
+         If an enum member name is used twice, an error is raised; duplicate
+         values are not checked for.
+         Single underscore (sunder) names are reserved.
+-
+         """
++        if _is_private(self._cls_name, key):
++            import warnings
++            warnings.warn(
++                    "private variables, such as %r, will be normal attributes in 3.10"
++                        % (key, ),
++                    DeprecationWarning,
++                    stacklevel=2,
++                    )
+         if _is_sunder(key):
+             if key not in (
+                     '_order_', '_create_pseudo_member_',
+@@ -90,7 +121,10 @@ class _EnumDict(dict):
+                 self._ignore = value
+                 already = set(value) & set(self._member_names)
+                 if already:
+-                    raise ValueError('_ignore_ cannot specify already set names: %r' % (already, ))
++                    raise ValueError(
++                            '_ignore_ cannot specify already set names: %r'
++                            % (already, )
++                            )
+         elif _is_dunder(key):
+             if key == '__order__':
+                 key = '_order_'
+@@ -105,7 +139,12 @@ class _EnumDict(dict):
+                 raise TypeError('%r already defined as: %r' % (key, self[key]))
+             if isinstance(value, auto):
+                 if value.value == _auto_null:
+-                    value.value = self._generate_next_value(key, 1, len(self._member_names), self._last_values[:])
++                    value.value = self._generate_next_value(
++                            key,
++                            1,
++                            len(self._member_names),
++                            self._last_values[:],
++                            )
+                     self._auto_called = True
+                 value = value.value
+             self._member_names.append(key)
+@@ -118,22 +157,26 @@ class _EnumDict(dict):
+ # This is also why there are checks in EnumMeta like `if Enum is not None`
+ Enum = None
+-
+ class EnumMeta(type):
+-    """Metaclass for Enum"""
++    """
++    Metaclass for Enum
++    """
+     @classmethod
+-    def __prepare__(metacls, cls, bases):
++    def __prepare__(metacls, cls, bases, **kwds):
+         # check that previous enum members do not exist
+         metacls._check_for_existing_members(cls, bases)
+         # create the namespace dict
+         enum_dict = _EnumDict()
++        enum_dict._cls_name = cls
+         # inherit previous flags and _generate_next_value_ function
+         member_type, first_enum = metacls._get_mixins_(cls, bases)
+         if first_enum is not None:
+-            enum_dict['_generate_next_value_'] = getattr(first_enum, '_generate_next_value_', None)
++            enum_dict['_generate_next_value_'] = getattr(
++                    first_enum, '_generate_next_value_', None,
++                    )
+         return enum_dict
+-    def __new__(metacls, cls, bases, classdict):
++    def __new__(metacls, cls, bases, classdict, **kwds):
+         # an Enum class is final once enumeration items have been defined; it
+         # cannot be mixed with other types (int, float, etc.) if it has an
+         # inherited __new__ unless a new __new__ is defined (or the resulting
+@@ -145,8 +188,9 @@ class EnumMeta(type):
+         for key in ignore:
+             classdict.pop(key, None)
+         member_type, first_enum = metacls._get_mixins_(cls, bases)
+-        __new__, save_new, use_args = metacls._find_new_(classdict, member_type,
+-                                                        first_enum)
++        __new__, save_new, use_args = metacls._find_new_(
++                classdict, member_type, first_enum,
++                )
+         # save enum items into separate mapping so they don't get baked into
+         # the new class
+@@ -167,17 +211,18 @@ class EnumMeta(type):
+         if '__doc__' not in classdict:
+             classdict['__doc__'] = 'An enumeration.'
+-        # create our new Enum type
+-        enum_class = super().__new__(metacls, cls, bases, classdict)
++        enum_class = super().__new__(metacls, cls, bases, classdict, **kwds)
+         enum_class._member_names_ = []               # names in definition order
+         enum_class._member_map_ = {}                 # name->value map
+         enum_class._member_type_ = member_type
+         # save DynamicClassAttribute attributes from super classes so we know
+         # if we can take the shortcut of storing members in the class dict
+-        dynamic_attributes = {k for c in enum_class.mro()
+-                              for k, v in c.__dict__.items()
+-                              if isinstance(v, DynamicClassAttribute)}
++        dynamic_attributes = {
++                k for c in enum_class.mro()
++                for k, v in c.__dict__.items()
++                if isinstance(v, DynamicClassAttribute)
++                }
+         # Reverse value->name map for hashable values.
+         enum_class._value2member_map_ = {}
+@@ -287,7 +332,8 @@ class EnumMeta(type):
+         return True
+     def __call__(cls, value, names=None, *, module=None, qualname=None, type=None, start=1):
+-        """Either returns an existing member, or creates a new enum class.
++        """
++        Either returns an existing member, or creates a new enum class.
+         This method is used both when an enum class is given a value to match
+         to an enumeration member (i.e. Color(3)) and for the functional API
+@@ -309,12 +355,18 @@ class EnumMeta(type):
+         not correct, unpickling will fail in some circumstances.
+         `type`, if set, will be mixed in as the first base class.
+-
+         """
+         if names is None:  # simple value lookup
+             return cls.__new__(cls, value)
+         # otherwise, functional API: we're creating a new Enum type
+-        return cls._create_(value, names, module=module, qualname=qualname, type=type, start=start)
++        return cls._create_(
++                value,
++                names,
++                module=module,
++                qualname=qualname,
++                type=type,
++                start=start,
++                )
+     def __contains__(cls, member):
+         if not isinstance(member, Enum):
+@@ -327,22 +379,23 @@ class EnumMeta(type):
+         # nicer error message when someone tries to delete an attribute
+         # (see issue19025).
+         if attr in cls._member_map_:
+-            raise AttributeError(
+-                    "%s: cannot delete Enum member." % cls.__name__)
++            raise AttributeError("%s: cannot delete Enum member." % cls.__name__)
+         super().__delattr__(attr)
+     def __dir__(self):
+-        return (['__class__', '__doc__', '__members__', '__module__'] +
+-                self._member_names_)
++        return (
++                ['__class__', '__doc__', '__members__', '__module__']
++                + self._member_names_
++                )
+     def __getattr__(cls, name):
+-        """Return the enum member matching `name`
++        """
++        Return the enum member matching `name`
+         We use __getattr__ instead of descriptors or inserting into the enum
+         class' __dict__ in order to support `name` and `value` being both
+         properties for enum members (which live in the class' __dict__) and
+         enum members themselves.
+-
+         """
+         if _is_dunder(name):
+             raise AttributeError(name)
+@@ -355,6 +408,9 @@ class EnumMeta(type):
+         return cls._member_map_[name]
+     def __iter__(cls):
++        """
++        Returns members in definition order.
++        """
+         return (cls._member_map_[name] for name in cls._member_names_)
+     def __len__(cls):
+@@ -362,11 +418,11 @@ class EnumMeta(type):
+     @property
+     def __members__(cls):
+-        """Returns a mapping of member name->value.
++        """
++        Returns a mapping of member name->value.
+         This mapping lists all enum members, including aliases. Note that this
+         is a read-only view of the internal mapping.
+-
+         """
+         return MappingProxyType(cls._member_map_)
+@@ -374,15 +430,18 @@ class EnumMeta(type):
+         return "<enum %r>" % cls.__name__
+     def __reversed__(cls):
++        """
++        Returns members in reverse definition order.
++        """
+         return (cls._member_map_[name] for name in reversed(cls._member_names_))
+     def __setattr__(cls, name, value):
+-        """Block attempts to reassign Enum members.
++        """
++        Block attempts to reassign Enum members.
+         A simple assignment to the class namespace only changes one of the
+         several possible ways to get an Enum member from the Enum class,
+         resulting in an inconsistent Enumeration.
+-
+         """
+         member_map = cls.__dict__.get('_member_map_', {})
+         if name in member_map:
+@@ -390,7 +449,8 @@ class EnumMeta(type):
+         super().__setattr__(name, value)
+     def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, start=1):
+-        """Convenience method to create a new Enum class.
++        """
++        Convenience method to create a new Enum class.
+         `names` can be:
+@@ -399,7 +459,6 @@ class EnumMeta(type):
+         * An iterable of member names.  Values are incremented by 1 from `start`.
+         * An iterable of (member name, value) pairs.
+         * A mapping of member name -> value pairs.
+-
+         """
+         metacls = cls.__class__
+         bases = (cls, ) if type is None else (type, cls)
+@@ -480,15 +539,18 @@ class EnumMeta(type):
+         for chain in bases:
+             for base in chain.__mro__:
+                 if issubclass(base, Enum) and base._member_names_:
+-                    raise TypeError("%s: cannot extend enumeration %r" % (class_name, base.__name__))
++                    raise TypeError(
++                            "%s: cannot extend enumeration %r"
++                            % (class_name, base.__name__)
++                            )
+     @staticmethod
+     def _get_mixins_(class_name, bases):
+-        """Returns the type for creating enum members, and the first inherited
++        """
++        Returns the type for creating enum members, and the first inherited
+         enum class.
+         bases: the tuple of bases that was given to __new__
+-
+         """
+         if not bases:
+             return object, Enum
+@@ -500,12 +562,16 @@ class EnumMeta(type):
+                 for base in chain.__mro__:
+                     if base is object:
+                         continue
++                    elif issubclass(base, Enum):
++                        if base._member_type_ is not object:
++                            data_types.append(base._member_type_)
++                            break
+                     elif '__new__' in base.__dict__:
+                         if issubclass(base, Enum):
+                             continue
+                         data_types.append(candidate or base)
+                         break
+-                    elif not issubclass(base, Enum):
++                    else:
+                         candidate = base
+             if len(data_types) > 1:
+                 raise TypeError('%r: too many data types: %r' % (class_name, data_types))
+@@ -527,12 +593,12 @@ class EnumMeta(type):
+     @staticmethod
+     def _find_new_(classdict, member_type, first_enum):
+-        """Returns the __new__ to be used for creating the enum members.
++        """
++        Returns the __new__ to be used for creating the enum members.
+         classdict: the class dictionary given to __new__
+         member_type: the data type whose __new__ will be used by default
+         first_enum: enumeration to check for an overriding __new__
+-
+         """
+         # now find the correct __new__, checking to see of one was defined
+         # by the user; also check earlier enum classes in case a __new__ was
+@@ -572,10 +638,10 @@ class EnumMeta(type):
+ class Enum(metaclass=EnumMeta):
+-    """Generic enumeration.
++    """
++    Generic enumeration.
+     Derive from this class to define new enumerations.
+-
+     """
+     def __new__(cls, value):
+         # all enum instances are actually created during class construction
+@@ -618,6 +684,14 @@ class Enum(metaclass=EnumMeta):
+             raise exc
+     def _generate_next_value_(name, start, count, last_values):
++        """
++        Generate the next value when not given.
++
++        name: the name of the member
++        start: the initial start value or None
++        count: the number of existing members
++        last_value: the last value assigned or None
++        """
+         for last_value in reversed(last_values):
+             try:
+                 return last_value + 1
+@@ -638,21 +712,27 @@ class Enum(metaclass=EnumMeta):
+         return "%s.%s" % (self.__class__.__name__, self._name_)
+     def __dir__(self):
++        """
++        Returns all members and all public methods
++        """
+         added_behavior = [
+                 m
+                 for cls in self.__class__.mro()
+                 for m in cls.__dict__
+                 if m[0] != '_' and m not in self._member_map_
+-                ]
++                ] + [m for m in self.__dict__ if m[0] != '_']
+         return (['__class__', '__doc__', '__module__'] + added_behavior)
+     def __format__(self, format_spec):
++        """
++        Returns format using actual value type unless __str__ has been overridden.
++        """
+         # mixed-in Enums should use the mixed-in type's __format__, otherwise
+         # we can get strange results with the Enum name showing up instead of
+         # the value
+         # pure Enum branch, or branch with __str__ explicitly overridden
+-        str_overridden = type(self).__str__ != Enum.__str__
++        str_overridden = type(self).__str__ not in (Enum.__str__, Flag.__str__)
+         if self._member_type_ is object or str_overridden:
+             cls = str
+             val = str(self)
+@@ -694,7 +774,9 @@ def _reduce_ex_by_name(self, proto):
+     return self.name
+ class Flag(Enum):
+-    """Support for flags"""
++    """
++    Support for flags
++    """
+     def _generate_next_value_(name, start, count, last_values):
+         """
+@@ -717,6 +799,9 @@ class Flag(Enum):
+     @classmethod
+     def _missing_(cls, value):
++        """
++        Returns member (possibly creating it) if one can be found for value.
++        """
+         original_value = value
+         if value < 0:
+             value = ~value
+@@ -746,6 +831,9 @@ class Flag(Enum):
+         return pseudo_member
+     def __contains__(self, other):
++        """
++        Returns True if self has at least the same flags set as other.
++        """
+         if not isinstance(other, self.__class__):
+             raise TypeError(
+                 "unsupported operand type(s) for 'in': '%s' and '%s'" % (
+@@ -804,10 +892,15 @@ class Flag(Enum):
+ class IntFlag(int, Flag):
+-    """Support for integer-based Flags"""
++    """
++    Support for integer-based Flags
++    """
+     @classmethod
+     def _missing_(cls, value):
++        """
++        Returns member (possibly creating it) if one can be found for value.
++        """
+         if not isinstance(value, int):
+             raise ValueError("%r is not a valid %s" % (value, cls.__qualname__))
+         new_member = cls._create_pseudo_member_(value)
+@@ -815,6 +908,9 @@ class IntFlag(int, Flag):
+     @classmethod
+     def _create_pseudo_member_(cls, value):
++        """
++        Create a composite member iff value contains only members.
++        """
+         pseudo_member = cls._value2member_map_.get(value, None)
+         if pseudo_member is None:
+             need_to_create = [value]
+@@ -869,11 +965,15 @@ class IntFlag(int, Flag):
+ def _high_bit(value):
+-    """returns index of highest bit, or -1 if value is zero or negative"""
++    """
++    returns index of highest bit, or -1 if value is zero or negative
++    """
+     return value.bit_length() - 1
+ def unique(enumeration):
+-    """Class decorator for enumerations ensuring unique member values."""
++    """
++    Class decorator for enumerations ensuring unique member values.
++    """
+     duplicates = []
+     for name, member in enumeration.__members__.items():
+         if name != member.name:
+@@ -886,7 +986,9 @@ def unique(enumeration):
+     return enumeration
+ def _decompose(flag, value):
+-    """Extract all members from the value."""
++    """
++    Extract all members from the value.
++    """
+     # _decompose is only called if the value is not named
+     not_covered = value
+     negative = value < 0
+diff --git a/Lib/fnmatch.py b/Lib/fnmatch.py
+index 0eb1802bdb..7c52c23067 100644
+--- a/Lib/fnmatch.py
++++ b/Lib/fnmatch.py
+@@ -52,7 +52,7 @@ def _compile_pattern(pat):
+     return re.compile(res).match
+ def filter(names, pat):
+-    """Return the subset of the list NAMES that match PAT."""
++    """Construct a list from those elements of the iterable NAMES that match PAT."""
+     result = []
+     pat = os.path.normcase(pat)
+     match = _compile_pattern(pat)
+diff --git a/Lib/html/parser.py b/Lib/html/parser.py
+index 6083077981..9e49effca1 100644
+--- a/Lib/html/parser.py
++++ b/Lib/html/parser.py
+@@ -46,7 +46,7 @@ locatestarttagend_tolerant = re.compile(r"""
+           |"[^"]*"                   # LIT-enclosed value
+           |(?!['"])[^>\s]*           # bare value
+          )
+-         (?:\s*,)*                   # possibly followed by a comma
++        \s*                          # possibly followed by a space
+        )?(?:\s|/(?!>))*
+      )*
+    )?
+diff --git a/Lib/http/client.py b/Lib/http/client.py
+index c2ad0471bf..16afc871ea 100644
+--- a/Lib/http/client.py
++++ b/Lib/http/client.py
+@@ -846,7 +846,7 @@ class HTTPConnection:
+         the endpoint passed to `set_tunnel`. This done by sending an HTTP
+         CONNECT request to the proxy server when the connection is established.
+-        This method must be called before the HTML connection has been
++        This method must be called before the HTTP connection has been
+         established.
+         The headers argument should be a mapping of extra HTTP headers to send
+diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt
+index 869be0a62b..4bc4aefd1a 100644
+--- a/Lib/idlelib/NEWS.txt
++++ b/Lib/idlelib/NEWS.txt
+@@ -1,8 +1,24 @@
+-What's New in IDLE 3.9.1
+-Released on 2020-12-07?
++What's New in IDLE 3.9.2
++Released on 2021-02-15?
+ ======================================
++bpo-23544: Disable Debug=>Stack Viewer when user code is running or
++Debugger is active, to prevent hang or crash.  Patch by Zackery Spytz.
++
++bpo-43008: Make IDLE invoke :func:`sys.excepthook` in normal,
++2-process mode.  Patch by Ken Hilton.
++
++bpo-33065: Fix problem debugging user classes with __repr__ method.
++
++bpo-32631: Finish zzdummy example extension module: make menu entries
++work; add docstrings and tests with 100% coverage.
++
++
++What's New in IDLE 3.9.1
++Released on 2020-12-07
++======================================
++
+ bpo-42508: Keep IDLE running on macOS.  Remove obsolete workaround
+ that prevented running files with shortcuts when using new universal2
+ installers built on macOS 11.
+diff --git a/Lib/idlelib/codecontext.py b/Lib/idlelib/codecontext.py
+index 989b30e599..f2f44f5f8d 100644
+--- a/Lib/idlelib/codecontext.py
++++ b/Lib/idlelib/codecontext.py
+@@ -7,11 +7,14 @@ the lines which contain the block opening keywords, e.g. 'if', for the
+ enclosing block.  The number of hint lines is determined by the maxlines
+ variable in the codecontext section of config-extensions.def. Lines which do
+ not open blocks are not shown in the context hints pane.
++
++For EditorWindows, <<toggle-code-context>> is bound to CodeContext(self).
++toggle_code_context_event.
+ """
+ import re
+ from sys import maxsize as INFINITY
+-import tkinter
++from tkinter import Frame, Text, TclError
+ from tkinter.constants import NSEW, SUNKEN
+ from idlelib.config import idleConf
+@@ -83,7 +86,7 @@ class CodeContext:
+         if self.t1 is not None:
+             try:
+                 self.text.after_cancel(self.t1)
+-            except tkinter.TclError:  # pragma: no cover
++            except TclError:  # pragma: no cover
+                 pass
+             self.t1 = None
+@@ -111,7 +114,7 @@ class CodeContext:
+                 padx += widget.tk.getint(info['padx'])
+                 padx += widget.tk.getint(widget.cget('padx'))
+                 border += widget.tk.getint(widget.cget('border'))
+-            context = self.context = tkinter.Text(
++            context = self.context = Text(
+                 self.editwin.text_frame,
+                 height=1,
+                 width=1,  # Don't request more than we get.
+@@ -127,7 +130,7 @@ class CodeContext:
+             line_number_colors = idleConf.GetHighlight(idleConf.CurrentTheme(),
+                                                        'linenumber')
+-            self.cell00 = tkinter.Frame(self.editwin.text_frame,
++            self.cell00 = Frame(self.editwin.text_frame,
+                                         bg=line_number_colors['background'])
+             self.cell00.grid(row=0, column=0, sticky=NSEW)
+             menu_status = 'Hide'
+@@ -139,7 +142,7 @@ class CodeContext:
+             self.text.after_cancel(self.t1)
+             self._reset()
+             menu_status = 'Show'
+-        self.editwin.update_menu_label(menu='options', index='* Code Context',
++        self.editwin.update_menu_label(menu='options', index='*ode*ontext',
+                                        label=f'{menu_status} Code Context')
+         return "break"
+@@ -221,7 +224,7 @@ class CodeContext:
+         """
+         try:
+             self.context.index("sel.first")
+-        except tkinter.TclError:
++        except TclError:
+             lines = len(self.info)
+             if lines == 1:  # No context lines are showing.
+                 newtop = 1
+diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py
+index a84e1c5668..c52a04b503 100644
+--- a/Lib/idlelib/configdialog.py
++++ b/Lib/idlelib/configdialog.py
+@@ -18,8 +18,8 @@ from tkinter import (Toplevel, Listbox, Scale, Canvas,
+                      HORIZONTAL, VERTICAL, ANCHOR, ACTIVE, END)
+ from tkinter.ttk import (Frame, LabelFrame, Button, Checkbutton, Entry, Label,
+                          OptionMenu, Notebook, Radiobutton, Scrollbar, Style)
+-import tkinter.colorchooser as tkColorChooser
+-import tkinter.font as tkFont
++from tkinter import colorchooser
++import tkinter.font as tkfont
+ from tkinter import messagebox
+ from idlelib.config import idleConf, ConfigChanges
+@@ -609,7 +609,7 @@ class FontPage(Frame):
+         font_bold  = configured_font[2]=='bold'
+         # Set sorted no-duplicate editor font selection list and font_name.
+-        fonts = sorted(set(tkFont.families(self)))
++        fonts = sorted(set(tkfont.families(self)))
+         for font in fonts:
+             self.fontlist.insert(END, font)
+         self.font_name.set(font_name)
+@@ -663,7 +663,7 @@ class FontPage(Frame):
+         Updates font_sample and highlight page highlight_sample.
+         """
+         font_name = self.font_name.get()
+-        font_weight = tkFont.BOLD if self.font_bold.get() else tkFont.NORMAL
++        font_weight = tkfont.BOLD if self.font_bold.get() else tkfont.NORMAL
+         new_font = (font_name, self.font_size.get(), font_weight)
+         self.font_sample['font'] = new_font
+         self.highlight_sample['font'] = new_font
+@@ -1100,7 +1100,7 @@ class HighPage(Frame):
+         target = self.highlight_target.get()
+         prev_color = self.style.lookup(self.frame_color_set['style'],
+                                        'background')
+-        rgbTuplet, color_string = tkColorChooser.askcolor(
++        rgbTuplet, color_string = colorchooser.askcolor(
+                 parent=self, title='Pick new color for : '+target,
+                 initialcolor=prev_color)
+         if color_string and (color_string != prev_color):
+@@ -2316,7 +2316,15 @@ display when Code Context is turned on for an editor window.
+ Shell Preferences: Auto-Squeeze Min. Lines is the minimum number of lines
+ of output to automatically "squeeze".
+-'''
++''',
++    'Extensions': '''
++ZzDummy: This extension is provided as an example for how to create and
++use an extension.  Enable indicates whether the extension is active or
++not; likewise enable_editor and enable_shell indicate which windows it
++will be active on.  For this extension, z-text is the text that will be
++inserted at or removed from the beginning of the lines of selected text,
++or the current line if no selection.
++''',
+ }
+diff --git a/Lib/idlelib/debugger_r.py b/Lib/idlelib/debugger_r.py
+index 9dcfc56414..2620443885 100644
+--- a/Lib/idlelib/debugger_r.py
++++ b/Lib/idlelib/debugger_r.py
+@@ -19,7 +19,7 @@ arguments and return values that cannot be transported through the RPC
+ barrier, in particular frame and traceback objects.
+ """
+-
++import reprlib
+ import types
+ from idlelib import debugger
+@@ -170,7 +170,7 @@ class IdbAdapter:
+     def dict_item(self, did, key):
+         dict = dicttable[did]
+         value = dict[key]
+-        value = repr(value) ### can't pickle module 'builtins'
++        value = reprlib.repr(value) ### can't pickle module 'builtins'
+         return value
+ #----------end class IdbAdapter----------
+@@ -390,4 +390,4 @@ def restart_subprocess_debugger(rpcclt):
+ if __name__ == "__main__":
+     from unittest import main
+-    main('idlelib.idle_test.test_debugger', verbosity=2, exit=False)
++    main('idlelib.idle_test.test_debugger_r', verbosity=2, exit=False)
+diff --git a/Lib/idlelib/editor.py b/Lib/idlelib/editor.py
+index a178eaf93c..b9cb50264f 100644
+--- a/Lib/idlelib/editor.py
++++ b/Lib/idlelib/editor.py
+@@ -12,8 +12,8 @@ import webbrowser
+ from tkinter import *
+ from tkinter.font import Font
+ from tkinter.ttk import Scrollbar
+-import tkinter.simpledialog as tkSimpleDialog
+-import tkinter.messagebox as tkMessageBox
++from tkinter import simpledialog
++from tkinter import messagebox
+ from idlelib.config import idleConf
+ from idlelib import configdialog
+@@ -46,7 +46,7 @@ def _sphinx_version():
+     return release
+-class EditorWindow(object):
++class EditorWindow:
+     from idlelib.percolator import Percolator
+     from idlelib.colorizer import ColorDelegator, color_config
+     from idlelib.undo import UndoDelegator
+@@ -295,9 +295,9 @@ class EditorWindow(object):
+             window.register_callback(self.postwindowsmenu)
+         # Some abstractions so IDLE extensions are cross-IDE
+-        self.askyesno = tkMessageBox.askyesno
+-        self.askinteger = tkSimpleDialog.askinteger
+-        self.showerror = tkMessageBox.showerror
++        self.askinteger = simpledialog.askinteger
++        self.askyesno = messagebox.askyesno
++        self.showerror = messagebox.showerror
+         # Add pseudoevents for former extension fixed keys.
+         # (This probably needs to be done once in the process.)
+@@ -339,7 +339,7 @@ class EditorWindow(object):
+             text.bind("<<toggle-code-context>>",
+                       self.code_context.toggle_code_context_event)
+         else:
+-            self.update_menu_state('options', '*Code Context', 'disabled')
++            self.update_menu_state('options', '*ode*ontext', 'disabled')
+         if self.allow_line_numbers:
+             self.line_numbers = self.LineNumbers(self)
+             if idleConf.GetOption('main', 'EditorWindow',
+@@ -347,7 +347,7 @@ class EditorWindow(object):
+                 self.toggle_line_numbers_event()
+             text.bind("<<toggle-line-numbers>>", self.toggle_line_numbers_event)
+         else:
+-            self.update_menu_state('options', '*Line Numbers', 'disabled')
++            self.update_menu_state('options', '*ine*umbers', 'disabled')
+     def handle_winconfig(self, event=None):
+         self.set_width()
+@@ -450,7 +450,9 @@ class EditorWindow(object):
+         self.menudict = menudict = {}
+         for name, label in self.menu_specs:
+             underline, label = prepstr(label)
+-            menudict[name] = menu = Menu(mbar, name=name, tearoff=0)
++            postcommand = getattr(self, f'{name}_menu_postcommand', None)
++            menudict[name] = menu = Menu(mbar, name=name, tearoff=0,
++                                         postcommand=postcommand)
+             mbar.add_cascade(label=label, menu=menu, underline=underline)
+         if macosx.isCarbonTk():
+             # Insert the application menu
+@@ -596,7 +598,7 @@ class EditorWindow(object):
+             try:
+                 os.startfile(self.help_url)
+             except OSError as why:
+-                tkMessageBox.showerror(title='Document Start Failure',
++                messagebox.showerror(title='Document Start Failure',
+                     message=str(why), parent=self.text)
+         else:
+             webbrowser.open(self.help_url)
+@@ -927,7 +929,7 @@ class EditorWindow(object):
+                 try:
+                     os.startfile(helpfile)
+                 except OSError as why:
+-                    tkMessageBox.showerror(title='Document Start Failure',
++                    messagebox.showerror(title='Document Start Failure',
+                         message=str(why), parent=self.text)
+             else:
+                 webbrowser.open(helpfile)
+@@ -963,7 +965,7 @@ class EditorWindow(object):
+             except OSError as err:
+                 if not getattr(self.root, "recentfiles_message", False):
+                     self.root.recentfiles_message = True
+-                    tkMessageBox.showwarning(title='IDLE Warning',
++                    messagebox.showwarning(title='IDLE Warning',
+                         message="Cannot save Recent Files list to disk.\n"
+                                 f"  {err}\n"
+                                 "Select OK to continue.",
+@@ -1527,7 +1529,7 @@ class EditorWindow(object):
+         else:
+             self.line_numbers.show_sidebar()
+             menu_label = "Hide"
+-        self.update_menu_label(menu='options', index='*Line Numbers',
++        self.update_menu_label(menu='options', index='*ine*umbers',
+                                label=f'{menu_label} Line Numbers')
+ # "line.col" -> line, as an int
+@@ -1546,7 +1548,7 @@ def get_line_indent(line, tabwidth):
+     return m.end(), len(m.group().expandtabs(tabwidth))
+-class IndentSearcher(object):
++class IndentSearcher:
+     # .run() chews over the Text widget, looking for a block opener
+     # and the stmt following it.  Returns a pair,
+diff --git a/Lib/idlelib/extend.txt b/Lib/idlelib/extend.txt
+index c9cb2e8297..b482f76c4f 100644
+--- a/Lib/idlelib/extend.txt
++++ b/Lib/idlelib/extend.txt
+@@ -28,8 +28,8 @@ variables:
+ (There are a few more, but they are rarely useful.)
+ The extension class must not directly bind Window Manager (e.g. X) events.
+-Rather, it must define one or more virtual events, e.g. <<zoom-height>>, and
+-corresponding methods, e.g. zoom_height_event().  The virtual events will be
++Rather, it must define one or more virtual events, e.g. <<z-in>>, and
++corresponding methods, e.g. z_in_event().  The virtual events will be
+ bound to the corresponding methods, and Window Manager events can then be bound
+ to the virtual events. (This indirection is done so that the key bindings can
+ easily be changed, and so that other sources of virtual events can exist, such
+@@ -54,21 +54,21 @@ Extensions are not required to define menu entries for all the events they
+ implement.  (They are also not required to create keybindings, but in that
+ case there must be empty bindings in cofig-extensions.def)
+-Here is a complete example:
++Here is a partial example from zzdummy.py:
+-class ZoomHeight:
++class ZzDummy:
+     menudefs = [
+-        ('edit', [
+-            None, # Separator
+-            ('_Zoom Height', '<<zoom-height>>'),
+-         ])
++        ('format', [
++            ('Z in', '<<z-in>>'),
++            ('Z out', '<<z-out>>'),
++        ] )
+     ]
+     def __init__(self, editwin):
+         self.editwin = editwin
+-    def zoom_height_event(self, event):
++    def z_in_event(self, event=None):
+         "...Do what you want here..."
+ The final piece of the puzzle is the file "config-extensions.def", which is
+diff --git a/Lib/idlelib/filelist.py b/Lib/idlelib/filelist.py
+index 0d200854ef..254f5caf6b 100644
+--- a/Lib/idlelib/filelist.py
++++ b/Lib/idlelib/filelist.py
+@@ -1,7 +1,7 @@
+ "idlelib.filelist"
+ import os
+-from tkinter import messagebox as tkMessageBox
++from tkinter import messagebox
+ class FileList:
+@@ -20,7 +20,7 @@ class FileList:
+         filename = self.canonize(filename)
+         if os.path.isdir(filename):
+             # This can happen when bad filename is passed on command line:
+-            tkMessageBox.showerror(
++            messagebox.showerror(
+                 "File Error",
+                 "%r is a directory." % (filename,),
+                 master=self.root)
+@@ -88,7 +88,7 @@ class FileList:
+         if newkey in self.dict:
+             conflict = self.dict[newkey]
+             self.inversedict[conflict] = None
+-            tkMessageBox.showerror(
++            messagebox.showerror(
+                 "Name Conflict",
+                 "You now have multiple edit windows open for %r" % (filename,),
+                 master=self.root)
+diff --git a/Lib/idlelib/idle_test/mock_tk.py b/Lib/idlelib/idle_test/mock_tk.py
+index b736bd001d..db58355383 100644
+--- a/Lib/idlelib/idle_test/mock_tk.py
++++ b/Lib/idlelib/idle_test/mock_tk.py
+@@ -59,27 +59,26 @@ class Mbox_func:
+ class Mbox:
+     """Mock for tkinter.messagebox with an Mbox_func for each function.
+-    This module was 'tkMessageBox' in 2.x; hence the 'import as' in  3.x.
+     Example usage in test_module.py for testing functions in module.py:
+     ---
+ from idlelib.idle_test.mock_tk import Mbox
+ import module
+-orig_mbox = module.tkMessageBox
++orig_mbox = module.messagebox
+ showerror = Mbox.showerror  # example, for attribute access in test methods
+ class Test(unittest.TestCase):
+     @classmethod
+     def setUpClass(cls):
+-        module.tkMessageBox = Mbox
++        module.messagebox = Mbox
+     @classmethod
+     def tearDownClass(cls):
+-        module.tkMessageBox = orig_mbox
++        module.messagebox = orig_mbox
+     ---
+     For 'ask' functions, set func.result return value before calling the method
+-    that uses the message function. When tkMessageBox functions are the
++    that uses the message function. When messagebox functions are the
+     only gui alls in a method, this replacement makes the method gui-free,
+     """
+     askokcancel = Mbox_func()     # True or False
+diff --git a/Lib/idlelib/idle_test/test_autocomplete.py b/Lib/idlelib/idle_test/test_autocomplete.py
+index 9c113bd893..642bb5db64 100644
+--- a/Lib/idlelib/idle_test/test_autocomplete.py
++++ b/Lib/idlelib/idle_test/test_autocomplete.py
+@@ -195,7 +195,7 @@ class AutoCompleteTest(unittest.TestCase):
+         self.assertFalse(acp.open_completions(ac.TAB))
+         self.text.delete('1.0', 'end')
+-    class dummy_acw():
++    class dummy_acw:
+         __init__ = Func()
+         show_window = Func(result=False)
+         hide_window = Func()
+diff --git a/Lib/idlelib/idle_test/test_calltip.py b/Lib/idlelib/idle_test/test_calltip.py
+index a76829f365..b23915c5ab 100644
+--- a/Lib/idlelib/idle_test/test_calltip.py
++++ b/Lib/idlelib/idle_test/test_calltip.py
+@@ -10,7 +10,7 @@ from idlelib.idle_test.mock_tk import Text
+ # Test Class TC is used in multiple get_argspec test methods
+-class TC():
++class TC:
+     'doc'
+     tip = "(ai=None, *b)"
+     def __init__(self, ai=None, *b): 'doc'
+@@ -268,7 +268,7 @@ class Get_entityTest(unittest.TestCase):
+ # open_calltip is about half the code; the others are fairly trivial.
+ # The default mocks are what are needed for open_calltip.
+-class mock_Shell():
++class mock_Shell:
+     "Return mock sufficient to pass to hyperparser."
+     def __init__(self, text):
+         text.tag_prevrange = Mock(return_value=None)
+diff --git a/Lib/idlelib/idle_test/test_codecontext.py b/Lib/idlelib/idle_test/test_codecontext.py
+index 9578cc731a..6969ad73b0 100644
+--- a/Lib/idlelib/idle_test/test_codecontext.py
++++ b/Lib/idlelib/idle_test/test_codecontext.py
+@@ -20,7 +20,7 @@ testcfg = {
+ }
+ code_sample = """\
+-class C1():
++class C1:
+     # Class comment.
+     def __init__(self, a, b):
+         self.a = a
+@@ -178,29 +178,29 @@ class CodeContextTest(unittest.TestCase):
+         with self.assertRaises(AssertionError):
+             gc(1, stopline=0)
+-        eq(gc(3), ([(2, 0, 'class C1():', 'class')], 0))
++        eq(gc(3), ([(2, 0, 'class C1:', 'class')], 0))
+         # Don't return comment.
+-        eq(gc(4), ([(2, 0, 'class C1():', 'class')], 0))
++        eq(gc(4), ([(2, 0, 'class C1:', 'class')], 0))
+         # Two indentation levels and no comment.
+-        eq(gc(5), ([(2, 0, 'class C1():', 'class'),
++        eq(gc(5), ([(2, 0, 'class C1:', 'class'),
+                     (4, 4, '    def __init__(self, a, b):', 'def')], 0))
+         # Only one 'def' is returned, not both at the same indent level.
+-        eq(gc(10), ([(2, 0, 'class C1():', 'class'),
++        eq(gc(10), ([(2, 0, 'class C1:', 'class'),
+                      (7, 4, '    def compare(self):', 'def'),
+                      (8, 8, '        if a > b:', 'if')], 0))
+         # With 'elif', also show the 'if' even though it's at the same level.
+-        eq(gc(11), ([(2, 0, 'class C1():', 'class'),
++        eq(gc(11), ([(2, 0, 'class C1:', 'class'),
+                      (7, 4, '    def compare(self):', 'def'),
+                      (8, 8, '        if a > b:', 'if'),
+                      (10, 8, '        elif a < b:', 'elif')], 0))
+         # Set stop_line to not go back to first line in source code.
+         # Return includes stop_line.
+-        eq(gc(11, stopline=2), ([(2, 0, 'class C1():', 'class'),
++        eq(gc(11, stopline=2), ([(2, 0, 'class C1:', 'class'),
+                                  (7, 4, '    def compare(self):', 'def'),
+                                  (8, 8, '        if a > b:', 'if'),
+                                  (10, 8, '        elif a < b:', 'elif')], 0))
+@@ -240,37 +240,37 @@ class CodeContextTest(unittest.TestCase):
+         # Scroll down to line 2.
+         cc.text.yview(2)
+         cc.update_code_context()
+-        eq(cc.info, [(0, -1, '', False), (2, 0, 'class C1():', 'class')])
++        eq(cc.info, [(0, -1, '', False), (2, 0, 'class C1:', 'class')])
+         eq(cc.topvisible, 3)
+-        eq(cc.context.get('1.0', 'end-1c'), 'class C1():')
++        eq(cc.context.get('1.0', 'end-1c'), 'class C1:')
+         # Scroll down to line 3.  Since it's a comment, nothing changes.
+         cc.text.yview(3)
+         cc.update_code_context()
+-        eq(cc.info, [(0, -1, '', False), (2, 0, 'class C1():', 'class')])
++        eq(cc.info, [(0, -1, '', False), (2, 0, 'class C1:', 'class')])
+         eq(cc.topvisible, 4)
+-        eq(cc.context.get('1.0', 'end-1c'), 'class C1():')
++        eq(cc.context.get('1.0', 'end-1c'), 'class C1:')
+         # Scroll down to line 4.
+         cc.text.yview(4)
+         cc.update_code_context()
+         eq(cc.info, [(0, -1, '', False),
+-                     (2, 0, 'class C1():', 'class'),
++                     (2, 0, 'class C1:', 'class'),
+                      (4, 4, '    def __init__(self, a, b):', 'def')])
+         eq(cc.topvisible, 5)
+-        eq(cc.context.get('1.0', 'end-1c'), 'class C1():\n'
++        eq(cc.context.get('1.0', 'end-1c'), 'class C1:\n'
+                                             '    def __init__(self, a, b):')
+         # Scroll down to line 11.  Last 'def' is removed.
+         cc.text.yview(11)
+         cc.update_code_context()
+         eq(cc.info, [(0, -1, '', False),
+-                     (2, 0, 'class C1():', 'class'),
++                     (2, 0, 'class C1:', 'class'),
+                      (7, 4, '    def compare(self):', 'def'),
+                      (8, 8, '        if a > b:', 'if'),
+                      (10, 8, '        elif a < b:', 'elif')])
+         eq(cc.topvisible, 12)
+-        eq(cc.context.get('1.0', 'end-1c'), 'class C1():\n'
++        eq(cc.context.get('1.0', 'end-1c'), 'class C1:\n'
+                                             '    def compare(self):\n'
+                                             '        if a > b:\n'
+                                             '        elif a < b:')
+@@ -279,12 +279,12 @@ class CodeContextTest(unittest.TestCase):
+         cc.update_code_context()
+         cc.context_depth = 1
+         eq(cc.info, [(0, -1, '', False),
+-                     (2, 0, 'class C1():', 'class'),
++                     (2, 0, 'class C1:', 'class'),
+                      (7, 4, '    def compare(self):', 'def'),
+                      (8, 8, '        if a > b:', 'if'),
+                      (10, 8, '        elif a < b:', 'elif')])
+         eq(cc.topvisible, 12)
+-        eq(cc.context.get('1.0', 'end-1c'), 'class C1():\n'
++        eq(cc.context.get('1.0', 'end-1c'), 'class C1:\n'
+                                             '    def compare(self):\n'
+                                             '        if a > b:\n'
+                                             '        elif a < b:')
+@@ -293,7 +293,7 @@ class CodeContextTest(unittest.TestCase):
+         cc.text.yview(5)
+         cc.update_code_context()
+         eq(cc.info, [(0, -1, '', False),
+-                     (2, 0, 'class C1():', 'class'),
++                     (2, 0, 'class C1:', 'class'),
+                      (4, 4, '    def __init__(self, a, b):', 'def')])
+         eq(cc.topvisible, 6)
+         # context_depth is 1.
+@@ -440,7 +440,7 @@ class HelperFunctionText(unittest.TestCase):
+         # Line 1 is not a BLOCKOPENER.
+         eq(gli(lines[0]), (codecontext.INFINITY, '', False))
+         # Line 2 is a BLOCKOPENER without an indent.
+-        eq(gli(lines[1]), (0, 'class C1():', 'class'))
++        eq(gli(lines[1]), (0, 'class C1:', 'class'))
+         # Line 3 is not a BLOCKOPENER and does not return the indent level.
+         eq(gli(lines[2]), (codecontext.INFINITY, '    # Class comment.', False))
+         # Line 4 is a BLOCKOPENER and is indented.
+diff --git a/Lib/idlelib/idle_test/test_configdialog.py b/Lib/idlelib/idle_test/test_configdialog.py
+index 1fea6d41df..98ddc67afd 100644
+--- a/Lib/idlelib/idle_test/test_configdialog.py
++++ b/Lib/idlelib/idle_test/test_configdialog.py
+@@ -423,7 +423,7 @@ class HighPageTest(unittest.TestCase):
+     def test_color(self):
+         d = self.page
+         d.on_new_color_set = Func()
+-        # self.color is only set in get_color through ColorChooser.
++        # self.color is only set in get_color through colorchooser.
+         d.color.set('green')
+         self.assertEqual(d.on_new_color_set.called, 1)
+         del d.on_new_color_set
+@@ -540,8 +540,8 @@ class HighPageTest(unittest.TestCase):
+     def test_get_color(self):
+         eq = self.assertEqual
+         d = self.page
+-        orig_chooser = configdialog.tkColorChooser.askcolor
+-        chooser = configdialog.tkColorChooser.askcolor = Func()
++        orig_chooser = configdialog.colorchooser.askcolor
++        chooser = configdialog.colorchooser.askcolor = Func()
+         gntn = d.get_new_theme_name = Func()
+         d.highlight_target.set('Editor Breakpoint')
+@@ -582,7 +582,7 @@ class HighPageTest(unittest.TestCase):
+         eq(d.color.get(), '#de0000')
+         del d.get_new_theme_name
+-        configdialog.tkColorChooser.askcolor = orig_chooser
++        configdialog.colorchooser.askcolor = orig_chooser
+     def test_on_new_color_set(self):
+         d = self.page
+diff --git a/Lib/idlelib/idle_test/test_debugger_r.py b/Lib/idlelib/idle_test/test_debugger_r.py
+index 199f63447c..638ebd36a7 100644
+--- a/Lib/idlelib/idle_test/test_debugger_r.py
++++ b/Lib/idlelib/idle_test/test_debugger_r.py
+@@ -25,5 +25,19 @@ class Test(unittest.TestCase):
+ # Classes GUIProxy, IdbAdapter, FrameProxy, CodeProxy, DictProxy,
+ # GUIAdapter, IdbProxy plus 7 module functions.
++class IdbAdapterTest(unittest.TestCase):
++
++    def test_dict_item_noattr(self):  # Issue 33065.
++
++        class BinData:
++            def __repr__(self):
++                return self.length
++
++        debugger_r.dicttable[0] = {'BinData': BinData()}
++        idb = debugger_r.IdbAdapter(None)
++        self.assertTrue(idb.dict_item(0, 'BinData'))
++        debugger_r.dicttable.clear()
++
++
+ if __name__ == '__main__':
+     unittest.main(verbosity=2)
+diff --git a/Lib/idlelib/idle_test/test_format.py b/Lib/idlelib/idle_test/test_format.py
+index a79bb51508..e5e9036885 100644
+--- a/Lib/idlelib/idle_test/test_format.py
++++ b/Lib/idlelib/idle_test/test_format.py
+@@ -418,7 +418,7 @@ class FormatRegionTest(unittest.TestCase):
+     code_sample = """\
+ # WS line needed for test.
+-class C1():
++class C1:
+     # Class comment.
+     def __init__(self, a, b):
+         self.a = a
+diff --git a/Lib/idlelib/idle_test/test_help_about.py b/Lib/idlelib/idle_test/test_help_about.py
+index 7c148d23a1..b915535aca 100644
+--- a/Lib/idlelib/idle_test/test_help_about.py
++++ b/Lib/idlelib/idle_test/test_help_about.py
+@@ -134,7 +134,7 @@ class CloseTest(unittest.TestCase):
+             self.dialog.winfo_class()
+-class Dummy_about_dialog():
++class Dummy_about_dialog:
+     # Dummy class for testing file display functions.
+     idle_credits = About.show_idle_credits
+     idle_readme = About.show_readme
+diff --git a/Lib/idlelib/idle_test/test_mainmenu.py b/Lib/idlelib/idle_test/test_mainmenu.py
+index 7ec0368371..51d2accfe4 100644
+--- a/Lib/idlelib/idle_test/test_mainmenu.py
++++ b/Lib/idlelib/idle_test/test_mainmenu.py
+@@ -2,6 +2,7 @@
+ # Reported as 88%; mocking turtledemo absence would have no point.
+ from idlelib import mainmenu
++import re
+ import unittest
+@@ -16,6 +17,26 @@ class MainMenuTest(unittest.TestCase):
+     def test_default_keydefs(self):
+         self.assertGreaterEqual(len(mainmenu.default_keydefs), 50)
++    def test_tcl_indexes(self):
++        # Test tcl patterns used to find menuitem to alter.
++        # On failure, change pattern here and in function(s).
++        # Patterns here have '.*' for re instead of '*' for tcl.
++        for menu, pattern in (
++            ('debug', '.*tack.*iewer'),  # PyShell.debug_menu_postcommand
++            ('options', '.*ode.*ontext'),  # EW.__init__, CodeContext.toggle...
++            ('options', '.*ine.*umbers'),  # EW.__init__, EW.toggle...event.
++            ):
++            with self.subTest(menu=menu, pattern=pattern):
++                for menutup in mainmenu.menudefs:
++                    if menutup[0] == menu:
++                        break
++                else:
++                    self.assertTrue(0, f"{menu} not in menudefs")
++                self.assertTrue(any(re.search(pattern, menuitem[0])
++                                    for menuitem in menutup[1]
++                                    if menuitem is not None),  # Separator.
++                                f"{pattern} not in {menu}")
++
+ if __name__ == '__main__':
+     unittest.main(verbosity=2)
+diff --git a/Lib/idlelib/idle_test/test_pyparse.py b/Lib/idlelib/idle_test/test_pyparse.py
+index f21baf7534..fb5726db1d 100644
+--- a/Lib/idlelib/idle_test/test_pyparse.py
++++ b/Lib/idlelib/idle_test/test_pyparse.py
+@@ -73,11 +73,12 @@ class PyParseTest(unittest.TestCase):
+         # Split def across lines.
+         setcode('"""This is a module docstring"""\n'
+-                'class C():\n'
++                'class C:\n'
+                 '    def __init__(self, a,\n'
+                 '                 b=True):\n'
+                 '        pass\n'
+                 )
++        pos0, pos = 33, 42  # Start of 'class...', '    def' lines.
+         # Passing no value or non-callable should fail (issue 32989).
+         with self.assertRaises(TypeError):
+@@ -91,40 +92,41 @@ class PyParseTest(unittest.TestCase):
+         # Make all text look like it's not in a string.  This means that it
+         # found a good start position.
+-        eq(start(char_in_string_false), 44)
++        eq(start(char_in_string_false), pos)
+         # If the beginning of the def line is not in a string, then it
+         # returns that as the index.
+-        eq(start(is_char_in_string=lambda index: index > 44), 44)
++        eq(start(is_char_in_string=lambda index: index > pos), pos)
+         # If the beginning of the def line is in a string, then it
+         # looks for a previous index.
+-        eq(start(is_char_in_string=lambda index: index >= 44), 33)
++        eq(start(is_char_in_string=lambda index: index >= pos), pos0)
+         # If everything before the 'def' is in a string, then returns None.
+         # The non-continuation def line returns 44 (see below).
+-        eq(start(is_char_in_string=lambda index: index < 44), None)
++        eq(start(is_char_in_string=lambda index: index < pos), None)
+         # Code without extra line break in def line - mostly returns the same
+         # values.
+         setcode('"""This is a module docstring"""\n'
+-                'class C():\n'
++                'class C:\n'
+                 '    def __init__(self, a, b=True):\n'
+                 '        pass\n'
+-                )
+-        eq(start(char_in_string_false), 44)
+-        eq(start(is_char_in_string=lambda index: index > 44), 44)
+-        eq(start(is_char_in_string=lambda index: index >= 44), 33)
++                )  # Does not affect class, def positions.
++        eq(start(char_in_string_false), pos)
++        eq(start(is_char_in_string=lambda index: index > pos), pos)
++        eq(start(is_char_in_string=lambda index: index >= pos), pos0)
+         # When the def line isn't split, this returns which doesn't match the
+         # split line test.
+-        eq(start(is_char_in_string=lambda index: index < 44), 44)
++        eq(start(is_char_in_string=lambda index: index < pos), pos)
+     def test_set_lo(self):
+         code = (
+                 '"""This is a module docstring"""\n'
+-                'class C():\n'
++                'class C:\n'
+                 '    def __init__(self, a,\n'
+                 '                 b=True):\n'
+                 '        pass\n'
+                 )
++        pos = 42
+         p = self.parser
+         p.set_code(code)
+@@ -137,8 +139,8 @@ class PyParseTest(unittest.TestCase):
+         self.assertEqual(p.code, code)
+         # An index that is preceded by a newline.
+-        p.set_lo(44)
+-        self.assertEqual(p.code, code[44:])
++        p.set_lo(pos)
++        self.assertEqual(p.code, code[pos:])
+     def test_study1(self):
+         eq = self.assertEqual
+diff --git a/Lib/idlelib/idle_test/test_replace.py b/Lib/idlelib/idle_test/test_replace.py
+index c3c5d2eeb9..6c07389b29 100644
+--- a/Lib/idlelib/idle_test/test_replace.py
++++ b/Lib/idlelib/idle_test/test_replace.py
+@@ -10,7 +10,7 @@ from unittest.mock import Mock
+ from idlelib.idle_test.mock_tk import Mbox
+ import idlelib.searchengine as se
+-orig_mbox = se.tkMessageBox
++orig_mbox = se.messagebox
+ showerror = Mbox.showerror
+@@ -20,7 +20,7 @@ class ReplaceDialogTest(unittest.TestCase):
+     def setUpClass(cls):
+         cls.root = Tk()
+         cls.root.withdraw()
+-        se.tkMessageBox = Mbox
++        se.messagebox = Mbox
+         cls.engine = se.SearchEngine(cls.root)
+         cls.dialog = ReplaceDialog(cls.root, cls.engine)
+         cls.dialog.bell = lambda: None
+@@ -32,7 +32,7 @@ class ReplaceDialogTest(unittest.TestCase):
+     @classmethod
+     def tearDownClass(cls):
+-        se.tkMessageBox = orig_mbox
++        se.messagebox = orig_mbox
+         del cls.text, cls.dialog, cls.engine
+         cls.root.destroy()
+         del cls.root
+diff --git a/Lib/idlelib/idle_test/test_run.py b/Lib/idlelib/idle_test/test_run.py
+index 37c0d4525e..a31671ee04 100644
+--- a/Lib/idlelib/idle_test/test_run.py
++++ b/Lib/idlelib/idle_test/test_run.py
+@@ -1,16 +1,18 @@
+ "Test run, coverage 49%."
+ from idlelib import run
++import io
++import sys
++from test.support import captured_output, captured_stderr
+ import unittest
+ from unittest import mock
++import idlelib
+ from idlelib.idle_test.mock_idle import Func
+-from test.support import captured_output, captured_stderr
+-import io
+-import sys
++idlelib.testing = True  # Use {} for executing test user code.
+-class RunTest(unittest.TestCase):
++class PrintExceptionTest(unittest.TestCase):
+     def test_print_exception_unhashable(self):
+         class UnhashableException(Exception):
+@@ -351,5 +353,38 @@ class HandleErrorTest(unittest.TestCase):
+             self.assertIn('IndexError', msg)
+             eq(func.called, 2)
++
++class ExecRuncodeTest(unittest.TestCase):
++
++    @classmethod
++    def setUpClass(cls):
++        cls.addClassCleanup(setattr,run,'print_exception',run.print_exception)
++        cls.prt = Func()  # Need reference.
++        run.print_exception = cls.prt
++        mockrpc = mock.Mock()
++        mockrpc.console.getvar = Func(result=False)
++        cls.ex = run.Executive(mockrpc)
++
++    @classmethod
++    def tearDownClass(cls):
++        assert sys.excepthook == sys.__excepthook__
++
++    def test_exceptions(self):
++        ex = self.ex
++        ex.runcode('1/0')
++        self.assertIs(ex.user_exc_info[0], ZeroDivisionError)
++
++        self.addCleanup(setattr, sys, 'excepthook', sys.__excepthook__)
++        sys.excepthook = lambda t, e, tb: run.print_exception(t)
++        ex.runcode('1/0')
++        self.assertIs(self.prt.args[0], ZeroDivisionError)
++
++        sys.excepthook = lambda: None
++        ex.runcode('1/0')
++        t, e, tb = ex.user_exc_info
++        self.assertIs(t, TypeError)
++        self.assertTrue(isinstance(e.__context__, ZeroDivisionError))
++
++
+ if __name__ == '__main__':
+     unittest.main(verbosity=2)
+diff --git a/Lib/idlelib/idle_test/test_searchengine.py b/Lib/idlelib/idle_test/test_searchengine.py
+index f8401ce938..9d97983941 100644
+--- a/Lib/idlelib/idle_test/test_searchengine.py
++++ b/Lib/idlelib/idle_test/test_searchengine.py
+@@ -4,7 +4,7 @@ from idlelib import searchengine as se
+ import unittest
+ # from test.support import requires
+ from tkinter import  BooleanVar, StringVar, TclError  # ,Tk, Text
+-import tkinter.messagebox as tkMessageBox
++from tkinter import messagebox
+ from idlelib.idle_test.mock_tk import Var, Mbox
+ from idlelib.idle_test.mock_tk import Text as mockText
+ import re
+@@ -19,13 +19,13 @@ def setUpModule():
+     # Replace s-e module tkinter imports other than non-gui TclError.
+     se.BooleanVar = Var
+     se.StringVar = Var
+-    se.tkMessageBox = Mbox
++    se.messagebox = Mbox
+ def tearDownModule():
+     # Restore 'just in case', though other tests should also replace.
+     se.BooleanVar = BooleanVar
+     se.StringVar = StringVar
+-    se.tkMessageBox = tkMessageBox
++    se.messagebox = messagebox
+ class Mock:
+diff --git a/Lib/idlelib/idle_test/test_squeezer.py b/Lib/idlelib/idle_test/test_squeezer.py
+index e3912f4bbb..ee1bbd76b5 100644
+--- a/Lib/idlelib/idle_test/test_squeezer.py
++++ b/Lib/idlelib/idle_test/test_squeezer.py
+@@ -396,7 +396,7 @@ class ExpandingButtonTest(unittest.TestCase):
+         expandingbutton.base_text = expandingbutton.text
+         # Patch the message box module to always return False.
+-        with patch('idlelib.squeezer.tkMessageBox') as mock_msgbox:
++        with patch('idlelib.squeezer.messagebox') as mock_msgbox:
+             mock_msgbox.askokcancel.return_value = False
+             mock_msgbox.askyesno.return_value = False
+             # Trigger the expand event.
+@@ -407,7 +407,7 @@ class ExpandingButtonTest(unittest.TestCase):
+         self.assertEqual(expandingbutton.text.get('1.0', 'end-1c'), '')
+         # Patch the message box module to always return True.
+-        with patch('idlelib.squeezer.tkMessageBox') as mock_msgbox:
++        with patch('idlelib.squeezer.messagebox') as mock_msgbox:
+             mock_msgbox.askokcancel.return_value = True
+             mock_msgbox.askyesno.return_value = True
+             # Trigger the expand event.
+diff --git a/Lib/idlelib/idle_test/test_zzdummy.py b/Lib/idlelib/idle_test/test_zzdummy.py
+new file mode 100644
+index 0000000000..1013cdc3c4
+--- /dev/null
++++ b/Lib/idlelib/idle_test/test_zzdummy.py
+@@ -0,0 +1,152 @@
++"Test zzdummy, coverage 100%."
++
++from idlelib import zzdummy
++import unittest
++from test.support import requires
++from tkinter import Tk, Text
++from unittest import mock
++from idlelib import config
++from idlelib import editor
++from idlelib import format
++
++
++usercfg = zzdummy.idleConf.userCfg
++testcfg = {
++    'main': config.IdleUserConfParser(''),
++    'highlight': config.IdleUserConfParser(''),
++    'keys': config.IdleUserConfParser(''),
++    'extensions': config.IdleUserConfParser(''),
++}
++code_sample = """\
++
++class C1():
++    # Class comment.
++    def __init__(self, a, b):
++        self.a = a
++        self.b = b
++"""
++
++
++class DummyEditwin:
++    get_selection_indices = editor.EditorWindow.get_selection_indices
++    def __init__(self, root, text):
++        self.root = root
++        self.top = root
++        self.text = text
++        self.fregion = format.FormatRegion(self)
++        self.text.undo_block_start = mock.Mock()
++        self.text.undo_block_stop = mock.Mock()
++
++
++class ZZDummyTest(unittest.TestCase):
++
++    @classmethod
++    def setUpClass(cls):
++        requires('gui')
++        root = cls.root = Tk()
++        root.withdraw()
++        text = cls.text = Text(cls.root)
++        cls.editor = DummyEditwin(root, text)
++        zzdummy.idleConf.userCfg = testcfg
++
++    @classmethod
++    def tearDownClass(cls):
++        zzdummy.idleConf.userCfg = usercfg
++        del cls.editor, cls.text
++        cls.root.update_idletasks()
++        for id in cls.root.tk.call('after', 'info'):
++            cls.root.after_cancel(id)  # Need for EditorWindow.
++        cls.root.destroy()
++        del cls.root
++
++    def setUp(self):
++        text = self.text
++        text.insert('1.0', code_sample)
++        text.undo_block_start.reset_mock()
++        text.undo_block_stop.reset_mock()
++        zz = self.zz = zzdummy.ZzDummy(self.editor)
++        zzdummy.ZzDummy.ztext = '# ignore #'
++
++    def tearDown(self):
++        self.text.delete('1.0', 'end')
++        del self.zz
++
++    def checklines(self, text, value):
++        # Verify that there are lines being checked.
++        end_line = int(float(text.index('end')))
++
++        # Check each line for the starting text.
++        actual = []
++        for line in range(1, end_line):
++            txt = text.get(f'{line}.0', f'{line}.end')
++            actual.append(txt.startswith(value))
++        return actual
++
++    def test_init(self):
++        zz = self.zz
++        self.assertEqual(zz.editwin, self.editor)
++        self.assertEqual(zz.text, self.editor.text)
++
++    def test_reload(self):
++        self.assertEqual(self.zz.ztext, '# ignore #')
++        testcfg['extensions'].SetOption('ZzDummy', 'z-text', 'spam')
++        zzdummy.ZzDummy.reload()
++        self.assertEqual(self.zz.ztext, 'spam')
++
++    def test_z_in_event(self):
++        eq = self.assertEqual
++        zz = self.zz
++        text = zz.text
++        eq(self.zz.ztext, '# ignore #')
++
++        # No lines have the leading text.
++        expected = [False, False, False, False, False, False, False]
++        actual = self.checklines(text, zz.ztext)
++        eq(expected, actual)
++
++        text.tag_add('sel', '2.0', '4.end')
++        eq(zz.z_in_event(), 'break')
++        expected = [False, True, True, True, False, False, False]
++        actual = self.checklines(text, zz.ztext)
++        eq(expected, actual)
++
++        text.undo_block_start.assert_called_once()
++        text.undo_block_stop.assert_called_once()
++
++    def test_z_out_event(self):
++        eq = self.assertEqual
++        zz = self.zz
++        text = zz.text
++        eq(self.zz.ztext, '# ignore #')
++
++        # Prepend text.
++        text.tag_add('sel', '2.0', '5.end')
++        zz.z_in_event()
++        text.undo_block_start.reset_mock()
++        text.undo_block_stop.reset_mock()
++
++        # Select a few lines to remove text.
++        text.tag_remove('sel', '1.0', 'end')
++        text.tag_add('sel', '3.0', '4.end')
++        eq(zz.z_out_event(), 'break')
++        expected = [False, True, False, False, True, False, False]
++        actual = self.checklines(text, zz.ztext)
++        eq(expected, actual)
++
++        text.undo_block_start.assert_called_once()
++        text.undo_block_stop.assert_called_once()
++
++    def test_roundtrip(self):
++        # Insert and remove to all code should give back original text.
++        zz = self.zz
++        text = zz.text
++
++        text.tag_add('sel', '1.0', 'end-1c')
++        zz.z_in_event()
++        zz.z_out_event()
++
++        self.assertEqual(text.get('1.0', 'end-1c'), code_sample)
++
++
++if __name__ == '__main__':
++    unittest.main(verbosity=2)
+diff --git a/Lib/idlelib/iomenu.py b/Lib/idlelib/iomenu.py
+index 8bb2fa6a6e..5ebf7089fb 100644
+--- a/Lib/idlelib/iomenu.py
++++ b/Lib/idlelib/iomenu.py
+@@ -5,8 +5,8 @@ import sys
+ import tempfile
+ import tokenize
+-import tkinter.filedialog as tkFileDialog
+-import tkinter.messagebox as tkMessageBox
++from tkinter import filedialog
++from tkinter import messagebox
+ from tkinter.simpledialog import askstring
+ import idlelib
+@@ -147,10 +147,10 @@ class IOBinding:
+                     eol_convention = f.newlines
+                     converted = True
+         except OSError as err:
+-            tkMessageBox.showerror("I/O Error", str(err), parent=self.text)
++            messagebox.showerror("I/O Error", str(err), parent=self.text)
+             return False
+         except UnicodeDecodeError:
+-            tkMessageBox.showerror("Decoding Error",
++            messagebox.showerror("Decoding Error",
+                                    "File %s\nFailed to Decode" % filename,
+                                    parent=self.text)
+             return False
+@@ -159,7 +159,7 @@ class IOBinding:
+             # If the file does not contain line separators, it is None.
+             # If the file contains mixed line separators, it is a tuple.
+             if eol_convention is not None:
+-                tkMessageBox.showwarning("Mixed Newlines",
++                messagebox.showwarning("Mixed Newlines",
+                                          "Mixed newlines detected.\n"
+                                          "The file will be changed on save.",
+                                          parent=self.text)
+@@ -187,10 +187,10 @@ class IOBinding:
+             return "yes"
+         message = "Do you want to save %s before closing?" % (
+             self.filename or "this untitled document")
+-        confirm = tkMessageBox.askyesnocancel(
++        confirm = messagebox.askyesnocancel(
+                   title="Save On Close",
+                   message=message,
+-                  default=tkMessageBox.YES,
++                  default=messagebox.YES,
+                   parent=self.text)
+         if confirm:
+             reply = "yes"
+@@ -249,7 +249,7 @@ class IOBinding:
+                 os.fsync(f.fileno())
+             return True
+         except OSError as msg:
+-            tkMessageBox.showerror("I/O Error", str(msg),
++            messagebox.showerror("I/O Error", str(msg),
+                                    parent=self.text)
+             return False
+@@ -286,7 +286,7 @@ class IOBinding:
+             failed = str(err)
+         except UnicodeEncodeError:
+             failed = "Invalid encoding '%s'" % enc
+-        tkMessageBox.showerror(
++        messagebox.showerror(
+             "I/O Error",
+             "%s.\nSaving as UTF-8" % failed,
+             parent=self.text)
+@@ -295,10 +295,10 @@ class IOBinding:
+         return chars.encode('utf-8-sig')
+     def print_window(self, event):
+-        confirm = tkMessageBox.askokcancel(
++        confirm = messagebox.askokcancel(
+                   title="Print",
+                   message="Print to Default Printer",
+-                  default=tkMessageBox.OK,
++                  default=messagebox.OK,
+                   parent=self.text)
+         if not confirm:
+             self.text.focus_set()
+@@ -336,10 +336,10 @@ class IOBinding:
+                          status + output
+             if output:
+                 output = "Printing command: %s\n" % repr(command) + output
+-                tkMessageBox.showerror("Print status", output, parent=self.text)
++                messagebox.showerror("Print status", output, parent=self.text)
+         else:  #no printing for this platform
+             message = "Printing is not enabled for this platform: %s" % platform
+-            tkMessageBox.showinfo("Print status", message, parent=self.text)
++            messagebox.showinfo("Print status", message, parent=self.text)
+         if tempfilename:
+             os.unlink(tempfilename)
+         return "break"
+@@ -358,7 +358,7 @@ class IOBinding:
+     def askopenfile(self):
+         dir, base = self.defaultfilename("open")
+         if not self.opendialog:
+-            self.opendialog = tkFileDialog.Open(parent=self.text,
++            self.opendialog = filedialog.Open(parent=self.text,
+                                                 filetypes=self.filetypes)
+         filename = self.opendialog.show(initialdir=dir, initialfile=base)
+         return filename
+@@ -378,7 +378,7 @@ class IOBinding:
+     def asksavefile(self):
+         dir, base = self.defaultfilename("save")
+         if not self.savedialog:
+-            self.savedialog = tkFileDialog.SaveAs(
++            self.savedialog = filedialog.SaveAs(
+                     parent=self.text,
+                     filetypes=self.filetypes,
+                     defaultextension=self.defaultextension)
+diff --git a/Lib/idlelib/pyshell.py b/Lib/idlelib/pyshell.py
+index adc302883a..fea3762461 100755
+--- a/Lib/idlelib/pyshell.py
++++ b/Lib/idlelib/pyshell.py
+@@ -21,13 +21,13 @@ if sys.platform == 'win32':
+     except (ImportError, AttributeError, OSError):
+         pass
+-import tkinter.messagebox as tkMessageBox
++from tkinter import messagebox
+ if TkVersion < 8.5:
+     root = Tk()  # otherwise create root in main
+     root.withdraw()
+     from idlelib.run import fix_scaling
+     fix_scaling(root)
+-    tkMessageBox.showerror("Idle Cannot Start",
++    messagebox.showerror("Idle Cannot Start",
+             "Idle requires tcl/tk 8.5+, not %s." % TkVersion,
+             parent=root)
+     raise SystemExit(1)
+@@ -261,7 +261,7 @@ class PyShellEditorWindow(EditorWindow):
+         except OSError as err:
+             if not getattr(self.root, "breakpoint_error_displayed", False):
+                 self.root.breakpoint_error_displayed = True
+-                tkMessageBox.showerror(title='IDLE Error',
++                messagebox.showerror(title='IDLE Error',
+                     message='Unable to update breakpoint list:\n%s'
+                         % str(err),
+                     parent=self.text)
+@@ -771,7 +771,7 @@ class ModifiedInterpreter(InteractiveInterpreter):
+                 exec(code, self.locals)
+         except SystemExit:
+             if not self.tkconsole.closing:
+-                if tkMessageBox.askyesno(
++                if messagebox.askyesno(
+                     "Exit?",
+                     "Do you want to exit altogether?",
+                     default="yes",
+@@ -805,7 +805,7 @@ class ModifiedInterpreter(InteractiveInterpreter):
+         return self.tkconsole.stderr.write(s)
+     def display_port_binding_error(self):
+-        tkMessageBox.showerror(
++        messagebox.showerror(
+             "Port Binding Error",
+             "IDLE can't bind to a TCP/IP port, which is necessary to "
+             "communicate with its Python execution server.  This might be "
+@@ -816,7 +816,7 @@ class ModifiedInterpreter(InteractiveInterpreter):
+             parent=self.tkconsole.text)
+     def display_no_subprocess_error(self):
+-        tkMessageBox.showerror(
++        messagebox.showerror(
+             "Subprocess Connection Error",
+             "IDLE's subprocess didn't make connection.\n"
+             "See the 'Startup failure' section of the IDLE doc, online at\n"
+@@ -824,7 +824,7 @@ class ModifiedInterpreter(InteractiveInterpreter):
+             parent=self.tkconsole.text)
+     def display_executing_dialog(self):
+-        tkMessageBox.showerror(
++        messagebox.showerror(
+             "Already executing",
+             "The Python Shell window is already executing a command; "
+             "please wait until it is finished.",
+@@ -945,7 +945,7 @@ class PyShell(OutputWindow):
+     def toggle_debugger(self, event=None):
+         if self.executing:
+-            tkMessageBox.showerror("Don't debug now",
++            messagebox.showerror("Don't debug now",
+                 "You can only toggle the debugger when idle",
+                 parent=self.text)
+             self.set_debugger_indicator()
+@@ -989,6 +989,10 @@ class PyShell(OutputWindow):
+         self.showprompt()
+         self.set_debugger_indicator()
++    def debug_menu_postcommand(self):
++        state = 'disabled' if self.executing else 'normal'
++        self.update_menu_state('debug', '*tack*iewer', state)
++
+     def beginexecuting(self):
+         "Helper for ModifiedInterpreter"
+         self.resetoutput()
+@@ -1003,7 +1007,7 @@ class PyShell(OutputWindow):
+     def close(self):
+         "Extend EditorWindow.close()"
+         if self.executing:
+-            response = tkMessageBox.askokcancel(
++            response = messagebox.askokcancel(
+                 "Kill?",
+                 "Your program is still running!\n Do you want to kill it?",
+                 default="ok",
+@@ -1061,8 +1065,10 @@ class PyShell(OutputWindow):
+                    (sys.version, sys.platform, self.COPYRIGHT, nosub))
+         self.text.focus_force()
+         self.showprompt()
++        # User code should use separate default Tk root window
+         import tkinter
+-        tkinter._default_root = None # 03Jan04 KBK What's this?
++        tkinter._support_default_root = True
++        tkinter._default_root = None
+         return True
+     def stop_readline(self):
+@@ -1252,7 +1258,7 @@ class PyShell(OutputWindow):
+         try:
+             sys.last_traceback
+         except:
+-            tkMessageBox.showerror("No stack trace",
++            messagebox.showerror("No stack trace",
+                 "There is no stack trace yet.\n"
+                 "(sys.last_traceback is not defined)",
+                 parent=self.text)
+diff --git a/Lib/idlelib/rpc.py b/Lib/idlelib/rpc.py
+index aa8cbd36c4..8efcf048fa 100644
+--- a/Lib/idlelib/rpc.py
++++ b/Lib/idlelib/rpc.py
+@@ -125,7 +125,7 @@ request_queue = queue.Queue(0)
+ response_queue = queue.Queue(0)
+-class SocketIO(object):
++class SocketIO:
+     nextseq = 0
+@@ -486,7 +486,7 @@ class SocketIO(object):
+ #----------------- end class SocketIO --------------------
+-class RemoteObject(object):
++class RemoteObject:
+     # Token mix-in class
+     pass
+@@ -497,7 +497,7 @@ def remoteref(obj):
+     return RemoteProxy(oid)
+-class RemoteProxy(object):
++class RemoteProxy:
+     def __init__(self, oid):
+         self.oid = oid
+@@ -547,7 +547,7 @@ class RPCClient(SocketIO):
+         return RPCProxy(self, oid)
+-class RPCProxy(object):
++class RPCProxy:
+     __methods = None
+     __attributes = None
+@@ -596,7 +596,7 @@ def _getattributes(obj, attributes):
+             attributes[name] = 1
+-class MethodProxy(object):
++class MethodProxy:
+     def __init__(self, sockio, oid, name):
+         self.sockio = sockio
+diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py
+index 1e84ecc658..07e9a2bf9c 100644
+--- a/Lib/idlelib/run.py
++++ b/Lib/idlelib/run.py
+@@ -16,6 +16,7 @@ import _thread as thread
+ import threading
+ import warnings
++import idlelib  # testing
+ from idlelib import autocomplete  # AutoComplete, fetch_encodings
+ from idlelib import calltip  # Calltip
+ from idlelib import debugger_r  # start_debugger
+@@ -538,18 +539,21 @@ class MyHandler(rpc.RPCHandler):
+         thread.interrupt_main()
+-class Executive(object):
++class Executive:
+     def __init__(self, rpchandler):
+         self.rpchandler = rpchandler
+-        self.locals = __main__.__dict__
+-        self.calltip = calltip.Calltip()
+-        self.autocomplete = autocomplete.AutoComplete()
++        if idlelib.testing is False:
++            self.locals = __main__.__dict__
++            self.calltip = calltip.Calltip()
++            self.autocomplete = autocomplete.AutoComplete()
++        else:
++            self.locals = {}
+     def runcode(self, code):
+         global interruptable
+         try:
+-            self.usr_exc_info = None
++            self.user_exc_info = None
+             interruptable = True
+             try:
+                 exec(code, self.locals)
+@@ -562,10 +566,17 @@ class Executive(object):
+                     print('SystemExit: ' + str(ob), file=sys.stderr)
+             # Return to the interactive prompt.
+         except:
+-            self.usr_exc_info = sys.exc_info()
++            self.user_exc_info = sys.exc_info()  # For testing, hook, viewer.
+             if quitting:
+                 exit()
+-            print_exception()
++            if sys.excepthook is sys.__excepthook__:
++                print_exception()
++            else:
++                try:
++                    sys.excepthook(*self.user_exc_info)
++                except:
++                    self.user_exc_info = sys.exc_info()  # For testing.
++                    print_exception()
+             jit = self.rpchandler.console.getvar("<<toggle-jit-stack-viewer>>")
+             if jit:
+                 self.rpchandler.interp.open_remote_stack_viewer()
+@@ -590,8 +601,8 @@ class Executive(object):
+         return self.autocomplete.fetch_completions(what, mode)
+     def stackviewer(self, flist_oid=None):
+-        if self.usr_exc_info:
+-            typ, val, tb = self.usr_exc_info
++        if self.user_exc_info:
++            typ, val, tb = self.user_exc_info
+         else:
+             return None
+         flist = None
+diff --git a/Lib/idlelib/runscript.py b/Lib/idlelib/runscript.py
+index 028b0dbd21..55712e9046 100644
+--- a/Lib/idlelib/runscript.py
++++ b/Lib/idlelib/runscript.py
+@@ -14,7 +14,7 @@ import tabnanny
+ import time
+ import tokenize
+-import tkinter.messagebox as tkMessageBox
++from tkinter import messagebox
+ from idlelib.config import idleConf
+ from idlelib import macosx
+@@ -195,15 +195,15 @@ class ScriptBinding:
+     def ask_save_dialog(self):
+         msg = "Source Must Be Saved\n" + 5*' ' + "OK to Save?"
+-        confirm = tkMessageBox.askokcancel(title="Save Before Run or Check",
++        confirm = messagebox.askokcancel(title="Save Before Run or Check",
+                                            message=msg,
+-                                           default=tkMessageBox.OK,
++                                           default=messagebox.OK,
+                                            parent=self.editwin.text)
+         return confirm
+     def errorbox(self, title, message):
+         # XXX This should really be a function of EditorWindow...
+-        tkMessageBox.showerror(title, message, parent=self.editwin.text)
++        messagebox.showerror(title, message, parent=self.editwin.text)
+         self.editwin.text.focus_set()
+         self.perf = time.perf_counter()
+diff --git a/Lib/idlelib/searchengine.py b/Lib/idlelib/searchengine.py
+index a50038e282..eddef581ab 100644
+--- a/Lib/idlelib/searchengine.py
++++ b/Lib/idlelib/searchengine.py
+@@ -2,7 +2,7 @@
+ import re
+ from tkinter import StringVar, BooleanVar, TclError
+-import tkinter.messagebox as tkMessageBox
++from tkinter import messagebox
+ def get(root):
+     '''Return the singleton SearchEngine instance for the process.
+@@ -96,7 +96,7 @@ class SearchEngine:
+             msg = msg + "\nPattern: " + str(pat)
+         if col is not None:
+             msg = msg + "\nOffset: " + str(col)
+-        tkMessageBox.showerror("Regular expression error",
++        messagebox.showerror("Regular expression error",
+                                msg, master=self.root)
+     def search_text(self, text, prog=None, ok=0):
+diff --git a/Lib/idlelib/squeezer.py b/Lib/idlelib/squeezer.py
+index be1538a25f..3046d803b7 100644
+--- a/Lib/idlelib/squeezer.py
++++ b/Lib/idlelib/squeezer.py
+@@ -17,7 +17,7 @@ messages and their tracebacks.
+ import re
+ import tkinter as tk
+-import tkinter.messagebox as tkMessageBox
++from tkinter import messagebox
+ from idlelib.config import idleConf
+ from idlelib.textview import view_text
+@@ -147,7 +147,7 @@ class ExpandingButton(tk.Button):
+         if self.is_dangerous is None:
+             self.set_is_dangerous()
+         if self.is_dangerous:
+-            confirm = tkMessageBox.askokcancel(
++            confirm = messagebox.askokcancel(
+                 title="Expand huge output?",
+                 message="\n\n".join([
+                     "The squeezed output is very long: %d lines, %d chars.",
+@@ -155,7 +155,7 @@ class ExpandingButton(tk.Button):
+                     "It is recommended to view or copy the output instead.",
+                     "Really expand?"
+                 ]) % (self.numoflines, len(self.s)),
+-                default=tkMessageBox.CANCEL,
++                default=messagebox.CANCEL,
+                 parent=self.text)
+             if not confirm:
+                 return "break"
+diff --git a/Lib/idlelib/tooltip.py b/Lib/idlelib/tooltip.py
+index 69658264db..d714318dae 100644
+--- a/Lib/idlelib/tooltip.py
++++ b/Lib/idlelib/tooltip.py
+@@ -7,7 +7,7 @@ This includes:
+ from tkinter import *
+-class TooltipBase(object):
++class TooltipBase:
+     """abstract base class for tooltips"""
+     def __init__(self, anchor_widget):
+diff --git a/Lib/idlelib/zzdummy.py b/Lib/idlelib/zzdummy.py
+index 3c4b1d23b0..1247e8f1cc 100644
+--- a/Lib/idlelib/zzdummy.py
++++ b/Lib/idlelib/zzdummy.py
+@@ -1,42 +1,73 @@
+-"Example extension, also used for testing."
++"""Example extension, also used for testing.
++
++See extend.txt for more details on creating an extension.
++See config-extension.def for configuring an extension.
++"""
+ from idlelib.config import idleConf
++from functools import wraps
++
++
++def format_selection(format_line):
++    "Apply a formatting function to all of the selected lines."
++
++    @wraps(format_line)
++    def apply(self, event=None):
++        head, tail, chars, lines = self.formatter.get_region()
++        for pos in range(len(lines) - 1):
++            line = lines[pos]
++            lines[pos] = format_line(self, line)
++        self.formatter.set_region(head, tail, chars, lines)
++        return 'break'
+-ztext = idleConf.GetOption('extensions', 'ZzDummy', 'z-text')
++    return apply
+ class ZzDummy:
++    """Prepend or remove initial text from selected lines."""
+-##    menudefs = [
+-##        ('format', [
+-##            ('Z in', '<<z-in>>'),
+-##            ('Z out', '<<z-out>>'),
+-##        ] )
+-##    ]
++    # Extend the format menu.
++    menudefs = [
++        ('format', [
++            ('Z in', '<<z-in>>'),
++            ('Z out', '<<z-out>>'),
++        ] )
++    ]
+     def __init__(self, editwin):
++        "Initialize the settings for this extension."
++        self.editwin = editwin
+         self.text = editwin.text
+-        z_in = False
++        self.formatter = editwin.fregion
+     @classmethod
+     def reload(cls):
++        "Load class variables from config."
+         cls.ztext = idleConf.GetOption('extensions', 'ZzDummy', 'z-text')
+-    def z_in_event(self, event):
++    @format_selection
++    def z_in_event(self, line):
++        """Insert text at the beginning of each selected line.
++
++        This is bound to the <<z-in>> virtual event when the extensions
++        are loaded.
+         """
++        return f'{self.ztext}{line}'
++
++    @format_selection
++    def z_out_event(self, line):
++        """Remove specific text from the beginning of each selected line.
++
++        This is bound to the <<z-out>> virtual event when the extensions
++        are loaded.
+         """
+-        text = self.text
+-        text.undo_block_start()
+-        for line in range(1, text.index('end')):
+-            text.insert('%d.0', ztext)
+-        text.undo_block_stop()
+-        return "break"
++        zlength = 0 if not line.startswith(self.ztext) else len(self.ztext)
++        return line[zlength:]
+-    def z_out_event(self, event): pass
+ ZzDummy.reload()
+-##if __name__ == "__main__":
+-##    import unittest
+-##    unittest.main('idlelib.idle_test.test_zzdummy',
+-##            verbosity=2, exit=False)
++
++if __name__ == "__main__":
++    import unittest
++    unittest.main('idlelib.idle_test.test_zzdummy', verbosity=2, exit=False)
+diff --git a/Lib/lib2to3/Grammar.txt b/Lib/lib2to3/Grammar.txt
+index e007dc188a..fa7b15061d 100644
+--- a/Lib/lib2to3/Grammar.txt
++++ b/Lib/lib2to3/Grammar.txt
+@@ -18,15 +18,55 @@ decorated: decorators (classdef | funcdef | async_funcdef)
+ async_funcdef: ASYNC funcdef
+ funcdef: 'def' NAME parameters ['->' test] ':' suite
+ parameters: '(' [typedargslist] ')'
+-typedargslist: ((tfpdef ['=' test] ',')*
+-                ('*' [tname] (',' tname ['=' test])* [',' ['**' tname [',']]] | '**' tname [','])
+-                | tfpdef ['=' test] (',' tfpdef ['=' test])* [','])
++
++# The following definition for typedarglist is equivalent to this set of rules:
++#
++#     arguments = argument (',' argument)*
++#     argument = tfpdef ['=' test]
++#     kwargs = '**' tname [',']
++#     args = '*' [tname]
++#     kwonly_kwargs = (',' argument)* [',' [kwargs]]
++#     args_kwonly_kwargs = args kwonly_kwargs | kwargs
++#     poskeyword_args_kwonly_kwargs = arguments [',' [args_kwonly_kwargs]]
++#     typedargslist_no_posonly  = poskeyword_args_kwonly_kwargs | args_kwonly_kwargs
++#     typedarglist = arguments ',' '/' [',' [typedargslist_no_posonly]])|(typedargslist_no_posonly)"
++#
++# It needs to be fully expanded to allow our LL(1) parser to work on it.
++
++typedargslist: tfpdef ['=' test] (',' tfpdef ['=' test])* ',' '/' [
++                     ',' [((tfpdef ['=' test] ',')* ('*' [tname] (',' tname ['=' test])*
++                            [',' ['**' tname [',']]] | '**' tname [','])
++                     | tfpdef ['=' test] (',' tfpdef ['=' test])* [','])]
++                ] | ((tfpdef ['=' test] ',')* ('*' [tname] (',' tname ['=' test])*
++                     [',' ['**' tname [',']]] | '**' tname [','])
++                     | tfpdef ['=' test] (',' tfpdef ['=' test])* [','])
++
+ tname: NAME [':' test]
+ tfpdef: tname | '(' tfplist ')'
+ tfplist: tfpdef (',' tfpdef)* [',']
+-varargslist: ((vfpdef ['=' test] ',')*
+-              ('*' [vname] (',' vname ['=' test])*  [',' ['**' vname [',']]] | '**' vname [','])
+-              | vfpdef ['=' test] (',' vfpdef ['=' test])* [','])
++
++# The following definition for varargslist is equivalent to this set of rules:
++#
++#     arguments = argument (',' argument )*
++#     argument = vfpdef ['=' test]
++#     kwargs = '**' vname [',']
++#     args = '*' [vname]
++#     kwonly_kwargs = (',' argument )* [',' [kwargs]]
++#     args_kwonly_kwargs = args kwonly_kwargs | kwargs
++#     poskeyword_args_kwonly_kwargs = arguments [',' [args_kwonly_kwargs]]
++#     vararglist_no_posonly = poskeyword_args_kwonly_kwargs | args_kwonly_kwargs
++#     varargslist = arguments ',' '/' [','[(vararglist_no_posonly)]] | (vararglist_no_posonly)
++#
++# It needs to be fully expanded to allow our LL(1) parser to work on it.
++
++varargslist: vfpdef ['=' test ](',' vfpdef ['=' test])* ',' '/' [',' [
++                     ((vfpdef ['=' test] ',')* ('*' [vname] (',' vname ['=' test])*
++                            [',' ['**' vname [',']]] | '**' vname [','])
++                            | vfpdef ['=' test] (',' vfpdef ['=' test])* [','])
++                     ]] | ((vfpdef ['=' test] ',')*
++                     ('*' [vname] (',' vname ['=' test])*  [',' ['**' vname [',']]]| '**' vname [','])
++                     | vfpdef ['=' test] (',' vfpdef ['=' test])* [','])
++
+ vname: NAME
+ vfpdef: vname | '(' vfplist ')'
+ vfplist: vfpdef (',' vfpdef)* [',']
+diff --git a/Lib/lib2to3/tests/test_parser.py b/Lib/lib2to3/tests/test_parser.py
+index ba2bb78733..d5db66b9b1 100644
+--- a/Lib/lib2to3/tests/test_parser.py
++++ b/Lib/lib2to3/tests/test_parser.py
+@@ -272,6 +272,12 @@ class TestUnpackingGeneralizations(GrammarTest):
+     def test_dict_display_2(self):
+         self.validate("""{**{}, 3:4, **{5:6, 7:8}}""")
++    def test_complex_star_expression(self):
++        self.validate("func(* [] or [1])")
++
++    def test_complex_double_star_expression(self):
++        self.validate("func(**{1: 3} if False else {x: x for x in range(3)})")
++
+     def test_argument_unpacking_1(self):
+         self.validate("""f(a, *b, *c, d)""")
+@@ -630,6 +636,7 @@ class TestLiterals(GrammarTest):
+ class TestNamedAssignments(GrammarTest):
++    """Also known as the walrus operator."""
+     def test_named_assignment_if(self):
+         driver.parse_string("if f := x(): pass\n")
+@@ -644,6 +651,30 @@ class TestNamedAssignments(GrammarTest):
+         driver.parse_string("[(lastNum := num) == 1 for num in [1, 2, 3]]\n")
++class TestPositionalOnlyArgs(GrammarTest):
++
++    def test_one_pos_only_arg(self):
++        driver.parse_string("def one_pos_only_arg(a, /): pass\n")
++
++    def test_all_markers(self):
++        driver.parse_string(
++                "def all_markers(a, b=2, /, c, d=4, *, e=5, f): pass\n")
++
++    def test_all_with_args_and_kwargs(self):
++        driver.parse_string(
++                """def all_markers_with_args_and_kwargs(
++                           aa, b, /, _cc, d, *args, e, f_f, **kwargs,
++                   ):
++                       pass\n""")
++
++    def test_lambda_soup(self):
++        driver.parse_string(
++                "lambda a, b, /, c, d, *args, e, f, **kw: kw\n")
++
++    def test_only_positional_or_keyword(self):
++        driver.parse_string("def func(a,b,/,*,g,e=3): pass\n")
++
++
+ class TestPickleableException(unittest.TestCase):
+     def test_ParseError(self):
+         err = ParseError('msg', 2, None, (1, 'context'))
+diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py
+index 7b169a16fb..6920a7b654 100644
+--- a/Lib/logging/__init__.py
++++ b/Lib/logging/__init__.py
+@@ -1269,6 +1269,14 @@ class Manager(object):
+         self.loggerClass = None
+         self.logRecordFactory = None
++    @property
++    def disable(self):
++        return self._disable
++
++    @disable.setter
++    def disable(self, value):
++        self._disable = _checkLevel(value)
++
+     def getLogger(self, name):
+         """
+         Get a logger with the specified name (channel name), creating it
+diff --git a/Lib/pdb.py b/Lib/pdb.py
+index d7d9571594..7a5192cbad 100755
+--- a/Lib/pdb.py
++++ b/Lib/pdb.py
+@@ -1686,8 +1686,9 @@ def main():
+     sys.argv[:] = args      # Hide "pdb.py" and pdb options from argument list
+-    # Replace pdb's dir with script's dir in front of module search path.
+     if not run_as_module:
++        mainpyfile = os.path.realpath(mainpyfile)
++        # Replace pdb's dir with script's dir in front of module search path.
+         sys.path[0] = os.path.dirname(mainpyfile)
+     # Note on saving/restoring sys.argv: it's a good idea when sys.argv was
+diff --git a/Lib/platform.py b/Lib/platform.py
+index e9f50ab622..6258827d0e 100755
+--- a/Lib/platform.py
++++ b/Lib/platform.py
+@@ -782,7 +782,7 @@ class uname_result(
+         ):
+     """
+     A uname_result that's largely compatible with a
+-    simple namedtuple except that 'platform' is
++    simple namedtuple except that 'processor' is
+     resolved late and cached to avoid calling "uname"
+     except when needed.
+     """
+@@ -797,12 +797,25 @@ class uname_result(
+             (self.processor,)
+         )
++    @classmethod
++    def _make(cls, iterable):
++        # override factory to affect length check
++        num_fields = len(cls._fields)
++        result = cls.__new__(cls, *iterable)
++        if len(result) != num_fields + 1:
++            msg = f'Expected {num_fields} arguments, got {len(result)}'
++            raise TypeError(msg)
++        return result
++
+     def __getitem__(self, key):
+-        return tuple(iter(self))[key]
++        return tuple(self)[key]
+     def __len__(self):
+         return len(tuple(iter(self)))
++    def __reduce__(self):
++        return uname_result, tuple(self)[:len(self._fields)]
++
+ _uname_cache = None
+diff --git a/Lib/profile.py b/Lib/profile.py
+index 5cb017ed83..d8599fb4ee 100755
+--- a/Lib/profile.py
++++ b/Lib/profile.py
+@@ -595,7 +595,12 @@ def main():
+                 '__package__': None,
+                 '__cached__': None,
+             }
+-        runctx(code, globs, None, options.outfile, options.sort)
++        try:
++            runctx(code, globs, None, options.outfile, options.sort)
++        except BrokenPipeError as exc:
++            # Prevent "Exception ignored" during interpreter shutdown.
++            sys.stdout = None
++            sys.exit(exc.errno)
+     else:
+         parser.print_usage()
+     return parser
+diff --git a/Lib/random.py b/Lib/random.py
+index a6454f520d..36e16a9063 100644
+--- a/Lib/random.py
++++ b/Lib/random.py
+@@ -77,6 +77,7 @@ __all__ = [
+     "lognormvariate",
+     "normalvariate",
+     "paretovariate",
++    "randbytes",
+     "randint",
+     "random",
+     "randrange",
+@@ -441,7 +442,7 @@ class Random(_random.Random):
+                 raise TypeError('Counts must be integers')
+             if total <= 0:
+                 raise ValueError('Total of counts must be greater than zero')
+-            selections = sample(range(total), k=k)
++            selections = self.sample(range(total), k=k)
+             bisect = _bisect
+             return [population[bisect(cum_counts, s)] for s in selections]
+         randbelow = self._randbelow
+diff --git a/Lib/smtplib.py b/Lib/smtplib.py
+index 7808ba01cb..f0472317de 100755
+--- a/Lib/smtplib.py
++++ b/Lib/smtplib.py
+@@ -1082,7 +1082,8 @@ class LMTP(SMTP):
+         # Handle Unix-domain sockets.
+         try:
+             self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+-            self.sock.settimeout(self.timeout)
++            if self.timeout is not socket._GLOBAL_DEFAULT_TIMEOUT:
++                self.sock.settimeout(self.timeout)
+             self.file = None
+             self.sock.connect(host)
+         except OSError:
+diff --git a/Lib/sqlite3/test/hooks.py b/Lib/sqlite3/test/hooks.py
+index d74e74bf27..214205c116 100644
+--- a/Lib/sqlite3/test/hooks.py
++++ b/Lib/sqlite3/test/hooks.py
+@@ -265,6 +265,14 @@ class TraceCallbackTests(unittest.TestCase):
+         cur.execute(queries[0])
+         con2.execute("create table bar(x)")
+         cur.execute(queries[1])
++
++        # Extract from SQLite 3.7.15 changelog:
++        # Avoid invoking the sqlite3_trace() callback multiple times when a
++        # statement is automatically reprepared due to SQLITE_SCHEMA errors.
++        #
++        # See bpo-40810
++        if sqlite.sqlite_version_info < (3, 7, 15):
++            queries.append(queries[-1])
+         self.assertEqual(traced_statements, queries)
+diff --git a/Lib/subprocess.py b/Lib/subprocess.py
+index f1d829a6f1..ddf1128fdd 100644
+--- a/Lib/subprocess.py
++++ b/Lib/subprocess.py
+@@ -415,7 +415,11 @@ def check_output(*popenargs, timeout=None, **kwargs):
+     if 'input' in kwargs and kwargs['input'] is None:
+         # Explicitly passing input=None was previously equivalent to passing an
+         # empty string. That is maintained here for backwards compatibility.
+-        kwargs['input'] = '' if kwargs.get('universal_newlines', False) else b''
++        if kwargs.get('universal_newlines') or kwargs.get('text'):
++            empty = ''
++        else:
++            empty = b''
++        kwargs['input'] = empty
+     return run(*popenargs, stdout=PIPE, timeout=timeout, check=True,
+                **kwargs).stdout
+diff --git a/Lib/sysconfig.py b/Lib/sysconfig.py
+index bf04ac541e..e3f79bfde5 100644
+--- a/Lib/sysconfig.py
++++ b/Lib/sysconfig.py
+@@ -18,6 +18,11 @@ __all__ = [
+     'parse_config_h',
+ ]
++# Keys for get_config_var() that are never converted to Python integers.
++_ALWAYS_STR = {
++    'MACOSX_DEPLOYMENT_TARGET',
++}
++
+ _INSTALL_SCHEMES = {
+     'posix_prefix': {
+         'stdlib': '{installed_base}/{platlibdir}/python{py_version_short}',
+@@ -240,6 +245,9 @@ def _parse_makefile(filename, vars=None):
+                 notdone[n] = v
+             else:
+                 try:
++                    if n in _ALWAYS_STR:
++                        raise ValueError
++
+                     v = int(v)
+                 except ValueError:
+                     # insert literal `$'
+@@ -298,6 +306,8 @@ def _parse_makefile(filename, vars=None):
+                         notdone[name] = value
+                     else:
+                         try:
++                            if name in _ALWAYS_STR:
++                                raise ValueError
+                             value = int(value)
+                         except ValueError:
+                             done[name] = value.strip()
+@@ -424,10 +434,11 @@ def _init_posix(vars):
+ def _init_non_posix(vars):
+     """Initialize the module as appropriate for NT"""
+     # set basic install directories
++    import _imp
+     vars['LIBDEST'] = get_path('stdlib')
+     vars['BINLIBDEST'] = get_path('platstdlib')
+     vars['INCLUDEPY'] = get_path('include')
+-    vars['EXT_SUFFIX'] = '.pyd'
++    vars['EXT_SUFFIX'] = _imp.extension_suffixes()[0]
+     vars['EXE'] = '.exe'
+     vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
+     vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
+@@ -458,6 +469,8 @@ def parse_config_h(fp, vars=None):
+         if m:
+             n, v = m.group(1, 2)
+             try:
++                if n in _ALWAYS_STR:
++                    raise ValueError
+                 v = int(v)
+             except ValueError:
+                 pass
+diff --git a/Lib/test/crashers/bogus_code_obj.py b/Lib/test/crashers/bogus_code_obj.py
+index 198d229491..e71b3582cf 100644
+--- a/Lib/test/crashers/bogus_code_obj.py
++++ b/Lib/test/crashers/bogus_code_obj.py
+@@ -14,6 +14,6 @@ the user build or load random bytecodes anyway.  Otherwise, this is a
+ import types
+-co = types.CodeType(0, 0, 0, 0, 0, b'\x04\x71\x00\x00',
++co = types.CodeType(0, 0, 0, 0, 0, 0, b'\x04\x00\x71\x00',
+                     (), (), (), '', '', 1, b'')
+ exec(co)
+diff --git a/Lib/test/mock_socket.py b/Lib/test/mock_socket.py
+index cda4db25cb..c7abddcf5f 100644
+--- a/Lib/test/mock_socket.py
++++ b/Lib/test/mock_socket.py
+@@ -107,6 +107,9 @@ class MockSocket:
+     def close(self):
+         pass
++    def connect(self, host):
++        pass
++
+ def socket(family=None, type=None, proto=None):
+     return MockSocket(family)
+@@ -152,8 +155,12 @@ error = socket_module.error
+ # Constants
++_GLOBAL_DEFAULT_TIMEOUT = socket_module._GLOBAL_DEFAULT_TIMEOUT
+ AF_INET = socket_module.AF_INET
+ AF_INET6 = socket_module.AF_INET6
+ SOCK_STREAM = socket_module.SOCK_STREAM
+ SOL_SOCKET = None
+ SO_REUSEADDR = None
++
++if hasattr(socket_module, 'AF_UNIX'):
++    AF_UNIX = socket_module.AF_UNIX
+diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py
+index 3d54617f68..7e279cc736 100644
+--- a/Lib/test/pickletester.py
++++ b/Lib/test/pickletester.py
+@@ -65,6 +65,10 @@ def count_opcode(code, pickle):
+     return n
++def identity(x):
++    return x
++
++
+ class UnseekableIO(io.BytesIO):
+     def peek(self, *args):
+         raise NotImplementedError
+@@ -134,11 +138,12 @@ class E(C):
+     def __getinitargs__(self):
+         return ()
+-class H(object):
++# Simple mutable object.
++class Object:
+     pass
+-# Hashable mutable key
+-class K(object):
++# Hashable immutable key object containing unheshable mutable data.
++class K:
+     def __init__(self, value):
+         self.value = value
+@@ -153,10 +158,6 @@ __main__.D = D
+ D.__module__ = "__main__"
+ __main__.E = E
+ E.__module__ = "__main__"
+-__main__.H = H
+-H.__module__ = "__main__"
+-__main__.K = K
+-K.__module__ = "__main__"
+ class myint(int):
+     def __init__(self, x):
+@@ -1492,54 +1493,182 @@ class AbstractPickleTests(unittest.TestCase):
+             got = filelike.getvalue()
+             self.assertEqual(expected, got)
+-    def test_recursive_list(self):
+-        l = []
++    def _test_recursive_list(self, cls, aslist=identity, minprotocol=0):
++        # List containing itself.
++        l = cls()
+         l.append(l)
+-        for proto in protocols:
++        for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
+             s = self.dumps(l, proto)
+             x = self.loads(s)
+-            self.assertIsInstance(x, list)
+-            self.assertEqual(len(x), 1)
+-            self.assertIs(x[0], x)
++            self.assertIsInstance(x, cls)
++            y = aslist(x)
++            self.assertEqual(len(y), 1)
++            self.assertIs(y[0], x)
+-    def test_recursive_tuple_and_list(self):
+-        t = ([],)
++    def test_recursive_list(self):
++        self._test_recursive_list(list)
++
++    def test_recursive_list_subclass(self):
++        self._test_recursive_list(MyList, minprotocol=2)
++
++    def test_recursive_list_like(self):
++        self._test_recursive_list(REX_six, aslist=lambda x: x.items)
++
++    def _test_recursive_tuple_and_list(self, cls, aslist=identity, minprotocol=0):
++        # Tuple containing a list containing the original tuple.
++        t = (cls(),)
+         t[0].append(t)
+-        for proto in protocols:
++        for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
+             s = self.dumps(t, proto)
+             x = self.loads(s)
+             self.assertIsInstance(x, tuple)
+             self.assertEqual(len(x), 1)
+-            self.assertIsInstance(x[0], list)
+-            self.assertEqual(len(x[0]), 1)
+-            self.assertIs(x[0][0], x)
++            self.assertIsInstance(x[0], cls)
++            y = aslist(x[0])
++            self.assertEqual(len(y), 1)
++            self.assertIs(y[0], x)
++
++        # List containing a tuple containing the original list.
++        t, = t
++        for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
++            s = self.dumps(t, proto)
++            x = self.loads(s)
++            self.assertIsInstance(x, cls)
++            y = aslist(x)
++            self.assertEqual(len(y), 1)
++            self.assertIsInstance(y[0], tuple)
++            self.assertEqual(len(y[0]), 1)
++            self.assertIs(y[0][0], x)
+-    def test_recursive_dict(self):
+-        d = {}
++    def test_recursive_tuple_and_list(self):
++        self._test_recursive_tuple_and_list(list)
++
++    def test_recursive_tuple_and_list_subclass(self):
++        self._test_recursive_tuple_and_list(MyList, minprotocol=2)
++
++    def test_recursive_tuple_and_list_like(self):
++        self._test_recursive_tuple_and_list(REX_six, aslist=lambda x: x.items)
++
++    def _test_recursive_dict(self, cls, asdict=identity, minprotocol=0):
++        # Dict containing itself.
++        d = cls()
+         d[1] = d
+-        for proto in protocols:
++        for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
+             s = self.dumps(d, proto)
+             x = self.loads(s)
+-            self.assertIsInstance(x, dict)
+-            self.assertEqual(list(x.keys()), [1])
+-            self.assertIs(x[1], x)
++            self.assertIsInstance(x, cls)
++            y = asdict(x)
++            self.assertEqual(list(y.keys()), [1])
++            self.assertIs(y[1], x)
+-    def test_recursive_dict_key(self):
+-        d = {}
+-        k = K(d)
+-        d[k] = 1
+-        for proto in protocols:
++    def test_recursive_dict(self):
++        self._test_recursive_dict(dict)
++
++    def test_recursive_dict_subclass(self):
++        self._test_recursive_dict(MyDict, minprotocol=2)
++
++    def test_recursive_dict_like(self):
++        self._test_recursive_dict(REX_seven, asdict=lambda x: x.table)
++
++    def _test_recursive_tuple_and_dict(self, cls, asdict=identity, minprotocol=0):
++        # Tuple containing a dict containing the original tuple.
++        t = (cls(),)
++        t[0][1] = t
++        for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
++            s = self.dumps(t, proto)
++            x = self.loads(s)
++            self.assertIsInstance(x, tuple)
++            self.assertEqual(len(x), 1)
++            self.assertIsInstance(x[0], cls)
++            y = asdict(x[0])
++            self.assertEqual(list(y), [1])
++            self.assertIs(y[1], x)
++
++        # Dict containing a tuple containing the original dict.
++        t, = t
++        for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
++            s = self.dumps(t, proto)
++            x = self.loads(s)
++            self.assertIsInstance(x, cls)
++            y = asdict(x)
++            self.assertEqual(list(y), [1])
++            self.assertIsInstance(y[1], tuple)
++            self.assertEqual(len(y[1]), 1)
++            self.assertIs(y[1][0], x)
++
++    def test_recursive_tuple_and_dict(self):
++        self._test_recursive_tuple_and_dict(dict)
++
++    def test_recursive_tuple_and_dict_subclass(self):
++        self._test_recursive_tuple_and_dict(MyDict, minprotocol=2)
++
++    def test_recursive_tuple_and_dict_like(self):
++        self._test_recursive_tuple_and_dict(REX_seven, asdict=lambda x: x.table)
++
++    def _test_recursive_dict_key(self, cls, asdict=identity, minprotocol=0):
++        # Dict containing an immutable object (as key) containing the original
++        # dict.
++        d = cls()
++        d[K(d)] = 1
++        for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
+             s = self.dumps(d, proto)
+             x = self.loads(s)
+-            self.assertIsInstance(x, dict)
+-            self.assertEqual(len(x.keys()), 1)
+-            self.assertIsInstance(list(x.keys())[0], K)
+-            self.assertIs(list(x.keys())[0].value, x)
++            self.assertIsInstance(x, cls)
++            y = asdict(x)
++            self.assertEqual(len(y.keys()), 1)
++            self.assertIsInstance(list(y.keys())[0], K)
++            self.assertIs(list(y.keys())[0].value, x)
++
++    def test_recursive_dict_key(self):
++        self._test_recursive_dict_key(dict)
++
++    def test_recursive_dict_subclass_key(self):
++        self._test_recursive_dict_key(MyDict, minprotocol=2)
++
++    def test_recursive_dict_like_key(self):
++        self._test_recursive_dict_key(REX_seven, asdict=lambda x: x.table)
++
++    def _test_recursive_tuple_and_dict_key(self, cls, asdict=identity, minprotocol=0):
++        # Tuple containing a dict containing an immutable object (as key)
++        # containing the original tuple.
++        t = (cls(),)
++        t[0][K(t)] = 1
++        for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
++            s = self.dumps(t, proto)
++            x = self.loads(s)
++            self.assertIsInstance(x, tuple)
++            self.assertEqual(len(x), 1)
++            self.assertIsInstance(x[0], cls)
++            y = asdict(x[0])
++            self.assertEqual(len(y), 1)
++            self.assertIsInstance(list(y.keys())[0], K)
++            self.assertIs(list(y.keys())[0].value, x)
++
++        # Dict containing an immutable object (as key) containing a tuple
++        # containing the original dict.
++        t, = t
++        for proto in range(minprotocol, pickle.HIGHEST_PROTOCOL + 1):
++            s = self.dumps(t, proto)
++            x = self.loads(s)
++            self.assertIsInstance(x, cls)
++            y = asdict(x)
++            self.assertEqual(len(y), 1)
++            self.assertIsInstance(list(y.keys())[0], K)
++            self.assertIs(list(y.keys())[0].value[0], x)
++
++    def test_recursive_tuple_and_dict_key(self):
++        self._test_recursive_tuple_and_dict_key(dict)
++
++    def test_recursive_tuple_and_dict_subclass_key(self):
++        self._test_recursive_tuple_and_dict_key(MyDict, minprotocol=2)
++
++    def test_recursive_tuple_and_dict_like_key(self):
++        self._test_recursive_tuple_and_dict_key(REX_seven, asdict=lambda x: x.table)
+     def test_recursive_set(self):
++        # Set containing an immutable object containing the original set.
+         y = set()
+-        k = K(y)
+-        y.add(k)
++        y.add(K(y))
+         for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
+             s = self.dumps(y, proto)
+             x = self.loads(s)
+@@ -1548,52 +1677,31 @@ class AbstractPickleTests(unittest.TestCase):
+             self.assertIsInstance(list(x)[0], K)
+             self.assertIs(list(x)[0].value, x)
+-    def test_recursive_list_subclass(self):
+-        y = MyList()
+-        y.append(y)
+-        for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
++        # Immutable object containing a set containing the original object.
++        y, = y
++        for proto in range(4, pickle.HIGHEST_PROTOCOL + 1):
+             s = self.dumps(y, proto)
+             x = self.loads(s)
+-            self.assertIsInstance(x, MyList)
+-            self.assertEqual(len(x), 1)
+-            self.assertIs(x[0], x)
+-
+-    def test_recursive_dict_subclass(self):
+-        d = MyDict()
+-        d[1] = d
+-        for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
+-            s = self.dumps(d, proto)
+-            x = self.loads(s)
+-            self.assertIsInstance(x, MyDict)
+-            self.assertEqual(list(x.keys()), [1])
+-            self.assertIs(x[1], x)
+-
+-    def test_recursive_dict_subclass_key(self):
+-        d = MyDict()
+-        k = K(d)
+-        d[k] = 1
+-        for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
+-            s = self.dumps(d, proto)
+-            x = self.loads(s)
+-            self.assertIsInstance(x, MyDict)
+-            self.assertEqual(len(list(x.keys())), 1)
+-            self.assertIsInstance(list(x.keys())[0], K)
+-            self.assertIs(list(x.keys())[0].value, x)
++            self.assertIsInstance(x, K)
++            self.assertIsInstance(x.value, set)
++            self.assertEqual(len(x.value), 1)
++            self.assertIs(list(x.value)[0], x)
+     def test_recursive_inst(self):
+-        i = C()
++        # Mutable object containing itself.
++        i = Object()
+         i.attr = i
+         for proto in protocols:
+             s = self.dumps(i, proto)
+             x = self.loads(s)
+-            self.assertIsInstance(x, C)
++            self.assertIsInstance(x, Object)
+             self.assertEqual(dir(x), dir(i))
+             self.assertIs(x.attr, x)
+     def test_recursive_multi(self):
+         l = []
+         d = {1:l}
+-        i = C()
++        i = Object()
+         i.attr = d
+         l.append(i)
+         for proto in protocols:
+@@ -1603,49 +1711,94 @@ class AbstractPickleTests(unittest.TestCase):
+             self.assertEqual(len(x), 1)
+             self.assertEqual(dir(x[0]), dir(i))
+             self.assertEqual(list(x[0].attr.keys()), [1])
+-            self.assertTrue(x[0].attr[1] is x)
+-
+-    def check_recursive_collection_and_inst(self, factory):
+-        h = H()
+-        y = factory([h])
+-        h.attr = y
++            self.assertIs(x[0].attr[1], x)
++
++    def _test_recursive_collection_and_inst(self, factory):
++        # Mutable object containing a collection containing the original
++        # object.
++        o = Object()
++        o.attr = factory([o])
++        t = type(o.attr)
+         for proto in protocols:
+-            s = self.dumps(y, proto)
++            s = self.dumps(o, proto)
+             x = self.loads(s)
+-            self.assertIsInstance(x, type(y))
++            self.assertIsInstance(x.attr, t)
++            self.assertEqual(len(x.attr), 1)
++            self.assertIsInstance(list(x.attr)[0], Object)
++            self.assertIs(list(x.attr)[0], x)
++
++        # Collection containing a mutable object containing the original
++        # collection.
++        o = o.attr
++        for proto in protocols:
++            s = self.dumps(o, proto)
++            x = self.loads(s)
++            self.assertIsInstance(x, t)
+             self.assertEqual(len(x), 1)
+-            self.assertIsInstance(list(x)[0], H)
++            self.assertIsInstance(list(x)[0], Object)
+             self.assertIs(list(x)[0].attr, x)
+     def test_recursive_list_and_inst(self):
+-        self.check_recursive_collection_and_inst(list)
++        self._test_recursive_collection_and_inst(list)
+     def test_recursive_tuple_and_inst(self):
+-        self.check_recursive_collection_and_inst(tuple)
++        self._test_recursive_collection_and_inst(tuple)
+     def test_recursive_dict_and_inst(self):
+-        self.check_recursive_collection_and_inst(dict.fromkeys)
++        self._test_recursive_collection_and_inst(dict.fromkeys)
+     def test_recursive_set_and_inst(self):
+-        self.check_recursive_collection_and_inst(set)
++        self._test_recursive_collection_and_inst(set)
+     def test_recursive_frozenset_and_inst(self):
+-        self.check_recursive_collection_and_inst(frozenset)
++        self._test_recursive_collection_and_inst(frozenset)
+     def test_recursive_list_subclass_and_inst(self):
+-        self.check_recursive_collection_and_inst(MyList)
++        self._test_recursive_collection_and_inst(MyList)
+     def test_recursive_tuple_subclass_and_inst(self):
+-        self.check_recursive_collection_and_inst(MyTuple)
++        self._test_recursive_collection_and_inst(MyTuple)
+     def test_recursive_dict_subclass_and_inst(self):
+-        self.check_recursive_collection_and_inst(MyDict.fromkeys)
++        self._test_recursive_collection_and_inst(MyDict.fromkeys)
+     def test_recursive_set_subclass_and_inst(self):
+-        self.check_recursive_collection_and_inst(MySet)
++        self._test_recursive_collection_and_inst(MySet)
+     def test_recursive_frozenset_subclass_and_inst(self):
+-        self.check_recursive_collection_and_inst(MyFrozenSet)
++        self._test_recursive_collection_and_inst(MyFrozenSet)
++
++    def test_recursive_inst_state(self):
++        # Mutable object containing itself.
++        y = REX_state()
++        y.state = y
++        for proto in protocols:
++            s = self.dumps(y, proto)
++            x = self.loads(s)
++            self.assertIsInstance(x, REX_state)
++            self.assertIs(x.state, x)
++
++    def test_recursive_tuple_and_inst_state(self):
++        # Tuple containing a mutable object containing the original tuple.
++        t = (REX_state(),)
++        t[0].state = t
++        for proto in protocols:
++            s = self.dumps(t, proto)
++            x = self.loads(s)
++            self.assertIsInstance(x, tuple)
++            self.assertEqual(len(x), 1)
++            self.assertIsInstance(x[0], REX_state)
++            self.assertIs(x[0].state, x)
++
++        # Mutable object containing a tuple containing the object.
++        t, = t
++        for proto in protocols:
++            s = self.dumps(t, proto)
++            x = self.loads(s)
++            self.assertIsInstance(x, REX_state)
++            self.assertIsInstance(x.state, tuple)
++            self.assertEqual(len(x.state), 1)
++            self.assertIs(x.state[0], x)
+     def test_unicode(self):
+         endcases = ['', '<\\u>', '<\\\u1234>', '<\n>',
+@@ -3058,6 +3211,19 @@ class REX_seven(object):
+     def __reduce__(self):
+         return type(self), (), None, None, iter(self.table.items())
++class REX_state(object):
++    """This class is used to check the 3th argument (state) of
++    the reduce protocol.
++    """
++    def __init__(self, state=None):
++        self.state = state
++    def __eq__(self, other):
++        return type(self) is type(other) and self.state == other.state
++    def __setstate__(self, state):
++        self.state = state
++    def __reduce__(self):
++        return type(self), (), self.state
++
+ # Test classes for newobj
+diff --git a/Lib/test/test_asyncio/test_asyncio_waitfor.py b/Lib/test/test_asyncio/test_asyncio_waitfor.py
+new file mode 100644
+index 0000000000..2ca64abbeb
+--- /dev/null
++++ b/Lib/test/test_asyncio/test_asyncio_waitfor.py
+@@ -0,0 +1,61 @@
++import asyncio
++import unittest
++import time
++
++def tearDownModule():
++    asyncio.set_event_loop_policy(None)
++
++
++class SlowTask:
++    """ Task will run for this defined time, ignoring cancel requests """
++    TASK_TIMEOUT = 0.2
++
++    def __init__(self):
++        self.exited = False
++
++    async def run(self):
++        exitat = time.monotonic() + self.TASK_TIMEOUT
++
++        while True:
++            tosleep = exitat - time.monotonic()
++            if tosleep <= 0:
++                break
++
++            try:
++                await asyncio.sleep(tosleep)
++            except asyncio.CancelledError:
++                pass
++
++        self.exited = True
++
++class AsyncioWaitForTest(unittest.TestCase):
++
++    async def atest_asyncio_wait_for_cancelled(self):
++        t  = SlowTask()
++
++        waitfortask = asyncio.create_task(asyncio.wait_for(t.run(), t.TASK_TIMEOUT * 2))
++        await asyncio.sleep(0)
++        waitfortask.cancel()
++        await asyncio.wait({waitfortask})
++
++        self.assertTrue(t.exited)
++
++    def test_asyncio_wait_for_cancelled(self):
++        asyncio.run(self.atest_asyncio_wait_for_cancelled())
++
++    async def atest_asyncio_wait_for_timeout(self):
++        t  = SlowTask()
++
++        try:
++            await asyncio.wait_for(t.run(), t.TASK_TIMEOUT / 2)
++        except asyncio.TimeoutError:
++            pass
++
++        self.assertTrue(t.exited)
++
++    def test_asyncio_wait_for_timeout(self):
++        asyncio.run(self.atest_asyncio_wait_for_timeout())
++
++
++if __name__ == '__main__':
++    unittest.main()
+diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py
+index 4df1b95bca..d009f57e47 100644
+--- a/Lib/test/test_builtin.py
++++ b/Lib/test/test_builtin.py
+@@ -6,6 +6,7 @@ import builtins
+ import collections
+ import decimal
+ import fractions
++import gc
+ import io
+ import locale
+ import os
+@@ -1606,6 +1607,18 @@ class BuiltinTest(unittest.TestCase):
+         self.assertIs(cm.exception, exception)
++    @support.cpython_only
++    def test_zip_result_gc(self):
++        # bpo-42536: zip's tuple-reuse speed trick breaks the GC's assumptions
++        # about what can be untracked. Make sure we re-track result tuples
++        # whenever we reuse them.
++        it = zip([[]])
++        gc.collect()
++        # That GC collection probably untracked the recycled internal result
++        # tuple, which is initialized to (None,). Make sure it's re-tracked when
++        # it's mutated and returned from __next__:
++        self.assertTrue(gc.is_tracked(next(it)))
++
+     def test_format(self):
+         # Test the basic machinery of the format() builtin.  Don't test
+         #  the specifics of the various formatters
+diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py
+index 057ec92015..3ff660cf7a 100644
+--- a/Lib/test/test_collections.py
++++ b/Lib/test/test_collections.py
+@@ -680,6 +680,11 @@ class TestNamedTuple(unittest.TestCase):
+         self.assertEqual(np.x, 1)
+         self.assertEqual(np.y, 2)
++    def test_new_builtins_issue_43102(self):
++        self.assertEqual(
++            namedtuple('C', ()).__new__.__globals__['__builtins__'],
++            {})
++
+ ################################################################################
+ ### Abstract Base Classes
+diff --git a/Lib/test/test_curses.py b/Lib/test/test_curses.py
+index 5e619d1383..c1ad23b456 100644
+--- a/Lib/test/test_curses.py
++++ b/Lib/test/test_curses.py
+@@ -1,14 +1,5 @@
+-#
+-# Test script for the curses module
+-#
+-# This script doesn't actually display anything very coherent. but it
+-# does call (nearly) every method and function.
+-#
+-# Functions not tested: {def,reset}_{shell,prog}_mode, getch(), getstr(),
+-# init_color()
+-# Only called, not tested: getmouse(), ungetmouse()
+-#
+-
++import functools
++import inspect
+ import os
+ import string
+ import sys
+@@ -20,7 +11,6 @@ from test.support import requires, import_module, verbose, SaveSignals
+ # Optionally test curses module.  This currently requires that the
+ # 'curses' resource be given on the regrtest command line using the -u
+ # option.  If not available, nothing after this line will be executed.
+-import inspect
+ requires('curses')
+ # If either of these don't exist, skip the tests.
+@@ -36,7 +26,28 @@ def requires_curses_func(name):
+     return unittest.skipUnless(hasattr(curses, name),
+                                'requires curses.%s' % name)
++def requires_curses_window_meth(name):
++    def deco(test):
++        @functools.wraps(test)
++        def wrapped(self, *args, **kwargs):
++            if not hasattr(self.stdscr, name):
++                raise unittest.SkipTest('requires curses.window.%s' % name)
++            test(self, *args, **kwargs)
++        return wrapped
++    return deco
++
++
++def requires_colors(test):
++    @functools.wraps(test)
++    def wrapped(self, *args, **kwargs):
++        if not curses.has_colors():
++            self.skipTest('requires colors support')
++        curses.start_color()
++        test(self, *args, **kwargs)
++    return wrapped
++
+ term = os.environ.get('TERM')
++SHORT_MAX = 0x7fff
+ # If newterm was supported we could use it instead of initscr and not exit
+ @unittest.skipIf(not term or term == 'unknown',
+@@ -47,254 +58,941 @@ class TestCurses(unittest.TestCase):
+     @classmethod
+     def setUpClass(cls):
+-        if not sys.__stdout__.isatty():
+-            # Temporary skip tests on non-tty
+-            raise unittest.SkipTest('sys.__stdout__ is not a tty')
+-            cls.tmp = tempfile.TemporaryFile()
+-            fd = cls.tmp.fileno()
+-        else:
+-            cls.tmp = None
+-            fd = sys.__stdout__.fileno()
++        if verbose:
++            print(f'TERM={term}', file=sys.stderr, flush=True)
+         # testing setupterm() inside initscr/endwin
+         # causes terminal breakage
+-        curses.setupterm(fd=fd)
+-
+-    @classmethod
+-    def tearDownClass(cls):
+-        if cls.tmp:
+-            cls.tmp.close()
+-            del cls.tmp
++        stdout_fd = sys.__stdout__.fileno()
++        curses.setupterm(fd=stdout_fd)
+     def setUp(self):
++        self.isatty = True
++        self.output = sys.__stdout__
++        stdout_fd = sys.__stdout__.fileno()
++        if not sys.__stdout__.isatty():
++            # initstr() unconditionally uses C stdout.
++            # If it is redirected to file or pipe, try to attach it
++            # to terminal.
++            # First, save a copy of the file descriptor of stdout, so it
++            # can be restored after finishing the test.
++            dup_fd = os.dup(stdout_fd)
++            self.addCleanup(os.close, dup_fd)
++            self.addCleanup(os.dup2, dup_fd, stdout_fd)
++
++            if sys.__stderr__.isatty():
++                # If stderr is connected to terminal, use it.
++                tmp = sys.__stderr__
++                self.output = sys.__stderr__
++            else:
++                try:
++                    # Try to open the terminal device.
++                    tmp = open('/dev/tty', 'wb', buffering=0)
++                except OSError:
++                    # As a fallback, use regular file to write control codes.
++                    # Some functions (like savetty) will not work, but at
++                    # least the garbage control sequences will not be mixed
++                    # with the testing report.
++                    tmp = tempfile.TemporaryFile(mode='wb', buffering=0)
++                    self.isatty = False
++                self.addCleanup(tmp.close)
++                self.output = None
++            os.dup2(tmp.fileno(), stdout_fd)
++
+         self.save_signals = SaveSignals()
+         self.save_signals.save()
+-        if verbose:
++        self.addCleanup(self.save_signals.restore)
++        if verbose and self.output is not None:
+             # just to make the test output a little more readable
+-            print()
++            sys.stderr.flush()
++            sys.stdout.flush()
++            print(file=self.output, flush=True)
+         self.stdscr = curses.initscr()
+-        curses.savetty()
++        if self.isatty:
++            curses.savetty()
++            self.addCleanup(curses.endwin)
++            self.addCleanup(curses.resetty)
++        self.stdscr.erase()
++
++    @requires_curses_func('filter')
++    def test_filter(self):
++        # TODO: Should be called before initscr() or newterm() are called.
++        # TODO: nofilter()
++        curses.filter()
++
++    @requires_curses_func('use_env')
++    def test_use_env(self):
++        # TODO: Should be called before initscr() or newterm() are called.
++        # TODO: use_tioctl()
++        curses.use_env(False)
++        curses.use_env(True)
++
++    def test_create_windows(self):
++        win = curses.newwin(5, 10)
++        self.assertEqual(win.getbegyx(), (0, 0))
++        self.assertEqual(win.getparyx(), (-1, -1))
++        self.assertEqual(win.getmaxyx(), (5, 10))
++
++        win = curses.newwin(10, 15, 2, 5)
++        self.assertEqual(win.getbegyx(), (2, 5))
++        self.assertEqual(win.getparyx(), (-1, -1))
++        self.assertEqual(win.getmaxyx(), (10, 15))
++
++        win2 = win.subwin(3, 7)
++        self.assertEqual(win2.getbegyx(), (3, 7))
++        self.assertEqual(win2.getparyx(), (1, 2))
++        self.assertEqual(win2.getmaxyx(), (9, 13))
++
++        win2 = win.subwin(5, 10, 3, 7)
++        self.assertEqual(win2.getbegyx(), (3, 7))
++        self.assertEqual(win2.getparyx(), (1, 2))
++        self.assertEqual(win2.getmaxyx(), (5, 10))
++
++        win3 = win.derwin(2, 3)
++        self.assertEqual(win3.getbegyx(), (4, 8))
++        self.assertEqual(win3.getparyx(), (2, 3))
++        self.assertEqual(win3.getmaxyx(), (8, 12))
++
++        win3 = win.derwin(6, 11, 2, 3)
++        self.assertEqual(win3.getbegyx(), (4, 8))
++        self.assertEqual(win3.getparyx(), (2, 3))
++        self.assertEqual(win3.getmaxyx(), (6, 11))
++
++        win.mvwin(0, 1)
++        self.assertEqual(win.getbegyx(), (0, 1))
++        self.assertEqual(win.getparyx(), (-1, -1))
++        self.assertEqual(win.getmaxyx(), (10, 15))
++        self.assertEqual(win2.getbegyx(), (3, 7))
++        self.assertEqual(win2.getparyx(), (1, 2))
++        self.assertEqual(win2.getmaxyx(), (5, 10))
++        self.assertEqual(win3.getbegyx(), (4, 8))
++        self.assertEqual(win3.getparyx(), (2, 3))
++        self.assertEqual(win3.getmaxyx(), (6, 11))
++
++        win2.mvderwin(2, 1)
++        self.assertEqual(win2.getbegyx(), (3, 7))
++        self.assertEqual(win2.getparyx(), (2, 1))
++        self.assertEqual(win2.getmaxyx(), (5, 10))
++
++        win3.mvderwin(2, 1)
++        self.assertEqual(win3.getbegyx(), (4, 8))
++        self.assertEqual(win3.getparyx(), (2, 1))
++        self.assertEqual(win3.getmaxyx(), (6, 11))
++
++    def test_move_cursor(self):
++        stdscr = self.stdscr
++        win = stdscr.subwin(10, 15, 2, 5)
++        stdscr.move(1, 2)
++        win.move(2, 4)
++        self.assertEqual(stdscr.getyx(), (1, 2))
++        self.assertEqual(win.getyx(), (2, 4))
+-    def tearDown(self):
+-        curses.resetty()
+-        curses.endwin()
+-        self.save_signals.restore()
++        win.cursyncup()
++        self.assertEqual(stdscr.getyx(), (4, 9))
++
++    def test_refresh_control(self):
++        stdscr = self.stdscr
++        # touchwin()/untouchwin()/is_wintouched()
++        stdscr.refresh()
++        self.assertIs(stdscr.is_wintouched(), False)
++        stdscr.touchwin()
++        self.assertIs(stdscr.is_wintouched(), True)
++        stdscr.refresh()
++        self.assertIs(stdscr.is_wintouched(), False)
++        stdscr.touchwin()
++        self.assertIs(stdscr.is_wintouched(), True)
++        stdscr.untouchwin()
++        self.assertIs(stdscr.is_wintouched(), False)
++
++        # touchline()/untouchline()/is_linetouched()
++        stdscr.touchline(5, 2)
++        self.assertIs(stdscr.is_linetouched(5), True)
++        self.assertIs(stdscr.is_linetouched(6), True)
++        self.assertIs(stdscr.is_wintouched(), True)
++        stdscr.touchline(5, 1, False)
++        self.assertIs(stdscr.is_linetouched(5), False)
++
++        # syncup()
++        win = stdscr.subwin(10, 15, 2, 5)
++        win2 = win.subwin(5, 10, 3, 7)
++        win2.touchwin()
++        stdscr.untouchwin()
++        win2.syncup()
++        self.assertIs(win.is_wintouched(), True)
++        self.assertIs(stdscr.is_wintouched(), True)
++
++        # syncdown()
++        stdscr.touchwin()
++        win.untouchwin()
++        win2.untouchwin()
++        win2.syncdown()
++        self.assertIs(win2.is_wintouched(), True)
++
++        # syncok()
++        if hasattr(stdscr, 'syncok') and not sys.platform.startswith("sunos"):
++            win.untouchwin()
++            stdscr.untouchwin()
++            for syncok in [False, True]:
++                win2.syncok(syncok)
++                win2.addch('a')
++                self.assertIs(win.is_wintouched(), syncok)
++                self.assertIs(stdscr.is_wintouched(), syncok)
++
++    def test_output_character(self):
++        stdscr = self.stdscr
++        encoding = stdscr.encoding
++        # addch()
++        stdscr.refresh()
++        stdscr.move(0, 0)
++        stdscr.addch('A')
++        stdscr.addch(b'A')
++        stdscr.addch(65)
++        c = '\u20ac'
++        try:
++            stdscr.addch(c)
++        except UnicodeEncodeError:
++            self.assertRaises(UnicodeEncodeError, c.encode, encoding)
++        except OverflowError:
++            encoded = c.encode(encoding)
++            self.assertNotEqual(len(encoded), 1, repr(encoded))
++        stdscr.addch('A', curses.A_BOLD)
++        stdscr.addch(1, 2, 'A')
++        stdscr.addch(2, 3, 'A', curses.A_BOLD)
++        self.assertIs(stdscr.is_wintouched(), True)
++
++        # echochar()
++        stdscr.refresh()
++        stdscr.move(0, 0)
++        stdscr.echochar('A')
++        stdscr.echochar(b'A')
++        stdscr.echochar(65)
++        with self.assertRaises((UnicodeEncodeError, OverflowError)):
++            stdscr.echochar('\u20ac')
++        stdscr.echochar('A', curses.A_BOLD)
++        self.assertIs(stdscr.is_wintouched(), False)
++
++    def test_output_string(self):
++        stdscr = self.stdscr
++        encoding = stdscr.encoding
++        # addstr()/insstr()
++        for func in [stdscr.addstr, stdscr.insstr]:
++            with self.subTest(func.__qualname__):
++                stdscr.move(0, 0)
++                func('abcd')
++                func(b'abcd')
++                s = 'àßçđ'
++                try:
++                    func(s)
++                except UnicodeEncodeError:
++                    self.assertRaises(UnicodeEncodeError, s.encode, encoding)
++                func('abcd', curses.A_BOLD)
++                func(1, 2, 'abcd')
++                func(2, 3, 'abcd', curses.A_BOLD)
++
++        # addnstr()/insnstr()
++        for func in [stdscr.addnstr, stdscr.insnstr]:
++            with self.subTest(func.__qualname__):
++                stdscr.move(0, 0)
++                func('1234', 3)
++                func(b'1234', 3)
++                s = '\u0661\u0662\u0663\u0664'
++                try:
++                    func(s, 3)
++                except UnicodeEncodeError:
++                    self.assertRaises(UnicodeEncodeError, s.encode, encoding)
++                func('1234', 5)
++                func('1234', 3, curses.A_BOLD)
++                func(1, 2, '1234', 3)
++                func(2, 3, '1234', 3, curses.A_BOLD)
++
++    def test_output_string_embedded_null_chars(self):
++        # reject embedded null bytes and characters
++        stdscr = self.stdscr
++        for arg in ['a\0', b'a\0']:
++            with self.subTest(arg=arg):
++                self.assertRaises(ValueError, stdscr.addstr, arg)
++                self.assertRaises(ValueError, stdscr.addnstr, arg, 1)
++                self.assertRaises(ValueError, stdscr.insstr, arg)
++                self.assertRaises(ValueError, stdscr.insnstr, arg, 1)
+-    def test_window_funcs(self):
+-        "Test the methods of windows"
++    def test_read_from_window(self):
+         stdscr = self.stdscr
+-        win = curses.newwin(10,10)
+-        win = curses.newwin(5,5, 5,5)
+-        win2 = curses.newwin(15,15, 5,5)
+-
+-        for meth in [stdscr.addch, stdscr.addstr]:
+-            for args in [('a',), ('a', curses.A_BOLD),
+-                         (4,4, 'a'), (5,5, 'a', curses.A_BOLD)]:
+-                with self.subTest(meth=meth.__qualname__, args=args):
+-                    meth(*args)
+-
+-        for meth in [stdscr.clear, stdscr.clrtobot,
+-                     stdscr.clrtoeol, stdscr.cursyncup, stdscr.delch,
+-                     stdscr.deleteln, stdscr.erase, stdscr.getbegyx,
+-                     stdscr.getbkgd, stdscr.getkey, stdscr.getmaxyx,
+-                     stdscr.getparyx, stdscr.getyx, stdscr.inch,
+-                     stdscr.insertln, stdscr.instr, stdscr.is_wintouched,
+-                     win.noutrefresh, stdscr.redrawwin, stdscr.refresh,
+-                     stdscr.standout, stdscr.standend, stdscr.syncdown,
+-                     stdscr.syncup, stdscr.touchwin, stdscr.untouchwin]:
+-            with self.subTest(meth=meth.__qualname__):
+-                meth()
+-
+-        stdscr.addnstr('1234', 3)
+-        stdscr.addnstr('1234', 3, curses.A_BOLD)
+-        stdscr.addnstr(4,4, '1234', 3)
+-        stdscr.addnstr(5,5, '1234', 3, curses.A_BOLD)
+-
+-        stdscr.attron(curses.A_BOLD)
+-        stdscr.attroff(curses.A_BOLD)
+-        stdscr.attrset(curses.A_BOLD)
+-        stdscr.bkgd(' ')
+-        stdscr.bkgd(' ', curses.A_REVERSE)
+-        stdscr.bkgdset(' ')
+-        stdscr.bkgdset(' ', curses.A_REVERSE)
++        stdscr.addstr(0, 1, 'ABCD', curses.A_BOLD)
++        # inch()
++        stdscr.move(0, 1)
++        self.assertEqual(stdscr.inch(), 65 | curses.A_BOLD)
++        self.assertEqual(stdscr.inch(0, 3), 67 | curses.A_BOLD)
++        stdscr.move(0, 0)
++        # instr()
++        self.assertEqual(stdscr.instr()[:6], b' ABCD ')
++        self.assertEqual(stdscr.instr(3)[:6], b' AB')
++        self.assertEqual(stdscr.instr(0, 2)[:4], b'BCD ')
++        self.assertEqual(stdscr.instr(0, 2, 4), b'BCD ')
++        self.assertRaises(ValueError, stdscr.instr, -2)
++        self.assertRaises(ValueError, stdscr.instr, 0, 2, -2)
++
++    def test_getch(self):
++        win = curses.newwin(5, 12, 5, 2)
++
++        # TODO: Test with real input by writing to master fd.
++        for c in 'spam\n'[::-1]:
++            curses.ungetch(c)
++        self.assertEqual(win.getch(3, 1), b's'[0])
++        self.assertEqual(win.getyx(), (3, 1))
++        self.assertEqual(win.getch(3, 4), b'p'[0])
++        self.assertEqual(win.getyx(), (3, 4))
++        self.assertEqual(win.getch(), b'a'[0])
++        self.assertEqual(win.getyx(), (3, 4))
++        self.assertEqual(win.getch(), b'm'[0])
++        self.assertEqual(win.getch(), b'\n'[0])
++
++    def test_getstr(self):
++        win = curses.newwin(5, 12, 5, 2)
++        curses.echo()
++        self.addCleanup(curses.noecho)
++
++        self.assertRaises(ValueError, win.getstr, -400)
++        self.assertRaises(ValueError, win.getstr, 2, 3, -400)
++
++        # TODO: Test with real input by writing to master fd.
++        for c in 'Lorem\nipsum\ndolor\nsit\namet\n'[::-1]:
++            curses.ungetch(c)
++        self.assertEqual(win.getstr(3, 1, 2), b'Lo')
++        self.assertEqual(win.instr(3, 0), b' Lo         ')
++        self.assertEqual(win.getstr(3, 5, 10), b'ipsum')
++        self.assertEqual(win.instr(3, 0), b' Lo  ipsum  ')
++        self.assertEqual(win.getstr(1, 5), b'dolor')
++        self.assertEqual(win.instr(1, 0), b'     dolor  ')
++        self.assertEqual(win.getstr(2), b'si')
++        self.assertEqual(win.instr(1, 0), b'si   dolor  ')
++        self.assertEqual(win.getstr(), b'amet')
++        self.assertEqual(win.instr(1, 0), b'amet dolor  ')
++
++    def test_clear(self):
++        win = curses.newwin(5, 15, 5, 2)
++        lorem_ipsum(win)
++
++        win.move(0, 8)
++        win.clrtoeol()
++        self.assertEqual(win.instr(0, 0).rstrip(), b'Lorem ip')
++        self.assertEqual(win.instr(1, 0).rstrip(), b'dolor sit amet,')
++
++        win.move(0, 3)
++        win.clrtobot()
++        self.assertEqual(win.instr(0, 0).rstrip(), b'Lor')
++        self.assertEqual(win.instr(1, 0).rstrip(), b'')
++
++        for func in [win.erase, win.clear]:
++            lorem_ipsum(win)
++            func()
++            self.assertEqual(win.instr(0, 0).rstrip(), b'')
++            self.assertEqual(win.instr(1, 0).rstrip(), b'')
++
++    def test_insert_delete(self):
++        win = curses.newwin(5, 15, 5, 2)
++        lorem_ipsum(win)
++
++        win.move(0, 2)
++        win.delch()
++        self.assertEqual(win.instr(0, 0), b'Loem ipsum     ')
++        win.delch(0, 7)
++        self.assertEqual(win.instr(0, 0), b'Loem ipum      ')
++
++        win.move(1, 5)
++        win.deleteln()
++        self.assertEqual(win.instr(0, 0), b'Loem ipum      ')
++        self.assertEqual(win.instr(1, 0), b'consectetur    ')
++        self.assertEqual(win.instr(2, 0), b'adipiscing elit')
++        self.assertEqual(win.instr(3, 0), b'sed do eiusmod ')
++        self.assertEqual(win.instr(4, 0), b'               ')
++
++        win.move(1, 5)
++        win.insertln()
++        self.assertEqual(win.instr(0, 0), b'Loem ipum      ')
++        self.assertEqual(win.instr(1, 0), b'               ')
++        self.assertEqual(win.instr(2, 0), b'consectetur    ')
++
++        win.clear()
++        lorem_ipsum(win)
++        win.move(1, 5)
++        win.insdelln(2)
++        self.assertEqual(win.instr(0, 0), b'Lorem ipsum    ')
++        self.assertEqual(win.instr(1, 0), b'               ')
++        self.assertEqual(win.instr(2, 0), b'               ')
++        self.assertEqual(win.instr(3, 0), b'dolor sit amet,')
++
++        win.clear()
++        lorem_ipsum(win)
++        win.move(1, 5)
++        win.insdelln(-2)
++        self.assertEqual(win.instr(0, 0), b'Lorem ipsum    ')
++        self.assertEqual(win.instr(1, 0), b'adipiscing elit')
++        self.assertEqual(win.instr(2, 0), b'sed do eiusmod ')
++        self.assertEqual(win.instr(3, 0), b'               ')
++
++    def test_scroll(self):
++        win = curses.newwin(5, 15, 5, 2)
++        lorem_ipsum(win)
++        win.scrollok(True)
++        win.scroll()
++        self.assertEqual(win.instr(0, 0), b'dolor sit amet,')
++        win.scroll(2)
++        self.assertEqual(win.instr(0, 0), b'adipiscing elit')
++        win.scroll(-3)
++        self.assertEqual(win.instr(0, 0), b'               ')
++        self.assertEqual(win.instr(2, 0), b'               ')
++        self.assertEqual(win.instr(3, 0), b'adipiscing elit')
++        win.scrollok(False)
++
++    def test_attributes(self):
++        # TODO: attr_get(), attr_set(), ...
++        win = curses.newwin(5, 15, 5, 2)
++        win.attron(curses.A_BOLD)
++        win.attroff(curses.A_BOLD)
++        win.attrset(curses.A_BOLD)
++
++        win.standout()
++        win.standend()
++
++    @requires_curses_window_meth('chgat')
++    def test_chgat(self):
++        win = curses.newwin(5, 15, 5, 2)
++        win.addstr(2, 0, 'Lorem ipsum')
++        win.addstr(3, 0, 'dolor sit amet')
++
++        win.move(2, 8)
++        win.chgat(curses.A_BLINK)
++        self.assertEqual(win.inch(2, 7), b'p'[0])
++        self.assertEqual(win.inch(2, 8), b's'[0] | curses.A_BLINK)
++        self.assertEqual(win.inch(2, 14), b' '[0] | curses.A_BLINK)
++
++        win.move(2, 1)
++        win.chgat(3, curses.A_BOLD)
++        self.assertEqual(win.inch(2, 0), b'L'[0])
++        self.assertEqual(win.inch(2, 1), b'o'[0] | curses.A_BOLD)
++        self.assertEqual(win.inch(2, 3), b'e'[0] | curses.A_BOLD)
++        self.assertEqual(win.inch(2, 4), b'm'[0])
++
++        win.chgat(3, 2, curses.A_UNDERLINE)
++        self.assertEqual(win.inch(3, 1), b'o'[0])
++        self.assertEqual(win.inch(3, 2), b'l'[0] | curses.A_UNDERLINE)
++        self.assertEqual(win.inch(3, 14), b' '[0] | curses.A_UNDERLINE)
++
++        win.chgat(3, 4, 7, curses.A_BLINK)
++        self.assertEqual(win.inch(3, 3), b'o'[0] | curses.A_UNDERLINE)
++        self.assertEqual(win.inch(3, 4), b'r'[0] | curses.A_BLINK)
++        self.assertEqual(win.inch(3, 10), b'a'[0] | curses.A_BLINK)
++        self.assertEqual(win.inch(3, 11), b'm'[0] | curses.A_UNDERLINE)
++        self.assertEqual(win.inch(3, 14), b' '[0] | curses.A_UNDERLINE)
++
++    def test_background(self):
++        win = curses.newwin(5, 15, 5, 2)
++        win.addstr(0, 0, 'Lorem ipsum')
++
++        self.assertIn(win.getbkgd(), (0, 32))
++
++        # bkgdset()
++        win.bkgdset('_')
++        self.assertEqual(win.getbkgd(), b'_'[0])
++        win.bkgdset(b'#')
++        self.assertEqual(win.getbkgd(), b'#'[0])
++        win.bkgdset(65)
++        self.assertEqual(win.getbkgd(), 65)
++        win.bkgdset(0)
++        self.assertEqual(win.getbkgd(), 32)
++
++        win.bkgdset('#', curses.A_REVERSE)
++        self.assertEqual(win.getbkgd(), b'#'[0] | curses.A_REVERSE)
++        self.assertEqual(win.inch(0, 0), b'L'[0])
++        self.assertEqual(win.inch(0, 5), b' '[0])
++        win.bkgdset(0)
++
++        # bkgd()
++        win.bkgd('_')
++        self.assertEqual(win.getbkgd(), b'_'[0])
++        self.assertEqual(win.inch(0, 0), b'L'[0])
++        self.assertEqual(win.inch(0, 5), b'_'[0])
++
++        win.bkgd('#', curses.A_REVERSE)
++        self.assertEqual(win.getbkgd(), b'#'[0] | curses.A_REVERSE)
++        self.assertEqual(win.inch(0, 0), b'L'[0] | curses.A_REVERSE)
++        self.assertEqual(win.inch(0, 5), b'#'[0] | curses.A_REVERSE)
++
++    def test_overlay(self):
++        srcwin = curses.newwin(5, 18, 3, 4)
++        lorem_ipsum(srcwin)
++        dstwin = curses.newwin(7, 17, 5, 7)
++        for i in range(6):
++            dstwin.addstr(i, 0, '_'*17)
++
++        srcwin.overlay(dstwin)
++        self.assertEqual(dstwin.instr(0, 0), b'sectetur_________')
++        self.assertEqual(dstwin.instr(1, 0), b'piscing_elit,____')
++        self.assertEqual(dstwin.instr(2, 0), b'_do_eiusmod______')
++        self.assertEqual(dstwin.instr(3, 0), b'_________________')
++
++        srcwin.overwrite(dstwin)
++        self.assertEqual(dstwin.instr(0, 0), b'sectetur       __')
++        self.assertEqual(dstwin.instr(1, 0), b'piscing elit,  __')
++        self.assertEqual(dstwin.instr(2, 0), b' do eiusmod    __')
++        self.assertEqual(dstwin.instr(3, 0), b'_________________')
++
++        srcwin.overlay(dstwin, 1, 4, 3, 2, 4, 11)
++        self.assertEqual(dstwin.instr(3, 0), b'__r_sit_amet_____')
++        self.assertEqual(dstwin.instr(4, 0), b'__ectetur________')
++        self.assertEqual(dstwin.instr(5, 0), b'_________________')
++
++        srcwin.overwrite(dstwin, 1, 4, 3, 2, 4, 11)
++        self.assertEqual(dstwin.instr(3, 0), b'__r sit amet_____')
++        self.assertEqual(dstwin.instr(4, 0), b'__ectetur   _____')
++        self.assertEqual(dstwin.instr(5, 0), b'_________________')
++
++    def test_refresh(self):
++        win = curses.newwin(5, 15, 2, 5)
++        win.noutrefresh()
++        win.redrawln(1, 2)
++        win.redrawwin()
++        win.refresh()
++        curses.doupdate()
++
++    @requires_curses_window_meth('resize')
++    def test_resize(self):
++        win = curses.newwin(5, 15, 2, 5)
++        win.resize(4, 20)
++        self.assertEqual(win.getmaxyx(), (4, 20))
++        win.resize(5, 15)
++        self.assertEqual(win.getmaxyx(), (5, 15))
++
++    @requires_curses_window_meth('enclose')
++    def test_enclose(self):
++        win = curses.newwin(5, 15, 2, 5)
++        # TODO: Return bool instead of 1/0
++        self.assertTrue(win.enclose(2, 5))
++        self.assertFalse(win.enclose(1, 5))
++        self.assertFalse(win.enclose(2, 4))
++        self.assertTrue(win.enclose(6, 19))
++        self.assertFalse(win.enclose(7, 19))
++        self.assertFalse(win.enclose(6, 20))
++
++    def test_putwin(self):
++        win = curses.newwin(5, 12, 1, 2)
++        win.addstr(2, 1, 'Lorem ipsum')
++        with tempfile.TemporaryFile() as f:
++            win.putwin(f)
++            del win
++            f.seek(0)
++            win = curses.getwin(f)
++            self.assertEqual(win.getbegyx(), (1, 2))
++            self.assertEqual(win.getmaxyx(), (5, 12))
++            self.assertEqual(win.instr(2, 0), b' Lorem ipsum')
+-        win.border(65, 66, 67, 68,
+-                   69, 70, 71, 72)
++    def test_borders_and_lines(self):
++        win = curses.newwin(5, 10, 5, 2)
+         win.border('|', '!', '-', '_',
+                    '+', '\\', '#', '/')
+-        with self.assertRaises(TypeError,
+-                               msg="Expected win.border() to raise TypeError"):
+-            win.border(65, 66, 67, 68,
+-                       69, [], 71, 72)
+-
+-        win.box(65, 67)
+-        win.box('!', '_')
++        self.assertEqual(win.instr(0, 0), b'+--------\\')
++        self.assertEqual(win.instr(1, 0), b'|        !')
++        self.assertEqual(win.instr(4, 0), b'#________/')
++        win.border(b'|', b'!', b'-', b'_',
++                   b'+', b'\\', b'#', b'/')
++        win.border(65, 66, 67, 68,
++                   69, 70, 71, 72)
++        self.assertRaises(TypeError, win.border,
++                          65, 66, 67, 68, 69, [], 71, 72)
++        self.assertRaises(TypeError, win.border,
++                          65, 66, 67, 68, 69, 70, 71, 72, 73)
++        self.assertRaises(TypeError, win.border,
++                          65, 66, 67, 68, 69, 70, 71, 72, 73)
++        win.border(65, 66, 67, 68, 69, 70, 71)
++        win.border(65, 66, 67, 68, 69, 70)
++        win.border(65, 66, 67, 68, 69)
++        win.border(65, 66, 67, 68)
++        win.border(65, 66, 67)
++        win.border(65, 66)
++        win.border(65)
++        win.border()
++
++        win.box(':', '~')
++        self.assertEqual(win.instr(0, 1, 8), b'~~~~~~~~')
++        self.assertEqual(win.instr(1, 0),   b':        :')
++        self.assertEqual(win.instr(4, 1, 8), b'~~~~~~~~')
+         win.box(b':', b'~')
++        win.box(65, 67)
+         self.assertRaises(TypeError, win.box, 65, 66, 67)
+         self.assertRaises(TypeError, win.box, 65)
+         win.box()
+-        stdscr.clearok(1)
++        win.move(1, 2)
++        win.hline('-', 5)
++        self.assertEqual(win.instr(1, 1, 7), b' ----- ')
++        win.hline(b'-', 5)
++        win.hline(45, 5)
++        win.hline('-', 5, curses.A_BOLD)
++        win.hline(1, 1, '-', 5)
++        win.hline(1, 1, '-', 5, curses.A_BOLD)
++
++        win.move(1, 2)
++        win.vline('a', 3)
++        win.vline(b'a', 3)
++        win.vline(97, 3)
++        win.vline('a', 3, curses.A_STANDOUT)
++        win.vline(1, 1, 'a', 3)
++        win.vline(1, 1, ';', 2, curses.A_STANDOUT)
++        self.assertEqual(win.inch(1, 1), b';'[0] | curses.A_STANDOUT)
++        self.assertEqual(win.inch(2, 1), b';'[0] | curses.A_STANDOUT)
++        self.assertEqual(win.inch(3, 1), b'a'[0])
++
++    def test_unctrl(self):
++        # TODO: wunctrl()
++        self.assertEqual(curses.unctrl(b'A'), b'A')
++        self.assertEqual(curses.unctrl('A'), b'A')
++        self.assertEqual(curses.unctrl(65), b'A')
++        self.assertEqual(curses.unctrl(b'\n'), b'^J')
++        self.assertEqual(curses.unctrl('\n'), b'^J')
++        self.assertEqual(curses.unctrl(10), b'^J')
++        self.assertRaises(TypeError, curses.unctrl, b'')
++        self.assertRaises(TypeError, curses.unctrl, b'AB')
++        self.assertRaises(TypeError, curses.unctrl, '')
++        self.assertRaises(TypeError, curses.unctrl, 'AB')
++        self.assertRaises(OverflowError, curses.unctrl, 2**64)
++
++    def test_endwin(self):
++        if not self.isatty:
++            self.skipTest('requires terminal')
++        self.assertIs(curses.isendwin(), False)
++        curses.endwin()
++        self.assertIs(curses.isendwin(), True)
++        curses.doupdate()
++        self.assertIs(curses.isendwin(), False)
++
++    def test_terminfo(self):
++        self.assertIsInstance(curses.tigetflag('hc'), int)
++        self.assertEqual(curses.tigetflag('cols'), -1)
++        self.assertEqual(curses.tigetflag('cr'), -1)
++
++        self.assertIsInstance(curses.tigetnum('cols'), int)
++        self.assertEqual(curses.tigetnum('hc'), -2)
++        self.assertEqual(curses.tigetnum('cr'), -2)
++
++        self.assertIsInstance(curses.tigetstr('cr'), (bytes, type(None)))
++        self.assertIsNone(curses.tigetstr('hc'))
++        self.assertIsNone(curses.tigetstr('cols'))
++
++        cud = curses.tigetstr('cud')
++        if cud is not None:
++            # See issue10570.
++            self.assertIsInstance(cud, bytes)
++            curses.tparm(cud, 2)
++            cud_2 = curses.tparm(cud, 2)
++            self.assertIsInstance(cud_2, bytes)
++            curses.putp(cud_2)
++
++        curses.putp(b'abc\n')
++
++    def test_misc_module_funcs(self):
++        curses.delay_output(1)
++        curses.flushinp()
++
++        curses.doupdate()
++        self.assertIs(curses.isendwin(), False)
+-        win4 = stdscr.derwin(2,2)
+-        win4 = stdscr.derwin(1,1, 5,5)
+-        win4.mvderwin(9,9)
++        curses.napms(100)
++
++        curses.newpad(50, 50)
++
++    def test_env_queries(self):
++        # TODO: term_attrs(), erasewchar(), killwchar()
++        self.assertIsInstance(curses.termname(), bytes)
++        self.assertIsInstance(curses.longname(), bytes)
++        self.assertIsInstance(curses.baudrate(), int)
++        self.assertIsInstance(curses.has_ic(), bool)
++        self.assertIsInstance(curses.has_il(), bool)
++        self.assertIsInstance(curses.termattrs(), int)
++
++        c = curses.killchar()
++        self.assertIsInstance(c, bytes)
++        self.assertEqual(len(c), 1)
++        c = curses.erasechar()
++        self.assertIsInstance(c, bytes)
++        self.assertEqual(len(c), 1)
++
++    def test_output_options(self):
++        stdscr = self.stdscr
++
++        stdscr.clearok(True)
++        stdscr.clearok(False)
+-        stdscr.echochar('a')
+-        stdscr.echochar('a', curses.A_BOLD)
+-        stdscr.hline('-', 5)
+-        stdscr.hline('-', 5, curses.A_BOLD)
+-        stdscr.hline(1,1,'-', 5)
+-        stdscr.hline(1,1,'-', 5, curses.A_BOLD)
++        stdscr.idcok(True)
++        stdscr.idcok(False)
++
++        stdscr.idlok(False)
++        stdscr.idlok(True)
+-        stdscr.idcok(1)
+-        stdscr.idlok(1)
+         if hasattr(stdscr, 'immedok'):
+-            stdscr.immedok(1)
+-            stdscr.immedok(0)
+-        stdscr.insch('c')
+-        stdscr.insdelln(1)
+-        stdscr.insnstr('abc', 3)
+-        stdscr.insnstr('abc', 3, curses.A_BOLD)
+-        stdscr.insnstr(5, 5, 'abc', 3)
+-        stdscr.insnstr(5, 5, 'abc', 3, curses.A_BOLD)
+-
+-        stdscr.insstr('def')
+-        stdscr.insstr('def', curses.A_BOLD)
+-        stdscr.insstr(5, 5, 'def')
+-        stdscr.insstr(5, 5, 'def', curses.A_BOLD)
+-        stdscr.is_linetouched(0)
+-        stdscr.keypad(1)
+-        stdscr.leaveok(1)
+-        stdscr.move(3,3)
+-        win.mvwin(2,2)
+-        stdscr.nodelay(1)
+-        stdscr.notimeout(1)
+-        win2.overlay(win)
+-        win2.overwrite(win)
+-        win2.overlay(win, 1, 2, 2, 1, 3, 3)
+-        win2.overwrite(win, 1, 2, 2, 1, 3, 3)
+-        stdscr.redrawln(1,2)
+-
+-        stdscr.scrollok(1)
+-        stdscr.scroll()
+-        stdscr.scroll(2)
+-        stdscr.scroll(-3)
+-
+-        stdscr.move(12, 2)
+-        stdscr.setscrreg(10,15)
+-        win3 = stdscr.subwin(10,10)
+-        win3 = stdscr.subwin(10,10, 5,5)
+-        if hasattr(stdscr, 'syncok') and not sys.platform.startswith("sunos"):
+-            stdscr.syncok(1)
+-        stdscr.timeout(5)
+-        stdscr.touchline(5,5)
+-        stdscr.touchline(5,5,0)
+-        stdscr.vline('a', 3)
+-        stdscr.vline('a', 3, curses.A_STANDOUT)
+-        if hasattr(stdscr, 'chgat'):
+-            stdscr.chgat(5, 2, 3, curses.A_BLINK)
+-            stdscr.chgat(3, curses.A_BOLD)
+-            stdscr.chgat(5, 8, curses.A_UNDERLINE)
+-            stdscr.chgat(curses.A_BLINK)
+-        stdscr.refresh()
++            stdscr.immedok(True)
++            stdscr.immedok(False)
+-        stdscr.vline(1,1, 'a', 3)
+-        stdscr.vline(1,1, 'a', 3, curses.A_STANDOUT)
++        stdscr.leaveok(True)
++        stdscr.leaveok(False)
+-        if hasattr(stdscr, 'resize'):
+-            stdscr.resize(25, 80)
+-        if hasattr(stdscr, 'enclose'):
+-            stdscr.enclose(10, 10)
++        stdscr.scrollok(True)
++        stdscr.scrollok(False)
+-        self.assertRaises(ValueError, stdscr.getstr, -400)
+-        self.assertRaises(ValueError, stdscr.getstr, 2, 3, -400)
+-        self.assertRaises(ValueError, stdscr.instr, -2)
+-        self.assertRaises(ValueError, stdscr.instr, 2, 3, -2)
++        stdscr.setscrreg(5, 10)
+-    def test_embedded_null_chars(self):
+-        # reject embedded null bytes and characters
++        curses.nonl()
++        curses.nl(True)
++        curses.nl(False)
++        curses.nl()
++
++
++    def test_input_options(self):
+         stdscr = self.stdscr
+-        for arg in ['a', b'a']:
+-            with self.subTest(arg=arg):
+-                self.assertRaises(ValueError, stdscr.addstr, 'a\0')
+-                self.assertRaises(ValueError, stdscr.addnstr, 'a\0', 1)
+-                self.assertRaises(ValueError, stdscr.insstr, 'a\0')
+-                self.assertRaises(ValueError, stdscr.insnstr, 'a\0', 1)
+-
+-    def test_module_funcs(self):
+-        "Test module-level functions"
+-        for func in [curses.baudrate, curses.beep, curses.can_change_color,
+-                     curses.cbreak, curses.def_prog_mode, curses.doupdate,
+-                     curses.flash, curses.flushinp,
+-                     curses.has_colors, curses.has_ic, curses.has_il,
+-                     curses.isendwin, curses.killchar, curses.longname,
+-                     curses.nocbreak, curses.noecho, curses.nonl,
+-                     curses.noqiflush, curses.noraw,
+-                     curses.reset_prog_mode, curses.termattrs,
+-                     curses.termname, curses.erasechar]:
+-            with self.subTest(func=func.__qualname__):
+-                func()
+-        if hasattr(curses, 'filter'):
+-            curses.filter()
+-        if hasattr(curses, 'getsyx'):
+-            curses.getsyx()
+-
+-        # Functions that actually need arguments
+-        if curses.tigetstr("cnorm"):
+-            curses.curs_set(1)
+-        curses.delay_output(1)
+-        curses.echo() ; curses.echo(1)
+-        with tempfile.TemporaryFile() as f:
+-            self.stdscr.putwin(f)
+-            f.seek(0)
+-            curses.getwin(f)
++        if self.isatty:
++            curses.nocbreak()
++            curses.cbreak()
++            curses.cbreak(False)
++            curses.cbreak(True)
++
++            curses.intrflush(True)
++            curses.intrflush(False)
++
++            curses.raw()
++            curses.raw(False)
++            curses.raw(True)
++            curses.noraw()
++        curses.noecho()
++        curses.echo()
++        curses.echo(False)
++        curses.echo(True)
++
++        curses.halfdelay(255)
+         curses.halfdelay(1)
+-        curses.intrflush(1)
+-        curses.meta(1)
+-        curses.napms(100)
+-        curses.newpad(50,50)
+-        win = curses.newwin(5,5)
+-        win = curses.newwin(5,5, 1,1)
+-        curses.nl() ; curses.nl(1)
+-        curses.putp(b'abc')
++
++        stdscr.keypad(True)
++        stdscr.keypad(False)
++
++        curses.meta(True)
++        curses.meta(False)
++
++        stdscr.nodelay(True)
++        stdscr.nodelay(False)
++
++        curses.noqiflush()
++        curses.qiflush(True)
++        curses.qiflush(False)
+         curses.qiflush()
+-        curses.raw() ; curses.raw(1)
++
++        stdscr.notimeout(True)
++        stdscr.notimeout(False)
++
++        stdscr.timeout(-1)
++        stdscr.timeout(0)
++        stdscr.timeout(5)
++
++    @requires_curses_func('typeahead')
++    def test_typeahead(self):
++        curses.typeahead(sys.__stdin__.fileno())
++        curses.typeahead(-1)
++
++    def test_prog_mode(self):
++        if not self.isatty:
++            self.skipTest('requires terminal')
++        curses.def_prog_mode()
++        curses.reset_prog_mode()
++
++    def test_beep(self):
++        if (curses.tigetstr("bel") is not None
++            or curses.tigetstr("flash") is not None):
++            curses.beep()
++        else:
++            try:
++                curses.beep()
++            except curses.error:
++                self.skipTest('beep() failed')
++
++    def test_flash(self):
++        if (curses.tigetstr("bel") is not None
++            or curses.tigetstr("flash") is not None):
++            curses.flash()
++        else:
++            try:
++                curses.flash()
++            except curses.error:
++                self.skipTest('flash() failed')
++
++    def test_curs_set(self):
++        for vis, cap in [(0, 'civis'), (2, 'cvvis'), (1, 'cnorm')]:
++            if curses.tigetstr(cap) is not None:
++                curses.curs_set(vis)
++            else:
++                try:
++                    curses.curs_set(vis)
++                except curses.error:
++                    pass
++
++    @requires_curses_func('get_escdelay')
++    def test_escdelay(self):
++        escdelay = curses.get_escdelay()
++        self.assertIsInstance(escdelay, int)
+         curses.set_escdelay(25)
+         self.assertEqual(curses.get_escdelay(), 25)
++        curses.set_escdelay(escdelay)
++
++    @requires_curses_func('get_tabsize')
++    def test_tabsize(self):
++        tabsize = curses.get_tabsize()
++        self.assertIsInstance(tabsize, int)
+         curses.set_tabsize(4)
+         self.assertEqual(curses.get_tabsize(), 4)
+-        if hasattr(curses, 'setsyx'):
+-            curses.setsyx(5,5)
+-        curses.tigetflag('hc')
+-        curses.tigetnum('co')
+-        curses.tigetstr('cr')
+-        curses.tparm(b'cr')
+-        if hasattr(curses, 'typeahead'):
+-            curses.typeahead(sys.__stdin__.fileno())
+-        curses.unctrl('a')
+-        curses.ungetch('a')
+-        if hasattr(curses, 'use_env'):
+-            curses.use_env(1)
+-
+-    # Functions only available on a few platforms
+-    def test_colors_funcs(self):
++        curses.set_tabsize(tabsize)
++
++    @requires_curses_func('getsyx')
++    def test_getsyx(self):
++        y, x = curses.getsyx()
++        self.assertIsInstance(y, int)
++        self.assertIsInstance(x, int)
++        curses.setsyx(4, 5)
++        self.assertEqual(curses.getsyx(), (4, 5))
++
++    def bad_colors(self):
++        return (-2**31 - 1, 2**31, -2**63 - 1, 2**63, 2**64)
++
++    def bad_pairs(self):
++        return (-2**31 - 1, 2**31, -2**63 - 1, 2**63, 2**64)
++
++    def test_has_colors(self):
++        self.assertIsInstance(curses.has_colors(), bool)
++        self.assertIsInstance(curses.can_change_color(), bool)
++
++    def test_start_color(self):
+         if not curses.has_colors():
+             self.skipTest('requires colors support')
+         curses.start_color()
+-        curses.init_pair(2, 1,1)
+-        curses.color_content(1)
+-        curses.color_pair(2)
+-        curses.pair_content(curses.COLOR_PAIRS - 1)
+-        curses.pair_number(0)
+-
+-        if hasattr(curses, 'use_default_colors'):
++        if verbose:
++            print(f'COLORS = {curses.COLORS}', file=sys.stderr)
++            print(f'COLOR_PAIRS = {curses.COLOR_PAIRS}', file=sys.stderr)
++
++    @requires_colors
++    def test_color_content(self):
++        self.assertEqual(curses.color_content(curses.COLOR_BLACK), (0, 0, 0))
++        curses.color_content(0)
++        maxcolor = min(curses.COLORS - 1, SHORT_MAX)
++        curses.color_content(maxcolor)
++
++        for color in self.bad_colors():
++            self.assertRaises(OverflowError, curses.color_content, color)
++        if curses.COLORS <= SHORT_MAX:
++            self.assertRaises(curses.error, curses.color_content, curses.COLORS)
++        self.assertRaises(curses.error, curses.color_content, -1)
++
++    @requires_colors
++    def test_init_color(self):
++        if not curses.can_change_color():
++            self.skipTest('cannot change color')
++
++        old = curses.color_content(0)
++        try:
++            curses.init_color(0, *old)
++        except curses.error:
++            self.skipTest('cannot change color (init_color() failed)')
++        self.addCleanup(curses.init_color, 0, *old)
++        curses.init_color(0, 0, 0, 0)
++        self.assertEqual(curses.color_content(0), (0, 0, 0))
++        curses.init_color(0, 1000, 1000, 1000)
++        self.assertEqual(curses.color_content(0), (1000, 1000, 1000))
++
++        maxcolor = min(curses.COLORS - 1, SHORT_MAX)
++        old = curses.color_content(maxcolor)
++        curses.init_color(maxcolor, *old)
++        self.addCleanup(curses.init_color, maxcolor, *old)
++        curses.init_color(maxcolor, 0, 500, 1000)
++        self.assertEqual(curses.color_content(maxcolor), (0, 500, 1000))
++
++        for color in self.bad_colors():
++            self.assertRaises(OverflowError, curses.init_color, color, 0, 0, 0)
++        if curses.COLORS <= SHORT_MAX:
++            self.assertRaises(curses.error, curses.init_color, curses.COLORS, 0, 0, 0)
++        self.assertRaises(curses.error, curses.init_color, -1, 0, 0, 0)
++        for comp in (-1, 1001):
++            self.assertRaises(curses.error, curses.init_color, 0, comp, 0, 0)
++            self.assertRaises(curses.error, curses.init_color, 0, 0, comp, 0)
++            self.assertRaises(curses.error, curses.init_color, 0, 0, 0, comp)
++
++    def get_pair_limit(self):
++        return min(curses.COLOR_PAIRS, SHORT_MAX)
++
++    @requires_colors
++    def test_pair_content(self):
++        if not hasattr(curses, 'use_default_colors'):
++            self.assertEqual(curses.pair_content(0),
++                             (curses.COLOR_WHITE, curses.COLOR_BLACK))
++        curses.pair_content(0)
++        maxpair = self.get_pair_limit() - 1
++        if maxpair > 0:
++            curses.pair_content(maxpair)
++
++        for pair in self.bad_pairs():
++            self.assertRaises(OverflowError, curses.pair_content, pair)
++        self.assertRaises(curses.error, curses.pair_content, -1)
++
++    @requires_colors
++    def test_init_pair(self):
++        old = curses.pair_content(1)
++        curses.init_pair(1, *old)
++        self.addCleanup(curses.init_pair, 1, *old)
++
++        curses.init_pair(1, 0, 0)
++        self.assertEqual(curses.pair_content(1), (0, 0))
++        maxcolor = min(curses.COLORS - 1, SHORT_MAX)
++        curses.init_pair(1, maxcolor, 0)
++        self.assertEqual(curses.pair_content(1), (maxcolor, 0))
++        curses.init_pair(1, 0, maxcolor)
++        self.assertEqual(curses.pair_content(1), (0, maxcolor))
++        maxpair = self.get_pair_limit() - 1
++        if maxpair > 1:
++            curses.init_pair(maxpair, 0, 0)
++            self.assertEqual(curses.pair_content(maxpair), (0, 0))
++
++        for pair in self.bad_pairs():
++            self.assertRaises(OverflowError, curses.init_pair, pair, 0, 0)
++        self.assertRaises(curses.error, curses.init_pair, -1, 0, 0)
++        for color in self.bad_colors():
++            self.assertRaises(OverflowError, curses.init_pair, 1, color, 0)
++            self.assertRaises(OverflowError, curses.init_pair, 1, 0, color)
++        if curses.COLORS <= SHORT_MAX:
++            self.assertRaises(curses.error, curses.init_pair, 1, curses.COLORS, 0)
++            self.assertRaises(curses.error, curses.init_pair, 1, 0, curses.COLORS)
++
++    @requires_colors
++    def test_color_attrs(self):
++        for pair in 0, 1, 255:
++            attr = curses.color_pair(pair)
++            self.assertEqual(curses.pair_number(attr), pair, attr)
++            self.assertEqual(curses.pair_number(attr | curses.A_BOLD), pair)
++        self.assertEqual(curses.color_pair(0), 0)
++        self.assertEqual(curses.pair_number(0), 0)
++
++    @requires_curses_func('use_default_colors')
++    @requires_colors
++    def test_use_default_colors(self):
++        old = curses.pair_content(0)
++        try:
+             curses.use_default_colors()
++        except curses.error:
++            self.skipTest('cannot change color (use_default_colors() failed)')
++        self.assertEqual(curses.pair_content(0), (-1, -1))
++        self.assertIn(old, [(curses.COLOR_WHITE, curses.COLOR_BLACK), (-1, -1), (0, 0)])
+-    @requires_curses_func('keyname')
+     def test_keyname(self):
+-        curses.keyname(13)
++        # TODO: key_name()
++        self.assertEqual(curses.keyname(65), b'A')
++        self.assertEqual(curses.keyname(13), b'^M')
++        self.assertEqual(curses.keyname(127), b'^?')
++        self.assertEqual(curses.keyname(0), b'^@')
++        self.assertRaises(ValueError, curses.keyname, -1)
++        self.assertIsInstance(curses.keyname(256), bytes)
+     @requires_curses_func('has_key')
+     def test_has_key(self):
+@@ -350,23 +1048,46 @@ class TestCurses(unittest.TestCase):
+     @requires_curses_func('is_term_resized')
+     def test_is_term_resized(self):
+-        curses.is_term_resized(*self.stdscr.getmaxyx())
++        lines, cols = curses.LINES, curses.COLS
++        self.assertIs(curses.is_term_resized(lines, cols), False)
++        self.assertIs(curses.is_term_resized(lines-1, cols-1), True)
+     @requires_curses_func('resize_term')
+     def test_resize_term(self):
+-        curses.resize_term(*self.stdscr.getmaxyx())
++        curses.update_lines_cols()
++        lines, cols = curses.LINES, curses.COLS
++        new_lines = lines - 1
++        new_cols = cols + 1
++        curses.resize_term(new_lines, new_cols)
++        self.assertEqual(curses.LINES, new_lines)
++        self.assertEqual(curses.COLS, new_cols)
++
++        curses.resize_term(lines, cols)
++        self.assertEqual(curses.LINES, lines)
++        self.assertEqual(curses.COLS, cols)
+     @requires_curses_func('resizeterm')
+     def test_resizeterm(self):
+-        stdscr = self.stdscr
++        curses.update_lines_cols()
+         lines, cols = curses.LINES, curses.COLS
+         new_lines = lines - 1
+         new_cols = cols + 1
+         curses.resizeterm(new_lines, new_cols)
+-
+         self.assertEqual(curses.LINES, new_lines)
+         self.assertEqual(curses.COLS, new_cols)
++        curses.resizeterm(lines, cols)
++        self.assertEqual(curses.LINES, lines)
++        self.assertEqual(curses.COLS, cols)
++
++    def test_ungetch(self):
++        curses.ungetch(b'A')
++        self.assertEqual(self.stdscr.getkey(), 'A')
++        curses.ungetch('B')
++        self.assertEqual(self.stdscr.getkey(), 'B')
++        curses.ungetch(67)
++        self.assertEqual(self.stdscr.getkey(), 'C')
++
+     def test_issue6243(self):
+         curses.ungetch(1025)
+         self.stdscr.getkey()
+@@ -395,10 +1116,6 @@ class TestCurses(unittest.TestCase):
+             read = stdscr.get_wch()
+             self.assertEqual(read, ch)
+-    def test_issue10570(self):
+-        b = curses.tparm(curses.tigetstr("cup"), 5, 3)
+-        self.assertIs(type(b), bytes)
+-
+     def test_encoding(self):
+         stdscr = self.stdscr
+         import codecs
+@@ -438,30 +1155,31 @@ class TestCurses(unittest.TestCase):
+         human_readable_signature = stdscr.addch.__doc__.split("\n")[0]
+         self.assertIn("[y, x,]", human_readable_signature)
++    @requires_curses_window_meth('resize')
+     def test_issue13051(self):
+-        stdscr = self.stdscr
+-        if not hasattr(stdscr, 'resize'):
+-            raise unittest.SkipTest('requires curses.window.resize')
+-        box = curses.textpad.Textbox(stdscr, insert_mode=True)
+-        lines, cols = stdscr.getmaxyx()
+-        stdscr.resize(lines-2, cols-2)
++        win = curses.newwin(5, 15, 2, 5)
++        box = curses.textpad.Textbox(win, insert_mode=True)
++        lines, cols = win.getmaxyx()
++        win.resize(lines-2, cols-2)
+         # this may cause infinite recursion, leading to a RuntimeError
+         box._insert_printable_char('a')
+ class MiscTests(unittest.TestCase):
+-    @requires_curses_func('update_lines_cols')
+     def test_update_lines_cols(self):
+-        # this doesn't actually test that LINES and COLS are updated,
+-        # because we can't automate changing them. See Issue #4254 for
+-        # a manual test script. We can only test that the function
+-        # can be called.
+         curses.update_lines_cols()
++        lines, cols = curses.LINES, curses.COLS
++        curses.LINES = curses.COLS = 0
++        curses.update_lines_cols()
++        self.assertEqual(curses.LINES, lines)
++        self.assertEqual(curses.COLS, cols)
+     @requires_curses_func('ncurses_version')
+     def test_ncurses_version(self):
+         v = curses.ncurses_version
++        if verbose:
++            print(f'ncurses_version = {curses.ncurses_version}', flush=True)
+         self.assertIsInstance(v[:], tuple)
+         self.assertEqual(len(v), 3)
+         self.assertIsInstance(v[0], int)
+@@ -477,6 +1195,7 @@ class MiscTests(unittest.TestCase):
+         self.assertGreaterEqual(v.minor, 0)
+         self.assertGreaterEqual(v.patch, 0)
++
+ class TestAscii(unittest.TestCase):
+     def test_controlnames(self):
+@@ -565,5 +1284,21 @@ class TestAscii(unittest.TestCase):
+         self.assertEqual(unctrl(ord('\xc1')), '!A')
++def lorem_ipsum(win):
++    text = [
++        'Lorem ipsum',
++        'dolor sit amet,',
++        'consectetur',
++        'adipiscing elit,',
++        'sed do eiusmod',
++        'tempor incididunt',
++        'ut labore et',
++        'dolore magna',
++        'aliqua.',
++    ]
++    maxy, maxx = win.getmaxyx()
++    for y, line in enumerate(text[:maxy]):
++        win.addstr(y, 0, line[:maxx - (y == maxy - 1)])
++
+ if __name__ == '__main__':
+     unittest.main()
+diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
+index 9e875da375..c7a191bccd 100644
+--- a/Lib/test/test_descr.py
++++ b/Lib/test/test_descr.py
+@@ -4,6 +4,8 @@ import gc
+ import itertools
+ import math
+ import pickle
++import random
++import string
+ import sys
+ import types
+ import unittest
+@@ -845,6 +847,14 @@ class ClassPropertiesAndMethods(unittest.TestCase):
+             self.fail("inheriting from ModuleType and str at the same time "
+                       "should fail")
++        # Issue 34805: Verify that definition order is retained
++        def random_name():
++            return ''.join(random.choices(string.ascii_letters, k=10))
++        class A:
++            pass
++        subclasses = [type(random_name(), (A,), {}) for i in range(100)]
++        self.assertEqual(A.__subclasses__(), subclasses)
++
+     def test_multiple_inheritance(self):
+         # Testing multiple inheritance...
+         class C(object):
+diff --git a/Lib/test/test_dict.py b/Lib/test/test_dict.py
+index 6b8596fff6..b10c07534d 100644
+--- a/Lib/test/test_dict.py
++++ b/Lib/test/test_dict.py
+@@ -1422,6 +1422,25 @@ class DictTest(unittest.TestCase):
+         d = CustomReversedDict(pairs)
+         self.assertEqual(pairs[::-1], list(dict(d).items()))
++    @support.cpython_only
++    def test_dict_items_result_gc(self):
++        # bpo-42536: dict.items's tuple-reuse speed trick breaks the GC's
++        # assumptions about what can be untracked. Make sure we re-track result
++        # tuples whenever we reuse them.
++        it = iter({None: []}.items())
++        gc.collect()
++        # That GC collection probably untracked the recycled internal result
++        # tuple, which is initialized to (None, None). Make sure it's re-tracked
++        # when it's mutated and returned from __next__:
++        self.assertTrue(gc.is_tracked(next(it)))
++
++    @support.cpython_only
++    def test_dict_items_result_gc(self):
++        # Same as test_dict_items_result_gc above, but reversed.
++        it = reversed({None: []}.items())
++        gc.collect()
++        self.assertTrue(gc.is_tracked(next(it)))
++
+ class CAPITest(unittest.TestCase):
+diff --git a/Lib/test/test_enum.py b/Lib/test/test_enum.py
+index 0e6b1b16ca..4e22986325 100644
+--- a/Lib/test/test_enum.py
++++ b/Lib/test/test_enum.py
+@@ -215,6 +215,18 @@ class TestEnum(unittest.TestCase):
+                 set(['__class__', '__doc__', '__module__', 'name', 'value', 'invisible']),
+                 )
++    def test_dir_on_sub_with_behavior_including_instance_dict_on_super(self):
++        # see issue40084
++        class SuperEnum(IntEnum):
++            def __new__(cls, value, description=""):
++                obj = int.__new__(cls, value)
++                obj._value_ = value
++                obj.description = description
++                return obj
++        class SubEnum(SuperEnum):
++            sample = 5
++        self.assertTrue({'description'} <= set(dir(SubEnum.sample)))
++
+     def test_enum_in_enum_out(self):
+         Season = self.Season
+         self.assertIs(Season(Season.WINTER), Season.WINTER)
+@@ -570,12 +582,15 @@ class TestEnum(unittest.TestCase):
+         class Test1Enum(MyMethodEnum, int, MyStrEnum):
+             One = 1
+             Two = 2
++        self.assertTrue(Test1Enum._member_type_ is int)
+         self.assertEqual(str(Test1Enum.One), 'MyStr')
++        self.assertEqual(format(Test1Enum.One, ''), 'MyStr')
+         #
+         class Test2Enum(MyStrEnum, MyMethodEnum):
+             One = 1
+             Two = 2
+         self.assertEqual(str(Test2Enum.One), 'MyStr')
++        self.assertEqual(format(Test1Enum.One, ''), 'MyStr')
+     def test_inherited_data_type(self):
+         class HexInt(int):
+@@ -1132,6 +1147,7 @@ class TestEnum(unittest.TestCase):
+         class auto_enum(type(Enum)):
+             def __new__(metacls, cls, bases, classdict):
+                 temp = type(classdict)()
++                temp._cls_name = cls
+                 names = set(classdict._member_names)
+                 i = 0
+                 for k in classdict._member_names:
+@@ -1998,6 +2014,32 @@ class TestEnum(unittest.TestCase):
+             REVERT_ALL = "REVERT_ALL"
+             RETRY = "RETRY"
++    def test_multiple_mixin_inherited(self):
++        class MyInt(int):
++            def __new__(cls, value):
++                return super().__new__(cls, value)
++
++        class HexMixin:
++            def __repr__(self):
++                return hex(self)
++
++        class MyIntEnum(HexMixin, MyInt, enum.Enum):
++            pass
++
++        class Foo(MyIntEnum):
++            TEST = 1
++        self.assertTrue(isinstance(Foo.TEST, MyInt))
++        self.assertEqual(repr(Foo.TEST), "0x1")
++
++        class Fee(MyIntEnum):
++            TEST = 1
++            def __new__(cls, value):
++                value += 1
++                member = int.__new__(cls, value)
++                member._value_ = value
++                return member
++        self.assertEqual(Fee.TEST, 2)
++
+     def test_empty_globals(self):
+         # bpo-35717: sys._getframe(2).f_globals['__name__'] fails with KeyError
+         # when using compile and exec because f_globals is empty
+@@ -2007,6 +2049,22 @@ class TestEnum(unittest.TestCase):
+         local_ls = {}
+         exec(code, global_ns, local_ls)
++    @unittest.skipUnless(
++            sys.version_info[:2] == (3, 9),
++            'private variables are now normal attributes',
++            )
++    def test_warning_for_private_variables(self):
++        with self.assertWarns(DeprecationWarning):
++            class Private(Enum):
++                __corporal = 'Radar'
++        self.assertEqual(Private._Private__corporal.value, 'Radar')
++        try:
++            with self.assertWarns(DeprecationWarning):
++                class Private(Enum):
++                    __major_ = 'Hoolihan'
++        except ValueError:
++            pass
++
+ class TestOrder(unittest.TestCase):
+@@ -2144,6 +2202,11 @@ class TestFlag(unittest.TestCase):
+         self.assertEqual(repr(~(Open.RO | Open.CE)), '<Open.AC: 3>')
+         self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: 2>')
++    def test_format(self):
++        Perm = self.Perm
++        self.assertEqual(format(Perm.R, ''), 'Perm.R')
++        self.assertEqual(format(Perm.R | Perm.X, ''), 'Perm.R|X')
++
+     def test_or(self):
+         Perm = self.Perm
+         for i in Perm:
+@@ -2452,6 +2515,42 @@ class TestFlag(unittest.TestCase):
+                 'at least one thread failed while creating composite members')
+         self.assertEqual(256, len(seen), 'too many composite members created')
++    def test_init_subclass(self):
++        class MyEnum(Flag):
++            def __init_subclass__(cls, **kwds):
++                super().__init_subclass__(**kwds)
++                self.assertFalse(cls.__dict__.get('_test', False))
++                cls._test1 = 'MyEnum'
++        #
++        class TheirEnum(MyEnum):
++            def __init_subclass__(cls, **kwds):
++                super(TheirEnum, cls).__init_subclass__(**kwds)
++                cls._test2 = 'TheirEnum'
++        class WhoseEnum(TheirEnum):
++            def __init_subclass__(cls, **kwds):
++                pass
++        class NoEnum(WhoseEnum):
++            ONE = 1
++        self.assertEqual(TheirEnum.__dict__['_test1'], 'MyEnum')
++        self.assertEqual(WhoseEnum.__dict__['_test1'], 'MyEnum')
++        self.assertEqual(WhoseEnum.__dict__['_test2'], 'TheirEnum')
++        self.assertFalse(NoEnum.__dict__.get('_test1', False))
++        self.assertFalse(NoEnum.__dict__.get('_test2', False))
++        #
++        class OurEnum(MyEnum):
++            def __init_subclass__(cls, **kwds):
++                cls._test2 = 'OurEnum'
++        class WhereEnum(OurEnum):
++            def __init_subclass__(cls, **kwds):
++                pass
++        class NeverEnum(WhereEnum):
++            ONE = 1
++        self.assertEqual(OurEnum.__dict__['_test1'], 'MyEnum')
++        self.assertFalse(WhereEnum.__dict__.get('_test1', False))
++        self.assertEqual(WhereEnum.__dict__['_test2'], 'OurEnum')
++        self.assertFalse(NeverEnum.__dict__.get('_test1', False))
++        self.assertFalse(NeverEnum.__dict__.get('_test2', False))
++
+ class TestIntFlag(unittest.TestCase):
+     """Tests of the IntFlags."""
+@@ -2477,6 +2576,7 @@ class TestIntFlag(unittest.TestCase):
+     def test_type(self):
+         Perm = self.Perm
++        self.assertTrue(Perm._member_type_ is int)
+         Open = self.Open
+         for f in Perm:
+             self.assertTrue(isinstance(f, Perm))
+@@ -2556,6 +2656,11 @@ class TestIntFlag(unittest.TestCase):
+         self.assertEqual(repr(~(Open.WO | Open.CE)), '<Open.RW: -524290>')
+         self.assertEqual(repr(Open(~4)), '<Open.CE|AC|RW|WO: -5>')
++    def test_format(self):
++        Perm = self.Perm
++        self.assertEqual(format(Perm.R, ''), '4')
++        self.assertEqual(format(Perm.R | Perm.X, ''), '5')
++
+     def test_or(self):
+         Perm = self.Perm
+         for i in Perm:
+diff --git a/Lib/test/test_enumerate.py b/Lib/test/test_enumerate.py
+index 5785cb4649..906bfc21a2 100644
+--- a/Lib/test/test_enumerate.py
++++ b/Lib/test/test_enumerate.py
+@@ -2,6 +2,7 @@ import unittest
+ import operator
+ import sys
+ import pickle
++import gc
+ from test import support
+@@ -134,6 +135,18 @@ class EnumerateTestCase(unittest.TestCase, PickleTest):
+         self.assertEqual(len(set(map(id, list(enumerate(self.seq))))), len(self.seq))
+         self.assertEqual(len(set(map(id, enumerate(self.seq)))), min(1,len(self.seq)))
++    @support.cpython_only
++    def test_enumerate_result_gc(self):
++        # bpo-42536: enumerate's tuple-reuse speed trick breaks the GC's
++        # assumptions about what can be untracked. Make sure we re-track result
++        # tuples whenever we reuse them.
++        it = self.enum([[]])
++        gc.collect()
++        # That GC collection probably untracked the recycled internal result
++        # tuple, which is initialized to (None, None). Make sure it's re-tracked
++        # when it's mutated and returned from __next__:
++        self.assertTrue(gc.is_tracked(next(it)))
++
+ class MyEnum(enumerate):
+     pass
+diff --git a/Lib/test/test_epoll.py b/Lib/test/test_epoll.py
+index 10f148fe5c..b623852f9e 100644
+--- a/Lib/test/test_epoll.py
++++ b/Lib/test/test_epoll.py
+@@ -160,44 +160,42 @@ class TestEPoll(unittest.TestCase):
+             self.fail("epoll on closed fd didn't raise EBADF")
+     def test_control_and_wait(self):
++        # create the epoll object
+         client, server = self._connected_pair()
+-
+         ep = select.epoll(16)
+         ep.register(server.fileno(),
+                     select.EPOLLIN | select.EPOLLOUT | select.EPOLLET)
+         ep.register(client.fileno(),
+                     select.EPOLLIN | select.EPOLLOUT | select.EPOLLET)
++        # EPOLLOUT
+         now = time.monotonic()
+         events = ep.poll(1, 4)
+         then = time.monotonic()
+         self.assertFalse(then - now > 0.1, then - now)
+-        events.sort()
+         expected = [(client.fileno(), select.EPOLLOUT),
+                     (server.fileno(), select.EPOLLOUT)]
+-        expected.sort()
+-
+-        self.assertEqual(events, expected)
++        self.assertEqual(sorted(events), sorted(expected))
+-        events = ep.poll(timeout=2.1, maxevents=4)
++        # no event
++        events = ep.poll(timeout=0.1, maxevents=4)
+         self.assertFalse(events)
+-        client.send(b"Hello!")
+-        server.send(b"world!!!")
++        # send: EPOLLIN and EPOLLOUT
++        client.sendall(b"Hello!")
++        server.sendall(b"world!!!")
+         now = time.monotonic()
+-        events = ep.poll(1, 4)
++        events = ep.poll(1.0, 4)
+         then = time.monotonic()
+         self.assertFalse(then - now > 0.01)
+-        events.sort()
+         expected = [(client.fileno(), select.EPOLLIN | select.EPOLLOUT),
+                     (server.fileno(), select.EPOLLIN | select.EPOLLOUT)]
+-        expected.sort()
+-
+-        self.assertEqual(events, expected)
++        self.assertEqual(sorted(events), sorted(expected))
++        # unregister, modify
+         ep.unregister(client.fileno())
+         ep.modify(server.fileno(), select.EPOLLOUT)
+         now = time.monotonic()
+diff --git a/Lib/test/test_fstring.py b/Lib/test/test_fstring.py
+index 2ae815aab1..2f08d35f26 100644
+--- a/Lib/test/test_fstring.py
++++ b/Lib/test/test_fstring.py
+@@ -332,6 +332,59 @@ non-important content
+         self.assertEqual(binop.left.col_offset, 4)
+         self.assertEqual(binop.right.col_offset, 7)
++    def test_ast_line_numbers_with_parentheses(self):
++        expr = """
++x = (
++    f" {test(t)}"
++)"""
++        t = ast.parse(expr)
++        self.assertEqual(type(t), ast.Module)
++        self.assertEqual(len(t.body), 1)
++        # check the test(t) location
++        call = t.body[0].value.values[1].value
++        self.assertEqual(type(call), ast.Call)
++        self.assertEqual(call.lineno, 3)
++        self.assertEqual(call.end_lineno, 3)
++        self.assertEqual(call.col_offset, 8)
++        self.assertEqual(call.end_col_offset, 15)
++
++        expr = """
++x = (
++        'PERL_MM_OPT', (
++            f'wat'
++            f'some_string={f(x)} '
++            f'wat'
++        ),
++)
++"""
++        t = ast.parse(expr)
++        self.assertEqual(type(t), ast.Module)
++        self.assertEqual(len(t.body), 1)
++        # check the fstring
++        fstring = t.body[0].value.elts[1]
++        self.assertEqual(type(fstring), ast.JoinedStr)
++        self.assertEqual(len(fstring.values), 3)
++        wat1, middle, wat2 = fstring.values
++        # check the first wat
++        self.assertEqual(type(wat1), ast.Constant)
++        self.assertEqual(wat1.lineno, 4)
++        self.assertEqual(wat1.end_lineno, 6)
++        self.assertEqual(wat1.col_offset, 12)
++        self.assertEqual(wat1.end_col_offset, 18)
++        # check the call
++        call = middle.value
++        self.assertEqual(type(call), ast.Call)
++        self.assertEqual(call.lineno, 5)
++        self.assertEqual(call.end_lineno, 5)
++        self.assertEqual(call.col_offset, 27)
++        self.assertEqual(call.end_col_offset, 31)
++        # check the second wat
++        self.assertEqual(type(wat2), ast.Constant)
++        self.assertEqual(wat2.lineno, 4)
++        self.assertEqual(wat2.end_lineno, 6)
++        self.assertEqual(wat2.col_offset, 12)
++        self.assertEqual(wat2.end_col_offset, 18)
++
+     def test_docstring(self):
+         def f():
+             f'''Not a docstring'''
+diff --git a/Lib/test/test_genericalias.py b/Lib/test/test_genericalias.py
+index c113e53824..ccf40b13d3 100644
+--- a/Lib/test/test_genericalias.py
++++ b/Lib/test/test_genericalias.py
+@@ -62,7 +62,6 @@ class BaseTest(unittest.TestCase):
+                      Iterable, Iterator,
+                      Reversible,
+                      Container, Collection,
+-                     Callable,
+                      Mailbox, _PartialFile,
+                      ContextVar, Token,
+                      Field,
+@@ -307,6 +306,69 @@ class BaseTest(unittest.TestCase):
+         with self.assertRaises(TypeError):
+             GenericAlias(bad=float)
++    def test_subclassing_types_genericalias(self):
++        class SubClass(GenericAlias): ...
++        alias = SubClass(list, int)
++        class Bad(GenericAlias):
++            def __new__(cls, *args, **kwargs):
++                super().__new__(cls, *args, **kwargs)
++
++        self.assertEqual(alias, list[int])
++        with self.assertRaises(TypeError):
++            Bad(list, int, bad=int)
++
++    def test_abc_callable(self):
++        # A separate test is needed for Callable since it uses a subclass of
++        # GenericAlias.
++        alias = Callable[[int, str], float]
++        with self.subTest("Testing subscription"):
++            self.assertIs(alias.__origin__, Callable)
++            self.assertEqual(alias.__args__, (int, str, float))
++            self.assertEqual(alias.__parameters__, ())
++
++        with self.subTest("Testing instance checks"):
++            self.assertIsInstance(alias, GenericAlias)
++
++        with self.subTest("Testing weakref"):
++            self.assertEqual(ref(alias)(), alias)
++
++        with self.subTest("Testing pickling"):
++            s = pickle.dumps(alias)
++            loaded = pickle.loads(s)
++            self.assertEqual(alias.__origin__, loaded.__origin__)
++            self.assertEqual(alias.__args__, loaded.__args__)
++            self.assertEqual(alias.__parameters__, loaded.__parameters__)
++
++        with self.subTest("Testing TypeVar substitution"):
++            C1 = Callable[[int, T], T]
++            C2 = Callable[[K, T], V]
++            C3 = Callable[..., T]
++            self.assertEqual(C1[str], Callable[[int, str], str])
++            self.assertEqual(C2[int, float, str], Callable[[int, float], str])
++            self.assertEqual(C3[int], Callable[..., int])
++
++            # multi chaining
++            C4 = C2[int, V, str]
++            self.assertEqual(repr(C4).split(".")[-1], "Callable[[int, ~V], str]")
++            self.assertEqual(repr(C4[dict]).split(".")[-1], "Callable[[int, dict], str]")
++            self.assertEqual(C4[dict], Callable[[int, dict], str])
++
++        with self.subTest("Testing type erasure"):
++            class C1(Callable):
++                def __call__(self):
++                    return None
++            a = C1[[int], T]
++            self.assertIs(a().__class__, C1)
++            self.assertEqual(a().__orig_class__, C1[[int], T])
++
++        # bpo-42195
++        with self.subTest("Testing collections.abc.Callable's consistency "
++                          "with typing.Callable"):
++            c1 = typing.Callable[[int, str], dict]
++            c2 = Callable[[int, str], dict]
++            self.assertEqual(c1.__args__, c2.__args__)
++            self.assertEqual(hash(c1.__args__), hash(c2.__args__))
++
+ if __name__ == "__main__":
+     unittest.main()
+diff --git a/Lib/test/test_htmlparser.py b/Lib/test/test_htmlparser.py
+index a2bfb39d16..12917755a5 100644
+--- a/Lib/test/test_htmlparser.py
++++ b/Lib/test/test_htmlparser.py
+@@ -452,42 +452,6 @@ text
+         self._run_check('<!spacer type="block" height="25">',
+                         [('comment', 'spacer type="block" height="25"')])
+-    def test_with_unquoted_attributes(self):
+-        # see #12008
+-        html = ("<html><body bgcolor=d0ca90 text='181008'>"
+-                "<table cellspacing=0 cellpadding=1 width=100% ><tr>"
+-                "<td align=left><font size=-1>"
+-                "- <a href=/rabota/><span class=en> software-and-i</span></a>"
+-                "- <a href='/1/'><span class=en> library</span></a></table>")
+-        expected = [
+-            ('starttag', 'html', []),
+-            ('starttag', 'body', [('bgcolor', 'd0ca90'), ('text', '181008')]),
+-            ('starttag', 'table',
+-                [('cellspacing', '0'), ('cellpadding', '1'), ('width', '100%')]),
+-            ('starttag', 'tr', []),
+-            ('starttag', 'td', [('align', 'left')]),
+-            ('starttag', 'font', [('size', '-1')]),
+-            ('data', '- '), ('starttag', 'a', [('href', '/rabota/')]),
+-            ('starttag', 'span', [('class', 'en')]), ('data', ' software-and-i'),
+-            ('endtag', 'span'), ('endtag', 'a'),
+-            ('data', '- '), ('starttag', 'a', [('href', '/1/')]),
+-            ('starttag', 'span', [('class', 'en')]), ('data', ' library'),
+-            ('endtag', 'span'), ('endtag', 'a'), ('endtag', 'table')
+-        ]
+-        self._run_check(html, expected)
+-
+-    def test_comma_between_attributes(self):
+-        self._run_check('<form action="/xxx.php?a=1&amp;b=2&amp", '
+-                        'method="post">', [
+-                            ('starttag', 'form',
+-                                [('action', '/xxx.php?a=1&b=2&'),
+-                                 (',', None), ('method', 'post')])])
+-
+-    def test_weird_chars_in_unquoted_attribute_values(self):
+-        self._run_check('<form action=bogus|&#()value>', [
+-                            ('starttag', 'form',
+-                                [('action', 'bogus|&#()value')])])
+-
+     def test_invalid_end_tags(self):
+         # A collection of broken end tags. <br> is used as separator.
+         # see http://www.w3.org/TR/html5/tokenization.html#end-tag-open-state
+@@ -766,6 +730,62 @@ class AttributesTestCase(TestCaseBase):
+                           [("href", "http://www.example.org/\">;")]),
+                          ("data", "spam"), ("endtag", "a")])
++    def test_with_unquoted_attributes(self):
++        # see #12008
++        html = ("<html><body bgcolor=d0ca90 text='181008'>"
++                "<table cellspacing=0 cellpadding=1 width=100% ><tr>"
++                "<td align=left><font size=-1>"
++                "- <a href=/rabota/><span class=en> software-and-i</span></a>"
++                "- <a href='/1/'><span class=en> library</span></a></table>")
++        expected = [
++            ('starttag', 'html', []),
++            ('starttag', 'body', [('bgcolor', 'd0ca90'), ('text', '181008')]),
++            ('starttag', 'table',
++                [('cellspacing', '0'), ('cellpadding', '1'), ('width', '100%')]),
++            ('starttag', 'tr', []),
++            ('starttag', 'td', [('align', 'left')]),
++            ('starttag', 'font', [('size', '-1')]),
++            ('data', '- '), ('starttag', 'a', [('href', '/rabota/')]),
++            ('starttag', 'span', [('class', 'en')]), ('data', ' software-and-i'),
++            ('endtag', 'span'), ('endtag', 'a'),
++            ('data', '- '), ('starttag', 'a', [('href', '/1/')]),
++            ('starttag', 'span', [('class', 'en')]), ('data', ' library'),
++            ('endtag', 'span'), ('endtag', 'a'), ('endtag', 'table')
++        ]
++        self._run_check(html, expected)
++
++    def test_comma_between_attributes(self):
++        # see bpo 41478
++        # HTMLParser preserves duplicate attributes, leaving the task of
++        # removing duplicate attributes to a conformant html tree builder
++        html = ('<div class=bar,baz=asd>'        # between attrs (unquoted)
++                '<div class="bar",baz="asd">'    # between attrs (quoted)
++                '<div class=bar, baz=asd,>'      # after values (unquoted)
++                '<div class="bar", baz="asd",>'  # after values (quoted)
++                '<div class="bar",>'             # one comma values (quoted)
++                '<div class=,bar baz=,asd>'      # before values (unquoted)
++                '<div class=,"bar" baz=,"asd">'  # before values (quoted)
++                '<div ,class=bar ,baz=asd>'      # before names
++                '<div class,="bar" baz,="asd">'  # after names
++        )
++        expected = [
++            ('starttag', 'div', [('class', 'bar,baz=asd'),]),
++            ('starttag', 'div', [('class', 'bar'), (',baz', 'asd')]),
++            ('starttag', 'div', [('class', 'bar,'), ('baz', 'asd,')]),
++            ('starttag', 'div', [('class', 'bar'), (',', None),
++                                 ('baz', 'asd'), (',', None)]),
++            ('starttag', 'div', [('class', 'bar'), (',', None)]),
++            ('starttag', 'div', [('class', ',bar'), ('baz', ',asd')]),
++            ('starttag', 'div', [('class', ',"bar"'), ('baz', ',"asd"')]),
++            ('starttag', 'div', [(',class', 'bar'), (',baz', 'asd')]),
++            ('starttag', 'div', [('class,', 'bar'), ('baz,', 'asd')]),
++        ]
++        self._run_check(html, expected)
++
++    def test_weird_chars_in_unquoted_attribute_values(self):
++        self._run_check('<form action=bogus|&#()value>', [
++                            ('starttag', 'form',
++                                [('action', 'bogus|&#()value')])])
+ if __name__ == "__main__":
+     unittest.main()
+diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py
+index ed125893d6..28943f0256 100644
+--- a/Lib/test/test_httplib.py
++++ b/Lib/test/test_httplib.py
+@@ -1,5 +1,5 @@
+ import errno
+-from http import client
++from http import client, HTTPStatus
+ import io
+ import itertools
+ import os
+@@ -516,6 +516,10 @@ class TransferEncodingTest(TestCase):
+ class BasicTest(TestCase):
++    def test_dir_with_added_behavior_on_status(self):
++        # see issue40084
++        self.assertTrue({'description', 'name', 'phrase', 'value'} <= set(dir(HTTPStatus(404))))
++
+     def test_status_lines(self):
+         # Test HTTP status lines
+diff --git a/Lib/test/test_idle.py b/Lib/test/test_idle.py
+index 8bc01deaa3..310b72c1d7 100644
+--- a/Lib/test/test_idle.py
++++ b/Lib/test/test_idle.py
+@@ -20,5 +20,5 @@ from idlelib.idle_test import load_tests
+ if __name__ == '__main__':
+     tk.NoDefaultRoot()
+     unittest.main(exit=False)
+-    tk._support_default_root = 1
++    tk._support_default_root = True
+     tk._default_root = None
+diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py
+index 702cf08203..7101264284 100644
+--- a/Lib/test/test_itertools.py
++++ b/Lib/test/test_itertools.py
+@@ -12,6 +12,8 @@ from functools import reduce
+ import sys
+ import struct
+ import threading
++import gc
++
+ maxsize = support.MAX_Py_ssize_t
+ minsize = -maxsize-1
+@@ -1554,6 +1556,51 @@ class TestBasicOps(unittest.TestCase):
+             self.assertRaises(StopIteration, next, f(lambda x:x, []))
+             self.assertRaises(StopIteration, next, f(lambda x:x, StopNow()))
++    @support.cpython_only
++    def test_combinations_result_gc(self):
++        # bpo-42536: combinations's tuple-reuse speed trick breaks the GC's
++        # assumptions about what can be untracked. Make sure we re-track result
++        # tuples whenever we reuse them.
++        it = combinations([None, []], 1)
++        next(it)
++        gc.collect()
++        # That GC collection probably untracked the recycled internal result
++        # tuple, which has the value (None,). Make sure it's re-tracked when
++        # it's mutated and returned from __next__:
++        self.assertTrue(gc.is_tracked(next(it)))
++
++    @support.cpython_only
++    def test_combinations_with_replacement_result_gc(self):
++        # Ditto for combinations_with_replacement.
++        it = combinations_with_replacement([None, []], 1)
++        next(it)
++        gc.collect()
++        self.assertTrue(gc.is_tracked(next(it)))
++
++    @support.cpython_only
++    def test_permutations_result_gc(self):
++        # Ditto for permutations.
++        it = permutations([None, []], 1)
++        next(it)
++        gc.collect()
++        self.assertTrue(gc.is_tracked(next(it)))
++
++    @support.cpython_only
++    def test_product_result_gc(self):
++        # Ditto for product.
++        it = product([None, []])
++        next(it)
++        gc.collect()
++        self.assertTrue(gc.is_tracked(next(it)))
++
++    @support.cpython_only
++    def test_zip_longest_result_gc(self):
++        # Ditto for zip_longest.
++        it = zip_longest([[]])
++        gc.collect()
++        self.assertTrue(gc.is_tracked(next(it)))
++
++
+ class TestExamples(unittest.TestCase):
+     def test_accumulate(self):
+diff --git a/Lib/test/test_logging.py b/Lib/test/test_logging.py
+index 410eae2208..a6cd291c9a 100644
+--- a/Lib/test/test_logging.py
++++ b/Lib/test/test_logging.py
+@@ -4191,6 +4191,15 @@ class ModuleLevelMiscTest(BaseTest):
+         logging.disable(83)
+         self.assertEqual(logging.root.manager.disable, 83)
++        self.assertRaises(ValueError, logging.disable, "doesnotexists")
++
++        class _NotAnIntOrString:
++            pass
++
++        self.assertRaises(TypeError, logging.disable, _NotAnIntOrString())
++
++        logging.disable("WARN")
++
+         # test the default value introduced in 3.7
+         # (Issue #28524)
+         logging.disable()
+diff --git a/Lib/test/test_nntplib.py b/Lib/test/test_nntplib.py
+index 1df64fa7c6..99386ddbae 100644
+--- a/Lib/test/test_nntplib.py
++++ b/Lib/test/test_nntplib.py
+@@ -82,7 +82,7 @@ class NetworkedNNTPTestsMixin:
+         desc = self.server.description(self.GROUP_NAME)
+         _check_desc(desc)
+         # Another sanity check
+-        self.assertIn("Python", desc)
++        self.assertIn(self.DESC, desc)
+         # With a pattern
+         desc = self.server.description(self.GROUP_PAT)
+         _check_desc(desc)
+@@ -309,6 +309,7 @@ class NetworkedNNTPTests(NetworkedNNTPTestsMixin, unittest.TestCase):
+     NNTP_HOST = 'news.trigofacile.com'
+     GROUP_NAME = 'fr.comp.lang.python'
+     GROUP_PAT = 'fr.comp.lang.*'
++    DESC = 'Python'
+     NNTP_CLASS = NNTP
+@@ -343,8 +344,11 @@ class NetworkedNNTP_SSLTests(NetworkedNNTPTests):
+     # 400 connections per day are accepted from each IP address."
+     NNTP_HOST = 'nntp.aioe.org'
+-    GROUP_NAME = 'comp.lang.python'
+-    GROUP_PAT = 'comp.lang.*'
++    # bpo-42794: aioe.test is one of the official groups on this server
++    # used for testing: https://news.aioe.org/manual/aioe-hierarchy/
++    GROUP_NAME = 'aioe.test'
++    GROUP_PAT = 'aioe.*'
++    DESC = 'test'
+     NNTP_CLASS = getattr(nntplib, 'NNTP_SSL', None)
+diff --git a/Lib/test/test_ordered_dict.py b/Lib/test/test_ordered_dict.py
+index fdea44e4d8..9df4efbfff 100644
+--- a/Lib/test/test_ordered_dict.py
++++ b/Lib/test/test_ordered_dict.py
+@@ -697,6 +697,17 @@ class OrderedDictTests:
+         with self.assertRaises(ValueError):
+             a |= "BAD"
++    @support.cpython_only
++    def test_ordered_dict_items_result_gc(self):
++        # bpo-42536: OrderedDict.items's tuple-reuse speed trick breaks the GC's
++        # assumptions about what can be untracked. Make sure we re-track result
++        # tuples whenever we reuse them.
++        it = iter(self.OrderedDict({None: []}).items())
++        gc.collect()
++        # That GC collection probably untracked the recycled internal result
++        # tuple, which is initialized to (None, None). Make sure it's re-tracked
++        # when it's mutated and returned from __next__:
++        self.assertTrue(gc.is_tracked(next(it)))
+ class PurePythonOrderedDictTests(OrderedDictTests, unittest.TestCase):
+diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
+index bf1cb5f511..35933e9c8c 100644
+--- a/Lib/test/test_os.py
++++ b/Lib/test/test_os.py
+@@ -3659,6 +3659,33 @@ class FDInheritanceTests(unittest.TestCase):
+         self.assertEqual(fcntl.fcntl(fd, fcntl.F_GETFD) & fcntl.FD_CLOEXEC,
+                          0)
++    @unittest.skipUnless(hasattr(os, 'O_PATH'), "need os.O_PATH")
++    def test_get_set_inheritable_o_path(self):
++        fd = os.open(__file__, os.O_PATH)
++        self.addCleanup(os.close, fd)
++        self.assertEqual(os.get_inheritable(fd), False)
++
++        os.set_inheritable(fd, True)
++        self.assertEqual(os.get_inheritable(fd), True)
++
++        os.set_inheritable(fd, False)
++        self.assertEqual(os.get_inheritable(fd), False)
++
++    def test_get_set_inheritable_badf(self):
++        fd = support.make_bad_fd()
++
++        with self.assertRaises(OSError) as ctx:
++            os.get_inheritable(fd)
++        self.assertEqual(ctx.exception.errno, errno.EBADF)
++
++        with self.assertRaises(OSError) as ctx:
++            os.set_inheritable(fd, True)
++        self.assertEqual(ctx.exception.errno, errno.EBADF)
++
++        with self.assertRaises(OSError) as ctx:
++            os.set_inheritable(fd, False)
++        self.assertEqual(ctx.exception.errno, errno.EBADF)
++
+     def test_open(self):
+         fd = os.open(__file__, os.O_RDONLY)
+         self.addCleanup(os.close, fd)
+diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py
+index 8016f81e5a..6c4eaf318e 100644
+--- a/Lib/test/test_pdb.py
++++ b/Lib/test/test_pdb.py
+@@ -1661,6 +1661,71 @@ def bÅ“r():
+             '(Pdb) ',
+         ])
++
++    def test_issue42384(self):
++        '''When running `python foo.py` sys.path[0] is an absolute path. `python -m pdb foo.py` should behave the same'''
++        script = textwrap.dedent("""
++            import sys
++            print('sys.path[0] is', sys.path[0])
++        """)
++        commands = 'c\nq'
++
++        with support.temp_cwd() as cwd:
++            expected = f'(Pdb) sys.path[0] is {os.path.realpath(cwd)}'
++
++            stdout, stderr = self.run_pdb_script(script, commands)
++
++            self.assertEqual(stdout.split('\n')[2].rstrip('\r'), expected)
++
++    @support.skip_unless_symlink
++    def test_issue42384_symlink(self):
++        '''When running `python foo.py` sys.path[0] resolves symlinks. `python -m pdb foo.py` should behave the same'''
++        script = textwrap.dedent("""
++            import sys
++            print('sys.path[0] is', sys.path[0])
++        """)
++        commands = 'c\nq'
++
++        with support.temp_cwd() as cwd:
++            cwd = os.path.realpath(cwd)
++            dir_one = os.path.join(cwd, 'dir_one')
++            dir_two = os.path.join(cwd, 'dir_two')
++            expected = f'(Pdb) sys.path[0] is {dir_one}'
++
++            os.mkdir(dir_one)
++            with open(os.path.join(dir_one, 'foo.py'), 'w') as f:
++                f.write(script)
++            os.mkdir(dir_two)
++            os.symlink(os.path.join(dir_one, 'foo.py'), os.path.join(dir_two, 'foo.py'))
++
++            stdout, stderr = self._run_pdb([os.path.join('dir_two', 'foo.py')], commands)
++
++            self.assertEqual(stdout.split('\n')[2].rstrip('\r'), expected)
++
++    def test_issue42383(self):
++        with support.temp_cwd() as cwd:
++            with open('foo.py', 'w') as f:
++                s = textwrap.dedent("""
++                    print('The correct file was executed')
++
++                    import os
++                    os.chdir("subdir")
++                """)
++                f.write(s)
++
++            subdir = os.path.join(cwd, 'subdir')
++            os.mkdir(subdir)
++            os.mkdir(os.path.join(subdir, 'subdir'))
++            wrong_file = os.path.join(subdir, 'foo.py')
++
++            with open(wrong_file, 'w') as f:
++                f.write('print("The wrong file was executed")')
++
++            stdout, stderr = self._run_pdb(['foo.py'], 'c\nc\nq')
++            expected = '(Pdb) The correct file was executed'
++            self.assertEqual(stdout.split('\n')[6].rstrip('\r'), expected)
++
++
+ def load_tests(*args):
+     from test import test_pdb
+     suites = [
+diff --git a/Lib/test/test_platform.py b/Lib/test/test_platform.py
+index a3b06feb65..9f04c79e09 100644
+--- a/Lib/test/test_platform.py
++++ b/Lib/test/test_platform.py
+@@ -1,4 +1,6 @@
+ import os
++import copy
++import pickle
+ import platform
+ import subprocess
+ import sys
+@@ -175,6 +177,38 @@ class PlatformTest(unittest.TestCase):
+         )
+         self.assertEqual(tuple(res), expected)
++    def test_uname_replace(self):
++        res = platform.uname()
++        new = res._replace(
++            system='system', node='node', release='release',
++            version='version', machine='machine')
++        self.assertEqual(new.system, 'system')
++        self.assertEqual(new.node, 'node')
++        self.assertEqual(new.release, 'release')
++        self.assertEqual(new.version, 'version')
++        self.assertEqual(new.machine, 'machine')
++        # processor cannot be replaced
++        self.assertEqual(new.processor, res.processor)
++
++    def test_uname_copy(self):
++        uname = platform.uname()
++        self.assertEqual(copy.copy(uname), uname)
++        self.assertEqual(copy.deepcopy(uname), uname)
++
++    def test_uname_pickle(self):
++        orig = platform.uname()
++        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
++            with self.subTest(protocol=proto):
++                pickled = pickle.dumps(orig, proto)
++                restored = pickle.loads(pickled)
++                self.assertEqual(restored, orig)
++
++    def test_uname_slices(self):
++        res = platform.uname()
++        expected = tuple(res)
++        self.assertEqual(res[:], expected)
++        self.assertEqual(res[:5], expected[:5])
++
+     @unittest.skipIf(sys.platform in ['win32', 'OpenVMS'], "uname -p not used")
+     def test_uname_processor(self):
+         """
+diff --git a/Lib/test/test_posix.py b/Lib/test/test_posix.py
+index bfbcbab3b6..f4edb8bd95 100644
+--- a/Lib/test/test_posix.py
++++ b/Lib/test/test_posix.py
+@@ -1045,7 +1045,7 @@ class PosixTester(unittest.TestCase):
+         if sys.platform == 'darwin':
+             import sysconfig
+             dt = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET') or '10.0'
+-            if tuple(int(n) for n in str(dt).split('.')[0:2]) < (10, 6):
++            if tuple(int(n) for n in dt.split('.')[0:2]) < (10, 6):
+                 raise unittest.SkipTest("getgroups(2) is broken prior to 10.6")
+         # 'id -G' and 'os.getgroups()' should return the same
+diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py
+index a80e71e67e..15a68418bd 100644
+--- a/Lib/test/test_random.py
++++ b/Lib/test/test_random.py
+@@ -207,33 +207,6 @@ class TestBasicOps:
+         with self.assertRaises(ValueError):
+             sample(['red', 'green', 'blue'], counts=[1, 2, 3, 4], k=2)      # too many counts
+-    def test_sample_counts_equivalence(self):
+-        # Test the documented strong equivalence to a sample with repeated elements.
+-        # We run this test on random.Random() which makes deterministic selections
+-        # for a given seed value.
+-        sample = random.sample
+-        seed = random.seed
+-
+-        colors =  ['red', 'green', 'blue', 'orange', 'black', 'amber']
+-        counts = [500,      200,     20,       10,       5,       1 ]
+-        k = 700
+-        seed(8675309)
+-        s1 = sample(colors, counts=counts, k=k)
+-        seed(8675309)
+-        expanded = [color for (color, count) in zip(colors, counts) for i in range(count)]
+-        self.assertEqual(len(expanded), sum(counts))
+-        s2 = sample(expanded, k=k)
+-        self.assertEqual(s1, s2)
+-
+-        pop = 'abcdefghi'
+-        counts = [10, 9, 8, 7, 6, 5, 4, 3, 2]
+-        seed(8675309)
+-        s1 = ''.join(sample(pop, counts=counts, k=30))
+-        expanded = ''.join([letter for (letter, count) in zip(pop, counts) for i in range(count)])
+-        seed(8675309)
+-        s2 = ''.join(sample(expanded, k=30))
+-        self.assertEqual(s1, s2)
+-
+     def test_choices(self):
+         choices = self.gen.choices
+         data = ['red', 'green', 'blue', 'yellow']
+@@ -888,6 +861,33 @@ class MersenneTwister_TestBasicOps(TestBasicOps, unittest.TestCase):
+             self.assertEqual(self.gen.randbytes(n),
+                              gen2.getrandbits(n * 8).to_bytes(n, 'little'))
++    def test_sample_counts_equivalence(self):
++        # Test the documented strong equivalence to a sample with repeated elements.
++        # We run this test on random.Random() which makes deterministic selections
++        # for a given seed value.
++        sample = self.gen.sample
++        seed = self.gen.seed
++
++        colors =  ['red', 'green', 'blue', 'orange', 'black', 'amber']
++        counts = [500,      200,     20,       10,       5,       1 ]
++        k = 700
++        seed(8675309)
++        s1 = sample(colors, counts=counts, k=k)
++        seed(8675309)
++        expanded = [color for (color, count) in zip(colors, counts) for i in range(count)]
++        self.assertEqual(len(expanded), sum(counts))
++        s2 = sample(expanded, k=k)
++        self.assertEqual(s1, s2)
++
++        pop = 'abcdefghi'
++        counts = [10, 9, 8, 7, 6, 5, 4, 3, 2]
++        seed(8675309)
++        s1 = ''.join(sample(pop, counts=counts, k=30))
++        expanded = ''.join([letter for (letter, count) in zip(pop, counts) for i in range(count)])
++        seed(8675309)
++        s2 = ''.join(sample(expanded, k=30))
++        self.assertEqual(s1, s2)
++
+ def gamma(z, sqrt2pi=(2.0*pi)**0.5):
+     # Reflection to right half of complex plane
+diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py
+index 5762999003..3451f3a411 100644
+--- a/Lib/test/test_smtplib.py
++++ b/Lib/test/test_smtplib.py
+@@ -165,6 +165,17 @@ class LMTPGeneralTests(GeneralTests, unittest.TestCase):
+     client = smtplib.LMTP
++    @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), "test requires Unix domain socket")
++    def testUnixDomainSocketTimeoutDefault(self):
++        local_host = '/some/local/lmtp/delivery/program'
++        mock_socket.reply_with(b"220 Hello world")
++        try:
++            client = self.client(local_host, self.port)
++        finally:
++            mock_socket.setdefaulttimeout(None)
++        self.assertIsNone(client.sock.gettimeout())
++        client.close()
++
+     def testTimeoutZero(self):
+         super().testTimeoutZero()
+         local_host = '/some/local/lmtp/delivery/program'
+diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py
+index 7373fe29c4..e8f9699ef7 100644
+--- a/Lib/test/test_subprocess.py
++++ b/Lib/test/test_subprocess.py
+@@ -196,6 +196,28 @@ class ProcessTestCase(BaseTestCase):
+                 input=b'pear')
+         self.assertIn(b'PEAR', output)
++    def test_check_output_input_none(self):
++        """input=None has a legacy meaning of input='' on check_output."""
++        output = subprocess.check_output(
++                [sys.executable, "-c",
++                 "import sys; print('XX' if sys.stdin.read() else '')"],
++                input=None)
++        self.assertNotIn(b'XX', output)
++
++    def test_check_output_input_none_text(self):
++        output = subprocess.check_output(
++                [sys.executable, "-c",
++                 "import sys; print('XX' if sys.stdin.read() else '')"],
++                input=None, text=True)
++        self.assertNotIn('XX', output)
++
++    def test_check_output_input_none_universal_newlines(self):
++        output = subprocess.check_output(
++                [sys.executable, "-c",
++                 "import sys; print('XX' if sys.stdin.read() else '')"],
++                input=None, universal_newlines=True)
++        self.assertNotIn('XX', output)
++
+     def test_check_output_stdout_arg(self):
+         # check_output() refuses to accept 'stdout' argument
+         with self.assertRaises(ValueError) as c:
+diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py
+index 44e44bf5ea..0ca5c9390d 100644
+--- a/Lib/test/test_sysconfig.py
++++ b/Lib/test/test_sysconfig.py
+@@ -358,10 +358,12 @@ class TestSysConfig(unittest.TestCase):
+     @unittest.skipIf(sysconfig.get_config_var('EXT_SUFFIX') is None,
+                      'EXT_SUFFIX required for this test')
+-    def test_SO_in_vars(self):
++    def test_EXT_SUFFIX_in_vars(self):
++        import _imp
+         vars = sysconfig.get_config_vars()
+         self.assertIsNotNone(vars['SO'])
+         self.assertEqual(vars['SO'], vars['EXT_SUFFIX'])
++        self.assertEqual(vars['EXT_SUFFIX'], _imp.extension_suffixes()[0])
+     @unittest.skipUnless(sys.platform == 'linux' and
+                          hasattr(sys.implementation, '_multiarch'),
+diff --git a/Lib/test/test_tcl.py b/Lib/test/test_tcl.py
+index 1c5b9cf2bd..0bbb39b147 100644
+--- a/Lib/test/test_tcl.py
++++ b/Lib/test/test_tcl.py
+@@ -1,4 +1,5 @@
+ import unittest
++import locale
+ import re
+ import subprocess
+ import sys
+@@ -59,6 +60,10 @@ class TclTest(unittest.TestCase):
+         tcl = self.interp
+         self.assertEqual(tcl.eval('set a "a\\0b"'), 'a\x00b')
++    def test_eval_surrogates_in_result(self):
++        tcl = self.interp
++        self.assertIn(tcl.eval(r'set a "<\ud83d\udcbb>"'), '<\U0001f4bb>')
++
+     def testEvalException(self):
+         tcl = self.interp
+         self.assertRaises(TclError,tcl.eval,'set a')
+@@ -131,10 +136,14 @@ class TclTest(unittest.TestCase):
+     def get_integers(self):
+         integers = (0, 1, -1, 2**31-1, -2**31, 2**31, -2**31-1, 2**63-1, -2**63)
+-        # bignum was added in Tcl 8.5, but its support is able only since 8.5.8
+-        if (get_tk_patchlevel() >= (8, 6, 0, 'final') or
+-            (8, 5, 8) <= get_tk_patchlevel() < (8, 6)):
+-            integers += (2**63, -2**63-1, 2**1000, -2**1000)
++        # bignum was added in Tcl 8.5, but its support is able only since 8.5.8.
++        # Actually it is determined at compile time, so using get_tk_patchlevel()
++        # is not reliable.
++        # TODO: expose full static version.
++        if tcl_version >= (8, 5):
++            v = get_tk_patchlevel()
++            if v >= (8, 6, 0, 'final') or (8, 5, 8) <= v < (8, 6):
++                integers += (2**63, -2**63-1, 2**1000, -2**1000)
+         return integers
+     def test_getint(self):
+@@ -191,29 +200,48 @@ class TclTest(unittest.TestCase):
+     def testEvalFile(self):
+         tcl = self.interp
+-        with open(support.TESTFN, 'w') as f:
+-            self.addCleanup(support.unlink, support.TESTFN)
++        filename = support.TESTFN_ASCII
++        self.addCleanup(support.unlink, filename)
++        with open(filename, 'w') as f:
+             f.write("""set a 1
+             set b 2
+             set c [ expr $a + $b ]
+             """)
+-        tcl.evalfile(support.TESTFN)
++        tcl.evalfile(filename)
+         self.assertEqual(tcl.eval('set a'),'1')
+         self.assertEqual(tcl.eval('set b'),'2')
+         self.assertEqual(tcl.eval('set c'),'3')
+     def test_evalfile_null_in_result(self):
+         tcl = self.interp
+-        with open(support.TESTFN, 'w') as f:
+-            self.addCleanup(support.unlink, support.TESTFN)
++        filename = support.TESTFN_ASCII
++        self.addCleanup(support.unlink, filename)
++        with open(filename, 'w') as f:
+             f.write("""
+             set a "a\0b"
+             set b "a\\0b"
+             """)
+-        tcl.evalfile(support.TESTFN)
++        tcl.evalfile(filename)
+         self.assertEqual(tcl.eval('set a'), 'a\x00b')
+         self.assertEqual(tcl.eval('set b'), 'a\x00b')
++    def test_evalfile_surrogates_in_result(self):
++        tcl = self.interp
++        encoding = tcl.call('encoding', 'system')
++        self.addCleanup(tcl.call, 'encoding', 'system', encoding)
++        tcl.call('encoding', 'system', 'utf-8')
++
++        filename = support.TESTFN_ASCII
++        self.addCleanup(support.unlink, filename)
++        with open(filename, 'wb') as f:
++            f.write(b"""
++            set a "<\xed\xa0\xbd\xed\xb2\xbb>"
++            set b "<\\ud83d\\udcbb>"
++            """)
++        tcl.evalfile(filename)
++        self.assertEqual(tcl.eval('set a'), '<\U0001f4bb>')
++        self.assertEqual(tcl.eval('set b'), '<\U0001f4bb>')
++
+     def testEvalFileException(self):
+         tcl = self.interp
+         filename = "doesnotexists"
+@@ -419,7 +447,7 @@ class TclTest(unittest.TestCase):
+             else:
+                 self.assertEqual(result, str(i))
+                 self.assertIsInstance(result, str)
+-        if tcl_version < (8, 5):  # bignum was added in Tcl 8.5
++        if get_tk_patchlevel() < (8, 5):  # bignum was added in Tcl 8.5
+             self.assertRaises(TclError, tcl.call, 'expr', str(2**1000))
+     def test_passing_values(self):
+@@ -436,6 +464,11 @@ class TclTest(unittest.TestCase):
+         self.assertEqual(passValue('str\x00ing\u20ac'), 'str\x00ing\u20ac')
+         self.assertEqual(passValue('str\x00ing\U0001f4bb'),
+                          'str\x00ing\U0001f4bb')
++        if sys.platform != 'win32':
++            self.assertEqual(passValue('<\udce2\udc82\udcac>'),
++                             '<\u20ac>')
++            self.assertEqual(passValue('<\udced\udca0\udcbd\udced\udcb2\udcbb>'),
++                             '<\U0001f4bb>')
+         self.assertEqual(passValue(b'str\x00ing'),
+                          b'str\x00ing' if self.wantobjects else 'str\x00ing')
+         self.assertEqual(passValue(b'str\xc0\x80ing'),
+@@ -495,6 +528,9 @@ class TclTest(unittest.TestCase):
+         check('string\xbd')
+         check('string\u20ac')
+         check('string\U0001f4bb')
++        if sys.platform != 'win32':
++            check('<\udce2\udc82\udcac>', '<\u20ac>')
++            check('<\udced\udca0\udcbd\udced\udcb2\udcbb>', '<\U0001f4bb>')
+         check('')
+         check(b'string', 'string')
+         check(b'string\xe2\x82\xac', 'string\xe2\x82\xac')
+@@ -538,6 +574,8 @@ class TclTest(unittest.TestCase):
+             ('a \u20ac', ('a', '\u20ac')),
+             ('a \U0001f4bb', ('a', '\U0001f4bb')),
+             (b'a \xe2\x82\xac', ('a', '\u20ac')),
++            (b'a \xf0\x9f\x92\xbb', ('a', '\U0001f4bb')),
++            (b'a \xed\xa0\xbd\xed\xb2\xbb', ('a', '\U0001f4bb')),
+             (b'a\xc0\x80b c\xc0\x80d', ('a\x00b', 'c\x00d')),
+             ('a {b c}', ('a', 'b c')),
+             (r'a b\ c', ('a', 'b c')),
+diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py
+index 8549ba2b75..5bb3a58b2a 100644
+--- a/Lib/test/test_traceback.py
++++ b/Lib/test/test_traceback.py
+@@ -667,6 +667,31 @@ class BaseExceptionReportingTests:
+         msg = self.get_report(e).splitlines()
+         self.assertEqual(msg[-2], '               ^')
++    def test_syntax_error_no_lineno(self):
++        # See #34463.
++
++        # Without filename
++        e = SyntaxError('bad syntax')
++        msg = self.get_report(e).splitlines()
++        self.assertEqual(msg,
++            ['SyntaxError: bad syntax'])
++        e.lineno = 100
++        msg = self.get_report(e).splitlines()
++        self.assertEqual(msg,
++            ['  File "<string>", line 100', 'SyntaxError: bad syntax'])
++
++        # With filename
++        e = SyntaxError('bad syntax')
++        e.filename = 'myfile.py'
++
++        msg = self.get_report(e).splitlines()
++        self.assertEqual(msg,
++            ['SyntaxError: bad syntax (myfile.py)'])
++        e.lineno = 100
++        msg = self.get_report(e).splitlines()
++        self.assertEqual(msg,
++            ['  File "myfile.py", line 100', 'SyntaxError: bad syntax'])
++
+     def test_message_none(self):
+         # A message that looks like "None" should not be treated specially
+         err = self.get_report(Exception(None))
+diff --git a/Lib/test/test_tracemalloc.py b/Lib/test/test_tracemalloc.py
+index c5ae4e6d65..b10d1798c2 100644
+--- a/Lib/test/test_tracemalloc.py
++++ b/Lib/test/test_tracemalloc.py
+@@ -84,6 +84,25 @@ def traceback_filename(filename):
+     return traceback_lineno(filename, 0)
++class TestTraceback(unittest.TestCase):
++    def test_repr(self):
++        def get_repr(*args) -> str:
++            return repr(tracemalloc.Traceback(*args))
++
++        self.assertEqual(get_repr(()), "<Traceback ()>")
++        self.assertEqual(get_repr((), 0), "<Traceback () total_nframe=0>")
++
++        frames = (("f1", 1), ("f2", 2))
++        exp_repr_frames = (
++            "(<Frame filename='f2' lineno=2>,"
++            " <Frame filename='f1' lineno=1>)"
++        )
++        self.assertEqual(get_repr(frames),
++                         f"<Traceback {exp_repr_frames}>")
++        self.assertEqual(get_repr(frames, 2),
++                         f"<Traceback {exp_repr_frames} total_nframe=2>")
++
++
+ class TestTracemallocEnabled(unittest.TestCase):
+     def setUp(self):
+         if tracemalloc.is_tracing():
+@@ -1064,6 +1083,7 @@ class TestCAPI(unittest.TestCase):
+ def test_main():
+     support.run_unittest(
++        TestTraceback,
+         TestTracemallocEnabled,
+         TestSnapshot,
+         TestFilters,
+diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
+index 13cf20eee0..4bdb2a0fad 100644
+--- a/Lib/test/test_typing.py
++++ b/Lib/test/test_typing.py
+@@ -450,14 +450,6 @@ class CallableTests(BaseTestCase):
+             type(c)()
+     def test_callable_wrong_forms(self):
+-        with self.assertRaises(TypeError):
+-            Callable[[...], int]
+-        with self.assertRaises(TypeError):
+-            Callable[(), int]
+-        with self.assertRaises(TypeError):
+-            Callable[[()], int]
+-        with self.assertRaises(TypeError):
+-            Callable[[int, 1], 2]
+         with self.assertRaises(TypeError):
+             Callable[int]
+@@ -3079,6 +3071,11 @@ class GetUtilitiesTestCase(TestCase):
+         self.assertEqual(get_args(Callable), ())
+         self.assertEqual(get_args(list[int]), (int,))
+         self.assertEqual(get_args(list), ())
++        self.assertEqual(get_args(collections.abc.Callable[[int], str]), ([int], str))
++        self.assertEqual(get_args(collections.abc.Callable[..., str]), (..., str))
++        self.assertEqual(get_args(collections.abc.Callable[[], str]), ([], str))
++        self.assertEqual(get_args(collections.abc.Callable[[int], str]),
++                         get_args(Callable[[int], str]))
+ class CollectionsAbcTests(BaseTestCase):
+@@ -3899,10 +3896,14 @@ class TypedDictTests(BaseTestCase):
+         self.assertEqual(D(), {})
+         self.assertEqual(D(x=1), {'x': 1})
+         self.assertEqual(D.__total__, False)
++        self.assertEqual(D.__required_keys__, frozenset())
++        self.assertEqual(D.__optional_keys__, {'x'})
+         self.assertEqual(Options(), {})
+         self.assertEqual(Options(log_level=2), {'log_level': 2})
+         self.assertEqual(Options.__total__, False)
++        self.assertEqual(Options.__required_keys__, frozenset())
++        self.assertEqual(Options.__optional_keys__, {'log_level', 'log_path'})
+     def test_optional_keys(self):
+         class Point2Dor3D(Point2D, total=False):
+diff --git a/Lib/test/test_unpack_ex.py b/Lib/test/test_unpack_ex.py
+index fcc93829cc..049e48b13f 100644
+--- a/Lib/test/test_unpack_ex.py
++++ b/Lib/test/test_unpack_ex.py
+@@ -346,6 +346,31 @@ Now some general starred expressions (all fail).
+       ...
+     SyntaxError: can't use starred expression here
++    >>> (*x),y = 1, 2 # doctest:+ELLIPSIS
++    Traceback (most recent call last):
++      ...
++    SyntaxError: can't use starred expression here
++
++    >>> (((*x))),y = 1, 2 # doctest:+ELLIPSIS
++    Traceback (most recent call last):
++      ...
++    SyntaxError: can't use starred expression here
++
++    >>> z,(*x),y = 1, 2, 4 # doctest:+ELLIPSIS
++    Traceback (most recent call last):
++      ...
++    SyntaxError: can't use starred expression here
++
++    >>> z,(*x) = 1, 2 # doctest:+ELLIPSIS
++    Traceback (most recent call last):
++      ...
++    SyntaxError: can't use starred expression here
++
++    >>> ((*x),y) = 1, 2 # doctest:+ELLIPSIS
++    Traceback (most recent call last):
++      ...
++    SyntaxError: can't use starred expression here
++
+ Some size constraints (all fail.)
+     >>> s = ", ".join("a%d" % i for i in range(1<<8)) + ", *rest = range(1<<8 + 1)"
+diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py
+index b71be549d2..12c3f4dbd5 100644
+--- a/Lib/test/test_urllib2.py
++++ b/Lib/test/test_urllib2.py
+@@ -1849,9 +1849,17 @@ class MiscTests(unittest.TestCase):
+              ('ftp', 'joe', 'password', 'proxy.example.com')),
+             # Test for no trailing '/' case
+             ('http://joe:password@proxy.example.com',
+-             ('http', 'joe', 'password', 'proxy.example.com'))
++             ('http', 'joe', 'password', 'proxy.example.com')),
++            # Testcases with '/' character in username, password
++            ('http://user/name:password@localhost:22',
++             ('http', 'user/name', 'password', 'localhost:22')),
++            ('http://username:pass/word@localhost:22',
++             ('http', 'username', 'pass/word', 'localhost:22')),
++            ('http://user/name:pass/word@localhost:22',
++             ('http', 'user/name', 'pass/word', 'localhost:22')),
+         ]
++
+         for tc, expected in parse_proxy_test_cases:
+             self.assertEqual(_parse_proxy(tc), expected)
+diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py
+index 2175afcffa..f15f6c5e57 100644
+--- a/Lib/tkinter/__init__.py
++++ b/Lib/tkinter/__init__.py
+@@ -270,7 +270,7 @@ class Event:
+         )
+-_support_default_root = 1
++_support_default_root = True
+ _default_root = None
+@@ -280,13 +280,26 @@ def NoDefaultRoot():
+     Call this function to inhibit that the first instance of
+     Tk is used for windows without an explicit parent window.
+     """
+-    global _support_default_root
+-    _support_default_root = 0
+-    global _default_root
++    global _support_default_root, _default_root
++    _support_default_root = False
++    # Delete, so any use of _default_root will immediately raise an exception.
++    # Rebind before deletion, so repeated calls will not fail.
+     _default_root = None
+     del _default_root
++def _get_default_root(what=None):
++    if not _support_default_root:
++        raise RuntimeError("No master specified and tkinter is "
++                           "configured to not support default root")
++    if not _default_root:
++        if what:
++            raise RuntimeError(f"Too early to {what}: no default root window")
++        root = Tk()
++        assert _default_root is root
++    return _default_root
++
++
+ def _tkerror(err):
+     """Internal function."""
+     pass
+@@ -330,7 +343,7 @@ class Variable:
+             raise TypeError("name must be a string")
+         global _varnum
+         if not master:
+-            master = _default_root
++            master = _get_default_root('create variable')
+         self._root = master._root()
+         self._tk = master.tk
+         if name:
+@@ -478,15 +491,11 @@ class Variable:
+             self._tk.call("trace", "vinfo", self._name))]
+     def __eq__(self, other):
+-        """Comparison for equality (==).
+-
+-        Note: if the Variable's master matters to behavior
+-        also compare self._master == other._master
+-        """
+         if not isinstance(other, Variable):
+             return NotImplemented
+-        return self.__class__.__name__ == other.__class__.__name__ \
+-            and self._name == other._name
++        return (self._name == other._name
++                and self.__class__.__name__ == other.__class__.__name__
++                and self._tk == other._tk)
+ class StringVar(Variable):
+@@ -591,7 +600,7 @@ class BooleanVar(Variable):
+ def mainloop(n=0):
+     """Run the main loop of Tcl."""
+-    _default_root.tk.mainloop(n)
++    _get_default_root('run the main loop').tk.mainloop(n)
+ getint = int
+@@ -600,9 +609,9 @@ getdouble = float
+ def getboolean(s):
+-    """Convert true and false to integer values 1 and 0."""
++    """Convert Tcl object to True or False."""
+     try:
+-        return _default_root.tk.getboolean(s)
++        return _get_default_root('use getboolean()').tk.getboolean(s)
+     except TclError:
+         raise ValueError("invalid literal for getboolean()")
+@@ -1151,8 +1160,7 @@ class Misc:
+             self.tk.call('winfo', 'reqwidth', self._w))
+     def winfo_rgb(self, color):
+-        """Return tuple of decimal values for red, green, blue for
+-        COLOR in this widget."""
++        """Return a tuple of integer RGB values in range(65536) for color in this widget."""
+         return self._getints(
+             self.tk.call('winfo', 'rgb', self._w, color))
+@@ -2248,7 +2256,7 @@ class Tk(Misc, Wm):
+         is the name of the widget class."""
+         self.master = None
+         self.children = {}
+-        self._tkloaded = 0
++        self._tkloaded = False
+         # to avoid recursions in the getattr code in case of failure, we
+         # ensure that self.tk is always _something_.
+         self.tk = None
+@@ -2272,7 +2280,7 @@ class Tk(Misc, Wm):
+             self._loadtk()
+     def _loadtk(self):
+-        self._tkloaded = 1
++        self._tkloaded = True
+         global _default_root
+         # Version sanity checks
+         tk_version = self.tk.getvar('tk_version')
+@@ -2521,12 +2529,8 @@ class BaseWidget(Misc):
+     def _setup(self, master, cnf):
+         """Internal function. Sets up information about children."""
+-        if _support_default_root:
+-            global _default_root
+-            if not master:
+-                if not _default_root:
+-                    _default_root = Tk()
+-                master = _default_root
++        if not master:
++            master = _get_default_root()
+         self.master = master
+         self.tk = master.tk
+         name = None
+@@ -3990,9 +3994,7 @@ class Image:
+     def __init__(self, imgtype, name=None, cnf={}, master=None, **kw):
+         self.name = None
+         if not master:
+-            master = _default_root
+-            if not master:
+-                raise RuntimeError('Too early to create image')
++            master = _get_default_root('create image')
+         self.tk = getattr(master, 'tk', master)
+         if not name:
+             Image._last_id += 1
+@@ -4146,11 +4148,13 @@ class BitmapImage(Image):
+ def image_names():
+-    return _default_root.tk.splitlist(_default_root.tk.call('image', 'names'))
++    tk = _get_default_root('use image_names()').tk
++    return tk.splitlist(tk.call('image', 'names'))
+ def image_types():
+-    return _default_root.tk.splitlist(_default_root.tk.call('image', 'types'))
++    tk = _get_default_root('use image_types()').tk
++    return tk.splitlist(tk.call('image', 'types'))
+ class Spinbox(Widget, XView):
+diff --git a/Lib/tkinter/colorchooser.py b/Lib/tkinter/colorchooser.py
+index 3cfc06f6f1..e2fb69dba9 100644
+--- a/Lib/tkinter/colorchooser.py
++++ b/Lib/tkinter/colorchooser.py
+@@ -8,57 +8,69 @@
+ # fixed initialcolor handling in August 1998
+ #
+-#
+-# options (all have default values):
+-#
+-# - initialcolor: color to mark as selected when dialog is displayed
+-#   (given as an RGB triplet or a Tk color string)
+-#
+-# - parent: which window to place the dialog on top of
+-#
+-# - title: dialog title
+-#
+ from tkinter.commondialog import Dialog
+ __all__ = ["Chooser", "askcolor"]
+-#
+-# color chooser class
+-
+ class Chooser(Dialog):
+-    "Ask for a color"
++    """Create a dialog for the tk_chooseColor command.
++
++    Args:
++        master: The master widget for this dialog.  If not provided,
++            defaults to options['parent'] (if defined).
++        options: Dictionary of options for the tk_chooseColor call.
++            initialcolor: Specifies the selected color when the
++                dialog is first displayed.  This can be a tk color
++                string or a 3-tuple of ints in the range (0, 255)
++                for an RGB triplet.
++            parent: The parent window of the color dialog.  The
++                color dialog is displayed on top of this.
++            title: A string for the title of the dialog box.
++    """
+     command = "tk_chooseColor"
+     def _fixoptions(self):
++        """Ensure initialcolor is a tk color string.
++
++        Convert initialcolor from a RGB triplet to a color string.
++        """
+         try:
+-            # make sure initialcolor is a tk color string
+             color = self.options["initialcolor"]
+             if isinstance(color, tuple):
+-                # assume an RGB triplet
++                # Assume an RGB triplet.
+                 self.options["initialcolor"] = "#%02x%02x%02x" % color
+         except KeyError:
+             pass
+     def _fixresult(self, widget, result):
+-        # result can be somethings: an empty tuple, an empty string or
+-        # a Tcl_Obj, so this somewhat weird check handles that
++        """Adjust result returned from call to tk_chooseColor.
++
++        Return both an RGB tuple of ints in the range (0, 255) and the
++        tk color string in the form #rrggbb.
++        """
++        # Result can be many things: an empty tuple, an empty string, or
++        # a _tkinter.Tcl_Obj, so this somewhat weird check handles that.
+         if not result or not str(result):
+-            return None, None # canceled
++            return None, None  # canceled
+-        # to simplify application code, the color chooser returns
+-        # an RGB tuple together with the Tk color string
++        # To simplify application code, the color chooser returns
++        # an RGB tuple together with the Tk color string.
+         r, g, b = widget.winfo_rgb(result)
+-        return (r/256, g/256, b/256), str(result)
++        return (r//256, g//256, b//256), str(result)
+ #
+ # convenience stuff
+-def askcolor(color = None, **options):
+-    "Ask for a color"
++def askcolor(color=None, **options):
++    """Display dialog window for selection of a color.
++
++    Convenience wrapper for the Chooser class.  Displays the color
++    chooser dialog with color as the initial value.
++    """
+     if color:
+         options = options.copy()
+diff --git a/Lib/tkinter/commondialog.py b/Lib/tkinter/commondialog.py
+index e56b5baf7d..cc3069842c 100644
+--- a/Lib/tkinter/commondialog.py
++++ b/Lib/tkinter/commondialog.py
+@@ -18,10 +18,10 @@ class Dialog:
+     command = None
+     def __init__(self, master=None, **options):
++        if not master:
++            master = options.get('parent')
+         self.master = master
+         self.options = options
+-        if not master and options.get('parent'):
+-            self.master = options['parent']
+     def _fixoptions(self):
+         pass # hook
+diff --git a/Lib/tkinter/font.py b/Lib/tkinter/font.py
+index 15ad7ab4b6..78b660c54b 100644
+--- a/Lib/tkinter/font.py
++++ b/Lib/tkinter/font.py
+@@ -69,7 +69,7 @@ class Font:
+     def __init__(self, root=None, font=None, name=None, exists=False,
+                  **options):
+         if not root:
+-            root = tkinter._default_root
++            root = tkinter._get_default_root('use font')
+         tk = getattr(root, 'tk', root)
+         if font:
+             # get actual settings corresponding to the given font
+@@ -103,7 +103,7 @@ class Font:
+     def __eq__(self, other):
+         if not isinstance(other, Font):
+             return NotImplemented
+-        return self.name == other.name
++        return self.name == other.name and self._tk == other._tk
+     def __getitem__(self, key):
+         return self.cget(key)
+@@ -180,7 +180,7 @@ class Font:
+ def families(root=None, displayof=None):
+     "Get font families (as a tuple)"
+     if not root:
+-        root = tkinter._default_root
++        root = tkinter._get_default_root('use font.families()')
+     args = ()
+     if displayof:
+         args = ('-displayof', displayof)
+@@ -190,7 +190,7 @@ def families(root=None, displayof=None):
+ def names(root=None):
+     "Get names of defined fonts (as a tuple)"
+     if not root:
+-        root = tkinter._default_root
++        root = tkinter._get_default_root('use font.names()')
+     return root.tk.splitlist(root.tk.call("font", "names"))
+diff --git a/Lib/tkinter/simpledialog.py b/Lib/tkinter/simpledialog.py
+index 8524417111..b882d47c96 100644
+--- a/Lib/tkinter/simpledialog.py
++++ b/Lib/tkinter/simpledialog.py
+@@ -24,9 +24,7 @@ askstring -- get a string from the user
+ """
+ from tkinter import *
+-from tkinter import messagebox
+-
+-import tkinter # used at _QueryDialog for tkinter._default_root
++from tkinter import messagebox, _get_default_root
+ class SimpleDialog:
+@@ -128,13 +126,17 @@ class Dialog(Toplevel):
+             title -- the dialog title
+         '''
+-        Toplevel.__init__(self, parent)
++        master = parent
++        if not master:
++            master = _get_default_root('create dialog window')
++
++        Toplevel.__init__(self, master)
+         self.withdraw() # remain invisible for now
+-        # If the master is not viewable, don't
++        # If the parent is not viewable, don't
+         # make the child transient, or else it
+         # would be opened withdrawn
+-        if parent.winfo_viewable():
++        if parent is not None and parent.winfo_viewable():
+             self.transient(parent)
+         if title:
+@@ -155,7 +157,7 @@ class Dialog(Toplevel):
+         self.protocol("WM_DELETE_WINDOW", self.cancel)
+-        if self.parent is not None:
++        if parent is not None:
+             self.geometry("+%d+%d" % (parent.winfo_rootx()+50,
+                                       parent.winfo_rooty()+50))
+@@ -259,9 +261,6 @@ class _QueryDialog(Dialog):
+                  minvalue = None, maxvalue = None,
+                  parent = None):
+-        if not parent:
+-            parent = tkinter._default_root
+-
+         self.prompt   = prompt
+         self.minvalue = minvalue
+         self.maxvalue = maxvalue
+diff --git a/Lib/tkinter/test/support.py b/Lib/tkinter/test/support.py
+index 467a0b66c2..dbc47a81e6 100644
+--- a/Lib/tkinter/test/support.py
++++ b/Lib/tkinter/test/support.py
+@@ -36,6 +36,33 @@ class AbstractTkTest:
+             w.destroy()
+         self.root.withdraw()
++
++class AbstractDefaultRootTest:
++
++    def setUp(self):
++        self._old_support_default_root = tkinter._support_default_root
++        destroy_default_root()
++        tkinter._support_default_root = True
++        self.wantobjects = tkinter.wantobjects
++
++    def tearDown(self):
++        destroy_default_root()
++        tkinter._default_root = None
++        tkinter._support_default_root = self._old_support_default_root
++
++    def _test_widget(self, constructor):
++        # no master passing
++        x = constructor()
++        self.assertIsNotNone(tkinter._default_root)
++        self.assertIs(x.master, tkinter._default_root)
++        self.assertIs(x.tk, tkinter._default_root.tk)
++        x.destroy()
++        destroy_default_root()
++        tkinter.NoDefaultRoot()
++        self.assertRaises(RuntimeError, constructor)
++        self.assertFalse(hasattr(tkinter, '_default_root'))
++
++
+ def destroy_default_root():
+     if getattr(tkinter, '_default_root', None):
+         tkinter._default_root.update_idletasks()
+diff --git a/Lib/tkinter/test/test_tkinter/test_colorchooser.py b/Lib/tkinter/test/test_tkinter/test_colorchooser.py
+new file mode 100644
+index 0000000000..4798bc9c26
+--- /dev/null
++++ b/Lib/tkinter/test/test_tkinter/test_colorchooser.py
+@@ -0,0 +1,43 @@
++import unittest
++import tkinter
++from test.support import requires, run_unittest, swap_attr
++from tkinter.test.support import AbstractTkTest
++from tkinter import colorchooser
++
++requires('gui')
++
++
++class ChooserTest(AbstractTkTest, unittest.TestCase):
++
++    @classmethod
++    def setUpClass(cls):
++        AbstractTkTest.setUpClass.__func__(cls)
++        cls.cc = colorchooser.Chooser(initialcolor='dark blue slate')
++
++    def test_fixoptions(self):
++        cc = self.cc
++        cc._fixoptions()
++        self.assertEqual(cc.options['initialcolor'], 'dark blue slate')
++
++        cc.options['initialcolor'] = '#D2D269691E1E'
++        cc._fixoptions()
++        self.assertEqual(cc.options['initialcolor'], '#D2D269691E1E')
++
++        cc.options['initialcolor'] = (210, 105, 30)
++        cc._fixoptions()
++        self.assertEqual(cc.options['initialcolor'], '#d2691e')
++
++    def test_fixresult(self):
++        cc = self.cc
++        self.assertEqual(cc._fixresult(self.root, ()), (None, None))
++        self.assertEqual(cc._fixresult(self.root, ''), (None, None))
++        self.assertEqual(cc._fixresult(self.root, 'chocolate'),
++                         ((210, 105, 30), 'chocolate'))
++        self.assertEqual(cc._fixresult(self.root, '#4a3c8c'),
++                         ((74, 60, 140), '#4a3c8c'))
++
++
++tests_gui = (ChooserTest,)
++
++if __name__ == "__main__":
++    run_unittest(*tests_gui)
+diff --git a/Lib/tkinter/test/test_tkinter/test_font.py b/Lib/tkinter/test/test_tkinter/test_font.py
+index a021ea3368..0ea7924f5d 100644
+--- a/Lib/tkinter/test/test_tkinter/test_font.py
++++ b/Lib/tkinter/test/test_tkinter/test_font.py
+@@ -2,7 +2,7 @@ import unittest
+ import tkinter
+ from tkinter import font
+ from test.support import requires, run_unittest, gc_collect, ALWAYS_EQ
+-from tkinter.test.support import AbstractTkTest
++from tkinter.test.support import AbstractTkTest, AbstractDefaultRootTest
+ requires('gui')
+@@ -63,15 +63,22 @@ class FontTest(AbstractTkTest, unittest.TestCase):
+         self.assertEqual(self.font.name, fontname)
+         self.assertEqual(str(self.font), fontname)
+-    def test_eq(self):
++    def test_equality(self):
+         font1 = font.Font(root=self.root, name=fontname, exists=True)
+         font2 = font.Font(root=self.root, name=fontname, exists=True)
+         self.assertIsNot(font1, font2)
+         self.assertEqual(font1, font2)
+         self.assertNotEqual(font1, font1.copy())
++
+         self.assertNotEqual(font1, 0)
+         self.assertEqual(font1, ALWAYS_EQ)
++        root2 = tkinter.Tk()
++        self.addCleanup(root2.destroy)
++        font3 = font.Font(root=root2, name=fontname, exists=True)
++        self.assertEqual(str(font1), str(font3))
++        self.assertNotEqual(font1, font3)
++
+     def test_measure(self):
+         self.assertIsInstance(self.font.measure('abc'), int)
+@@ -101,7 +108,38 @@ class FontTest(AbstractTkTest, unittest.TestCase):
+             self.assertTrue(name)
+         self.assertIn(fontname, names)
+-tests_gui = (FontTest, )
++
++class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase):
++
++    def test_families(self):
++        self.assertRaises(RuntimeError, font.families)
++        root = tkinter.Tk()
++        families = font.families()
++        self.assertIsInstance(families, tuple)
++        self.assertTrue(families)
++        for family in families:
++            self.assertIsInstance(family, str)
++            self.assertTrue(family)
++        root.destroy()
++        tkinter.NoDefaultRoot()
++        self.assertRaises(RuntimeError, font.families)
++
++    def test_names(self):
++        self.assertRaises(RuntimeError, font.names)
++        root = tkinter.Tk()
++        names = font.names()
++        self.assertIsInstance(names, tuple)
++        self.assertTrue(names)
++        for name in names:
++            self.assertIsInstance(name, str)
++            self.assertTrue(name)
++        self.assertIn(fontname, names)
++        root.destroy()
++        tkinter.NoDefaultRoot()
++        self.assertRaises(RuntimeError, font.names)
++
++
++tests_gui = (FontTest, DefaultRootTest)
+ if __name__ == "__main__":
+     run_unittest(*tests_gui)
+diff --git a/Lib/tkinter/test/test_tkinter/test_images.py b/Lib/tkinter/test/test_tkinter/test_images.py
+index 2805d35a1f..94bba8518f 100644
+--- a/Lib/tkinter/test/test_tkinter/test_images.py
++++ b/Lib/tkinter/test/test_tkinter/test_images.py
+@@ -1,7 +1,7 @@
+ import unittest
+ import tkinter
+ from test import support
+-from tkinter.test.support import AbstractTkTest, requires_tcl
++from tkinter.test.support import AbstractTkTest, AbstractDefaultRootTest, requires_tcl
+ support.requires('gui')
+@@ -19,6 +19,47 @@ class MiscTest(AbstractTkTest, unittest.TestCase):
+         self.assertIsInstance(image_names, tuple)
++class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase):
++
++    def test_image_types(self):
++        self.assertRaises(RuntimeError, tkinter.image_types)
++        root = tkinter.Tk()
++        image_types = tkinter.image_types()
++        self.assertIsInstance(image_types, tuple)
++        self.assertIn('photo', image_types)
++        self.assertIn('bitmap', image_types)
++        root.destroy()
++        tkinter.NoDefaultRoot()
++        self.assertRaises(RuntimeError, tkinter.image_types)
++
++    def test_image_names(self):
++        self.assertRaises(RuntimeError, tkinter.image_names)
++        root = tkinter.Tk()
++        image_names = tkinter.image_names()
++        self.assertIsInstance(image_names, tuple)
++        root.destroy()
++        tkinter.NoDefaultRoot()
++        self.assertRaises(RuntimeError, tkinter.image_names)
++
++    def test_image_create_bitmap(self):
++        self.assertRaises(RuntimeError, tkinter.BitmapImage)
++        root = tkinter.Tk()
++        image = tkinter.BitmapImage()
++        self.assertIn(image.name, tkinter.image_names())
++        root.destroy()
++        tkinter.NoDefaultRoot()
++        self.assertRaises(RuntimeError, tkinter.BitmapImage)
++
++    def test_image_create_photo(self):
++        self.assertRaises(RuntimeError, tkinter.PhotoImage)
++        root = tkinter.Tk()
++        image = tkinter.PhotoImage()
++        self.assertIn(image.name, tkinter.image_names())
++        root.destroy()
++        tkinter.NoDefaultRoot()
++        self.assertRaises(RuntimeError, tkinter.PhotoImage)
++
++
+ class BitmapImageTest(AbstractTkTest, unittest.TestCase):
+     @classmethod
+@@ -330,7 +371,7 @@ class PhotoImageTest(AbstractTkTest, unittest.TestCase):
+         self.assertEqual(image.transparency_get(4, 6), False)
+-tests_gui = (MiscTest, BitmapImageTest, PhotoImageTest,)
++tests_gui = (MiscTest, DefaultRootTest, BitmapImageTest, PhotoImageTest,)
+ if __name__ == "__main__":
+     support.run_unittest(*tests_gui)
+diff --git a/Lib/tkinter/test/test_tkinter/test_misc.py b/Lib/tkinter/test/test_tkinter/test_misc.py
+index b8eea2544f..f6e5b4db1a 100644
+--- a/Lib/tkinter/test/test_tkinter/test_misc.py
++++ b/Lib/tkinter/test/test_tkinter/test_misc.py
+@@ -1,7 +1,7 @@
+ import unittest
+ import tkinter
+ from test import support
+-from tkinter.test.support import AbstractTkTest
++from tkinter.test.support import AbstractTkTest, AbstractDefaultRootTest
+ support.requires('gui')
+@@ -192,6 +192,26 @@ class MiscTest(AbstractTkTest, unittest.TestCase):
+         with self.assertRaises(tkinter.TclError):
+             root.clipboard_get()
++    def test_winfo_rgb(self):
++        root = self.root
++        rgb = root.winfo_rgb
++
++        # Color name.
++        self.assertEqual(rgb('red'), (65535, 0, 0))
++        self.assertEqual(rgb('dark slate blue'), (18504, 15677, 35723))
++        # #RGB - extends each 4-bit hex value to be 16-bit.
++        self.assertEqual(rgb('#F0F'), (0xFFFF, 0x0000, 0xFFFF))
++        # #RRGGBB - extends each 8-bit hex value to be 16-bit.
++        self.assertEqual(rgb('#4a3c8c'), (0x4a4a, 0x3c3c, 0x8c8c))
++        # #RRRRGGGGBBBB
++        self.assertEqual(rgb('#dede14143939'), (0xdede, 0x1414, 0x3939))
++        # Invalid string.
++        with self.assertRaises(tkinter.TclError):
++            rgb('#123456789a')
++        # RGB triplet is invalid input.
++        with self.assertRaises(tkinter.TclError):
++            rgb((111, 78, 55))
++
+     def test_event_repr_defaults(self):
+         e = tkinter.Event()
+         e.serial = 12345
+@@ -241,7 +261,85 @@ class MiscTest(AbstractTkTest, unittest.TestCase):
+                          " num=3 delta=-1 focus=True"
+                          " x=10 y=20 width=300 height=200>")
+-tests_gui = (MiscTest, )
++    def test_getboolean(self):
++        for v in 'true', 'yes', 'on', '1', 't', 'y', 1, True:
++            self.assertIs(self.root.getboolean(v), True)
++        for v in 'false', 'no', 'off', '0', 'f', 'n', 0, False:
++            self.assertIs(self.root.getboolean(v), False)
++        self.assertRaises(ValueError, self.root.getboolean, 'yea')
++        self.assertRaises(ValueError, self.root.getboolean, '')
++        self.assertRaises(TypeError, self.root.getboolean, None)
++        self.assertRaises(TypeError, self.root.getboolean, ())
++
++    def test_mainloop(self):
++        log = []
++        def callback():
++            log.append(1)
++            self.root.after(100, self.root.quit)
++        self.root.after(100, callback)
++        self.root.mainloop(1)
++        self.assertEqual(log, [])
++        self.root.mainloop(0)
++        self.assertEqual(log, [1])
++        self.assertTrue(self.root.winfo_exists())
++
++
++class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase):
++
++    def test_default_root(self):
++        self.assertIs(tkinter._support_default_root, True)
++        self.assertIsNone(tkinter._default_root)
++        root = tkinter.Tk()
++        root2 = tkinter.Tk()
++        root3 = tkinter.Tk()
++        self.assertIs(tkinter._default_root, root)
++        root2.destroy()
++        self.assertIs(tkinter._default_root, root)
++        root.destroy()
++        self.assertIsNone(tkinter._default_root)
++        root3.destroy()
++        self.assertIsNone(tkinter._default_root)
++
++    def test_no_default_root(self):
++        self.assertIs(tkinter._support_default_root, True)
++        self.assertIsNone(tkinter._default_root)
++        root = tkinter.Tk()
++        self.assertIs(tkinter._default_root, root)
++        tkinter.NoDefaultRoot()
++        self.assertIs(tkinter._support_default_root, False)
++        self.assertFalse(hasattr(tkinter, '_default_root'))
++        # repeated call is no-op
++        tkinter.NoDefaultRoot()
++        self.assertIs(tkinter._support_default_root, False)
++        self.assertFalse(hasattr(tkinter, '_default_root'))
++        root.destroy()
++        self.assertIs(tkinter._support_default_root, False)
++        self.assertFalse(hasattr(tkinter, '_default_root'))
++        root = tkinter.Tk()
++        self.assertIs(tkinter._support_default_root, False)
++        self.assertFalse(hasattr(tkinter, '_default_root'))
++        root.destroy()
++
++    def test_getboolean(self):
++        self.assertRaises(RuntimeError, tkinter.getboolean, '1')
++        root = tkinter.Tk()
++        self.assertIs(tkinter.getboolean('1'), True)
++        self.assertRaises(ValueError, tkinter.getboolean, 'yea')
++        root.destroy()
++        tkinter.NoDefaultRoot()
++        self.assertRaises(RuntimeError, tkinter.getboolean, '1')
++
++    def test_mainloop(self):
++        self.assertRaises(RuntimeError, tkinter.mainloop)
++        root = tkinter.Tk()
++        root.after_idle(root.quit)
++        tkinter.mainloop()
++        root.destroy()
++        tkinter.NoDefaultRoot()
++        self.assertRaises(RuntimeError, tkinter.mainloop)
++
++
++tests_gui = (MiscTest, DefaultRootTest)
+ if __name__ == "__main__":
+     support.run_unittest(*tests_gui)
+diff --git a/Lib/tkinter/test/test_tkinter/test_simpledialog.py b/Lib/tkinter/test/test_tkinter/test_simpledialog.py
+new file mode 100644
+index 0000000000..9119172588
+--- /dev/null
++++ b/Lib/tkinter/test/test_tkinter/test_simpledialog.py
+@@ -0,0 +1,25 @@
++import unittest
++import tkinter
++from test.support import requires, run_unittest, swap_attr
++from tkinter.test.support import AbstractDefaultRootTest
++from tkinter.simpledialog import Dialog, askinteger
++
++requires('gui')
++
++
++class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase):
++
++    def test_askinteger(self):
++        self.assertRaises(RuntimeError, askinteger, "Go To Line", "Line number")
++        root = tkinter.Tk()
++        with swap_attr(Dialog, 'wait_window', lambda self, w: w.destroy()):
++            askinteger("Go To Line", "Line number")
++        root.destroy()
++        tkinter.NoDefaultRoot()
++        self.assertRaises(RuntimeError, askinteger, "Go To Line", "Line number")
++
++
++tests_gui = (DefaultRootTest,)
++
++if __name__ == "__main__":
++    run_unittest(*tests_gui)
+diff --git a/Lib/tkinter/test/test_tkinter/test_variables.py b/Lib/tkinter/test/test_tkinter/test_variables.py
+index 08b7dedcaf..6aebe8d16d 100644
+--- a/Lib/tkinter/test/test_tkinter/test_variables.py
++++ b/Lib/tkinter/test/test_tkinter/test_variables.py
+@@ -1,8 +1,10 @@
+ import unittest
+ import gc
++import tkinter
+ from tkinter import (Variable, StringVar, IntVar, DoubleVar, BooleanVar, Tcl,
+                      TclError)
+ from test.support import ALWAYS_EQ
++from tkinter.test.support import AbstractDefaultRootTest
+ class Var(Variable):
+@@ -56,22 +58,32 @@ class TestVariable(TestBase):
+         del v2
+         self.assertFalse(self.info_exists("name"))
+-    def test___eq__(self):
++    def test_equality(self):
+         # values doesn't matter, only class and name are checked
+         v1 = Variable(self.root, name="abc")
+         v2 = Variable(self.root, name="abc")
+         self.assertIsNot(v1, v2)
+         self.assertEqual(v1, v2)
+-        v3 = StringVar(self.root, name="abc")
++        v3 = Variable(self.root, name="cba")
+         self.assertNotEqual(v1, v3)
++        v4 = StringVar(self.root, name="abc")
++        self.assertEqual(str(v1), str(v4))
++        self.assertNotEqual(v1, v4)
++
+         V = type('Variable', (), {})
+         self.assertNotEqual(v1, V())
+         self.assertNotEqual(v1, object())
+         self.assertEqual(v1, ALWAYS_EQ)
++        root2 = tkinter.Tk()
++        self.addCleanup(root2.destroy)
++        v5 = Variable(root2, name="abc")
++        self.assertEqual(str(v1), str(v5))
++        self.assertNotEqual(v1, v5)
++
+     def test_invalid_name(self):
+         with self.assertRaises(TypeError):
+             Variable(self.root, name=123)
+@@ -308,8 +320,21 @@ class TestBooleanVar(TestBase):
+             v.get()
++class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase):
++
++    def test_variable(self):
++        self.assertRaises(RuntimeError, Variable)
++        root = tkinter.Tk()
++        v = Variable()
++        v.set("value")
++        self.assertEqual(v.get(), "value")
++        root.destroy()
++        tkinter.NoDefaultRoot()
++        self.assertRaises(RuntimeError, Variable)
++
++
+ tests_gui = (TestVariable, TestStringVar, TestIntVar,
+-             TestDoubleVar, TestBooleanVar)
++             TestDoubleVar, TestBooleanVar, DefaultRootTest)
+ if __name__ == "__main__":
+diff --git a/Lib/tkinter/test/test_tkinter/test_widgets.py b/Lib/tkinter/test/test_tkinter/test_widgets.py
+index b6f792d6c2..39334de8cf 100644
+--- a/Lib/tkinter/test/test_tkinter/test_widgets.py
++++ b/Lib/tkinter/test/test_tkinter/test_widgets.py
+@@ -2,11 +2,11 @@ import unittest
+ import tkinter
+ from tkinter import TclError
+ import os
+-import sys
+ from test.support import requires
+ from tkinter.test.support import (tcl_version, requires_tcl,
+-                                  get_tk_patchlevel, widget_eq)
++                                  get_tk_patchlevel, widget_eq,
++                                  AbstractDefaultRootTest)
+ from tkinter.test.widget_tests import (
+     add_standard_options, noconv, pixels_round,
+     AbstractWidgetTest, StandardOptionsTests, IntegerSizeTests, PixelSizeTests,
+@@ -22,7 +22,7 @@ def float_round(x):
+ class AbstractToplevelTest(AbstractWidgetTest, PixelSizeTests):
+     _conv_pad_pixels = noconv
+-    def test_class(self):
++    def test_configure_class(self):
+         widget = self.create()
+         self.assertEqual(widget['class'],
+                          widget.__class__.__name__.title())
+@@ -31,7 +31,7 @@ class AbstractToplevelTest(AbstractWidgetTest, PixelSizeTests):
+         widget2 = self.create(class_='Foo')
+         self.assertEqual(widget2['class'], 'Foo')
+-    def test_colormap(self):
++    def test_configure_colormap(self):
+         widget = self.create()
+         self.assertEqual(widget['colormap'], '')
+         self.checkInvalidParam(widget, 'colormap', 'new',
+@@ -39,7 +39,7 @@ class AbstractToplevelTest(AbstractWidgetTest, PixelSizeTests):
+         widget2 = self.create(colormap='new')
+         self.assertEqual(widget2['colormap'], 'new')
+-    def test_container(self):
++    def test_configure_container(self):
+         widget = self.create()
+         self.assertEqual(widget['container'], 0 if self.wantobjects else '0')
+         self.checkInvalidParam(widget, 'container', 1,
+@@ -47,7 +47,7 @@ class AbstractToplevelTest(AbstractWidgetTest, PixelSizeTests):
+         widget2 = self.create(container=True)
+         self.assertEqual(widget2['container'], 1 if self.wantobjects else '1')
+-    def test_visual(self):
++    def test_configure_visual(self):
+         widget = self.create()
+         self.assertEqual(widget['visual'], '')
+         self.checkInvalidParam(widget, 'visual', 'default',
+@@ -69,13 +69,13 @@ class ToplevelTest(AbstractToplevelTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return tkinter.Toplevel(self.root, **kwargs)
+-    def test_menu(self):
++    def test_configure_menu(self):
+         widget = self.create()
+         menu = tkinter.Menu(self.root)
+         self.checkParam(widget, 'menu', menu, eq=widget_eq)
+         self.checkParam(widget, 'menu', '')
+-    def test_screen(self):
++    def test_configure_screen(self):
+         widget = self.create()
+         self.assertEqual(widget['screen'], '')
+         try:
+@@ -87,7 +87,7 @@ class ToplevelTest(AbstractToplevelTest, unittest.TestCase):
+         widget2 = self.create(screen=display)
+         self.assertEqual(widget2['screen'], display)
+-    def test_use(self):
++    def test_configure_use(self):
+         widget = self.create()
+         self.assertEqual(widget['use'], '')
+         parent = self.create(container=True)
+@@ -124,14 +124,14 @@ class LabelFrameTest(AbstractToplevelTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return tkinter.LabelFrame(self.root, **kwargs)
+-    def test_labelanchor(self):
++    def test_configure_labelanchor(self):
+         widget = self.create()
+         self.checkEnumParam(widget, 'labelanchor',
+                             'e', 'en', 'es', 'n', 'ne', 'nw',
+                             's', 'se', 'sw', 'w', 'wn', 'ws')
+         self.checkInvalidParam(widget, 'labelanchor', 'center')
+-    def test_labelwidget(self):
++    def test_configure_labelwidget(self):
+         widget = self.create()
+         label = tkinter.Label(self.root, text='Mupp', name='foo')
+         self.checkParam(widget, 'labelwidget', label, expected='.foo')
+@@ -141,7 +141,7 @@ class LabelFrameTest(AbstractToplevelTest, unittest.TestCase):
+ class AbstractLabelTest(AbstractWidgetTest, IntegerSizeTests):
+     _conv_pixels = noconv
+-    def test_highlightthickness(self):
++    def test_configure_highlightthickness(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'highlightthickness',
+                               0, 1.3, 2.6, 6, -2, '10p')
+@@ -179,7 +179,7 @@ class ButtonTest(AbstractLabelTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return tkinter.Button(self.root, **kwargs)
+-    def test_default(self):
++    def test_configure_default(self):
+         widget = self.create()
+         self.checkEnumParam(widget, 'default', 'active', 'disabled', 'normal')
+@@ -204,11 +204,11 @@ class CheckbuttonTest(AbstractLabelTest, unittest.TestCase):
+         return tkinter.Checkbutton(self.root, **kwargs)
+-    def test_offvalue(self):
++    def test_configure_offvalue(self):
+         widget = self.create()
+         self.checkParams(widget, 'offvalue', 1, 2.3, '', 'any string')
+-    def test_onvalue(self):
++    def test_configure_onvalue(self):
+         widget = self.create()
+         self.checkParams(widget, 'onvalue', 1, 2.3, '', 'any string')
+@@ -231,7 +231,7 @@ class RadiobuttonTest(AbstractLabelTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return tkinter.Radiobutton(self.root, **kwargs)
+-    def test_value(self):
++    def test_configure_value(self):
+         widget = self.create()
+         self.checkParams(widget, 'value', 1, 2.3, '', 'any string')
+@@ -254,20 +254,19 @@ class MenubuttonTest(AbstractLabelTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return tkinter.Menubutton(self.root, **kwargs)
+-    def test_direction(self):
++    def test_configure_direction(self):
+         widget = self.create()
+         self.checkEnumParam(widget, 'direction',
+                 'above', 'below', 'flush', 'left', 'right')
+-    def test_height(self):
++    def test_configure_height(self):
+         widget = self.create()
+         self.checkIntegerParam(widget, 'height', 100, -100, 0, conv=str)
+-    test_highlightthickness = StandardOptionsTests.test_highlightthickness
++    test_configure_highlightthickness = \
++        StandardOptionsTests.test_configure_highlightthickness
+-    @unittest.skipIf(sys.platform == 'darwin',
+-                     'crashes with Cocoa Tk (issue19733)')
+-    def test_image(self):
++    def test_configure_image(self):
+         widget = self.create()
+         image = tkinter.PhotoImage(master=self.root, name='image1')
+         self.checkParam(widget, 'image', image, conv=str)
+@@ -281,23 +280,23 @@ class MenubuttonTest(AbstractLabelTest, unittest.TestCase):
+         if errmsg is not None:
+             self.assertEqual(str(cm.exception), errmsg)
+-    def test_menu(self):
++    def test_configure_menu(self):
+         widget = self.create()
+         menu = tkinter.Menu(widget, name='menu')
+         self.checkParam(widget, 'menu', menu, eq=widget_eq)
+         menu.destroy()
+-    def test_padx(self):
++    def test_configure_padx(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'padx', 3, 4.4, 5.6, '12m')
+         self.checkParam(widget, 'padx', -2, expected=0)
+-    def test_pady(self):
++    def test_configure_pady(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'pady', 3, 4.4, 5.6, '12m')
+         self.checkParam(widget, 'pady', -2, expected=0)
+-    def test_width(self):
++    def test_configure_width(self):
+         widget = self.create()
+         self.checkIntegerParam(widget, 'width', 402, -402, 0, conv=str)
+@@ -330,18 +329,18 @@ class EntryTest(AbstractWidgetTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return tkinter.Entry(self.root, **kwargs)
+-    def test_disabledbackground(self):
++    def test_configure_disabledbackground(self):
+         widget = self.create()
+         self.checkColorParam(widget, 'disabledbackground')
+-    def test_insertborderwidth(self):
++    def test_configure_insertborderwidth(self):
+         widget = self.create(insertwidth=100)
+         self.checkPixelsParam(widget, 'insertborderwidth',
+                               0, 1.3, 2.6, 6, -2, '10p')
+         # insertborderwidth is bounded above by a half of insertwidth.
+         self.checkParam(widget, 'insertborderwidth', 60, expected=100//2)
+-    def test_insertwidth(self):
++    def test_configure_insertwidth(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'insertwidth', 1.3, 3.6, '10p')
+         self.checkParam(widget, 'insertwidth', 0.1, expected=2)
+@@ -351,32 +350,32 @@ class EntryTest(AbstractWidgetTest, unittest.TestCase):
+         else:
+             self.checkParam(widget, 'insertwidth', 0.9, expected=1)
+-    def test_invalidcommand(self):
++    def test_configure_invalidcommand(self):
+         widget = self.create()
+         self.checkCommandParam(widget, 'invalidcommand')
+         self.checkCommandParam(widget, 'invcmd')
+-    def test_readonlybackground(self):
++    def test_configure_readonlybackground(self):
+         widget = self.create()
+         self.checkColorParam(widget, 'readonlybackground')
+-    def test_show(self):
++    def test_configure_show(self):
+         widget = self.create()
+         self.checkParam(widget, 'show', '*')
+         self.checkParam(widget, 'show', '')
+         self.checkParam(widget, 'show', ' ')
+-    def test_state(self):
++    def test_configure_state(self):
+         widget = self.create()
+         self.checkEnumParam(widget, 'state',
+                             'disabled', 'normal', 'readonly')
+-    def test_validate(self):
++    def test_configure_validate(self):
+         widget = self.create()
+         self.checkEnumParam(widget, 'validate',
+                 'all', 'key', 'focus', 'focusin', 'focusout', 'none')
+-    def test_validatecommand(self):
++    def test_configure_validatecommand(self):
+         widget = self.create()
+         self.checkCommandParam(widget, 'validatecommand')
+         self.checkCommandParam(widget, 'vcmd')
+@@ -429,25 +428,25 @@ class SpinboxTest(EntryTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return tkinter.Spinbox(self.root, **kwargs)
+-    test_show = None
++    test_configure_show = None
+-    def test_buttonbackground(self):
++    def test_configure_buttonbackground(self):
+         widget = self.create()
+         self.checkColorParam(widget, 'buttonbackground')
+-    def test_buttoncursor(self):
++    def test_configure_buttoncursor(self):
+         widget = self.create()
+         self.checkCursorParam(widget, 'buttoncursor')
+-    def test_buttondownrelief(self):
++    def test_configure_buttondownrelief(self):
+         widget = self.create()
+         self.checkReliefParam(widget, 'buttondownrelief')
+-    def test_buttonuprelief(self):
++    def test_configure_buttonuprelief(self):
+         widget = self.create()
+         self.checkReliefParam(widget, 'buttonuprelief')
+-    def test_format(self):
++    def test_configure_format(self):
+         widget = self.create()
+         self.checkParam(widget, 'format', '%2f')
+         self.checkParam(widget, 'format', '%2.2f')
+@@ -462,25 +461,25 @@ class SpinboxTest(EntryTest, unittest.TestCase):
+         self.checkParam(widget, 'format', '%09.200f')
+         self.checkInvalidParam(widget, 'format', '%d')
+-    def test_from(self):
++    def test_configure_from(self):
+         widget = self.create()
+         self.checkParam(widget, 'to', 100.0)
+         self.checkFloatParam(widget, 'from', -10, 10.2, 11.7)
+         self.checkInvalidParam(widget, 'from', 200,
+                 errmsg='-to value must be greater than -from value')
+-    def test_increment(self):
++    def test_configure_increment(self):
+         widget = self.create()
+         self.checkFloatParam(widget, 'increment', -1, 1, 10.2, 12.8, 0)
+-    def test_to(self):
++    def test_configure_to(self):
+         widget = self.create()
+         self.checkParam(widget, 'from', -100.0)
+         self.checkFloatParam(widget, 'to', -10, 10.2, 11.7)
+         self.checkInvalidParam(widget, 'to', -200,
+                 errmsg='-to value must be greater than -from value')
+-    def test_values(self):
++    def test_configure_values(self):
+         # XXX
+         widget = self.create()
+         self.assertEqual(widget['values'], '')
+@@ -491,7 +490,7 @@ class SpinboxTest(EntryTest, unittest.TestCase):
+                         expected='42 3.14 {} {any string}')
+         self.checkParam(widget, 'values', '')
+-    def test_wrap(self):
++    def test_configure_wrap(self):
+         widget = self.create()
+         self.checkBooleanParam(widget, 'wrap')
+@@ -557,17 +556,17 @@ class TextTest(AbstractWidgetTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return tkinter.Text(self.root, **kwargs)
+-    def test_autoseparators(self):
++    def test_configure_autoseparators(self):
+         widget = self.create()
+         self.checkBooleanParam(widget, 'autoseparators')
+     @requires_tcl(8, 5)
+-    def test_blockcursor(self):
++    def test_configure_blockcursor(self):
+         widget = self.create()
+         self.checkBooleanParam(widget, 'blockcursor')
+     @requires_tcl(8, 5)
+-    def test_endline(self):
++    def test_configure_endline(self):
+         widget = self.create()
+         text = '\n'.join('Line %d' for i in range(100))
+         widget.insert('end', text)
+@@ -580,50 +579,50 @@ class TextTest(AbstractWidgetTest, unittest.TestCase):
+         self.checkInvalidParam(widget, 'endline', 10,
+                 errmsg='-startline must be less than or equal to -endline')
+-    def test_height(self):
++    def test_configure_height(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'height', 100, 101.2, 102.6, '3c')
+         self.checkParam(widget, 'height', -100, expected=1)
+         self.checkParam(widget, 'height', 0, expected=1)
+-    def test_maxundo(self):
++    def test_configure_maxundo(self):
+         widget = self.create()
+         self.checkIntegerParam(widget, 'maxundo', 0, 5, -1)
+     @requires_tcl(8, 5)
+-    def test_inactiveselectbackground(self):
++    def test_configure_inactiveselectbackground(self):
+         widget = self.create()
+         self.checkColorParam(widget, 'inactiveselectbackground')
+     @requires_tcl(8, 6)
+-    def test_insertunfocussed(self):
++    def test_configure_insertunfocussed(self):
+         widget = self.create()
+         self.checkEnumParam(widget, 'insertunfocussed',
+                             'hollow', 'none', 'solid')
+-    def test_selectborderwidth(self):
++    def test_configure_selectborderwidth(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'selectborderwidth',
+                               1.3, 2.6, -2, '10p', conv=noconv,
+                               keep_orig=tcl_version >= (8, 5))
+-    def test_spacing1(self):
++    def test_configure_spacing1(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'spacing1', 20, 21.4, 22.6, '0.5c')
+         self.checkParam(widget, 'spacing1', -5, expected=0)
+-    def test_spacing2(self):
++    def test_configure_spacing2(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'spacing2', 5, 6.4, 7.6, '0.1c')
+         self.checkParam(widget, 'spacing2', -1, expected=0)
+-    def test_spacing3(self):
++    def test_configure_spacing3(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'spacing3', 20, 21.4, 22.6, '0.5c')
+         self.checkParam(widget, 'spacing3', -10, expected=0)
+     @requires_tcl(8, 5)
+-    def test_startline(self):
++    def test_configure_startline(self):
+         widget = self.create()
+         text = '\n'.join('Line %d' for i in range(100))
+         widget.insert('end', text)
+@@ -636,14 +635,14 @@ class TextTest(AbstractWidgetTest, unittest.TestCase):
+         self.checkInvalidParam(widget, 'startline', 70,
+                 errmsg='-startline must be less than or equal to -endline')
+-    def test_state(self):
++    def test_configure_state(self):
+         widget = self.create()
+         if tcl_version < (8, 5):
+             self.checkParams(widget, 'state', 'disabled', 'normal')
+         else:
+             self.checkEnumParam(widget, 'state', 'disabled', 'normal')
+-    def test_tabs(self):
++    def test_configure_tabs(self):
+         widget = self.create()
+         if get_tk_patchlevel() < (8, 5, 11):
+             self.checkParam(widget, 'tabs', (10.2, 20.7, '1i', '2i'),
+@@ -659,21 +658,21 @@ class TextTest(AbstractWidgetTest, unittest.TestCase):
+                                keep_orig=tcl_version >= (8, 5))
+     @requires_tcl(8, 5)
+-    def test_tabstyle(self):
++    def test_configure_tabstyle(self):
+         widget = self.create()
+         self.checkEnumParam(widget, 'tabstyle', 'tabular', 'wordprocessor')
+-    def test_undo(self):
++    def test_configure_undo(self):
+         widget = self.create()
+         self.checkBooleanParam(widget, 'undo')
+-    def test_width(self):
++    def test_configure_width(self):
+         widget = self.create()
+         self.checkIntegerParam(widget, 'width', 402)
+         self.checkParam(widget, 'width', -402, expected=1)
+         self.checkParam(widget, 'width', 0, expected=1)
+-    def test_wrap(self):
++    def test_configure_wrap(self):
+         widget = self.create()
+         if tcl_version < (8, 5):
+             self.checkParams(widget, 'wrap', 'char', 'none', 'word')
+@@ -711,16 +710,16 @@ class CanvasTest(AbstractWidgetTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return tkinter.Canvas(self.root, **kwargs)
+-    def test_closeenough(self):
++    def test_configure_closeenough(self):
+         widget = self.create()
+         self.checkFloatParam(widget, 'closeenough', 24, 2.4, 3.6, -3,
+                              conv=float)
+-    def test_confine(self):
++    def test_configure_confine(self):
+         widget = self.create()
+         self.checkBooleanParam(widget, 'confine')
+-    def test_offset(self):
++    def test_configure_offset(self):
+         widget = self.create()
+         self.assertEqual(widget['offset'], '0,0')
+         self.checkParams(widget, 'offset',
+@@ -729,7 +728,7 @@ class CanvasTest(AbstractWidgetTest, unittest.TestCase):
+         self.checkParam(widget, 'offset', '#5,6')
+         self.checkInvalidParam(widget, 'offset', 'spam')
+-    def test_scrollregion(self):
++    def test_configure_scrollregion(self):
+         widget = self.create()
+         self.checkParam(widget, 'scrollregion', '0 0 200 150')
+         self.checkParam(widget, 'scrollregion', (0, 0, 200, 150),
+@@ -741,17 +740,17 @@ class CanvasTest(AbstractWidgetTest, unittest.TestCase):
+         self.checkInvalidParam(widget, 'scrollregion', (0, 0, 200))
+         self.checkInvalidParam(widget, 'scrollregion', (0, 0, 200, 150, 0))
+-    def test_state(self):
++    def test_configure_state(self):
+         widget = self.create()
+         self.checkEnumParam(widget, 'state', 'disabled', 'normal',
+                 errmsg='bad state value "{}": must be normal or disabled')
+-    def test_xscrollincrement(self):
++    def test_configure_xscrollincrement(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'xscrollincrement',
+                               40, 0, 41.2, 43.6, -40, '0.5i')
+-    def test_yscrollincrement(self):
++    def test_configure_yscrollincrement(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'yscrollincrement',
+                               10, 0, 11.2, 13.6, -10, '0.1i')
+@@ -796,26 +795,26 @@ class ListboxTest(AbstractWidgetTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return tkinter.Listbox(self.root, **kwargs)
+-    def test_activestyle(self):
++    def test_configure_activestyle(self):
+         widget = self.create()
+         self.checkEnumParam(widget, 'activestyle',
+                             'dotbox', 'none', 'underline')
+-    test_justify = requires_tcl(8, 6, 5)(StandardOptionsTests.test_justify)
++    test_justify = requires_tcl(8, 6, 5)(StandardOptionsTests.test_configure_justify)
+-    def test_listvariable(self):
++    def test_configure_listvariable(self):
+         widget = self.create()
+         var = tkinter.DoubleVar(self.root)
+         self.checkVariableParam(widget, 'listvariable', var)
+-    def test_selectmode(self):
++    def test_configure_selectmode(self):
+         widget = self.create()
+         self.checkParam(widget, 'selectmode', 'single')
+         self.checkParam(widget, 'selectmode', 'browse')
+         self.checkParam(widget, 'selectmode', 'multiple')
+         self.checkParam(widget, 'selectmode', 'extended')
+-    def test_state(self):
++    def test_configure_state(self):
+         widget = self.create()
+         self.checkEnumParam(widget, 'state', 'disabled', 'normal')
+@@ -930,53 +929,53 @@ class ScaleTest(AbstractWidgetTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return tkinter.Scale(self.root, **kwargs)
+-    def test_bigincrement(self):
++    def test_configure_bigincrement(self):
+         widget = self.create()
+         self.checkFloatParam(widget, 'bigincrement', 12.4, 23.6, -5)
+-    def test_digits(self):
++    def test_configure_digits(self):
+         widget = self.create()
+         self.checkIntegerParam(widget, 'digits', 5, 0)
+-    def test_from(self):
++    def test_configure_from(self):
+         widget = self.create()
+         conv = False if get_tk_patchlevel() >= (8, 6, 10) else float_round
+         self.checkFloatParam(widget, 'from', 100, 14.9, 15.1, conv=conv)
+-    def test_label(self):
++    def test_configure_label(self):
+         widget = self.create()
+         self.checkParam(widget, 'label', 'any string')
+         self.checkParam(widget, 'label', '')
+-    def test_length(self):
++    def test_configure_length(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'length', 130, 131.2, 135.6, '5i')
+-    def test_resolution(self):
++    def test_configure_resolution(self):
+         widget = self.create()
+         self.checkFloatParam(widget, 'resolution', 4.2, 0, 6.7, -2)
+-    def test_showvalue(self):
++    def test_configure_showvalue(self):
+         widget = self.create()
+         self.checkBooleanParam(widget, 'showvalue')
+-    def test_sliderlength(self):
++    def test_configure_sliderlength(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'sliderlength',
+                               10, 11.2, 15.6, -3, '3m')
+-    def test_sliderrelief(self):
++    def test_configure_sliderrelief(self):
+         widget = self.create()
+         self.checkReliefParam(widget, 'sliderrelief')
+-    def test_tickinterval(self):
++    def test_configure_tickinterval(self):
+         widget = self.create()
+         self.checkFloatParam(widget, 'tickinterval', 1, 4.3, 7.6, 0,
+                              conv=float_round)
+         self.checkParam(widget, 'tickinterval', -2, expected=2,
+                         conv=float_round)
+-    def test_to(self):
++    def test_configure_to(self):
+         widget = self.create()
+         self.checkFloatParam(widget, 'to', 300, 14.9, 15.1, -10,
+                              conv=float_round)
+@@ -1000,15 +999,15 @@ class ScrollbarTest(AbstractWidgetTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return tkinter.Scrollbar(self.root, **kwargs)
+-    def test_activerelief(self):
++    def test_configure_activerelief(self):
+         widget = self.create()
+         self.checkReliefParam(widget, 'activerelief')
+-    def test_elementborderwidth(self):
++    def test_configure_elementborderwidth(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'elementborderwidth', 4.3, 5.6, -2, '1m')
+-    def test_orient(self):
++    def test_configure_orient(self):
+         widget = self.create()
+         self.checkEnumParam(widget, 'orient', 'vertical', 'horizontal',
+                 errmsg='bad orientation "{}": must be vertical or horizontal')
+@@ -1049,63 +1048,63 @@ class PanedWindowTest(AbstractWidgetTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return tkinter.PanedWindow(self.root, **kwargs)
+-    def test_handlepad(self):
++    def test_configure_handlepad(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'handlepad', 5, 6.4, 7.6, -3, '1m')
+-    def test_handlesize(self):
++    def test_configure_handlesize(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'handlesize', 8, 9.4, 10.6, -3, '2m',
+                               conv=noconv)
+-    def test_height(self):
++    def test_configure_height(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'height', 100, 101.2, 102.6, -100, 0, '1i',
+                               conv=noconv)
+-    def test_opaqueresize(self):
++    def test_configure_opaqueresize(self):
+         widget = self.create()
+         self.checkBooleanParam(widget, 'opaqueresize')
+     @requires_tcl(8, 6, 5)
+-    def test_proxybackground(self):
++    def test_configure_proxybackground(self):
+         widget = self.create()
+         self.checkColorParam(widget, 'proxybackground')
+     @requires_tcl(8, 6, 5)
+-    def test_proxyborderwidth(self):
++    def test_configure_proxyborderwidth(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'proxyborderwidth',
+                               0, 1.3, 2.9, 6, -2, '10p',
+                               conv=noconv)
+     @requires_tcl(8, 6, 5)
+-    def test_proxyrelief(self):
++    def test_configure_proxyrelief(self):
+         widget = self.create()
+         self.checkReliefParam(widget, 'proxyrelief')
+-    def test_sashcursor(self):
++    def test_configure_sashcursor(self):
+         widget = self.create()
+         self.checkCursorParam(widget, 'sashcursor')
+-    def test_sashpad(self):
++    def test_configure_sashpad(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'sashpad', 8, 1.3, 2.6, -2, '2m')
+-    def test_sashrelief(self):
++    def test_configure_sashrelief(self):
+         widget = self.create()
+         self.checkReliefParam(widget, 'sashrelief')
+-    def test_sashwidth(self):
++    def test_configure_sashwidth(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'sashwidth', 10, 11.1, 15.6, -3, '1m',
+                               conv=noconv)
+-    def test_showhandle(self):
++    def test_configure_showhandle(self):
+         widget = self.create()
+         self.checkBooleanParam(widget, 'showhandle')
+-    def test_width(self):
++    def test_configure_width(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'width', 402, 403.4, 404.6, -402, 0, '5i',
+                               conv=noconv)
+@@ -1224,23 +1223,23 @@ class MenuTest(AbstractWidgetTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return tkinter.Menu(self.root, **kwargs)
+-    def test_postcommand(self):
++    def test_configure_postcommand(self):
+         widget = self.create()
+         self.checkCommandParam(widget, 'postcommand')
+-    def test_tearoff(self):
++    def test_configure_tearoff(self):
+         widget = self.create()
+         self.checkBooleanParam(widget, 'tearoff')
+-    def test_tearoffcommand(self):
++    def test_configure_tearoffcommand(self):
+         widget = self.create()
+         self.checkCommandParam(widget, 'tearoffcommand')
+-    def test_title(self):
++    def test_configure_title(self):
+         widget = self.create()
+         self.checkParam(widget, 'title', 'any string')
+-    def test_type(self):
++    def test_configure_type(self):
+         widget = self.create()
+         self.checkEnumParam(widget, 'type',
+                 'normal', 'tearoff', 'menubar')
+@@ -1293,17 +1292,26 @@ class MessageTest(AbstractWidgetTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return tkinter.Message(self.root, **kwargs)
+-    def test_aspect(self):
++    def test_configure_aspect(self):
+         widget = self.create()
+         self.checkIntegerParam(widget, 'aspect', 250, 0, -300)
++class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase):
++
++    def test_frame(self):
++        self._test_widget(tkinter.Frame)
++
++    def test_label(self):
++        self._test_widget(tkinter.Label)
++
++
+ tests_gui = (
+         ButtonTest, CanvasTest, CheckbuttonTest, EntryTest,
+         FrameTest, LabelFrameTest,LabelTest, ListboxTest,
+         MenubuttonTest, MenuTest, MessageTest, OptionMenuTest,
+         PanedWindowTest, RadiobuttonTest, ScaleTest, ScrollbarTest,
+-        SpinboxTest, TextTest, ToplevelTest,
++        SpinboxTest, TextTest, ToplevelTest, DefaultRootTest,
+ )
+ if __name__ == '__main__':
+diff --git a/Lib/tkinter/test/test_ttk/test_extensions.py b/Lib/tkinter/test/test_ttk/test_extensions.py
+index 6937ba1ca9..1a70e0befe 100644
+--- a/Lib/tkinter/test/test_ttk/test_extensions.py
++++ b/Lib/tkinter/test/test_ttk/test_extensions.py
+@@ -2,8 +2,8 @@ import sys
+ import unittest
+ import tkinter
+ from tkinter import ttk
+-from test.support import requires, run_unittest, swap_attr
+-from tkinter.test.support import AbstractTkTest, destroy_default_root
++from test.support import requires, run_unittest
++from tkinter.test.support import AbstractTkTest, AbstractDefaultRootTest
+ requires('gui')
+@@ -46,20 +46,6 @@ class LabeledScaleTest(AbstractTkTest, unittest.TestCase):
+         if hasattr(sys, 'last_type'):
+             self.assertNotEqual(sys.last_type, tkinter.TclError)
+-
+-    def test_initialization_no_master(self):
+-        # no master passing
+-        with swap_attr(tkinter, '_default_root', None), \
+-             swap_attr(tkinter, '_support_default_root', True):
+-            try:
+-                x = ttk.LabeledScale()
+-                self.assertIsNotNone(tkinter._default_root)
+-                self.assertEqual(x.master, tkinter._default_root)
+-                self.assertEqual(x.tk, tkinter._default_root.tk)
+-                x.destroy()
+-            finally:
+-                destroy_default_root()
+-
+     def test_initialization(self):
+         # master passing
+         master = tkinter.Frame(self.root)
+@@ -311,7 +297,13 @@ class OptionMenuTest(AbstractTkTest, unittest.TestCase):
+         optmenu2.destroy()
+-tests_gui = (LabeledScaleTest, OptionMenuTest)
++class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase):
++
++    def test_labeledscale(self):
++        self._test_widget(ttk.LabeledScale)
++
++
++tests_gui = (LabeledScaleTest, OptionMenuTest, DefaultRootTest)
+ if __name__ == "__main__":
+     run_unittest(*tests_gui)
+diff --git a/Lib/tkinter/test/test_ttk/test_widgets.py b/Lib/tkinter/test/test_ttk/test_widgets.py
+index 157ef0e8f8..1fac83a004 100644
+--- a/Lib/tkinter/test/test_ttk/test_widgets.py
++++ b/Lib/tkinter/test/test_ttk/test_widgets.py
+@@ -6,7 +6,7 @@ import sys
+ from tkinter.test.test_ttk.test_functions import MockTclObj
+ from tkinter.test.support import (AbstractTkTest, tcl_version, get_tk_patchlevel,
+-                                  simulate_mouse_click)
++                                  simulate_mouse_click, AbstractDefaultRootTest)
+ from tkinter.test.widget_tests import (add_standard_options, noconv,
+     AbstractWidgetTest, StandardOptionsTests, IntegerSizeTests, PixelSizeTests,
+     setUpModule)
+@@ -16,7 +16,7 @@ requires('gui')
+ class StandardTtkOptionsTests(StandardOptionsTests):
+-    def test_class(self):
++    def test_configure_class(self):
+         widget = self.create()
+         self.assertEqual(widget['class'], '')
+         errmsg='attempt to change read-only option'
+@@ -26,7 +26,7 @@ class StandardTtkOptionsTests(StandardOptionsTests):
+         widget2 = self.create(class_='Foo')
+         self.assertEqual(widget2['class'], 'Foo')
+-    def test_padding(self):
++    def test_configure_padding(self):
+         widget = self.create()
+         self.checkParam(widget, 'padding', 0, expected=('0',))
+         self.checkParam(widget, 'padding', 5, expected=('5',))
+@@ -38,7 +38,7 @@ class StandardTtkOptionsTests(StandardOptionsTests):
+         self.checkParam(widget, 'padding', ('5p', '6p', '7p', '8p'))
+         self.checkParam(widget, 'padding', (), expected='')
+-    def test_style(self):
++    def test_configure_style(self):
+         widget = self.create()
+         self.assertEqual(widget['style'], '')
+         errmsg = 'Layout Foo not found'
+@@ -139,14 +139,14 @@ class LabelFrameTest(AbstractToplevelTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return ttk.LabelFrame(self.root, **kwargs)
+-    def test_labelanchor(self):
++    def test_configure_labelanchor(self):
+         widget = self.create()
+         self.checkEnumParam(widget, 'labelanchor',
+                 'e', 'en', 'es', 'n', 'ne', 'nw', 's', 'se', 'sw', 'w', 'wn', 'ws',
+                 errmsg='Bad label anchor specification {}')
+         self.checkInvalidParam(widget, 'labelanchor', 'center')
+-    def test_labelwidget(self):
++    def test_configure_labelwidget(self):
+         widget = self.create()
+         label = ttk.Label(self.root, text='Mupp', name='foo')
+         self.checkParam(widget, 'labelwidget', label, expected='.foo')
+@@ -168,17 +168,17 @@ class AbstractLabelTest(AbstractWidgetTest):
+         self.checkInvalidParam(widget, name, 'spam',
+                 errmsg='image "spam" doesn\'t exist')
+-    def test_compound(self):
++    def test_configure_compound(self):
+         widget = self.create()
+         self.checkEnumParam(widget, 'compound',
+                 'none', 'text', 'image', 'center',
+                 'top', 'bottom', 'left', 'right')
+-    def test_state(self):
++    def test_configure_state(self):
+         widget = self.create()
+         self.checkParams(widget, 'state', 'active', 'disabled', 'normal')
+-    def test_width(self):
++    def test_configure_width(self):
+         widget = self.create()
+         self.checkParams(widget, 'width', 402, -402, 0)
+@@ -197,7 +197,7 @@ class LabelTest(AbstractLabelTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return ttk.Label(self.root, **kwargs)
+-    def test_font(self):
++    def test_configure_font(self):
+         widget = self.create()
+         self.checkParam(widget, 'font',
+                         '-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*')
+@@ -215,7 +215,7 @@ class ButtonTest(AbstractLabelTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return ttk.Button(self.root, **kwargs)
+-    def test_default(self):
++    def test_configure_default(self):
+         widget = self.create()
+         self.checkEnumParam(widget, 'default', 'normal', 'active', 'disabled')
+@@ -240,11 +240,11 @@ class CheckbuttonTest(AbstractLabelTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return ttk.Checkbutton(self.root, **kwargs)
+-    def test_offvalue(self):
++    def test_configure_offvalue(self):
+         widget = self.create()
+         self.checkParams(widget, 'offvalue', 1, 2.3, '', 'any string')
+-    def test_onvalue(self):
++    def test_configure_onvalue(self):
+         widget = self.create()
+         self.checkParams(widget, 'onvalue', 1, 2.3, '', 'any string')
+@@ -292,27 +292,27 @@ class EntryTest(AbstractWidgetTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return ttk.Entry(self.root, **kwargs)
+-    def test_invalidcommand(self):
++    def test_configure_invalidcommand(self):
+         widget = self.create()
+         self.checkCommandParam(widget, 'invalidcommand')
+-    def test_show(self):
++    def test_configure_show(self):
+         widget = self.create()
+         self.checkParam(widget, 'show', '*')
+         self.checkParam(widget, 'show', '')
+         self.checkParam(widget, 'show', ' ')
+-    def test_state(self):
++    def test_configure_state(self):
+         widget = self.create()
+         self.checkParams(widget, 'state',
+                          'disabled', 'normal', 'readonly')
+-    def test_validate(self):
++    def test_configure_validate(self):
+         widget = self.create()
+         self.checkEnumParam(widget, 'validate',
+                 'all', 'key', 'focus', 'focusin', 'focusout', 'none')
+-    def test_validatecommand(self):
++    def test_configure_validatecommand(self):
+         widget = self.create()
+         self.checkCommandParam(widget, 'validatecommand')
+@@ -429,7 +429,7 @@ class ComboboxTest(EntryTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return ttk.Combobox(self.root, **kwargs)
+-    def test_height(self):
++    def test_configure_height(self):
+         widget = self.create()
+         self.checkParams(widget, 'height', 100, 101.2, 102.6, -100, 0, '1i')
+@@ -459,7 +459,7 @@ class ComboboxTest(EntryTest, unittest.TestCase):
+         self.assertTrue(success)
+-    def test_postcommand(self):
++    def test_configure_postcommand(self):
+         success = []
+         self.combo['postcommand'] = lambda: success.append(True)
+@@ -475,7 +475,7 @@ class ComboboxTest(EntryTest, unittest.TestCase):
+         self.assertEqual(len(success), 1)
+-    def test_values(self):
++    def test_configure_values(self):
+         def check_get_current(getval, currval):
+             self.assertEqual(self.combo.get(), getval)
+             self.assertEqual(self.combo.current(), currval)
+@@ -551,7 +551,7 @@ class PanedWindowTest(AbstractWidgetTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return ttk.PanedWindow(self.root, **kwargs)
+-    def test_orient(self):
++    def test_configure_orient(self):
+         widget = self.create()
+         self.assertEqual(str(widget['orient']), 'vertical')
+         errmsg='attempt to change read-only option'
+@@ -684,11 +684,11 @@ class RadiobuttonTest(AbstractLabelTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return ttk.Radiobutton(self.root, **kwargs)
+-    def test_value(self):
++    def test_configure_value(self):
+         widget = self.create()
+         self.checkParams(widget, 'value', 1, 2.3, '', 'any string')
+-    def test_invoke(self):
++    def test_configure_invoke(self):
+         success = []
+         def cb_test():
+             success.append(1)
+@@ -739,7 +739,7 @@ class MenubuttonTest(AbstractLabelTest, unittest.TestCase):
+         self.checkEnumParam(widget, 'direction',
+                 'above', 'below', 'left', 'right', 'flush')
+-    def test_menu(self):
++    def test_configure_menu(self):
+         widget = self.create()
+         menu = tkinter.Menu(widget, name='menu')
+         self.checkParam(widget, 'menu', menu, conv=str)
+@@ -764,19 +764,19 @@ class ScaleTest(AbstractWidgetTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return ttk.Scale(self.root, **kwargs)
+-    def test_from(self):
++    def test_configure_from(self):
+         widget = self.create()
+         self.checkFloatParam(widget, 'from', 100, 14.9, 15.1, conv=False)
+-    def test_length(self):
++    def test_configure_length(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'length', 130, 131.2, 135.6, '5i')
+-    def test_to(self):
++    def test_configure_to(self):
+         widget = self.create()
+         self.checkFloatParam(widget, 'to', 300, 14.9, 15.1, -10, conv=False)
+-    def test_value(self):
++    def test_configure_value(self):
+         widget = self.create()
+         self.checkFloatParam(widget, 'value', 300, 14.9, 15.1, -10, conv=False)
+@@ -866,23 +866,23 @@ class ProgressbarTest(AbstractWidgetTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return ttk.Progressbar(self.root, **kwargs)
+-    def test_length(self):
++    def test_configure_length(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'length', 100.1, 56.7, '2i')
+-    def test_maximum(self):
++    def test_configure_maximum(self):
+         widget = self.create()
+         self.checkFloatParam(widget, 'maximum', 150.2, 77.7, 0, -10, conv=False)
+-    def test_mode(self):
++    def test_configure_mode(self):
+         widget = self.create()
+         self.checkEnumParam(widget, 'mode', 'determinate', 'indeterminate')
+-    def test_phase(self):
++    def test_configure_phase(self):
+         # XXX
+         pass
+-    def test_value(self):
++    def test_configure_value(self):
+         widget = self.create()
+         self.checkFloatParam(widget, 'value', 150.2, 77.7, 0, -10,
+                              conv=False)
+@@ -1071,7 +1071,7 @@ class NotebookTest(AbstractWidgetTest, unittest.TestCase):
+         self.assertEqual(self.nb.tab(self.child1, 'text'), 'abc')
+-    def test_tabs(self):
++    def test_configure_tabs(self):
+         self.assertEqual(len(self.nb.tabs()), 2)
+         self.nb.forget(self.child1)
+@@ -1147,7 +1147,7 @@ class SpinboxTest(EntryTest, unittest.TestCase):
+         self.spin.event_generate('<ButtonRelease-1>', x=x, y=y)
+         self.spin.update_idletasks()
+-    def test_command(self):
++    def test_configure_command(self):
+         success = []
+         self.spin['command'] = lambda: success.append(True)
+@@ -1167,7 +1167,7 @@ class SpinboxTest(EntryTest, unittest.TestCase):
+         self.spin.update()
+         self.assertEqual(len(success), 2)
+-    def test_to(self):
++    def test_configure_to(self):
+         self.spin['from'] = 0
+         self.spin['to'] = 5
+         self.spin.set(4)
+@@ -1179,7 +1179,7 @@ class SpinboxTest(EntryTest, unittest.TestCase):
+         self._click_increment_arrow()  # 5
+         self.assertEqual(self.spin.get(), '5')
+-    def test_from(self):
++    def test_configure_from(self):
+         self.spin['from'] = 1
+         self.spin['to'] = 10
+         self.spin.set(2)
+@@ -1189,7 +1189,7 @@ class SpinboxTest(EntryTest, unittest.TestCase):
+         self._click_decrement_arrow()  # 1
+         self.assertEqual(self.spin.get(), '1')
+-    def test_increment(self):
++    def test_configure_increment(self):
+         self.spin['from'] = 0
+         self.spin['to'] = 10
+         self.spin['increment'] = 4
+@@ -1203,7 +1203,7 @@ class SpinboxTest(EntryTest, unittest.TestCase):
+         self._click_decrement_arrow()  # 3
+         self.assertEqual(self.spin.get(), '3')
+-    def test_format(self):
++    def test_configure_format(self):
+         self.spin.set(1)
+         self.spin['format'] = '%10.3f'
+         self.spin.update()
+@@ -1220,7 +1220,7 @@ class SpinboxTest(EntryTest, unittest.TestCase):
+         self.assertTrue('.' not in value)
+         self.assertEqual(len(value), 1)
+-    def test_wrap(self):
++    def test_configure_wrap(self):
+         self.spin['to'] = 10
+         self.spin['from'] = 1
+         self.spin.set(1)
+@@ -1239,7 +1239,7 @@ class SpinboxTest(EntryTest, unittest.TestCase):
+         self._click_decrement_arrow()
+         self.assertEqual(self.spin.get(), '1')
+-    def test_values(self):
++    def test_configure_values(self):
+         self.assertEqual(self.spin['values'],
+                          () if tcl_version < (8, 5) else '')
+         self.checkParam(self.spin, 'values', 'mon tue wed thur',
+@@ -1299,14 +1299,14 @@ class TreeviewTest(AbstractWidgetTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return ttk.Treeview(self.root, **kwargs)
+-    def test_columns(self):
++    def test_configure_columns(self):
+         widget = self.create()
+         self.checkParam(widget, 'columns', 'a b c',
+                         expected=('a', 'b', 'c'))
+         self.checkParam(widget, 'columns', ('a', 'b', 'c'))
+         self.checkParam(widget, 'columns', '')
+-    def test_displaycolumns(self):
++    def test_configure_displaycolumns(self):
+         widget = self.create()
+         widget['columns'] = ('a', 'b', 'c')
+         self.checkParam(widget, 'displaycolumns', 'b a c',
+@@ -1322,17 +1322,17 @@ class TreeviewTest(AbstractWidgetTest, unittest.TestCase):
+         self.checkInvalidParam(widget, 'displaycolumns', (1, -2),
+                                errmsg='Column index -2 out of bounds')
+-    def test_height(self):
++    def test_configure_height(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'height', 100, -100, 0, '3c', conv=False)
+         self.checkPixelsParam(widget, 'height', 101.2, 102.6, conv=noconv)
+-    def test_selectmode(self):
++    def test_configure_selectmode(self):
+         widget = self.create()
+         self.checkEnumParam(widget, 'selectmode',
+                             'none', 'browse', 'extended')
+-    def test_show(self):
++    def test_configure_show(self):
+         widget = self.create()
+         self.checkParam(widget, 'show', 'tree headings',
+                         expected=('tree', 'headings'))
+@@ -1860,12 +1860,22 @@ class SizegripTest(AbstractWidgetTest, unittest.TestCase):
+     def create(self, **kwargs):
+         return ttk.Sizegrip(self.root, **kwargs)
++
++class DefaultRootTest(AbstractDefaultRootTest, unittest.TestCase):
++
++    def test_frame(self):
++        self._test_widget(ttk.Frame)
++
++    def test_label(self):
++        self._test_widget(ttk.Label)
++
++
+ tests_gui = (
+         ButtonTest, CheckbuttonTest, ComboboxTest, EntryTest,
+         FrameTest, LabelFrameTest, LabelTest, MenubuttonTest,
+         NotebookTest, PanedWindowTest, ProgressbarTest,
+         RadiobuttonTest, ScaleTest, ScrollbarTest, SeparatorTest,
+-        SizegripTest, SpinboxTest, TreeviewTest, WidgetTest,
++        SizegripTest, SpinboxTest, TreeviewTest, WidgetTest, DefaultRootTest,
+         )
+ if __name__ == "__main__":
+diff --git a/Lib/tkinter/test/widget_tests.py b/Lib/tkinter/test/widget_tests.py
+index b42ff52178..9702ff4530 100644
+--- a/Lib/tkinter/test/widget_tests.py
++++ b/Lib/tkinter/test/widget_tests.py
+@@ -1,7 +1,6 @@
+ # Common tests for test_tkinter/test_widgets.py and test_ttk/test_widgets.py
+ import unittest
+-import sys
+ import tkinter
+ from tkinter.test.support import (AbstractTkTest, tcl_version, requires_tcl,
+                                   get_tk_patchlevel, pixels_conv, tcl_obj_eq)
+@@ -243,31 +242,31 @@ class StandardOptionsTests:
+         'underline', 'wraplength', 'xscrollcommand', 'yscrollcommand',
+     )
+-    def test_activebackground(self):
++    def test_configure_activebackground(self):
+         widget = self.create()
+         self.checkColorParam(widget, 'activebackground')
+-    def test_activeborderwidth(self):
++    def test_configure_activeborderwidth(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'activeborderwidth',
+                               0, 1.3, 2.9, 6, -2, '10p')
+-    def test_activeforeground(self):
++    def test_configure_activeforeground(self):
+         widget = self.create()
+         self.checkColorParam(widget, 'activeforeground')
+-    def test_anchor(self):
++    def test_configure_anchor(self):
+         widget = self.create()
+         self.checkEnumParam(widget, 'anchor',
+                 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw', 'center')
+-    def test_background(self):
++    def test_configure_background(self):
+         widget = self.create()
+         self.checkColorParam(widget, 'background')
+         if 'bg' in self.OPTIONS:
+             self.checkColorParam(widget, 'bg')
+-    def test_bitmap(self):
++    def test_configure_bitmap(self):
+         widget = self.create()
+         self.checkParam(widget, 'bitmap', 'questhead')
+         self.checkParam(widget, 'bitmap', 'gray50')
+@@ -280,90 +279,88 @@ class StandardOptionsTests:
+             self.checkInvalidParam(widget, 'bitmap', 'spam',
+                     errmsg='bitmap "spam" not defined')
+-    def test_borderwidth(self):
++    def test_configure_borderwidth(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'borderwidth',
+                               0, 1.3, 2.6, 6, -2, '10p')
+         if 'bd' in self.OPTIONS:
+             self.checkPixelsParam(widget, 'bd', 0, 1.3, 2.6, 6, -2, '10p')
+-    def test_compound(self):
++    def test_configure_compound(self):
+         widget = self.create()
+         self.checkEnumParam(widget, 'compound',
+                 'bottom', 'center', 'left', 'none', 'right', 'top')
+-    def test_cursor(self):
++    def test_configure_cursor(self):
+         widget = self.create()
+         self.checkCursorParam(widget, 'cursor')
+-    def test_disabledforeground(self):
++    def test_configure_disabledforeground(self):
+         widget = self.create()
+         self.checkColorParam(widget, 'disabledforeground')
+-    def test_exportselection(self):
++    def test_configure_exportselection(self):
+         widget = self.create()
+         self.checkBooleanParam(widget, 'exportselection')
+-    def test_font(self):
++    def test_configure_font(self):
+         widget = self.create()
+         self.checkParam(widget, 'font',
+                         '-Adobe-Helvetica-Medium-R-Normal--*-120-*-*-*-*-*-*')
+         self.checkInvalidParam(widget, 'font', '',
+                                errmsg='font "" doesn\'t exist')
+-    def test_foreground(self):
++    def test_configure_foreground(self):
+         widget = self.create()
+         self.checkColorParam(widget, 'foreground')
+         if 'fg' in self.OPTIONS:
+             self.checkColorParam(widget, 'fg')
+-    def test_highlightbackground(self):
++    def test_configure_highlightbackground(self):
+         widget = self.create()
+         self.checkColorParam(widget, 'highlightbackground')
+-    def test_highlightcolor(self):
++    def test_configure_highlightcolor(self):
+         widget = self.create()
+         self.checkColorParam(widget, 'highlightcolor')
+-    def test_highlightthickness(self):
++    def test_configure_highlightthickness(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'highlightthickness',
+                               0, 1.3, 2.6, 6, '10p')
+         self.checkParam(widget, 'highlightthickness', -2, expected=0,
+                         conv=self._conv_pixels)
+-    @unittest.skipIf(sys.platform == 'darwin',
+-                     'crashes with Cocoa Tk (issue19733)')
+-    def test_image(self):
++    def test_configure_image(self):
+         widget = self.create()
+         self.checkImageParam(widget, 'image')
+-    def test_insertbackground(self):
++    def test_configure_insertbackground(self):
+         widget = self.create()
+         self.checkColorParam(widget, 'insertbackground')
+-    def test_insertborderwidth(self):
++    def test_configure_insertborderwidth(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'insertborderwidth',
+                               0, 1.3, 2.6, 6, -2, '10p')
+-    def test_insertofftime(self):
++    def test_configure_insertofftime(self):
+         widget = self.create()
+         self.checkIntegerParam(widget, 'insertofftime', 100)
+-    def test_insertontime(self):
++    def test_configure_insertontime(self):
+         widget = self.create()
+         self.checkIntegerParam(widget, 'insertontime', 100)
+-    def test_insertwidth(self):
++    def test_configure_insertwidth(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'insertwidth', 1.3, 2.6, -2, '10p')
+-    def test_jump(self):
++    def test_configure_jump(self):
+         widget = self.create()
+         self.checkBooleanParam(widget, 'jump')
+-    def test_justify(self):
++    def test_configure_justify(self):
+         widget = self.create()
+         self.checkEnumParam(widget, 'justify', 'left', 'right', 'center',
+                 errmsg='bad justification "{}": must be '
+@@ -372,154 +369,155 @@ class StandardOptionsTests:
+                 errmsg='ambiguous justification "": must be '
+                        'left, right, or center')
+-    def test_orient(self):
++    def test_configure_orient(self):
+         widget = self.create()
+         self.assertEqual(str(widget['orient']), self.default_orient)
+         self.checkEnumParam(widget, 'orient', 'horizontal', 'vertical')
+-    def test_padx(self):
++    def test_configure_padx(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'padx', 3, 4.4, 5.6, -2, '12m',
+                               conv=self._conv_pad_pixels)
+-    def test_pady(self):
++    def test_configure_pady(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'pady', 3, 4.4, 5.6, -2, '12m',
+                               conv=self._conv_pad_pixels)
+-    def test_relief(self):
++    def test_configure_relief(self):
+         widget = self.create()
+         self.checkReliefParam(widget, 'relief')
+-    def test_repeatdelay(self):
++    def test_configure_repeatdelay(self):
+         widget = self.create()
+         self.checkIntegerParam(widget, 'repeatdelay', -500, 500)
+-    def test_repeatinterval(self):
++    def test_configure_repeatinterval(self):
+         widget = self.create()
+         self.checkIntegerParam(widget, 'repeatinterval', -500, 500)
+-    def test_selectbackground(self):
++    def test_configure_selectbackground(self):
+         widget = self.create()
+         self.checkColorParam(widget, 'selectbackground')
+-    def test_selectborderwidth(self):
++    def test_configure_selectborderwidth(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'selectborderwidth', 1.3, 2.6, -2, '10p')
+-    def test_selectforeground(self):
++    def test_configure_selectforeground(self):
+         widget = self.create()
+         self.checkColorParam(widget, 'selectforeground')
+-    def test_setgrid(self):
++    def test_configure_setgrid(self):
+         widget = self.create()
+         self.checkBooleanParam(widget, 'setgrid')
+-    def test_state(self):
++    def test_configure_state(self):
+         widget = self.create()
+         self.checkEnumParam(widget, 'state', 'active', 'disabled', 'normal')
+-    def test_takefocus(self):
++    def test_configure_takefocus(self):
+         widget = self.create()
+         self.checkParams(widget, 'takefocus', '0', '1', '')
+-    def test_text(self):
++    def test_configure_text(self):
+         widget = self.create()
+         self.checkParams(widget, 'text', '', 'any string')
+-    def test_textvariable(self):
++    def test_configure_textvariable(self):
+         widget = self.create()
+         var = tkinter.StringVar(self.root)
+         self.checkVariableParam(widget, 'textvariable', var)
+-    def test_troughcolor(self):
++    def test_configure_troughcolor(self):
+         widget = self.create()
+         self.checkColorParam(widget, 'troughcolor')
+-    def test_underline(self):
++    def test_configure_underline(self):
+         widget = self.create()
+         self.checkIntegerParam(widget, 'underline', 0, 1, 10)
+-    def test_wraplength(self):
++    def test_configure_wraplength(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'wraplength', 100)
+-    def test_xscrollcommand(self):
++    def test_configure_xscrollcommand(self):
+         widget = self.create()
+         self.checkCommandParam(widget, 'xscrollcommand')
+-    def test_yscrollcommand(self):
++    def test_configure_yscrollcommand(self):
+         widget = self.create()
+         self.checkCommandParam(widget, 'yscrollcommand')
+     # non-standard but common options
+-    def test_command(self):
++    def test_configure_command(self):
+         widget = self.create()
+         self.checkCommandParam(widget, 'command')
+-    def test_indicatoron(self):
++    def test_configure_indicatoron(self):
+         widget = self.create()
+         self.checkBooleanParam(widget, 'indicatoron')
+-    def test_offrelief(self):
++    def test_configure_offrelief(self):
+         widget = self.create()
+         self.checkReliefParam(widget, 'offrelief')
+-    def test_overrelief(self):
++    def test_configure_overrelief(self):
+         widget = self.create()
+         self.checkReliefParam(widget, 'overrelief')
+-    def test_selectcolor(self):
++    def test_configure_selectcolor(self):
+         widget = self.create()
+         self.checkColorParam(widget, 'selectcolor')
+-    def test_selectimage(self):
++    def test_configure_selectimage(self):
+         widget = self.create()
+         self.checkImageParam(widget, 'selectimage')
+     @requires_tcl(8, 5)
+-    def test_tristateimage(self):
++    def test_configure_tristateimage(self):
+         widget = self.create()
+         self.checkImageParam(widget, 'tristateimage')
+     @requires_tcl(8, 5)
+-    def test_tristatevalue(self):
++    def test_configure_tristatevalue(self):
+         widget = self.create()
+         self.checkParam(widget, 'tristatevalue', 'unknowable')
+-    def test_variable(self):
++    def test_configure_variable(self):
+         widget = self.create()
+         var = tkinter.DoubleVar(self.root)
+         self.checkVariableParam(widget, 'variable', var)
+ class IntegerSizeTests:
+-    def test_height(self):
++    def test_configure_height(self):
+         widget = self.create()
+         self.checkIntegerParam(widget, 'height', 100, -100, 0)
+-    def test_width(self):
++    def test_configure_width(self):
+         widget = self.create()
+         self.checkIntegerParam(widget, 'width', 402, -402, 0)
+ class PixelSizeTests:
+-    def test_height(self):
++    def test_configure_height(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'height', 100, 101.2, 102.6, -100, 0, '3c')
+-    def test_width(self):
++    def test_configure_width(self):
+         widget = self.create()
+         self.checkPixelsParam(widget, 'width', 402, 403.4, 404.6, -402, 0, '5i')
+ def add_standard_options(*source_classes):
+-    # This decorator adds test_xxx methods from source classes for every xxx
+-    # option in the OPTIONS class attribute if they are not defined explicitly.
++    # This decorator adds test_configure_xxx methods from source classes for
++    # every xxx option in the OPTIONS class attribute if they are not defined
++    # explicitly.
+     def decorator(cls):
+         for option in cls.OPTIONS:
+-            methodname = 'test_' + option
++            methodname = 'test_configure_' + option
+             if not hasattr(cls, methodname):
+                 for source_class in source_classes:
+                     if hasattr(source_class, methodname):
+diff --git a/Lib/tkinter/tix.py b/Lib/tkinter/tix.py
+index ac545502e4..ef1e7406bc 100644
+--- a/Lib/tkinter/tix.py
++++ b/Lib/tkinter/tix.py
+@@ -387,9 +387,7 @@ class TixWidget(tkinter.Widget):
+     # These are missing from Tkinter
+     def image_create(self, imgtype, cnf={}, master=None, **kw):
+         if not master:
+-            master = tkinter._default_root
+-            if not master:
+-                raise RuntimeError('Too early to create image')
++            master = self
+         if kw and cnf: cnf = _cnfmerge((cnf, kw))
+         elif kw: cnf = kw
+         options = ()
+@@ -475,10 +473,7 @@ class DisplayStyle:
+             elif 'refwindow' in cnf:
+                 master = cnf['refwindow']
+             else:
+-                master = tkinter._default_root
+-                if not master:
+-                    raise RuntimeError("Too early to create display style: "
+-                                       "no root window")
++                master = tkinter._get_default_root('create display style')
+         self.tk = master.tk
+         self.stylename = self.tk.call('tixDisplayStyle', itemtype,
+                             *self._options(cnf,kw) )
+diff --git a/Lib/tkinter/ttk.py b/Lib/tkinter/ttk.py
+index 968fd54dce..ab7aeb15e8 100644
+--- a/Lib/tkinter/ttk.py
++++ b/Lib/tkinter/ttk.py
+@@ -349,12 +349,7 @@ def setup_master(master=None):
+     If it is not allowed to use the default root and master is None,
+     RuntimeError is raised."""
+     if master is None:
+-        if tkinter._support_default_root:
+-            master = tkinter._default_root or tkinter.Tk()
+-        else:
+-            raise RuntimeError(
+-                    "No master specified and tkinter is "
+-                    "configured to not support default root")
++        master = tkinter._get_default_root()
+     return master
+@@ -1538,7 +1533,10 @@ class LabeledScale(Frame):
+         scale_side = 'bottom' if self._label_top else 'top'
+         label_side = 'top' if scale_side == 'bottom' else 'bottom'
+         self.scale.pack(side=scale_side, fill='x')
+-        tmp = Label(self).pack(side=label_side) # place holder
++        # Dummy required to make frame correct height
++        dummy = Label(self)
++        dummy.pack(side=label_side)
++        dummy.lower()
+         self.label.place(anchor='n' if label_side == 'top' else 's')
+         # update the label as scale or variable changes
+diff --git a/Lib/traceback.py b/Lib/traceback.py
+index fb34de9489..d7fbdae680 100644
+--- a/Lib/traceback.py
++++ b/Lib/traceback.py
+@@ -515,7 +515,8 @@ class TracebackException:
+         if exc_type and issubclass(exc_type, SyntaxError):
+             # Handle SyntaxError's specially
+             self.filename = exc_value.filename
+-            self.lineno = str(exc_value.lineno)
++            lno = exc_value.lineno
++            self.lineno = str(lno) if lno is not None else None
+             self.text = exc_value.text
+             self.offset = exc_value.offset
+             self.msg = exc_value.msg
+@@ -574,9 +575,12 @@ class TracebackException:
+     def _format_syntax_error(self, stype):
+         """Format SyntaxError exceptions (internal helper)."""
+         # Show exactly where the problem was found.
+-        filename = self.filename or "<string>"
+-        lineno = str(self.lineno) or '?'
+-        yield '  File "{}", line {}\n'.format(filename, lineno)
++        filename_suffix = ''
++        if self.lineno is not None:
++            yield '  File "{}", line {}\n'.format(
++                self.filename or "<string>", self.lineno)
++        elif self.filename is not None:
++            filename_suffix = ' ({})'.format(self.filename)
+         text = self.text
+         if text is not None:
+@@ -594,7 +598,7 @@ class TracebackException:
+                 caretspace = ((c if c.isspace() else ' ') for c in ltext[:caret])
+                 yield '    {}^\n'.format(''.join(caretspace))
+         msg = self.msg or "<no detail available>"
+-        yield "{}: {}\n".format(stype, msg)
++        yield "{}: {}{}\n".format(stype, msg, filename_suffix)
+     def format(self, *, chain=True):
+         """Format the exception.
+diff --git a/Lib/tracemalloc.py b/Lib/tracemalloc.py
+index 69b4170ec8..cec99c5970 100644
+--- a/Lib/tracemalloc.py
++++ b/Lib/tracemalloc.py
+@@ -226,7 +226,7 @@ class Traceback(Sequence):
+         return str(self[0])
+     def __repr__(self):
+-        s = "<Traceback %r" % tuple(self)
++        s = f"<Traceback {tuple(self)}"
+         if self._total_nframe is None:
+             s += ">"
+         else:
+diff --git a/Lib/typing.py b/Lib/typing.py
+index f5316ab8a5..3556b8adb8 100644
+--- a/Lib/typing.py
++++ b/Lib/typing.py
+@@ -118,6 +118,15 @@ __all__ = [
+ # legitimate imports of those modules.
++def _type_convert(arg):
++    """For converting None to type(None), and strings to ForwardRef."""
++    if arg is None:
++        return type(None)
++    if isinstance(arg, str):
++        return ForwardRef(arg)
++    return arg
++
++
+ def _type_check(arg, msg, is_argument=True):
+     """Check that the argument is a type, and return it (internal helper).
+@@ -134,10 +143,7 @@ def _type_check(arg, msg, is_argument=True):
+     if is_argument:
+         invalid_generic_forms = invalid_generic_forms + (ClassVar, Final)
+-    if arg is None:
+-        return type(None)
+-    if isinstance(arg, str):
+-        return ForwardRef(arg)
++    arg = _type_convert(arg)
+     if (isinstance(arg, _GenericAlias) and
+             arg.__origin__ in invalid_generic_forms):
+         raise TypeError(f"{arg} is not valid as type argument")
+@@ -859,13 +865,13 @@ class _CallableType(_SpecialGenericAlias, _root=True):
+             raise TypeError("Callable must be used as "
+                             "Callable[[arg, ...], result].")
+         args, result = params
+-        if args is Ellipsis:
+-            params = (Ellipsis, result)
+-        else:
+-            if not isinstance(args, list):
+-                raise TypeError(f"Callable[args, result]: args must be a list."
+-                                f" Got {args}")
++        # This relaxes what args can be on purpose to allow things like
++        # PEP 612 ParamSpec.  Responsibility for whether a user is using
++        # Callable[...] properly is deferred to static type checkers.
++        if isinstance(args, list):
+             params = (tuple(args), result)
++        else:
++            params = (args, result)
+         return self.__getitem_inner__(params)
+     @_tp_cache
+@@ -875,8 +881,9 @@ class _CallableType(_SpecialGenericAlias, _root=True):
+         result = _type_check(result, msg)
+         if args is Ellipsis:
+             return self.copy_with((_TypingEllipsis, result))
+-        msg = "Callable[[arg, ...], result]: each arg must be a type."
+-        args = tuple(_type_check(arg, msg) for arg in args)
++        if not isinstance(args, tuple):
++            args = (args,)
++        args = tuple(_type_convert(arg) for arg in args)
+         params = args + (result,)
+         return self.copy_with(params)
+@@ -1500,13 +1507,11 @@ def get_args(tp):
+     """
+     if isinstance(tp, _AnnotatedAlias):
+         return (tp.__origin__,) + tp.__metadata__
+-    if isinstance(tp, _GenericAlias):
++    if isinstance(tp, (_GenericAlias, GenericAlias)):
+         res = tp.__args__
+         if tp.__origin__ is collections.abc.Callable and res[0] is not Ellipsis:
+             res = (list(res[:-1]), res[-1])
+         return res
+-    if isinstance(tp, GenericAlias):
+-        return tp.__args__
+     return ()
+@@ -1980,14 +1985,14 @@ def TypedDict(typename, fields=None, /, *, total=True, **kwargs):
+         raise TypeError("TypedDict takes either a dict or keyword arguments,"
+                         " but not both")
+-    ns = {'__annotations__': dict(fields), '__total__': total}
++    ns = {'__annotations__': dict(fields)}
+     try:
+         # Setting correct module is necessary to make typed dict classes pickleable.
+         ns['__module__'] = sys._getframe(1).f_globals.get('__name__', '__main__')
+     except (AttributeError, ValueError):
+         pass
+-    return _TypedDictMeta(typename, (), ns)
++    return _TypedDictMeta(typename, (), ns, total=total)
+ _TypedDict = type.__new__(_TypedDictMeta, 'TypedDict', (), {})
+ TypedDict.__mro_entries__ = lambda bases: (_TypedDict,)
+diff --git a/Lib/unittest/async_case.py b/Lib/unittest/async_case.py
+index 1bc1312c8c..520213c372 100644
+--- a/Lib/unittest/async_case.py
++++ b/Lib/unittest/async_case.py
+@@ -102,9 +102,9 @@ class IsolatedAsyncioTestCase(TestCase):
+                 ret = await awaitable
+                 if not fut.cancelled():
+                     fut.set_result(ret)
+-            except asyncio.CancelledError:
++            except (SystemExit, KeyboardInterrupt):
+                 raise
+-            except Exception as ex:
++            except (BaseException, asyncio.CancelledError) as ex:
+                 if not fut.cancelled():
+                     fut.set_exception(ex)
+diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py
+index b495a5f6cc..f03c88baca 100644
+--- a/Lib/unittest/mock.py
++++ b/Lib/unittest/mock.py
+@@ -406,7 +406,7 @@ class NonCallableMock(Base):
+             # Check if spec is an async object or function
+             bound_args = _MOCK_SIG.bind_partial(cls, *args, **kw).arguments
+             spec_arg = bound_args.get('spec_set', bound_args.get('spec'))
+-            if spec_arg and _is_async_obj(spec_arg):
++            if spec_arg is not None and _is_async_obj(spec_arg):
+                 bases = (AsyncMockMixin, cls)
+         new = type(cls.__name__, bases, {'__doc__': cls.__doc__})
+         instance = _safe_super(NonCallableMock, cls).__new__(new)
+diff --git a/Lib/unittest/test/test_async_case.py b/Lib/unittest/test/test_async_case.py
+index 2db441da20..d01864b693 100644
+--- a/Lib/unittest/test/test_async_case.py
++++ b/Lib/unittest/test/test_async_case.py
+@@ -190,6 +190,33 @@ class TestAsyncCase(unittest.TestCase):
+                                   'async_cleanup 2',
+                                   'sync_cleanup 1'])
++    def test_base_exception_from_async_method(self):
++        events = []
++        class Test(unittest.IsolatedAsyncioTestCase):
++            async def test_base(self):
++                events.append("test_base")
++                raise BaseException()
++                events.append("not it")
++
++            async def test_no_err(self):
++                events.append("test_no_err")
++
++            async def test_cancel(self):
++                raise asyncio.CancelledError()
++
++        test = Test("test_base")
++        output = test.run()
++        self.assertFalse(output.wasSuccessful())
++
++        test = Test("test_no_err")
++        test.run()
++        self.assertEqual(events, ['test_base', 'test_no_err'])
++
++        test = Test("test_cancel")
++        output = test.run()
++        self.assertFalse(output.wasSuccessful())
++
++
+ if __name__ == "__main__":
+     unittest.main()
+diff --git a/Lib/unittest/test/testmock/testmock.py b/Lib/unittest/test/testmock/testmock.py
+index ce674e713e..f930724530 100644
+--- a/Lib/unittest/test/testmock/testmock.py
++++ b/Lib/unittest/test/testmock/testmock.py
+@@ -2156,6 +2156,16 @@ class MockTest(unittest.TestCase):
+                 obj = mock(spec=Something)
+                 self.assertIsInstance(obj, Something)
++    def test_bool_not_called_when_passing_spec_arg(self):
++        class Something:
++            def __init__(self):
++                self.obj_with_bool_func = unittest.mock.MagicMock()
++
++        obj = Something()
++        with unittest.mock.patch.object(obj, 'obj_with_bool_func', autospec=True): pass
++
++        self.assertEqual(obj.obj_with_bool_func.__bool__.call_count, 0)
++
+ if __name__ == '__main__':
+     unittest.main()
+diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py
+index a8c870b977..57d991465a 100644
+--- a/Lib/urllib/request.py
++++ b/Lib/urllib/request.py
+@@ -771,7 +771,11 @@ def _parse_proxy(proxy):
+             raise ValueError("proxy URL with no authority: %r" % proxy)
+         # We have an authority, so for RFC 3986-compliant URLs (by ss 3.
+         # and 3.3.), path is empty or starts with '/'
+-        end = r_scheme.find("/", 2)
++        if '@' in r_scheme:
++            host_separator = r_scheme.find('@')
++            end = r_scheme.find("/", host_separator)
++        else:
++            end = r_scheme.find("/", 2)
+         if end == -1:
+             end = None
+         authority = r_scheme[2:end]
+diff --git a/Mac/BuildScript/build-installer.py b/Mac/BuildScript/build-installer.py
+index 16816d1cf8..ef64502ab7 100755
+--- a/Mac/BuildScript/build-installer.py
++++ b/Mac/BuildScript/build-installer.py
+@@ -242,15 +242,12 @@ def library_recipes():
+     result.extend([
+           dict(
+-              name="OpenSSL 1.1.1g",
+-              url="https://www.openssl.org/source/openssl-1.1.1g.tar.gz",
+-              checksum='76766e98997660138cdaf13a187bd234',
++              name="OpenSSL 1.1.1i",
++              url="https://www.openssl.org/source/openssl-1.1.1i.tar.gz",
++              checksum='08987c3cf125202e2b0840035efb392c',
+               buildrecipe=build_universal_openssl,
+               configure=None,
+               install=None,
+-              patches=[
+-                  "openssl-mac-arm64.patch",
+-                   ],
+           ),
+     ])
+@@ -263,10 +260,10 @@ def library_recipes():
+             tk_patches = ['tk868_on_10_8_10_9.patch']
+         else:
+-            tcl_tk_ver='8.6.10'
+-            tcl_checksum='97c55573f8520bcab74e21bfd8d0aadc'
++            tcl_tk_ver='8.6.11'
++            tcl_checksum='8a4c004f48984a03a7747e9ba06e4da4'
+-            tk_checksum='602a47ad9ecac7bf655ada729d140a94'
++            tk_checksum='c7ee71a2d05bba78dfffd76528dc17c6'
+             tk_patches = [ ]
+@@ -357,9 +354,9 @@ def library_recipes():
+                   ),
+           ),
+           dict(
+-              name="SQLite 3.33.0",
+-              url="https://sqlite.org/2020/sqlite-autoconf-3330000.tar.gz",
+-              checksum='842a8a100d7b01b09e543deb2b7951dd',
++              name="SQLite 3.34.0",
++              url="https://sqlite.org/2020/sqlite-autoconf-3340000.tar.gz",
++              checksum='7f33c9db7b713957fcb9271fe9049fef',
+               extra_cflags=('-Os '
+                             '-DSQLITE_ENABLE_FTS5 '
+                             '-DSQLITE_ENABLE_FTS4 '
+@@ -1138,7 +1135,6 @@ def buildPythonDocs():
+     if not os.path.exists(htmlDir):
+         # Create virtual environment for docs builds with blurb and sphinx
+         runCommand('make venv')
+-        runCommand('venv/bin/python3 -m pip install -U Sphinx==2.3.1')
+         runCommand('make html PYTHON=venv/bin/python')
+     os.rename(htmlDir, docdir)
+     os.chdir(curDir)
+@@ -1615,7 +1611,7 @@ def buildDMG():
+     if os.path.exists(outdir):
+         shutil.rmtree(outdir)
+-    # We used to use the deployment target as the last characters of the 
++    # We used to use the deployment target as the last characters of the
+     # installer file name. With the introduction of weaklinked installer
+     # variants, we may have two variants with the same file name, i.e.
+     # both ending in '10.9'.  To avoid this, we now use the major/minor
+diff --git a/Mac/BuildScript/openssl-mac-arm64.patch b/Mac/BuildScript/openssl-mac-arm64.patch
+deleted file mode 100644
+index 11267fb118..0000000000
+--- a/Mac/BuildScript/openssl-mac-arm64.patch
++++ /dev/null
+@@ -1,41 +0,0 @@
+-diff -ur openssl-1.1.1g-orig/Configurations/10-main.conf openssl-1.1.1g/Configurations/10-main.conf
+---- openssl-1.1.1g-orig/Configurations/10-main.conf   2020-04-21 14:22:39.000000000 +0200
+-+++ openssl-1.1.1g/Configurations/10-main.conf        2020-07-26 12:21:32.000000000 +0200
+-@@ -1557,6 +1557,14 @@
+-         bn_ops           => "SIXTY_FOUR_BIT_LONG",
+-         perlasm_scheme   => "macosx",
+-     },
+-+    "darwin64-arm64-cc" => {
+-+        inherit_from     => [ "darwin-common", asm("aarch64_asm") ],
+-+        CFLAGS           => add("-Wall"),
+-+        cflags           => add("-arch arm64"),
+-+        lib_cppflags     => add("-DL_ENDIAN"),
+-+        bn_ops           => "SIXTY_FOUR_BIT_LONG",
+-+        perlasm_scheme   => "ios64",
+-+    },
+- 
+- ##### GNU Hurd
+-     "hurd-x86" => {
+-diff -ur openssl-1.1.1g-orig/config openssl-1.1.1g/config
+---- openssl-1.1.1g-orig/config        2020-04-21 14:22:39.000000000 +0200
+-+++ openssl-1.1.1g/config     2020-07-26 12:21:59.000000000 +0200
+-@@ -255,6 +255,9 @@
+-              ;;
+-          x86_64)
+-              echo "x86_64-apple-darwin${VERSION}"
+-+                ;;
+-+         arm64)
+-+             echo "arm64-apple-darwin${VERSION}"
+-              ;;
+-          *)
+-              echo "i686-apple-darwin${VERSION}"
+-@@ -497,6 +500,9 @@
+-      else
+-          OUT="darwin64-x86_64-cc"
+-      fi ;;
+-+  x86_64-apple-darwin*)
+-+     OUT="darwin64-arm64-cc"
+-+        ;;
+-   armv6+7-*-iphoneos)
+-      __CNF_CFLAGS="$__CNF_CFLAGS -arch armv6 -arch armv7"
+-      __CNF_CXXFLAGS="$__CNF_CXXFLAGS -arch armv6 -arch armv7"
+diff --git a/Mac/BuildScript/scripts/postflight.patch-profile b/Mac/BuildScript/scripts/postflight.patch-profile
+index 0a62e327f5..68b8e4bb04 100755
+--- a/Mac/BuildScript/scripts/postflight.patch-profile
++++ b/Mac/BuildScript/scripts/postflight.patch-profile
+@@ -20,7 +20,7 @@ fi
+ # Make sure the directory ${PYTHON_ROOT}/bin is on the users PATH.
+ BSH="`basename "${theShell}"`"
+ case "${BSH}" in
+-bash|ksh|sh|*csh|zsh)
++bash|ksh|sh|*csh|zsh|fish)
+       if [ `id -ur` = 0 ]; then
+               P=`su - ${USER} -c 'echo A-X-4-X@@$PATH@@X-4-X-A' | grep 'A-X-4-X@@.*@@X-4-X-A' | sed -e 's/^A-X-4-X@@//g' -e 's/@@X-4-X-A$//g'`
+       else
+@@ -76,6 +76,22 @@ bash)
+               PR="${HOME}/.bash_profile"
+       fi
+       ;;
++fish)
++      CONFIG_DIR="${HOME}/.config/fish"
++      RC="${CONFIG_DIR}/config.fish"
++      mkdir -p "$CONFIG_DIR"
++      if [ -f "${RC}" ]; then
++              cp -fp "${RC}" "${RC}.pysave"
++      fi
++      echo "" >> "${RC}"
++      echo "# Setting PATH for Python ${PYVER}" >> "${RC}"
++      echo "# The original version is saved in ${RC}.pysave" >> "${RC}"
++      echo "set -x PATH \"${PYTHON_ROOT}/bin\" \"\$PATH\"" >> "${RC}"
++      if [ `id -ur` = 0 ]; then
++              chown "${USER}" "${RC}"
++      fi
++      exit 0
++      ;;
+ zsh)
+         PR="${HOME}/.zprofile"
+         ;;
+diff --git a/Mac/IDLE/IDLE.app/Contents/Info.plist b/Mac/IDLE/IDLE.app/Contents/Info.plist
+index dcc48abdd2..f6b5cfe8d5 100644
+--- a/Mac/IDLE/IDLE.app/Contents/Info.plist
++++ b/Mac/IDLE/IDLE.app/Contents/Info.plist
+@@ -36,7 +36,7 @@
+       <key>CFBundleExecutable</key>
+       <string>IDLE</string>
+       <key>CFBundleGetInfoString</key>
+-      <string>%version%, Â© 2001-2020 Python Software Foundation</string>
++      <string>%version%, Â© 2001-2021 Python Software Foundation</string>
+       <key>CFBundleIconFile</key>
+       <string>IDLE.icns</string>
+       <key>CFBundleIdentifier</key>
+diff --git a/Mac/PythonLauncher/Info.plist.in b/Mac/PythonLauncher/Info.plist.in
+index 21a051535f..3d8bc3e415 100644
+--- a/Mac/PythonLauncher/Info.plist.in
++++ b/Mac/PythonLauncher/Info.plist.in
+@@ -40,7 +40,7 @@
+       <key>CFBundleExecutable</key>
+       <string>Python Launcher</string>
+       <key>CFBundleGetInfoString</key>
+-      <string>%VERSION%, Â© 2001-2020 Python Software Foundation</string>
++      <string>%VERSION%, Â© 2001-2021 Python Software Foundation</string>
+       <key>CFBundleIconFile</key>
+       <string>PythonLauncher.icns</string>
+       <key>CFBundleIdentifier</key>
+diff --git a/Mac/Resources/app/Info.plist.in b/Mac/Resources/app/Info.plist.in
+index 1d624984a8..2c80133233 100644
+--- a/Mac/Resources/app/Info.plist.in
++++ b/Mac/Resources/app/Info.plist.in
+@@ -37,7 +37,7 @@
+       <key>CFBundleInfoDictionaryVersion</key>
+       <string>6.0</string>
+       <key>CFBundleLongVersionString</key>
+-      <string>%version%, (c) 2001-2020 Python Software Foundation.</string>
++      <string>%version%, (c) 2001-2021 Python Software Foundation.</string>
+       <key>CFBundleName</key>
+       <string>Python</string>
+       <key>CFBundlePackageType</key>
+diff --git a/Misc/ACKS b/Misc/ACKS
+index 12a5ac1410..58a4accd13 100644
+--- a/Misc/ACKS
++++ b/Misc/ACKS
+@@ -192,6 +192,7 @@ Gawain Bolton
+ Carl Friedrich Bolz-Tereick
+ Forest Bond
+ Gregory Bond
++Angelin Booz
+ Médéric Boquien
+ Matias Bordese
+ Jonas Borgström
+@@ -1640,6 +1641,7 @@ Quentin Stafford-Fraser
+ Frank Stajano
+ Joel Stanley
+ Kyle Stanley
++Brandon Stansbury
+ Anthony Starks
+ David Steele
+ Oliver Steele
+@@ -1828,6 +1830,7 @@ Zachary Ware
+ Barry Warsaw
+ Steve Waterbury
+ Bob Watson
++Colin Watson
+ David Watson
+ Aaron Watters
+ Henrik Weber
+diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c
+index b0a36a3024..f2506de544 100644
+--- a/Modules/_ctypes/callproc.c
++++ b/Modules/_ctypes/callproc.c
+@@ -489,58 +489,47 @@ is_literal_char(unsigned char c)
+ static PyObject *
+ PyCArg_repr(PyCArgObject *self)
+ {
+-    char buffer[256];
+     switch(self->tag) {
+     case 'b':
+     case 'B':
+-        sprintf(buffer, "<cparam '%c' (%d)>",
++        return PyUnicode_FromFormat("<cparam '%c' (%d)>",
+             self->tag, self->value.b);
+-        break;
+     case 'h':
+     case 'H':
+-        sprintf(buffer, "<cparam '%c' (%d)>",
++        return PyUnicode_FromFormat("<cparam '%c' (%d)>",
+             self->tag, self->value.h);
+-        break;
+     case 'i':
+     case 'I':
+-        sprintf(buffer, "<cparam '%c' (%d)>",
++        return PyUnicode_FromFormat("<cparam '%c' (%d)>",
+             self->tag, self->value.i);
+-        break;
+     case 'l':
+     case 'L':
+-        sprintf(buffer, "<cparam '%c' (%ld)>",
++        return PyUnicode_FromFormat("<cparam '%c' (%ld)>",
+             self->tag, self->value.l);
+-        break;
+     case 'q':
+     case 'Q':
+-        sprintf(buffer,
+-#ifdef MS_WIN32
+-            "<cparam '%c' (%I64d)>",
+-#else
+-            "<cparam '%c' (%lld)>",
+-#endif
++        return PyUnicode_FromFormat("<cparam '%c' (%lld)>",
+             self->tag, self->value.q);
+-        break;
+     case 'd':
+-        sprintf(buffer, "<cparam '%c' (%f)>",
+-            self->tag, self->value.d);
+-        break;
+-    case 'f':
+-        sprintf(buffer, "<cparam '%c' (%f)>",
+-            self->tag, self->value.f);
+-        break;
+-
++    case 'f': {
++        PyObject *f = PyFloat_FromDouble((self->tag == 'f') ? self->value.f : self->value.d);
++        if (f == NULL) {
++            return NULL;
++        }
++        PyObject *result = PyUnicode_FromFormat("<cparam '%c' (%R)>", self->tag, f);
++        Py_DECREF(f);
++        return result;
++    }
+     case 'c':
+         if (is_literal_char((unsigned char)self->value.c)) {
+-            sprintf(buffer, "<cparam '%c' ('%c')>",
++            return PyUnicode_FromFormat("<cparam '%c' ('%c')>",
+                 self->tag, self->value.c);
+         }
+         else {
+-            sprintf(buffer, "<cparam '%c' ('\\x%02x')>",
++            return PyUnicode_FromFormat("<cparam '%c' ('\\x%02x')>",
+                 self->tag, (unsigned char)self->value.c);
+         }
+-        break;
+ /* Hm, are these 'z' and 'Z' codes useful at all?
+    Shouldn't they be replaced by the functionality of c_string
+@@ -549,22 +538,20 @@ PyCArg_repr(PyCArgObject *self)
+     case 'z':
+     case 'Z':
+     case 'P':
+-        sprintf(buffer, "<cparam '%c' (%p)>",
++        return PyUnicode_FromFormat("<cparam '%c' (%p)>",
+             self->tag, self->value.p);
+         break;
+     default:
+         if (is_literal_char((unsigned char)self->tag)) {
+-            sprintf(buffer, "<cparam '%c' at %p>",
++            return PyUnicode_FromFormat("<cparam '%c' at %p>",
+                 (unsigned char)self->tag, (void *)self);
+         }
+         else {
+-            sprintf(buffer, "<cparam 0x%02x at %p>",
++            return PyUnicode_FromFormat("<cparam 0x%02x at %p>",
+                 (unsigned char)self->tag, (void *)self);
+         }
+-        break;
+     }
+-    return PyUnicode_FromString(buffer);
+ }
+ static PyMemberDef PyCArgType_members[] = {
+diff --git a/Modules/_ctypes/malloc_closure.c b/Modules/_ctypes/malloc_closure.c
+index 4f220e42ff..788bae6a96 100644
+--- a/Modules/_ctypes/malloc_closure.c
++++ b/Modules/_ctypes/malloc_closure.c
+@@ -91,11 +91,15 @@ static void more_core(void)
+ /* put the item back into the free list */
+ void Py_ffi_closure_free(void *p)
+ {
+-#if USING_APPLE_OS_LIBFFI && HAVE_FFI_CLOSURE_ALLOC
++#if HAVE_FFI_CLOSURE_ALLOC
++#if USING_APPLE_OS_LIBFFI
+     if (__builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)) {
++#endif
+         ffi_closure_free(p);
+         return;
++#if USING_APPLE_OS_LIBFFI
+     }
++#endif
+ #endif
+     ITEM *item = (ITEM *)p;
+     item->next = free_list;
+@@ -105,10 +109,14 @@ void Py_ffi_closure_free(void *p)
+ /* return one item from the free list, allocating more if needed */
+ void *Py_ffi_closure_alloc(size_t size, void** codeloc)
+ {
+-#if USING_APPLE_OS_LIBFFI && HAVE_FFI_CLOSURE_ALLOC
++#if HAVE_FFI_CLOSURE_ALLOC
++#if USING_APPLE_OS_LIBFFI
+     if (__builtin_available(macos 10.15, ios 13, watchos 6, tvos 13, *)) {
++#endif
+         return ffi_closure_alloc(size, codeloc);
++#if USING_APPLE_OS_LIBFFI
+     }
++#endif
+ #endif
+     ITEM *item;
+     if (!free_list)
+diff --git a/Modules/_curses_panel.c b/Modules/_curses_panel.c
+index f124803493..4f026794e3 100644
+--- a/Modules/_curses_panel.c
++++ b/Modules/_curses_panel.c
+@@ -440,7 +440,9 @@ _curses_panel_panel_set_userptr(PyCursesPanelObject *self, PyObject *obj)
+         /* In case of an ncurses error, decref the new object again */
+         Py_DECREF(obj);
+     }
+-    Py_XDECREF(oldobj);
++    else {
++        Py_XDECREF(oldobj);
++    }
+     return PyCursesCheckERR(rc, "set_panel_userptr");
+ }
+diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c
+index c70b0e2a19..c84f838227 100644
+--- a/Modules/_cursesmodule.c
++++ b/Modules/_cursesmodule.c
+@@ -176,18 +176,6 @@ static char *screen_encoding = NULL;
+ /* Utility Functions */
+-static inline int
+-color_pair_to_attr(short color_number)
+-{
+-    return ((int)color_number << 8);
+-}
+-
+-static inline short
+-attr_to_color_pair(int attr)
+-{
+-    return (short)((attr & A_COLOR) >> 8);
+-}
+-
+ /*
+  * Check the return code from a curses function and return None
+  * or raise an exception as appropriate.  These are exported using the
+@@ -377,6 +365,7 @@ PyCurses_ConvertToString(PyCursesWindowObject *win, PyObject *obj,
+         *bytes = obj;
+         /* check for embedded null bytes */
+         if (PyBytes_AsStringAndSize(*bytes, &str, NULL) < 0) {
++            Py_DECREF(obj);
+             return 0;
+         }
+         return 1;
+@@ -618,7 +607,7 @@ _curses_window_addch_impl(PyCursesWindowObject *self, int group_left_1,
+     if (type == 2) {
+         funcname = "add_wch";
+         wstr[1] = L'\0';
+-        setcchar(&wcval, wstr, attr, attr_to_color_pair(attr), NULL);
++        setcchar(&wcval, wstr, attr, PAIR_NUMBER(attr), NULL);
+         if (coordinates_group)
+             rtn = mvwadd_wch(self->win,y,x, &wcval);
+         else {
+@@ -691,8 +680,9 @@ _curses_window_addstr_impl(PyCursesWindowObject *self, int group_left_1,
+ #else
+     strtype = PyCurses_ConvertToString(self, str, &bytesobj, NULL);
+ #endif
+-    if (strtype == 0)
++    if (strtype == 0) {
+         return NULL;
++    }
+     if (use_attr) {
+         attr_old = getattrs(self->win);
+         (void)wattrset(self->win,attr);
+@@ -2586,7 +2576,7 @@ NoArgOrFlagNoReturnFunctionBody(cbreak, flag)
+ _curses.color_content
+     color_number: short
+-        The number of the color (0 - COLORS).
++        The number of the color (0 - (COLORS-1)).
+     /
+ Return the red, green, and blue (RGB) components of the specified color.
+@@ -2597,27 +2587,32 @@ which will be between 0 (no component) and 1000 (maximum amount of component).
+ static PyObject *
+ _curses_color_content_impl(PyObject *module, short color_number)
+-/*[clinic end generated code: output=cb15cf3120d4bfc1 input=5555abb1c11e11b7]*/
++/*[clinic end generated code: output=cb15cf3120d4bfc1 input=630f6737514db6ad]*/
+ {
+     short r,g,b;
+     PyCursesInitialised;
+     PyCursesInitialisedColor;
+-    if (color_content(color_number, &r, &g, &b) != ERR)
+-        return Py_BuildValue("(iii)", r, g, b);
+-    else {
+-        PyErr_SetString(PyCursesError,
+-                        "Argument 1 was out of range. Check value of COLORS.");
++    if (color_content(color_number, &r, &g, &b) == ERR) {
++        if (color_number >= COLORS) {
++            PyErr_SetString(PyCursesError,
++                            "Argument 1 was out of range. Check value of COLORS.");
++        }
++        else {
++            PyErr_SetString(PyCursesError, "color_content() returned ERR");
++        }
+         return NULL;
+     }
++
++    return Py_BuildValue("(iii)", r, g, b);
+ }
+ /*[clinic input]
+ _curses.color_pair
+-    color_number: short
+-        The number of the color (0 - COLORS).
++    pair_number: short
++        The number of the color pair.
+     /
+ Return the attribute value for displaying text in the specified color.
+@@ -2627,13 +2622,13 @@ other A_* attributes.  pair_number() is the counterpart to this function.
+ [clinic start generated code]*/
+ static PyObject *
+-_curses_color_pair_impl(PyObject *module, short color_number)
+-/*[clinic end generated code: output=6a84cb6b29ecaf9a input=a9d3eb6f50e4dc12]*/
++_curses_color_pair_impl(PyObject *module, short pair_number)
++/*[clinic end generated code: output=ce609d238b70dc11 input=8dd0d5da94cb15b5]*/
+ {
+     PyCursesInitialised;
+     PyCursesInitialisedColor;
+-    return  PyLong_FromLong(color_pair_to_attr(color_number));
++    return  PyLong_FromLong(COLOR_PAIR(pair_number));
+ }
+ /*[clinic input]
+@@ -3028,7 +3023,7 @@ _curses_has_key_impl(PyObject *module, int key)
+ _curses.init_color
+     color_number: short
+-        The number of the color to be changed (0 - COLORS).
++        The number of the color to be changed (0 - (COLORS-1)).
+     r: short
+         Red component (0 - 1000).
+     g: short
+@@ -3041,13 +3036,13 @@ Change the definition of a color.
+ When init_color() is used, all occurrences of that color on the screen
+ immediately change to the new definition.  This function is a no-op on
+-most terminals; it is active only if can_change_color() returns 1.
++most terminals; it is active only if can_change_color() returns true.
+ [clinic start generated code]*/
+ static PyObject *
+ _curses_init_color_impl(PyObject *module, short color_number, short r,
+                         short g, short b)
+-/*[clinic end generated code: output=280236f5efe9776a input=f3a05bd38f619175]*/
++/*[clinic end generated code: output=280236f5efe9776a input=128601b5dc76d548]*/
+ {
+     PyCursesInitialised;
+     PyCursesInitialisedColor;
+@@ -3061,9 +3056,9 @@ _curses.init_pair
+     pair_number: short
+         The number of the color-pair to be changed (1 - (COLOR_PAIRS-1)).
+     fg: short
+-        Foreground color number (0 - COLORS).
++        Foreground color number (-1 - (COLORS-1)).
+     bg: short
+-        Background color number (0 - COLORS).
++        Background color number (-1 - (COLORS-1)).
+     /
+ Change the definition of a color-pair.
+@@ -3075,7 +3070,7 @@ all occurrences of that color-pair are changed to the new definition.
+ static PyObject *
+ _curses_init_pair_impl(PyObject *module, short pair_number, short fg,
+                        short bg)
+-/*[clinic end generated code: output=9c2ce39c22f376b6 input=c9f0b11b17a2ac6d]*/
++/*[clinic end generated code: output=9c2ce39c22f376b6 input=12c320ec14396ea2]*/
+ {
+     PyCursesInitialised;
+     PyCursesInitialisedColor;
+@@ -3713,9 +3708,14 @@ _curses_pair_content_impl(PyObject *module, short pair_number)
+     PyCursesInitialised;
+     PyCursesInitialisedColor;
+-    if (pair_content(pair_number, &f, &b)==ERR) {
+-        PyErr_SetString(PyCursesError,
+-                        "Argument 1 was out of range. (1..COLOR_PAIRS-1)");
++    if (pair_content(pair_number, &f, &b) == ERR) {
++        if (pair_number >= COLOR_PAIRS) {
++            PyErr_SetString(PyCursesError,
++                            "Argument 1 was out of range. (0..COLOR_PAIRS-1)");
++        }
++        else {
++            PyErr_SetString(PyCursesError, "pair_content() returned ERR");
++        }
+         return NULL;
+     }
+@@ -3740,7 +3740,7 @@ _curses_pair_number_impl(PyObject *module, int attr)
+     PyCursesInitialised;
+     PyCursesInitialisedColor;
+-    return PyLong_FromLong(attr_to_color_pair(attr));
++    return PyLong_FromLong(PAIR_NUMBER(attr));
+ }
+ /*[clinic input]
+diff --git a/Modules/_functoolsmodule.c b/Modules/_functoolsmodule.c
+index d158d3bae1..42764a181d 100644
+--- a/Modules/_functoolsmodule.c
++++ b/Modules/_functoolsmodule.c
+@@ -1,4 +1,5 @@
+ #include "Python.h"
++#include "pycore_object.h"        // _PyObject_GC_TRACK
+ #include "pycore_pystate.h"       // _PyThreadState_GET()
+ #include "pycore_tupleobject.h"
+ #include "structmember.h"         // PyMemberDef
+@@ -673,6 +674,11 @@ functools_reduce(PyObject *self, PyObject *args)
+             if ((result = PyObject_Call(func, args, NULL)) == NULL) {
+                 goto Fail;
+             }
++            // bpo-42536: The GC may have untracked this args tuple. Since we're
++            // recycling it, make sure it's tracked again:
++            if (!_PyObject_GC_IS_TRACKED(args)) {
++                _PyObject_GC_TRACK(args);
++            }
+         }
+     }
+diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c
+index 5356417dd7..d64e0a1cfa 100644
+--- a/Modules/_posixsubprocess.c
++++ b/Modules/_posixsubprocess.c
+@@ -46,7 +46,7 @@
+ # endif
+ #endif
+-#if defined(__FreeBSD__) || (defined(__APPLE__) && defined(__MACH__))
++#if defined(__FreeBSD__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__DragonFly__)
+ # define FD_DIR "/dev/fd"
+ #else
+ # define FD_DIR "/proc/self/fd"
+@@ -116,9 +116,9 @@ _pos_int_from_ascii(const char *name)
+ }
+-#if defined(__FreeBSD__)
++#if defined(__FreeBSD__) || defined(__DragonFly__)
+ /* When /dev/fd isn't mounted it is often a static directory populated
+- * with 0 1 2 or entries for 0 .. 63 on FreeBSD, NetBSD and OpenBSD.
++ * with 0 1 2 or entries for 0 .. 63 on FreeBSD, NetBSD, OpenBSD and DragonFlyBSD.
+  * NetBSD and OpenBSD have a /proc fs available (though not necessarily
+  * mounted) and do not have fdescfs for /dev/fd.  MacOS X has a devfs
+  * that properly supports /dev/fd.
+@@ -377,7 +377,7 @@ _close_open_fds_maybe_unsafe(long start_fd, PyObject* py_fds_to_keep)
+     ++start_fd;
+ #endif
+-#if defined(__FreeBSD__)
++#if defined(__FreeBSD__) || defined(__DragonFly__)
+     if (!_is_fdescfs_mounted_on_dev_fd())
+         proc_fd_dir = NULL;
+     else
+@@ -753,7 +753,7 @@ subprocess_fork_exec(PyObject* self, PyObject *args)
+     if (groups_list != Py_None) {
+ #ifdef HAVE_SETGROUPS
+         Py_ssize_t i;
+-        unsigned long gid;
++        gid_t gid;
+         if (!PyList_Check(groups_list)) {
+             PyErr_SetString(PyExc_TypeError,
+@@ -787,10 +787,6 @@ subprocess_fork_exec(PyObject* self, PyObject *args)
+                 Py_DECREF(elem);
+                 goto cleanup;
+             } else {
+-                /* In posixmodule.c UnsignedLong is used as a fallback value
+-                * if the value provided does not fit in a Long. Since we are
+-                * already doing the bounds checking on the Python side, we
+-                * can go directly to an UnsignedLong here. */
+                 if (!_Py_Gid_Converter(elem, &gid)) {
+                     Py_DECREF(elem);
+                     PyErr_SetString(PyExc_ValueError, "invalid group id");
+diff --git a/Modules/_sqlite/connection.c b/Modules/_sqlite/connection.c
+index b80037347f..d20339ca3f 100644
+--- a/Modules/_sqlite/connection.c
++++ b/Modules/_sqlite/connection.c
+@@ -1704,7 +1704,11 @@ pysqlite_connection_create_collation(pysqlite_Connection* self, PyObject* args)
+                                   (callable != Py_None) ? callable : NULL,
+                                   (callable != Py_None) ? pysqlite_collation_callback : NULL);
+     if (rc != SQLITE_OK) {
+-        PyDict_DelItem(self->collations, uppercase_name);
++        if (callable != Py_None) {
++            if (PyDict_DelItem(self->collations, uppercase_name) < 0) {
++                PyErr_Clear();
++            }
++        }
+         _pysqlite_seterror(self->db, NULL);
+         goto finally;
+     }
+diff --git a/Modules/_sqlite/cursor.c b/Modules/_sqlite/cursor.c
+index 5cfb4b97d6..dd0ce7e1ea 100644
+--- a/Modules/_sqlite/cursor.c
++++ b/Modules/_sqlite/cursor.c
+@@ -569,11 +569,13 @@ _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args)
+         }
+         if (!multiple) {
+-            Py_DECREF(self->lastrowid);
+             Py_BEGIN_ALLOW_THREADS
+             lastrowid = sqlite3_last_insert_rowid(self->connection->db);
+             Py_END_ALLOW_THREADS
+-            self->lastrowid = PyLong_FromLongLong(lastrowid);
++            Py_SETREF(self->lastrowid, PyLong_FromLongLong(lastrowid));
++            if (self->lastrowid == NULL) {
++                goto error;
++            }
+         }
+         if (rc == SQLITE_ROW) {
+@@ -802,8 +804,11 @@ PyObject* pysqlite_cursor_fetchmany(pysqlite_Cursor* self, PyObject* args, PyObj
+     }
+     while ((row = pysqlite_cursor_iternext(self))) {
+-        PyList_Append(list, row);
+-        Py_XDECREF(row);
++        if (PyList_Append(list, row) < 0) {
++            Py_DECREF(row);
++            break;
++        }
++        Py_DECREF(row);
+         if (++counter == maxrows) {
+             break;
+@@ -829,8 +834,11 @@ PyObject* pysqlite_cursor_fetchall(pysqlite_Cursor* self, PyObject* args)
+     }
+     while ((row = pysqlite_cursor_iternext(self))) {
+-        PyList_Append(list, row);
+-        Py_XDECREF(row);
++        if (PyList_Append(list, row) < 0) {
++            Py_DECREF(row);
++            break;
++        }
++        Py_DECREF(row);
+     }
+     if (PyErr_Occurred()) {
+diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c
+index 793c5e7154..b30141d449 100644
+--- a/Modules/_tkinter.c
++++ b/Modules/_tkinter.c
+@@ -395,7 +395,8 @@ unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
+     char *buf = NULL;
+     PyErr_Clear();
+-    /* Tcl encodes null character as \xc0\x80 */
++    /* Tcl encodes null character as \xc0\x80.
++       https://en.wikipedia.org/wiki/UTF-8#Modified_UTF-8 */
+     if (memchr(s, '\xc0', size)) {
+         char *q;
+         const char *e = s + size;
+@@ -419,6 +420,57 @@ unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
+     if (buf != NULL) {
+         PyMem_Free(buf);
+     }
++    if (r == NULL || PyUnicode_KIND(r) == PyUnicode_1BYTE_KIND) {
++        return r;
++    }
++
++    /* In CESU-8 non-BMP characters are represented as a surrogate pair,
++       like in UTF-16, and then each surrogate code point is encoded in UTF-8.
++       https://en.wikipedia.org/wiki/CESU-8 */
++    Py_ssize_t len = PyUnicode_GET_LENGTH(r);
++    Py_ssize_t i, j;
++    /* All encoded surrogate characters start with \xED. */
++    i = PyUnicode_FindChar(r, 0xdcED, 0, len, 1);
++    if (i == -2) {
++        Py_DECREF(r);
++        return NULL;
++    }
++    if (i == -1) {
++        return r;
++    }
++    Py_UCS4 *u = PyUnicode_AsUCS4Copy(r);
++    Py_DECREF(r);
++    if (u == NULL) {
++        return NULL;
++    }
++    Py_UCS4 ch;
++    for (j = i; i < len; i++, u[j++] = ch) {
++        Py_UCS4 ch1, ch2, ch3, high, low;
++        /* Low surrogates U+D800 - U+DBFF are encoded as
++           \xED\xA0\x80 - \xED\xAF\xBF. */
++        ch1 = ch = u[i];
++        if (ch1 != 0xdcED) continue;
++        ch2 = u[i + 1];
++        if (!(0xdcA0 <= ch2 && ch2 <= 0xdcAF)) continue;
++        ch3 = u[i + 2];
++        if (!(0xdc80 <= ch3 && ch3 <= 0xdcBF)) continue;
++        high = 0xD000 | ((ch2 & 0x3F) << 6) | (ch3 & 0x3F);
++        assert(Py_UNICODE_IS_HIGH_SURROGATE(high));
++        /* High surrogates U+DC00 - U+DFFF are encoded as
++           \xED\xB0\x80 - \xED\xBF\xBF. */
++        ch1 = u[i + 3];
++        if (ch1 != 0xdcED) continue;
++        ch2 = u[i + 4];
++        if (!(0xdcB0 <= ch2 && ch2 <= 0xdcBF)) continue;
++        ch3 = u[i + 5];
++        if (!(0xdc80 <= ch3 && ch3 <= 0xdcBF)) continue;
++        low = 0xD000 | ((ch2 & 0x3F) << 6) | (ch3 & 0x3F);
++        assert(Py_UNICODE_IS_HIGH_SURROGATE(high));
++        ch = Py_UNICODE_JOIN_SURROGATES(high, low);
++        i += 5;
++    }
++    r = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, u, j);
++    PyMem_Free(u);
+     return r;
+ }
+diff --git a/Modules/_zoneinfo.c b/Modules/_zoneinfo.c
+index 2cee65fac6..0a4b38a6dc 100644
+--- a/Modules/_zoneinfo.c
++++ b/Modules/_zoneinfo.c
+@@ -171,7 +171,7 @@ static void
+ update_strong_cache(const PyTypeObject *const type, PyObject *key,
+                     PyObject *zone);
+ static PyObject *
+-zone_from_strong_cache(const PyTypeObject *const type, PyObject *key);
++zone_from_strong_cache(const PyTypeObject *const type, PyObject *const key);
+ static PyObject *
+ zoneinfo_new_instance(PyTypeObject *type, PyObject *key)
+@@ -909,7 +909,13 @@ load_data(PyZoneInfo_ZoneInfo *self, PyObject *file_obj)
+     // Load the transition indices and list
+     self->trans_list_utc =
+         PyMem_Malloc(self->num_transitions * sizeof(int64_t));
++    if (self->trans_list_utc == NULL) {
++        goto error;
++    }
+     trans_idx = PyMem_Malloc(self->num_transitions * sizeof(Py_ssize_t));
++    if (trans_idx == NULL) {
++        goto error;
++    }
+     for (size_t i = 0; i < self->num_transitions; ++i) {
+         PyObject *num = PyTuple_GetItem(trans_utc, i);
+@@ -991,6 +997,9 @@ load_data(PyZoneInfo_ZoneInfo *self, PyObject *file_obj)
+     // Build _ttinfo objects from utcoff, dstoff and abbr
+     self->_ttinfos = PyMem_Malloc(self->num_ttinfos * sizeof(_ttinfo));
++    if (self->_ttinfos == NULL) {
++        goto error;
++    }
+     for (size_t i = 0; i < self->num_ttinfos; ++i) {
+         PyObject *tzname = PyTuple_GetItem(abbr, i);
+         if (tzname == NULL) {
+@@ -1006,6 +1015,9 @@ load_data(PyZoneInfo_ZoneInfo *self, PyObject *file_obj)
+     // Build our mapping from transition to the ttinfo that applies
+     self->trans_ttinfos =
+         PyMem_Calloc(self->num_transitions, sizeof(_ttinfo *));
++    if (self->trans_ttinfos == NULL) {
++        goto error;
++    }
+     for (size_t i = 0; i < self->num_transitions; ++i) {
+         size_t ttinfo_idx = trans_idx[i];
+         assert(ttinfo_idx < self->num_ttinfos);
+@@ -1219,15 +1231,9 @@ calendarrule_new(uint8_t month, uint8_t week, uint8_t day, int8_t hour,
+         return -1;
+     }
+-    // day is an unsigned integer, so day < 0 should always return false, but
+-    // if day's type changes to a signed integer *without* changing this value,
+-    // it may create a bug. Considering that the compiler should be able to
+-    // optimize out the first comparison if day is an unsigned integer anyway,
+-    // we will leave this comparison in place and disable the compiler warning.
+-#pragma GCC diagnostic push
+-#pragma GCC diagnostic ignored "-Wtype-limits"
+-    if (day < 0 || day > 6) {
+-#pragma GCC diagnostic pop
++    // If the 'day' parameter type is changed to a signed type,
++    // "day < 0" check must be added.
++    if (/* day < 0 || */ day > 6) {
+         PyErr_Format(PyExc_ValueError, "Day must be in [0, 6]");
+         return -1;
+     }
+@@ -2524,7 +2530,11 @@ zoneinfo_init_subclass(PyTypeObject *cls, PyObject *args, PyObject **kwargs)
+         return NULL;
+     }
+-    PyObject_SetAttrString((PyObject *)cls, "_weak_cache", weak_cache);
++    if (PyObject_SetAttrString((PyObject *)cls, "_weak_cache",
++                               weak_cache) < 0) {
++        Py_DECREF(weak_cache);
++        return NULL;
++    }
+     Py_DECREF(weak_cache);
+     Py_RETURN_NONE;
+ }
+@@ -2624,6 +2634,9 @@ static int
+ zoneinfomodule_exec(PyObject *m)
+ {
+     PyDateTime_IMPORT;
++    if (PyDateTimeAPI == NULL) {
++        goto error;
++    }
+     PyZoneInfo_ZoneInfoType.tp_base = PyDateTimeAPI->TZInfoType;
+     if (PyType_Ready(&PyZoneInfo_ZoneInfoType) < 0) {
+         goto error;
+diff --git a/Modules/clinic/_cursesmodule.c.h b/Modules/clinic/_cursesmodule.c.h
+index 50d7f213e0..66ffcdfdb3 100644
+--- a/Modules/clinic/_cursesmodule.c.h
++++ b/Modules/clinic/_cursesmodule.c.h
+@@ -2028,7 +2028,7 @@ PyDoc_STRVAR(_curses_color_content__doc__,
+ "Return the red, green, and blue (RGB) components of the specified color.\n"
+ "\n"
+ "  color_number\n"
+-"    The number of the color (0 - COLORS).\n"
++"    The number of the color (0 - (COLORS-1)).\n"
+ "\n"
+ "A 3-tuple is returned, containing the R, G, B values for the given color,\n"
+ "which will be between 0 (no component) and 1000 (maximum amount of component).");
+@@ -2076,13 +2076,13 @@ exit:
+ }
+ PyDoc_STRVAR(_curses_color_pair__doc__,
+-"color_pair($module, color_number, /)\n"
++"color_pair($module, pair_number, /)\n"
+ "--\n"
+ "\n"
+ "Return the attribute value for displaying text in the specified color.\n"
+ "\n"
+-"  color_number\n"
+-"    The number of the color (0 - COLORS).\n"
++"  pair_number\n"
++"    The number of the color pair.\n"
+ "\n"
+ "This attribute value can be combined with A_STANDOUT, A_REVERSE, and the\n"
+ "other A_* attributes.  pair_number() is the counterpart to this function.");
+@@ -2091,13 +2091,13 @@ PyDoc_STRVAR(_curses_color_pair__doc__,
+     {"color_pair", (PyCFunction)_curses_color_pair, METH_O, _curses_color_pair__doc__},
+ static PyObject *
+-_curses_color_pair_impl(PyObject *module, short color_number);
++_curses_color_pair_impl(PyObject *module, short pair_number);
+ static PyObject *
+ _curses_color_pair(PyObject *module, PyObject *arg)
+ {
+     PyObject *return_value = NULL;
+-    short color_number;
++    short pair_number;
+     if (PyFloat_Check(arg)) {
+         PyErr_SetString(PyExc_TypeError,
+@@ -2120,10 +2120,10 @@ _curses_color_pair(PyObject *module, PyObject *arg)
+             goto exit;
+         }
+         else {
+-            color_number = (short) ival;
++            pair_number = (short) ival;
+         }
+     }
+-    return_value = _curses_color_pair_impl(module, color_number);
++    return_value = _curses_color_pair_impl(module, pair_number);
+ exit:
+     return return_value;
+@@ -2699,7 +2699,7 @@ PyDoc_STRVAR(_curses_init_color__doc__,
+ "Change the definition of a color.\n"
+ "\n"
+ "  color_number\n"
+-"    The number of the color to be changed (0 - COLORS).\n"
++"    The number of the color to be changed (0 - (COLORS-1)).\n"
+ "  r\n"
+ "    Red component (0 - 1000).\n"
+ "  g\n"
+@@ -2709,7 +2709,7 @@ PyDoc_STRVAR(_curses_init_color__doc__,
+ "\n"
+ "When init_color() is used, all occurrences of that color on the screen\n"
+ "immediately change to the new definition.  This function is a no-op on\n"
+-"most terminals; it is active only if can_change_color() returns 1.");
++"most terminals; it is active only if can_change_color() returns true.");
+ #define _CURSES_INIT_COLOR_METHODDEF    \
+     {"init_color", (PyCFunction)(void(*)(void))_curses_init_color, METH_FASTCALL, _curses_init_color__doc__},
+@@ -2841,9 +2841,9 @@ PyDoc_STRVAR(_curses_init_pair__doc__,
+ "  pair_number\n"
+ "    The number of the color-pair to be changed (1 - (COLOR_PAIRS-1)).\n"
+ "  fg\n"
+-"    Foreground color number (0 - COLORS).\n"
++"    Foreground color number (-1 - (COLORS-1)).\n"
+ "  bg\n"
+-"    Background color number (0 - COLORS).\n"
++"    Background color number (-1 - (COLORS-1)).\n"
+ "\n"
+ "If the color-pair was previously initialized, the screen is refreshed and\n"
+ "all occurrences of that color-pair are changed to the new definition.");
+@@ -4713,4 +4713,4 @@ _curses_use_default_colors(PyObject *module, PyObject *Py_UNUSED(ignored))
+ #ifndef _CURSES_USE_DEFAULT_COLORS_METHODDEF
+     #define _CURSES_USE_DEFAULT_COLORS_METHODDEF
+ #endif /* !defined(_CURSES_USE_DEFAULT_COLORS_METHODDEF) */
+-/*[clinic end generated code: output=b53652f8acafd817 input=a9049054013a1b77]*/
++/*[clinic end generated code: output=5e739120041df368 input=a9049054013a1b77]*/
+diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c
+index 18fcebdf25..95ef8d79a1 100644
+--- a/Modules/itertoolsmodule.c
++++ b/Modules/itertoolsmodule.c
+@@ -2,6 +2,7 @@
+ #define PY_SSIZE_T_CLEAN
+ #include "Python.h"
+ #include "pycore_tupleobject.h"
++#include "pycore_object.h"        // _PyObject_GC_TRACK()
+ #include <stddef.h>               // offsetof()
+ /* Itertools module written and maintained
+@@ -2245,6 +2246,11 @@ product_next(productobject *lz)
+             lz->result = result;
+             Py_DECREF(old_result);
+         }
++        // bpo-42536: The GC may have untracked this result tuple. Since we're
++        // recycling it, make sure it's tracked again:
++        else if (!_PyObject_GC_IS_TRACKED(result)) {
++            _PyObject_GC_TRACK(result);
++        }
+         /* Now, we've got the only copy so we can update it in-place */
+         assert (npools==0 || Py_REFCNT(result) == 1);
+@@ -2568,6 +2574,11 @@ combinations_next(combinationsobject *co)
+             co->result = result;
+             Py_DECREF(old_result);
+         }
++        // bpo-42536: The GC may have untracked this result tuple. Since we're
++        // recycling it, make sure it's tracked again:
++        else if (!_PyObject_GC_IS_TRACKED(result)) {
++            _PyObject_GC_TRACK(result);
++        }
+         /* Now, we've got the only copy so we can update it in-place
+          * CPython's empty tuple is a singleton and cached in
+          * PyTuple's freelist.
+@@ -2902,6 +2913,11 @@ cwr_next(cwrobject *co)
+             co->result = result;
+             Py_DECREF(old_result);
+         }
++        // bpo-42536: The GC may have untracked this result tuple. Since we're
++        // recycling it, make sure it's tracked again:
++        else if (!_PyObject_GC_IS_TRACKED(result)) {
++            _PyObject_GC_TRACK(result);
++        }
+         /* Now, we've got the only copy so we can update it in-place CPython's
+            empty tuple is a singleton and cached in PyTuple's freelist. */
+         assert(r == 0 || Py_REFCNT(result) == 1);
+@@ -3246,6 +3262,11 @@ permutations_next(permutationsobject *po)
+             po->result = result;
+             Py_DECREF(old_result);
+         }
++        // bpo-42536: The GC may have untracked this result tuple. Since we're
++        // recycling it, make sure it's tracked again:
++        else if (!_PyObject_GC_IS_TRACKED(result)) {
++            _PyObject_GC_TRACK(result);
++        }
+         /* Now, we've got the only copy so we can update it in-place */
+         assert(r == 0 || Py_REFCNT(result) == 1);
+@@ -4515,6 +4536,11 @@ zip_longest_next(ziplongestobject *lz)
+             PyTuple_SET_ITEM(result, i, item);
+             Py_DECREF(olditem);
+         }
++        // bpo-42536: The GC may have untracked this result tuple. Since we're
++        // recycling it, make sure it's tracked again:
++        if (!_PyObject_GC_IS_TRACKED(result)) {
++            _PyObject_GC_TRACK(result);
++        }
+     } else {
+         result = PyTuple_New(tuplesize);
+         if (result == NULL)
+diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
+index 12f72f525f..5e33502721 100644
+--- a/Modules/posixmodule.c
++++ b/Modules/posixmodule.c
+@@ -56,7 +56,13 @@
+  */
+ #if defined(__APPLE__)
+-#if defined(__has_builtin) && __has_builtin(__builtin_available)
++#if defined(__has_builtin)
++#if __has_builtin(__builtin_available)
++#define HAVE_BUILTIN_AVAILABLE 1
++#endif
++#endif
++
++#ifdef HAVE_BUILTIN_AVAILABLE
+ #  define HAVE_FSTATAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
+ #  define HAVE_FACCESSAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
+ #  define HAVE_FCHMODAT_RUNTIME __builtin_available(macOS 10.10, iOS 8.0, *)
+@@ -632,7 +638,7 @@ _PyLong_FromGid(gid_t gid)
+ }
+ int
+-_Py_Uid_Converter(PyObject *obj, void *p)
++_Py_Uid_Converter(PyObject *obj, uid_t *p)
+ {
+     uid_t uid;
+     PyObject *index;
+@@ -719,7 +725,7 @@ _Py_Uid_Converter(PyObject *obj, void *p)
+ success:
+     Py_DECREF(index);
+-    *(uid_t *)p = uid;
++    *p = uid;
+     return 1;
+ underflow:
+@@ -738,7 +744,7 @@ fail:
+ }
+ int
+-_Py_Gid_Converter(PyObject *obj, void *p)
++_Py_Gid_Converter(PyObject *obj, gid_t *p)
+ {
+     gid_t gid;
+     PyObject *index;
+@@ -826,7 +832,7 @@ _Py_Gid_Converter(PyObject *obj, void *p)
+ success:
+     Py_DECREF(index);
+-    *(gid_t *)p = gid;
++    *p = gid;
+     return 1;
+ underflow:
+diff --git a/Modules/posixmodule.h b/Modules/posixmodule.h
+index 1e00562abc..711ac68693 100644
+--- a/Modules/posixmodule.h
++++ b/Modules/posixmodule.h
+@@ -14,8 +14,8 @@ extern "C" {
+ #ifndef MS_WINDOWS
+ PyAPI_FUNC(PyObject *) _PyLong_FromUid(uid_t);
+ PyAPI_FUNC(PyObject *) _PyLong_FromGid(gid_t);
+-PyAPI_FUNC(int) _Py_Uid_Converter(PyObject *, void *);
+-PyAPI_FUNC(int) _Py_Gid_Converter(PyObject *, void *);
++PyAPI_FUNC(int) _Py_Uid_Converter(PyObject *, uid_t *);
++PyAPI_FUNC(int) _Py_Gid_Converter(PyObject *, gid_t *);
+ #endif /* MS_WINDOWS */
+ #if defined(PYPTHREAD_SIGMASK) || defined(HAVE_SIGWAIT) || \
+diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
+index 76ef606e10..be75e681d4 100644
+--- a/Modules/socketmodule.c
++++ b/Modules/socketmodule.c
+@@ -3407,8 +3407,9 @@ sock_getsockname(PySocketSockObject *s, PyObject *Py_UNUSED(ignored))
+ PyDoc_STRVAR(getsockname_doc,
+ "getsockname() -> address info\n\
+ \n\
+-Return the address of the local endpoint.  For IP sockets, the address\n\
+-info is a pair (hostaddr, port).");
++Return the address of the local endpoint. The format depends on the\n\
++address family. For IPv4 sockets, the address info is a pair\n\
++(hostaddr, port).");
+ #ifdef HAVE_GETPEERNAME         /* Cray APP doesn't have this :-( */
+diff --git a/Objects/call.c b/Objects/call.c
+index 61426c7e09..87dc0dbbdb 100644
+--- a/Objects/call.c
++++ b/Objects/call.c
+@@ -205,6 +205,7 @@ PyObject *
+ PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *kwargs)
+ {
+     PyThreadState *tstate = _PyThreadState_GET();
++    vectorcallfunc func;
+     /* get vectorcallfunc as in PyVectorcall_Function, but without
+      * the Py_TPFLAGS_HAVE_VECTORCALL check */
+@@ -215,7 +216,7 @@ PyVectorcall_Call(PyObject *callable, PyObject *tuple, PyObject *kwargs)
+                       Py_TYPE(callable)->tp_name);
+         return NULL;
+     }
+-    vectorcallfunc func = *(vectorcallfunc *)(((char *)callable) + offset);
++    memcpy(&func, (char *) callable + offset, sizeof(func));
+     if (func == NULL) {
+         _PyErr_Format(tstate, PyExc_TypeError,
+                       "'%.200s' object does not support vectorcall",
+diff --git a/Objects/dictobject.c b/Objects/dictobject.c
+index faee6bc901..8a056530a4 100644
+--- a/Objects/dictobject.c
++++ b/Objects/dictobject.c
+@@ -3861,6 +3861,11 @@ dictiter_iternextitem(dictiterobject *di)
+         Py_INCREF(result);
+         Py_DECREF(oldkey);
+         Py_DECREF(oldvalue);
++        // bpo-42536: The GC may have untracked this result tuple. Since we're
++        // recycling it, make sure it's tracked again:
++        if (!_PyObject_GC_IS_TRACKED(result)) {
++            _PyObject_GC_TRACK(result);
++        }
+     }
+     else {
+         result = PyTuple_New(2);
+@@ -3976,6 +3981,11 @@ dictreviter_iternext(dictiterobject *di)
+             Py_INCREF(result);
+             Py_DECREF(oldkey);
+             Py_DECREF(oldvalue);
++            // bpo-42536: The GC may have untracked this result tuple. Since
++            // we're recycling it, make sure it's tracked again:
++            if (!_PyObject_GC_IS_TRACKED(result)) {
++                _PyObject_GC_TRACK(result);
++            }
+         }
+         else {
+             result = PyTuple_New(2);
+diff --git a/Objects/enumobject.c b/Objects/enumobject.c
+index 4a83bb45aa..bdd0ea5f39 100644
+--- a/Objects/enumobject.c
++++ b/Objects/enumobject.c
+@@ -1,6 +1,7 @@
+ /* enumerate object */
+ #include "Python.h"
++#include "pycore_object.h"        // _PyObject_GC_TRACK()
+ #include "clinic/enumobject.c.h"
+@@ -130,6 +131,11 @@ enum_next_long(enumobject *en, PyObject* next_item)
+         PyTuple_SET_ITEM(result, 1, next_item);
+         Py_DECREF(old_index);
+         Py_DECREF(old_item);
++        // bpo-42536: The GC may have untracked this result tuple. Since we're
++        // recycling it, make sure it's tracked again:
++        if (!_PyObject_GC_IS_TRACKED(result)) {
++            _PyObject_GC_TRACK(result);
++        }
+         return result;
+     }
+     result = PyTuple_New(2);
+@@ -175,6 +181,11 @@ enum_next(enumobject *en)
+         PyTuple_SET_ITEM(result, 1, next_item);
+         Py_DECREF(old_index);
+         Py_DECREF(old_item);
++        // bpo-42536: The GC may have untracked this result tuple. Since we're
++        // recycling it, make sure it's tracked again:
++        if (!_PyObject_GC_IS_TRACKED(result)) {
++            _PyObject_GC_TRACK(result);
++        }
+         return result;
+     }
+     result = PyTuple_New(2);
+diff --git a/Objects/exceptions.c b/Objects/exceptions.c
+index e44ce727af..eb72de53e9 100644
+--- a/Objects/exceptions.c
++++ b/Objects/exceptions.c
+@@ -2531,8 +2531,10 @@ _PyExc_Init(void)
+     do { \
+         PyObject *_code = PyLong_FromLong(CODE); \
+         assert(_PyObject_RealIsSubclass(PyExc_ ## TYPE, PyExc_OSError)); \
+-        if (!_code || PyDict_SetItem(errnomap, _code, PyExc_ ## TYPE)) \
++        if (!_code || PyDict_SetItem(errnomap, _code, PyExc_ ## TYPE)) { \
++            Py_XDECREF(_code); \
+             return _PyStatus_ERR("errmap insertion problem."); \
++        } \
+         Py_DECREF(_code); \
+     } while (0)
+diff --git a/Objects/genericaliasobject.c b/Objects/genericaliasobject.c
+index c5a81a5c1a..945d20593c 100644
+--- a/Objects/genericaliasobject.c
++++ b/Objects/genericaliasobject.c
+@@ -428,8 +428,8 @@ ga_getattro(PyObject *self, PyObject *name)
+ static PyObject *
+ ga_richcompare(PyObject *a, PyObject *b, int op)
+ {
+-    if (!Py_IS_TYPE(a, &Py_GenericAliasType) ||
+-        !Py_IS_TYPE(b, &Py_GenericAliasType) ||
++    if (!PyObject_TypeCheck(a, &Py_GenericAliasType) ||
++        !PyObject_TypeCheck(b, &Py_GenericAliasType) ||
+         (op != Py_EQ && op != Py_NE))
+     {
+         Py_RETURN_NOTIMPLEMENTED;
+@@ -563,6 +563,29 @@ static PyGetSetDef ga_properties[] = {
+     {0}
+ };
++/* A helper function to create GenericAlias' args tuple and set its attributes.
++ * Returns 1 on success, 0 on failure. 
++ */
++static inline int
++setup_ga(gaobject *alias, PyObject *origin, PyObject *args) {
++    if (!PyTuple_Check(args)) {
++        args = PyTuple_Pack(1, args);
++        if (args == NULL) {
++            return 0;
++        }
++    }
++    else {
++        Py_INCREF(args);
++    }
++
++    Py_INCREF(origin);
++    alias->origin = origin;
++    alias->args = args;
++    alias->parameters = NULL;
++    alias->weakreflist = NULL;
++    return 1;
++}
++
+ static PyObject *
+ ga_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+ {
+@@ -574,7 +597,15 @@ ga_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+     }
+     PyObject *origin = PyTuple_GET_ITEM(args, 0);
+     PyObject *arguments = PyTuple_GET_ITEM(args, 1);
+-    return Py_GenericAlias(origin, arguments);
++    gaobject *self = (gaobject *)type->tp_alloc(type, 0);
++    if (self == NULL) {
++        return NULL;
++    }
++    if (!setup_ga(self, origin, arguments)) {
++        type->tp_free((PyObject *)self);
++        return NULL;
++    }
++    return (PyObject *)self;
+ }
+ // TODO:
+@@ -594,7 +625,7 @@ PyTypeObject Py_GenericAliasType = {
+     .tp_hash = ga_hash,
+     .tp_call = ga_call,
+     .tp_getattro = ga_getattro,
+-    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
++    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE,
+     .tp_traverse = ga_traverse,
+     .tp_richcompare = ga_richcompare,
+     .tp_weaklistoffset = offsetof(gaobject, weakreflist),
+@@ -609,27 +640,14 @@ PyTypeObject Py_GenericAliasType = {
+ PyObject *
+ Py_GenericAlias(PyObject *origin, PyObject *args)
+ {
+-    if (!PyTuple_Check(args)) {
+-        args = PyTuple_Pack(1, args);
+-        if (args == NULL) {
+-            return NULL;
+-        }
+-    }
+-    else {
+-        Py_INCREF(args);
+-    }
+-
+     gaobject *alias = PyObject_GC_New(gaobject, &Py_GenericAliasType);
+     if (alias == NULL) {
+-        Py_DECREF(args);
+         return NULL;
+     }
+-
+-    Py_INCREF(origin);
+-    alias->origin = origin;
+-    alias->args = args;
+-    alias->parameters = NULL;
+-    alias->weakreflist = NULL;
++    if (!setup_ga(alias, origin, args)) {
++        PyObject_GC_Del((PyObject *)alias);
++        return NULL;
++    }
+     _PyObject_GC_TRACK(alias);
+     return (PyObject *)alias;
+ }
+diff --git a/Objects/odictobject.c b/Objects/odictobject.c
+index d5bf499575..b9f2169a72 100644
+--- a/Objects/odictobject.c
++++ b/Objects/odictobject.c
+@@ -1817,6 +1817,11 @@ odictiter_iternext(odictiterobject *di)
+         Py_INCREF(result);
+         Py_DECREF(PyTuple_GET_ITEM(result, 0));  /* borrowed */
+         Py_DECREF(PyTuple_GET_ITEM(result, 1));  /* borrowed */
++        // bpo-42536: The GC may have untracked this result tuple. Since we're
++        // recycling it, make sure it's tracked again:
++        if (!_PyObject_GC_IS_TRACKED(result)) {
++            _PyObject_GC_TRACK(result);
++        }
+     }
+     else {
+         result = PyTuple_New(2);
+diff --git a/PC/python3.def b/PC/python3.def
+index 66d1595c94..fce0124975 100644
+--- a/PC/python3.def
++++ b/PC/python3.def
+@@ -266,6 +266,8 @@ EXPORTS
+   PyFloat_GetMax=python39.PyFloat_GetMax
+   PyFloat_GetMin=python39.PyFloat_GetMin
+   PyFloat_Type=python39.PyFloat_Type DATA
++  PyFrame_GetCode=python39.PyFrame_GetCode
++  PyFrame_GetLineNumber=python39.PyFrame_GetLineNumber
+   PyFrozenSet_New=python39.PyFrozenSet_New
+   PyFrozenSet_Type=python39.PyFrozenSet_Type DATA
+   PyGC_Collect=python39.PyGC_Collect
+@@ -453,6 +455,7 @@ EXPORTS
+   PyObject_CallFunctionObjArgs=python39.PyObject_CallFunctionObjArgs
+   PyObject_CallMethod=python39.PyObject_CallMethod
+   PyObject_CallMethodObjArgs=python39.PyObject_CallMethodObjArgs
++  PyObject_CallNoArgs=python39.PyObject_CallNoArgs
+   PyObject_CallObject=python39.PyObject_CallObject
+   PyObject_Calloc=python39.PyObject_Calloc
+   PyObject_CheckReadBuffer=python39.PyObject_CheckReadBuffer
+@@ -569,6 +572,9 @@ EXPORTS
+   PyThreadState_DeleteCurrent=python39.PyThreadState_DeleteCurrent
+   PyThreadState_Get=python39.PyThreadState_Get
+   PyThreadState_GetDict=python39.PyThreadState_GetDict
++  PyThreadState_GetFrame=python39.PyThreadState_GetFrame
++  PyThreadState_GetID=python39.PyThreadState_GetID
++  PyThreadState_GetInterpreter=python39.PyThreadState_GetInterpreter
+   PyThreadState_New=python39.PyThreadState_New
+   PyThreadState_SetAsyncExc=python39.PyThreadState_SetAsyncExc
+   PyThreadState_Swap=python39.PyThreadState_Swap
+diff --git a/PC/python_ver_rc.h b/PC/python_ver_rc.h
+index 060aecdc67..90fc6ba1a1 100644
+--- a/PC/python_ver_rc.h
++++ b/PC/python_ver_rc.h
+@@ -5,7 +5,7 @@
+ #include "winver.h"
+ #define PYTHON_COMPANY   "Python Software Foundation"
+-#define PYTHON_COPYRIGHT "Copyright \xA9 2001-2016 Python Software Foundation. Copyright \xA9 2000 BeOpen.com. Copyright \xA9 1995-2001 CNRI. Copyright \xA9 1991-1995 SMC."
++#define PYTHON_COPYRIGHT "Copyright \xA9 2001-2021 Python Software Foundation. Copyright \xA9 2000 BeOpen.com. Copyright \xA9 1995-2001 CNRI. Copyright \xA9 1991-1995 SMC."
+ #define MS_WINDOWS
+ #include "modsupport.h"
+diff --git a/Parser/pegen/parse.c b/Parser/pegen/parse.c
+index 0eb61db39a..98008a5fc1 100644
+--- a/Parser/pegen/parse.c
++++ b/Parser/pegen/parse.c
+@@ -204,192 +204,196 @@ static KeywordToken *reserved_keywords[] = {
+ #define kwarg_or_starred_type 1126
+ #define kwarg_or_double_starred_type 1127
+ #define star_targets_type 1128
+-#define star_targets_seq_type 1129
+-#define star_target_type 1130
+-#define star_atom_type 1131
+-#define single_target_type 1132
+-#define single_subscript_attribute_target_type 1133
+-#define del_targets_type 1134
+-#define del_target_type 1135
+-#define del_t_atom_type 1136
+-#define targets_type 1137
+-#define target_type 1138
+-#define t_primary_type 1139  // Left-recursive
+-#define t_lookahead_type 1140
+-#define t_atom_type 1141
+-#define invalid_arguments_type 1142
+-#define invalid_kwarg_type 1143
+-#define invalid_named_expression_type 1144
+-#define invalid_assignment_type 1145
+-#define invalid_ann_assign_target_type 1146
+-#define invalid_del_stmt_type 1147
+-#define invalid_block_type 1148
+-#define invalid_primary_type 1149  // Left-recursive
+-#define invalid_comprehension_type 1150
+-#define invalid_dict_comprehension_type 1151
+-#define invalid_parameters_type 1152
+-#define invalid_lambda_parameters_type 1153
+-#define invalid_star_etc_type 1154
+-#define invalid_lambda_star_etc_type 1155
+-#define invalid_double_type_comments_type 1156
+-#define invalid_with_item_type 1157
+-#define invalid_for_target_type 1158
+-#define invalid_group_type 1159
+-#define invalid_import_from_targets_type 1160
+-#define _loop0_1_type 1161
+-#define _loop0_2_type 1162
+-#define _loop0_4_type 1163
+-#define _gather_3_type 1164
+-#define _loop0_6_type 1165
+-#define _gather_5_type 1166
+-#define _loop0_8_type 1167
+-#define _gather_7_type 1168
+-#define _loop0_10_type 1169
+-#define _gather_9_type 1170
+-#define _loop1_11_type 1171
+-#define _loop0_13_type 1172
+-#define _gather_12_type 1173
+-#define _tmp_14_type 1174
+-#define _tmp_15_type 1175
+-#define _tmp_16_type 1176
+-#define _tmp_17_type 1177
+-#define _tmp_18_type 1178
+-#define _tmp_19_type 1179
+-#define _tmp_20_type 1180
+-#define _tmp_21_type 1181
+-#define _loop1_22_type 1182
+-#define _tmp_23_type 1183
+-#define _tmp_24_type 1184
+-#define _loop0_26_type 1185
+-#define _gather_25_type 1186
+-#define _loop0_28_type 1187
+-#define _gather_27_type 1188
+-#define _tmp_29_type 1189
+-#define _tmp_30_type 1190
+-#define _loop0_31_type 1191
+-#define _loop1_32_type 1192
+-#define _loop0_34_type 1193
+-#define _gather_33_type 1194
+-#define _tmp_35_type 1195
+-#define _loop0_37_type 1196
+-#define _gather_36_type 1197
+-#define _tmp_38_type 1198
+-#define _loop0_40_type 1199
+-#define _gather_39_type 1200
+-#define _loop0_42_type 1201
+-#define _gather_41_type 1202
+-#define _loop0_44_type 1203
+-#define _gather_43_type 1204
+-#define _loop0_46_type 1205
+-#define _gather_45_type 1206
+-#define _tmp_47_type 1207
+-#define _loop1_48_type 1208
+-#define _tmp_49_type 1209
+-#define _tmp_50_type 1210
+-#define _tmp_51_type 1211
+-#define _tmp_52_type 1212
+-#define _tmp_53_type 1213
+-#define _loop0_54_type 1214
+-#define _loop0_55_type 1215
+-#define _loop0_56_type 1216
+-#define _loop1_57_type 1217
+-#define _loop0_58_type 1218
+-#define _loop1_59_type 1219
+-#define _loop1_60_type 1220
+-#define _loop1_61_type 1221
+-#define _loop0_62_type 1222
+-#define _loop1_63_type 1223
+-#define _loop0_64_type 1224
+-#define _loop1_65_type 1225
+-#define _loop0_66_type 1226
+-#define _loop1_67_type 1227
+-#define _loop1_68_type 1228
+-#define _tmp_69_type 1229
+-#define _loop1_70_type 1230
+-#define _loop0_72_type 1231
+-#define _gather_71_type 1232
+-#define _loop1_73_type 1233
+-#define _loop0_74_type 1234
+-#define _loop0_75_type 1235
+-#define _loop0_76_type 1236
+-#define _loop1_77_type 1237
+-#define _loop0_78_type 1238
+-#define _loop1_79_type 1239
+-#define _loop1_80_type 1240
+-#define _loop1_81_type 1241
+-#define _loop0_82_type 1242
+-#define _loop1_83_type 1243
+-#define _loop0_84_type 1244
+-#define _loop1_85_type 1245
+-#define _loop0_86_type 1246
+-#define _loop1_87_type 1247
+-#define _loop1_88_type 1248
+-#define _loop1_89_type 1249
+-#define _loop1_90_type 1250
+-#define _tmp_91_type 1251
+-#define _loop0_93_type 1252
+-#define _gather_92_type 1253
+-#define _tmp_94_type 1254
+-#define _tmp_95_type 1255
+-#define _tmp_96_type 1256
+-#define _tmp_97_type 1257
+-#define _loop1_98_type 1258
+-#define _tmp_99_type 1259
+-#define _tmp_100_type 1260
+-#define _loop0_102_type 1261
+-#define _gather_101_type 1262
+-#define _loop1_103_type 1263
+-#define _loop0_104_type 1264
+-#define _loop0_105_type 1265
+-#define _loop0_107_type 1266
+-#define _gather_106_type 1267
+-#define _tmp_108_type 1268
+-#define _loop0_110_type 1269
+-#define _gather_109_type 1270
+-#define _loop0_112_type 1271
+-#define _gather_111_type 1272
+-#define _loop0_114_type 1273
+-#define _gather_113_type 1274
+-#define _loop0_116_type 1275
+-#define _gather_115_type 1276
+-#define _loop0_117_type 1277
+-#define _loop0_119_type 1278
+-#define _gather_118_type 1279
+-#define _tmp_120_type 1280
+-#define _loop0_122_type 1281
+-#define _gather_121_type 1282
+-#define _loop0_124_type 1283
+-#define _gather_123_type 1284
+-#define _tmp_125_type 1285
+-#define _loop0_126_type 1286
+-#define _loop0_127_type 1287
+-#define _loop0_128_type 1288
+-#define _tmp_129_type 1289
+-#define _tmp_130_type 1290
+-#define _loop0_131_type 1291
+-#define _tmp_132_type 1292
+-#define _loop0_133_type 1293
+-#define _tmp_134_type 1294
+-#define _tmp_135_type 1295
+-#define _tmp_136_type 1296
+-#define _tmp_137_type 1297
+-#define _tmp_138_type 1298
+-#define _tmp_139_type 1299
+-#define _tmp_140_type 1300
+-#define _tmp_141_type 1301
+-#define _tmp_142_type 1302
+-#define _tmp_143_type 1303
+-#define _tmp_144_type 1304
+-#define _tmp_145_type 1305
+-#define _tmp_146_type 1306
+-#define _tmp_147_type 1307
+-#define _tmp_148_type 1308
+-#define _tmp_149_type 1309
+-#define _tmp_150_type 1310
+-#define _loop1_151_type 1311
+-#define _loop1_152_type 1312
+-#define _tmp_153_type 1313
+-#define _tmp_154_type 1314
++#define star_targets_list_seq_type 1129
++#define star_targets_tuple_seq_type 1130
++#define star_target_type 1131
++#define target_with_star_atom_type 1132
++#define star_atom_type 1133
++#define single_target_type 1134
++#define single_subscript_attribute_target_type 1135
++#define del_targets_type 1136
++#define del_target_type 1137
++#define del_t_atom_type 1138
++#define targets_type 1139
++#define target_type 1140
++#define t_primary_type 1141  // Left-recursive
++#define t_lookahead_type 1142
++#define t_atom_type 1143
++#define invalid_arguments_type 1144
++#define invalid_kwarg_type 1145
++#define invalid_named_expression_type 1146
++#define invalid_assignment_type 1147
++#define invalid_ann_assign_target_type 1148
++#define invalid_del_stmt_type 1149
++#define invalid_block_type 1150
++#define invalid_primary_type 1151  // Left-recursive
++#define invalid_comprehension_type 1152
++#define invalid_dict_comprehension_type 1153
++#define invalid_parameters_type 1154
++#define invalid_lambda_parameters_type 1155
++#define invalid_star_etc_type 1156
++#define invalid_lambda_star_etc_type 1157
++#define invalid_double_type_comments_type 1158
++#define invalid_with_item_type 1159
++#define invalid_for_target_type 1160
++#define invalid_group_type 1161
++#define invalid_import_from_targets_type 1162
++#define _loop0_1_type 1163
++#define _loop0_2_type 1164
++#define _loop0_4_type 1165
++#define _gather_3_type 1166
++#define _loop0_6_type 1167
++#define _gather_5_type 1168
++#define _loop0_8_type 1169
++#define _gather_7_type 1170
++#define _loop0_10_type 1171
++#define _gather_9_type 1172
++#define _loop1_11_type 1173
++#define _loop0_13_type 1174
++#define _gather_12_type 1175
++#define _tmp_14_type 1176
++#define _tmp_15_type 1177
++#define _tmp_16_type 1178
++#define _tmp_17_type 1179
++#define _tmp_18_type 1180
++#define _tmp_19_type 1181
++#define _tmp_20_type 1182
++#define _tmp_21_type 1183
++#define _loop1_22_type 1184
++#define _tmp_23_type 1185
++#define _tmp_24_type 1186
++#define _loop0_26_type 1187
++#define _gather_25_type 1188
++#define _loop0_28_type 1189
++#define _gather_27_type 1190
++#define _tmp_29_type 1191
++#define _tmp_30_type 1192
++#define _loop0_31_type 1193
++#define _loop1_32_type 1194
++#define _loop0_34_type 1195
++#define _gather_33_type 1196
++#define _tmp_35_type 1197
++#define _loop0_37_type 1198
++#define _gather_36_type 1199
++#define _tmp_38_type 1200
++#define _loop0_40_type 1201
++#define _gather_39_type 1202
++#define _loop0_42_type 1203
++#define _gather_41_type 1204
++#define _loop0_44_type 1205
++#define _gather_43_type 1206
++#define _loop0_46_type 1207
++#define _gather_45_type 1208
++#define _tmp_47_type 1209
++#define _loop1_48_type 1210
++#define _tmp_49_type 1211
++#define _tmp_50_type 1212
++#define _tmp_51_type 1213
++#define _tmp_52_type 1214
++#define _tmp_53_type 1215
++#define _loop0_54_type 1216
++#define _loop0_55_type 1217
++#define _loop0_56_type 1218
++#define _loop1_57_type 1219
++#define _loop0_58_type 1220
++#define _loop1_59_type 1221
++#define _loop1_60_type 1222
++#define _loop1_61_type 1223
++#define _loop0_62_type 1224
++#define _loop1_63_type 1225
++#define _loop0_64_type 1226
++#define _loop1_65_type 1227
++#define _loop0_66_type 1228
++#define _loop1_67_type 1229
++#define _loop1_68_type 1230
++#define _tmp_69_type 1231
++#define _loop1_70_type 1232
++#define _loop0_72_type 1233
++#define _gather_71_type 1234
++#define _loop1_73_type 1235
++#define _loop0_74_type 1236
++#define _loop0_75_type 1237
++#define _loop0_76_type 1238
++#define _loop1_77_type 1239
++#define _loop0_78_type 1240
++#define _loop1_79_type 1241
++#define _loop1_80_type 1242
++#define _loop1_81_type 1243
++#define _loop0_82_type 1244
++#define _loop1_83_type 1245
++#define _loop0_84_type 1246
++#define _loop1_85_type 1247
++#define _loop0_86_type 1248
++#define _loop1_87_type 1249
++#define _loop1_88_type 1250
++#define _loop1_89_type 1251
++#define _loop1_90_type 1252
++#define _tmp_91_type 1253
++#define _loop0_93_type 1254
++#define _gather_92_type 1255
++#define _tmp_94_type 1256
++#define _tmp_95_type 1257
++#define _tmp_96_type 1258
++#define _tmp_97_type 1259
++#define _loop1_98_type 1260
++#define _tmp_99_type 1261
++#define _tmp_100_type 1262
++#define _loop0_102_type 1263
++#define _gather_101_type 1264
++#define _loop1_103_type 1265
++#define _loop0_104_type 1266
++#define _loop0_105_type 1267
++#define _loop0_107_type 1268
++#define _gather_106_type 1269
++#define _tmp_108_type 1270
++#define _loop0_110_type 1271
++#define _gather_109_type 1272
++#define _loop0_112_type 1273
++#define _gather_111_type 1274
++#define _loop0_114_type 1275
++#define _gather_113_type 1276
++#define _loop0_116_type 1277
++#define _gather_115_type 1278
++#define _loop0_117_type 1279
++#define _loop0_119_type 1280
++#define _gather_118_type 1281
++#define _loop1_120_type 1282
++#define _tmp_121_type 1283
++#define _loop0_123_type 1284
++#define _gather_122_type 1285
++#define _loop0_125_type 1286
++#define _gather_124_type 1287
++#define _tmp_126_type 1288
++#define _loop0_127_type 1289
++#define _loop0_128_type 1290
++#define _loop0_129_type 1291
++#define _tmp_130_type 1292
++#define _tmp_131_type 1293
++#define _loop0_132_type 1294
++#define _tmp_133_type 1295
++#define _loop0_134_type 1296
++#define _tmp_135_type 1297
++#define _tmp_136_type 1298
++#define _tmp_137_type 1299
++#define _tmp_138_type 1300
++#define _tmp_139_type 1301
++#define _tmp_140_type 1302
++#define _tmp_141_type 1303
++#define _tmp_142_type 1304
++#define _tmp_143_type 1305
++#define _tmp_144_type 1306
++#define _tmp_145_type 1307
++#define _tmp_146_type 1308
++#define _tmp_147_type 1309
++#define _tmp_148_type 1310
++#define _tmp_149_type 1311
++#define _tmp_150_type 1312
++#define _tmp_151_type 1313
++#define _tmp_152_type 1314
++#define _loop1_153_type 1315
++#define _loop1_154_type 1316
++#define _tmp_155_type 1317
++#define _tmp_156_type 1318
+ static mod_ty file_rule(Parser *p);
+ static mod_ty interactive_rule(Parser *p);
+@@ -520,8 +524,10 @@ static expr_ty starred_expression_rule(Parser *p);
+ static KeywordOrStarred* kwarg_or_starred_rule(Parser *p);
+ static KeywordOrStarred* kwarg_or_double_starred_rule(Parser *p);
+ static expr_ty star_targets_rule(Parser *p);
+-static asdl_seq* star_targets_seq_rule(Parser *p);
++static asdl_seq* star_targets_list_seq_rule(Parser *p);
++static asdl_seq* star_targets_tuple_seq_rule(Parser *p);
+ static expr_ty star_target_rule(Parser *p);
++static expr_ty target_with_star_atom_rule(Parser *p);
+ static expr_ty star_atom_rule(Parser *p);
+ static expr_ty single_target_rule(Parser *p);
+ static expr_ty single_subscript_attribute_target_rule(Parser *p);
+@@ -671,21 +677,21 @@ static asdl_seq *_gather_115_rule(Parser *p);
+ static asdl_seq *_loop0_117_rule(Parser *p);
+ static asdl_seq *_loop0_119_rule(Parser *p);
+ static asdl_seq *_gather_118_rule(Parser *p);
+-static void *_tmp_120_rule(Parser *p);
+-static asdl_seq *_loop0_122_rule(Parser *p);
+-static asdl_seq *_gather_121_rule(Parser *p);
+-static asdl_seq *_loop0_124_rule(Parser *p);
+-static asdl_seq *_gather_123_rule(Parser *p);
+-static void *_tmp_125_rule(Parser *p);
+-static asdl_seq *_loop0_126_rule(Parser *p);
++static asdl_seq *_loop1_120_rule(Parser *p);
++static void *_tmp_121_rule(Parser *p);
++static asdl_seq *_loop0_123_rule(Parser *p);
++static asdl_seq *_gather_122_rule(Parser *p);
++static asdl_seq *_loop0_125_rule(Parser *p);
++static asdl_seq *_gather_124_rule(Parser *p);
++static void *_tmp_126_rule(Parser *p);
+ static asdl_seq *_loop0_127_rule(Parser *p);
+ static asdl_seq *_loop0_128_rule(Parser *p);
+-static void *_tmp_129_rule(Parser *p);
++static asdl_seq *_loop0_129_rule(Parser *p);
+ static void *_tmp_130_rule(Parser *p);
+-static asdl_seq *_loop0_131_rule(Parser *p);
+-static void *_tmp_132_rule(Parser *p);
+-static asdl_seq *_loop0_133_rule(Parser *p);
+-static void *_tmp_134_rule(Parser *p);
++static void *_tmp_131_rule(Parser *p);
++static asdl_seq *_loop0_132_rule(Parser *p);
++static void *_tmp_133_rule(Parser *p);
++static asdl_seq *_loop0_134_rule(Parser *p);
+ static void *_tmp_135_rule(Parser *p);
+ static void *_tmp_136_rule(Parser *p);
+ static void *_tmp_137_rule(Parser *p);
+@@ -702,10 +708,12 @@ static void *_tmp_147_rule(Parser *p);
+ static void *_tmp_148_rule(Parser *p);
+ static void *_tmp_149_rule(Parser *p);
+ static void *_tmp_150_rule(Parser *p);
+-static asdl_seq *_loop1_151_rule(Parser *p);
+-static asdl_seq *_loop1_152_rule(Parser *p);
+-static void *_tmp_153_rule(Parser *p);
+-static void *_tmp_154_rule(Parser *p);
++static void *_tmp_151_rule(Parser *p);
++static void *_tmp_152_rule(Parser *p);
++static asdl_seq *_loop1_153_rule(Parser *p);
++static asdl_seq *_loop1_154_rule(Parser *p);
++static void *_tmp_155_rule(Parser *p);
++static void *_tmp_156_rule(Parser *p);
+ // file: statements? $
+@@ -12791,9 +12799,9 @@ star_targets_rule(Parser *p)
+     return _res;
+ }
+-// star_targets_seq: ','.star_target+ ','?
++// star_targets_list_seq: ','.star_target+ ','?
+ static asdl_seq*
+-star_targets_seq_rule(Parser *p)
++star_targets_list_seq_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -12807,7 +12815,7 @@ star_targets_seq_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> star_targets_seq[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.star_target+ ','?"));
++        D(fprintf(stderr, "%*c> star_targets_list_seq[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "','.star_target+ ','?"));
+         void *_opt_var;
+         UNUSED(_opt_var); // Silence compiler warnings
+         asdl_seq * a;
+@@ -12817,7 +12825,7 @@ star_targets_seq_rule(Parser *p)
+             (_opt_var = _PyPegen_expect_token(p, 12), 1)  // ','?
+         )
+         {
+-            D(fprintf(stderr, "%*c+ star_targets_seq[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.star_target+ ','?"));
++            D(fprintf(stderr, "%*c+ star_targets_list_seq[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "','.star_target+ ','?"));
+             _res = a;
+             if (_res == NULL && PyErr_Occurred()) {
+                 p->error_indicator = 1;
+@@ -12827,7 +12835,7 @@ star_targets_seq_rule(Parser *p)
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s star_targets_seq[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s star_targets_list_seq[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "','.star_target+ ','?"));
+     }
+     _res = NULL;
+@@ -12836,11 +12844,82 @@ star_targets_seq_rule(Parser *p)
+     return _res;
+ }
+-// star_target:
+-//     | '*' (!'*' star_target)
+-//     | t_primary '.' NAME !t_lookahead
+-//     | t_primary '[' slices ']' !t_lookahead
+-//     | star_atom
++// star_targets_tuple_seq: star_target ((',' star_target))+ ','? | star_target ','
++static asdl_seq*
++star_targets_tuple_seq_rule(Parser *p)
++{
++    D(p->level++);
++    if (p->error_indicator) {
++        D(p->level--);
++        return NULL;
++    }
++    asdl_seq* _res = NULL;
++    int _mark = p->mark;
++    { // star_target ((',' star_target))+ ','?
++        if (p->error_indicator) {
++            D(p->level--);
++            return NULL;
++        }
++        D(fprintf(stderr, "%*c> star_targets_tuple_seq[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target ((',' star_target))+ ','?"));
++        void *_opt_var;
++        UNUSED(_opt_var); // Silence compiler warnings
++        expr_ty a;
++        asdl_seq * b;
++        if (
++            (a = star_target_rule(p))  // star_target
++            &&
++            (b = _loop1_120_rule(p))  // ((',' star_target))+
++            &&
++            (_opt_var = _PyPegen_expect_token(p, 12), 1)  // ','?
++        )
++        {
++            D(fprintf(stderr, "%*c+ star_targets_tuple_seq[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target ((',' star_target))+ ','?"));
++            _res = _PyPegen_seq_insert_in_front ( p , a , b );
++            if (_res == NULL && PyErr_Occurred()) {
++                p->error_indicator = 1;
++                D(p->level--);
++                return NULL;
++            }
++            goto done;
++        }
++        p->mark = _mark;
++        D(fprintf(stderr, "%*c%s star_targets_tuple_seq[%d-%d]: %s failed!\n", p->level, ' ',
++                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_target ((',' star_target))+ ','?"));
++    }
++    { // star_target ','
++        if (p->error_indicator) {
++            D(p->level--);
++            return NULL;
++        }
++        D(fprintf(stderr, "%*c> star_targets_tuple_seq[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_target ','"));
++        Token * _literal;
++        expr_ty a;
++        if (
++            (a = star_target_rule(p))  // star_target
++            &&
++            (_literal = _PyPegen_expect_token(p, 12))  // token=','
++        )
++        {
++            D(fprintf(stderr, "%*c+ star_targets_tuple_seq[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_target ','"));
++            _res = _PyPegen_singleton_seq ( p , a );
++            if (_res == NULL && PyErr_Occurred()) {
++                p->error_indicator = 1;
++                D(p->level--);
++                return NULL;
++            }
++            goto done;
++        }
++        p->mark = _mark;
++        D(fprintf(stderr, "%*c%s star_targets_tuple_seq[%d-%d]: %s failed!\n", p->level, ' ',
++                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_target ','"));
++    }
++    _res = NULL;
++  done:
++    D(p->level--);
++    return _res;
++}
++
++// star_target: '*' (!'*' star_target) | target_with_star_atom
+ static expr_ty
+ star_target_rule(Parser *p)
+ {
+@@ -12875,7 +12954,7 @@ star_target_rule(Parser *p)
+         if (
+             (_literal = _PyPegen_expect_token(p, 16))  // token='*'
+             &&
+-            (a = _tmp_120_rule(p))  // !'*' star_target
++            (a = _tmp_121_rule(p))  // !'*' star_target
+         )
+         {
+             D(fprintf(stderr, "%*c+ star_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (!'*' star_target)"));
+@@ -12900,12 +12979,65 @@ star_target_rule(Parser *p)
+         D(fprintf(stderr, "%*c%s star_target[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'*' (!'*' star_target)"));
+     }
++    { // target_with_star_atom
++        if (p->error_indicator) {
++            D(p->level--);
++            return NULL;
++        }
++        D(fprintf(stderr, "%*c> star_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "target_with_star_atom"));
++        expr_ty target_with_star_atom_var;
++        if (
++            (target_with_star_atom_var = target_with_star_atom_rule(p))  // target_with_star_atom
++        )
++        {
++            D(fprintf(stderr, "%*c+ star_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "target_with_star_atom"));
++            _res = target_with_star_atom_var;
++            goto done;
++        }
++        p->mark = _mark;
++        D(fprintf(stderr, "%*c%s star_target[%d-%d]: %s failed!\n", p->level, ' ',
++                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "target_with_star_atom"));
++    }
++    _res = NULL;
++  done:
++    _PyPegen_insert_memo(p, _mark, star_target_type, _res);
++    D(p->level--);
++    return _res;
++}
++
++// target_with_star_atom:
++//     | t_primary '.' NAME !t_lookahead
++//     | t_primary '[' slices ']' !t_lookahead
++//     | star_atom
++static expr_ty
++target_with_star_atom_rule(Parser *p)
++{
++    D(p->level++);
++    if (p->error_indicator) {
++        D(p->level--);
++        return NULL;
++    }
++    expr_ty _res = NULL;
++    if (_PyPegen_is_memoized(p, target_with_star_atom_type, &_res)) {
++        D(p->level--);
++        return _res;
++    }
++    int _mark = p->mark;
++    if (p->mark == p->fill && _PyPegen_fill_token(p) < 0) {
++        p->error_indicator = 1;
++        D(p->level--);
++        return NULL;
++    }
++    int _start_lineno = p->tokens[_mark]->lineno;
++    UNUSED(_start_lineno); // Only used by EXTRA macro
++    int _start_col_offset = p->tokens[_mark]->col_offset;
++    UNUSED(_start_col_offset); // Only used by EXTRA macro
+     { // t_primary '.' NAME !t_lookahead
+         if (p->error_indicator) {
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> star_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead"));
++        D(fprintf(stderr, "%*c> target_with_star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead"));
+         Token * _literal;
+         expr_ty a;
+         expr_ty b;
+@@ -12919,7 +13051,7 @@ star_target_rule(Parser *p)
+             _PyPegen_lookahead(0, t_lookahead_rule, p)
+         )
+         {
+-            D(fprintf(stderr, "%*c+ star_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead"));
++            D(fprintf(stderr, "%*c+ target_with_star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '.' NAME !t_lookahead"));
+             Token *_token = _PyPegen_get_last_nonnwhitespace_token(p);
+             if (_token == NULL) {
+                 D(p->level--);
+@@ -12938,7 +13070,7 @@ star_target_rule(Parser *p)
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s star_target[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s target_with_star_atom[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "t_primary '.' NAME !t_lookahead"));
+     }
+     { // t_primary '[' slices ']' !t_lookahead
+@@ -12946,7 +13078,7 @@ star_target_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> star_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead"));
++        D(fprintf(stderr, "%*c> target_with_star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead"));
+         Token * _literal;
+         Token * _literal_1;
+         expr_ty a;
+@@ -12963,7 +13095,7 @@ star_target_rule(Parser *p)
+             _PyPegen_lookahead(0, t_lookahead_rule, p)
+         )
+         {
+-            D(fprintf(stderr, "%*c+ star_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead"));
++            D(fprintf(stderr, "%*c+ target_with_star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "t_primary '[' slices ']' !t_lookahead"));
+             Token *_token = _PyPegen_get_last_nonnwhitespace_token(p);
+             if (_token == NULL) {
+                 D(p->level--);
+@@ -12982,7 +13114,7 @@ star_target_rule(Parser *p)
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s star_target[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s target_with_star_atom[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "t_primary '[' slices ']' !t_lookahead"));
+     }
+     { // star_atom
+@@ -12990,32 +13122,32 @@ star_target_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> star_target[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_atom"));
++        D(fprintf(stderr, "%*c> target_with_star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_atom"));
+         expr_ty star_atom_var;
+         if (
+             (star_atom_var = star_atom_rule(p))  // star_atom
+         )
+         {
+-            D(fprintf(stderr, "%*c+ star_target[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_atom"));
++            D(fprintf(stderr, "%*c+ target_with_star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_atom"));
+             _res = star_atom_var;
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s star_target[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s target_with_star_atom[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_atom"));
+     }
+     _res = NULL;
+   done:
+-    _PyPegen_insert_memo(p, _mark, star_target_type, _res);
++    _PyPegen_insert_memo(p, _mark, target_with_star_atom_type, _res);
+     D(p->level--);
+     return _res;
+ }
+ // star_atom:
+ //     | NAME
+-//     | '(' star_target ')'
+-//     | '(' star_targets_seq? ')'
+-//     | '[' star_targets_seq? ']'
++//     | '(' target_with_star_atom ')'
++//     | '(' star_targets_tuple_seq? ')'
++//     | '[' star_targets_list_seq? ']'
+ static expr_ty
+ star_atom_rule(Parser *p)
+ {
+@@ -13059,24 +13191,24 @@ star_atom_rule(Parser *p)
+         D(fprintf(stderr, "%*c%s star_atom[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "NAME"));
+     }
+-    { // '(' star_target ')'
++    { // '(' target_with_star_atom ')'
+         if (p->error_indicator) {
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' star_target ')'"));
++        D(fprintf(stderr, "%*c> star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' target_with_star_atom ')'"));
+         Token * _literal;
+         Token * _literal_1;
+         expr_ty a;
+         if (
+             (_literal = _PyPegen_expect_token(p, 7))  // token='('
+             &&
+-            (a = star_target_rule(p))  // star_target
++            (a = target_with_star_atom_rule(p))  // target_with_star_atom
+             &&
+             (_literal_1 = _PyPegen_expect_token(p, 8))  // token=')'
+         )
+         {
+-            D(fprintf(stderr, "%*c+ star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' star_target ')'"));
++            D(fprintf(stderr, "%*c+ star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' target_with_star_atom ')'"));
+             _res = _PyPegen_set_expr_context ( p , a , Store );
+             if (_res == NULL && PyErr_Occurred()) {
+                 p->error_indicator = 1;
+@@ -13087,26 +13219,26 @@ star_atom_rule(Parser *p)
+         }
+         p->mark = _mark;
+         D(fprintf(stderr, "%*c%s star_atom[%d-%d]: %s failed!\n", p->level, ' ',
+-                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' star_target ')'"));
++                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' target_with_star_atom ')'"));
+     }
+-    { // '(' star_targets_seq? ')'
++    { // '(' star_targets_tuple_seq? ')'
+         if (p->error_indicator) {
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' star_targets_seq? ')'"));
++        D(fprintf(stderr, "%*c> star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'(' star_targets_tuple_seq? ')'"));
+         Token * _literal;
+         Token * _literal_1;
+         void *a;
+         if (
+             (_literal = _PyPegen_expect_token(p, 7))  // token='('
+             &&
+-            (a = star_targets_seq_rule(p), 1)  // star_targets_seq?
++            (a = star_targets_tuple_seq_rule(p), 1)  // star_targets_tuple_seq?
+             &&
+             (_literal_1 = _PyPegen_expect_token(p, 8))  // token=')'
+         )
+         {
+-            D(fprintf(stderr, "%*c+ star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' star_targets_seq? ')'"));
++            D(fprintf(stderr, "%*c+ star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'(' star_targets_tuple_seq? ')'"));
+             Token *_token = _PyPegen_get_last_nonnwhitespace_token(p);
+             if (_token == NULL) {
+                 D(p->level--);
+@@ -13126,26 +13258,26 @@ star_atom_rule(Parser *p)
+         }
+         p->mark = _mark;
+         D(fprintf(stderr, "%*c%s star_atom[%d-%d]: %s failed!\n", p->level, ' ',
+-                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' star_targets_seq? ')'"));
++                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'(' star_targets_tuple_seq? ')'"));
+     }
+-    { // '[' star_targets_seq? ']'
++    { // '[' star_targets_list_seq? ']'
+         if (p->error_indicator) {
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'[' star_targets_seq? ']'"));
++        D(fprintf(stderr, "%*c> star_atom[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'[' star_targets_list_seq? ']'"));
+         Token * _literal;
+         Token * _literal_1;
+         void *a;
+         if (
+             (_literal = _PyPegen_expect_token(p, 9))  // token='['
+             &&
+-            (a = star_targets_seq_rule(p), 1)  // star_targets_seq?
++            (a = star_targets_list_seq_rule(p), 1)  // star_targets_list_seq?
+             &&
+             (_literal_1 = _PyPegen_expect_token(p, 10))  // token=']'
+         )
+         {
+-            D(fprintf(stderr, "%*c+ star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' star_targets_seq? ']'"));
++            D(fprintf(stderr, "%*c+ star_atom[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'[' star_targets_list_seq? ']'"));
+             Token *_token = _PyPegen_get_last_nonnwhitespace_token(p);
+             if (_token == NULL) {
+                 D(p->level--);
+@@ -13165,7 +13297,7 @@ star_atom_rule(Parser *p)
+         }
+         p->mark = _mark;
+         D(fprintf(stderr, "%*c%s star_atom[%d-%d]: %s failed!\n", p->level, ' ',
+-                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'[' star_targets_seq? ']'"));
++                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'[' star_targets_list_seq? ']'"));
+     }
+     _res = NULL;
+   done:
+@@ -13397,7 +13529,7 @@ del_targets_rule(Parser *p)
+         UNUSED(_opt_var); // Silence compiler warnings
+         asdl_seq * a;
+         if (
+-            (a = _gather_121_rule(p))  // ','.del_target+
++            (a = _gather_122_rule(p))  // ','.del_target+
+             &&
+             (_opt_var = _PyPegen_expect_token(p, 12), 1)  // ','?
+         )
+@@ -13738,7 +13870,7 @@ targets_rule(Parser *p)
+         UNUSED(_opt_var); // Silence compiler warnings
+         asdl_seq * a;
+         if (
+-            (a = _gather_123_rule(p))  // ','.target+
++            (a = _gather_124_rule(p))  // ','.target+
+             &&
+             (_opt_var = _PyPegen_expect_token(p, 12), 1)  // ','?
+         )
+@@ -14452,7 +14584,7 @@ invalid_arguments_rule(Parser *p)
+             &&
+             (_literal = _PyPegen_expect_token(p, 12))  // token=','
+             &&
+-            (_opt_var = _tmp_125_rule(p), 1)  // [args | expression for_if_clauses]
++            (_opt_var = _tmp_126_rule(p), 1)  // [args | expression for_if_clauses]
+         )
+         {
+             D(fprintf(stderr, "%*c+ invalid_arguments[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses ',' [args | expression for_if_clauses]"));
+@@ -14710,7 +14842,7 @@ invalid_assignment_rule(Parser *p)
+         D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expression ',' star_named_expressions* ':' expression"));
+         Token * _literal;
+         Token * _literal_1;
+-        asdl_seq * _loop0_126_var;
++        asdl_seq * _loop0_127_var;
+         expr_ty a;
+         expr_ty expression_var;
+         if (
+@@ -14718,7 +14850,7 @@ invalid_assignment_rule(Parser *p)
+             &&
+             (_literal = _PyPegen_expect_token(p, 12))  // token=','
+             &&
+-            (_loop0_126_var = _loop0_126_rule(p))  // star_named_expressions*
++            (_loop0_127_var = _loop0_127_rule(p))  // star_named_expressions*
+             &&
+             (_literal_1 = _PyPegen_expect_token(p, 11))  // token=':'
+             &&
+@@ -14775,10 +14907,10 @@ invalid_assignment_rule(Parser *p)
+         }
+         D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* star_expressions '='"));
+         Token * _literal;
+-        asdl_seq * _loop0_127_var;
++        asdl_seq * _loop0_128_var;
+         expr_ty a;
+         if (
+-            (_loop0_127_var = _loop0_127_rule(p))  // ((star_targets '='))*
++            (_loop0_128_var = _loop0_128_rule(p))  // ((star_targets '='))*
+             &&
+             (a = star_expressions_rule(p))  // star_expressions
+             &&
+@@ -14805,10 +14937,10 @@ invalid_assignment_rule(Parser *p)
+         }
+         D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "((star_targets '='))* yield_expr '='"));
+         Token * _literal;
+-        asdl_seq * _loop0_128_var;
++        asdl_seq * _loop0_129_var;
+         expr_ty a;
+         if (
+-            (_loop0_128_var = _loop0_128_rule(p))  // ((star_targets '='))*
++            (_loop0_129_var = _loop0_129_rule(p))  // ((star_targets '='))*
+             &&
+             (a = yield_expr_rule(p))  // yield_expr
+             &&
+@@ -14834,7 +14966,7 @@ invalid_assignment_rule(Parser *p)
+             return NULL;
+         }
+         D(fprintf(stderr, "%*c> invalid_assignment[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions augassign (yield_expr | star_expressions)"));
+-        void *_tmp_129_var;
++        void *_tmp_130_var;
+         expr_ty a;
+         AugOperator* augassign_var;
+         if (
+@@ -14842,7 +14974,7 @@ invalid_assignment_rule(Parser *p)
+             &&
+             (augassign_var = augassign_rule(p))  // augassign
+             &&
+-            (_tmp_129_var = _tmp_129_rule(p))  // yield_expr | star_expressions
++            (_tmp_130_var = _tmp_130_rule(p))  // yield_expr | star_expressions
+         )
+         {
+             D(fprintf(stderr, "%*c+ invalid_assignment[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions augassign (yield_expr | star_expressions)"));
+@@ -15098,11 +15230,11 @@ invalid_comprehension_rule(Parser *p)
+             return NULL;
+         }
+         D(fprintf(stderr, "%*c> invalid_comprehension[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('[' | '(' | '{') starred_expression for_if_clauses"));
+-        void *_tmp_130_var;
++        void *_tmp_131_var;
+         expr_ty a;
+         asdl_seq* for_if_clauses_var;
+         if (
+-            (_tmp_130_var = _tmp_130_rule(p))  // '[' | '(' | '{'
++            (_tmp_131_var = _tmp_131_rule(p))  // '[' | '(' | '{'
+             &&
+             (a = starred_expression_rule(p))  // starred_expression
+             &&
+@@ -15199,13 +15331,13 @@ invalid_parameters_rule(Parser *p)
+             return NULL;
+         }
+         D(fprintf(stderr, "%*c> invalid_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default* (slash_with_default | param_with_default+) param_no_default"));
+-        asdl_seq * _loop0_131_var;
+-        void *_tmp_132_var;
++        asdl_seq * _loop0_132_var;
++        void *_tmp_133_var;
+         arg_ty param_no_default_var;
+         if (
+-            (_loop0_131_var = _loop0_131_rule(p))  // param_no_default*
++            (_loop0_132_var = _loop0_132_rule(p))  // param_no_default*
+             &&
+-            (_tmp_132_var = _tmp_132_rule(p))  // slash_with_default | param_with_default+
++            (_tmp_133_var = _tmp_133_rule(p))  // slash_with_default | param_with_default+
+             &&
+             (param_no_default_var = param_no_default_rule(p))  // param_no_default
+         )
+@@ -15247,13 +15379,13 @@ invalid_lambda_parameters_rule(Parser *p)
+             return NULL;
+         }
+         D(fprintf(stderr, "%*c> invalid_lambda_parameters[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default* (lambda_slash_with_default | lambda_param_with_default+) lambda_param_no_default"));
+-        asdl_seq * _loop0_133_var;
+-        void *_tmp_134_var;
++        asdl_seq * _loop0_134_var;
++        void *_tmp_135_var;
+         arg_ty lambda_param_no_default_var;
+         if (
+-            (_loop0_133_var = _loop0_133_rule(p))  // lambda_param_no_default*
++            (_loop0_134_var = _loop0_134_rule(p))  // lambda_param_no_default*
+             &&
+-            (_tmp_134_var = _tmp_134_rule(p))  // lambda_slash_with_default | lambda_param_with_default+
++            (_tmp_135_var = _tmp_135_rule(p))  // lambda_slash_with_default | lambda_param_with_default+
+             &&
+             (lambda_param_no_default_var = lambda_param_no_default_rule(p))  // lambda_param_no_default
+         )
+@@ -15295,11 +15427,11 @@ invalid_star_etc_rule(Parser *p)
+         }
+         D(fprintf(stderr, "%*c> invalid_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))"));
+         Token * _literal;
+-        void *_tmp_135_var;
++        void *_tmp_136_var;
+         if (
+             (_literal = _PyPegen_expect_token(p, 16))  // token='*'
+             &&
+-            (_tmp_135_var = _tmp_135_rule(p))  // ')' | ',' (')' | '**')
++            (_tmp_136_var = _tmp_136_rule(p))  // ')' | ',' (')' | '**')
+         )
+         {
+             D(fprintf(stderr, "%*c+ invalid_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (')' | ',' (')' | '**'))"));
+@@ -15369,11 +15501,11 @@ invalid_lambda_star_etc_rule(Parser *p)
+         }
+         D(fprintf(stderr, "%*c> invalid_lambda_star_etc[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))"));
+         Token * _literal;
+-        void *_tmp_136_var;
++        void *_tmp_137_var;
+         if (
+             (_literal = _PyPegen_expect_token(p, 16))  // token='*'
+             &&
+-            (_tmp_136_var = _tmp_136_rule(p))  // ':' | ',' (':' | '**')
++            (_tmp_137_var = _tmp_137_rule(p))  // ':' | ',' (':' | '**')
+         )
+         {
+             D(fprintf(stderr, "%*c+ invalid_lambda_star_etc[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'*' (':' | ',' (':' | '**'))"));
+@@ -16882,12 +17014,12 @@ _loop1_22_rule(Parser *p)
+             return NULL;
+         }
+         D(fprintf(stderr, "%*c> _loop1_22[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')"));
+-        void *_tmp_137_var;
++        void *_tmp_138_var;
+         while (
+-            (_tmp_137_var = _tmp_137_rule(p))  // star_targets '='
++            (_tmp_138_var = _tmp_138_rule(p))  // star_targets '='
+         )
+         {
+-            _res = _tmp_137_var;
++            _res = _tmp_138_var;
+             if (_n == _children_capacity) {
+                 _children_capacity *= 2;
+                 void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
+@@ -17390,12 +17522,12 @@ _loop0_31_rule(Parser *p)
+             return NULL;
+         }
+         D(fprintf(stderr, "%*c> _loop0_31[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')"));
+-        void *_tmp_138_var;
++        void *_tmp_139_var;
+         while (
+-            (_tmp_138_var = _tmp_138_rule(p))  // '.' | '...'
++            (_tmp_139_var = _tmp_139_rule(p))  // '.' | '...'
+         )
+         {
+-            _res = _tmp_138_var;
++            _res = _tmp_139_var;
+             if (_n == _children_capacity) {
+                 _children_capacity *= 2;
+                 void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
+@@ -17456,12 +17588,12 @@ _loop1_32_rule(Parser *p)
+             return NULL;
+         }
+         D(fprintf(stderr, "%*c> _loop1_32[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('.' | '...')"));
+-        void *_tmp_139_var;
++        void *_tmp_140_var;
+         while (
+-            (_tmp_139_var = _tmp_139_rule(p))  // '.' | '...'
++            (_tmp_140_var = _tmp_140_rule(p))  // '.' | '...'
+         )
+         {
+-            _res = _tmp_139_var;
++            _res = _tmp_140_var;
+             if (_n == _children_capacity) {
+                 _children_capacity *= 2;
+                 void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
+@@ -19618,12 +19750,12 @@ _loop1_68_rule(Parser *p)
+             return NULL;
+         }
+         D(fprintf(stderr, "%*c> _loop1_68[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('@' named_expression NEWLINE)"));
+-        void *_tmp_140_var;
++        void *_tmp_141_var;
+         while (
+-            (_tmp_140_var = _tmp_140_rule(p))  // '@' named_expression NEWLINE
++            (_tmp_141_var = _tmp_141_rule(p))  // '@' named_expression NEWLINE
+         )
+         {
+-            _res = _tmp_140_var;
++            _res = _tmp_141_var;
+             if (_n == _children_capacity) {
+                 _children_capacity *= 2;
+                 void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
+@@ -19736,12 +19868,12 @@ _loop1_70_rule(Parser *p)
+             return NULL;
+         }
+         D(fprintf(stderr, "%*c> _loop1_70[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_expression)"));
+-        void *_tmp_141_var;
++        void *_tmp_142_var;
+         while (
+-            (_tmp_141_var = _tmp_141_rule(p))  // ',' star_expression
++            (_tmp_142_var = _tmp_142_rule(p))  // ',' star_expression
+         )
+         {
+-            _res = _tmp_141_var;
++            _res = _tmp_142_var;
+             if (_n == _children_capacity) {
+                 _children_capacity *= 2;
+                 void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
+@@ -19921,12 +20053,12 @@ _loop1_73_rule(Parser *p)
+             return NULL;
+         }
+         D(fprintf(stderr, "%*c> _loop1_73[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' expression)"));
+-        void *_tmp_142_var;
++        void *_tmp_143_var;
+         while (
+-            (_tmp_142_var = _tmp_142_rule(p))  // ',' expression
++            (_tmp_143_var = _tmp_143_rule(p))  // ',' expression
+         )
+         {
+-            _res = _tmp_142_var;
++            _res = _tmp_143_var;
+             if (_n == _children_capacity) {
+                 _children_capacity *= 2;
+                 void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
+@@ -20951,12 +21083,12 @@ _loop1_88_rule(Parser *p)
+             return NULL;
+         }
+         D(fprintf(stderr, "%*c> _loop1_88[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('or' conjunction)"));
+-        void *_tmp_143_var;
++        void *_tmp_144_var;
+         while (
+-            (_tmp_143_var = _tmp_143_rule(p))  // 'or' conjunction
++            (_tmp_144_var = _tmp_144_rule(p))  // 'or' conjunction
+         )
+         {
+-            _res = _tmp_143_var;
++            _res = _tmp_144_var;
+             if (_n == _children_capacity) {
+                 _children_capacity *= 2;
+                 void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
+@@ -21022,12 +21154,12 @@ _loop1_89_rule(Parser *p)
+             return NULL;
+         }
+         D(fprintf(stderr, "%*c> _loop1_89[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('and' inversion)"));
+-        void *_tmp_144_var;
++        void *_tmp_145_var;
+         while (
+-            (_tmp_144_var = _tmp_144_rule(p))  // 'and' inversion
++            (_tmp_145_var = _tmp_145_rule(p))  // 'and' inversion
+         )
+         {
+-            _res = _tmp_144_var;
++            _res = _tmp_145_var;
+             if (_n == _children_capacity) {
+                 _children_capacity *= 2;
+                 void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
+@@ -21943,12 +22075,12 @@ _loop0_104_rule(Parser *p)
+             return NULL;
+         }
+         D(fprintf(stderr, "%*c> _loop0_104[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)"));
+-        void *_tmp_145_var;
++        void *_tmp_146_var;
+         while (
+-            (_tmp_145_var = _tmp_145_rule(p))  // 'if' disjunction
++            (_tmp_146_var = _tmp_146_rule(p))  // 'if' disjunction
+         )
+         {
+-            _res = _tmp_145_var;
++            _res = _tmp_146_var;
+             if (_n == _children_capacity) {
+                 _children_capacity *= 2;
+                 void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
+@@ -22009,12 +22141,12 @@ _loop0_105_rule(Parser *p)
+             return NULL;
+         }
+         D(fprintf(stderr, "%*c> _loop0_105[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "('if' disjunction)"));
+-        void *_tmp_146_var;
++        void *_tmp_147_var;
+         while (
+-            (_tmp_146_var = _tmp_146_rule(p))  // 'if' disjunction
++            (_tmp_147_var = _tmp_147_rule(p))  // 'if' disjunction
+         )
+         {
+-            _res = _tmp_146_var;
++            _res = _tmp_147_var;
+             if (_n == _children_capacity) {
+                 _children_capacity *= 2;
+                 void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
+@@ -22080,7 +22212,7 @@ _loop0_107_rule(Parser *p)
+         while (
+             (_literal = _PyPegen_expect_token(p, 12))  // token=','
+             &&
+-            (elem = _tmp_147_rule(p))  // starred_expression | named_expression !'='
++            (elem = _tmp_148_rule(p))  // starred_expression | named_expression !'='
+         )
+         {
+             _res = elem;
+@@ -22143,7 +22275,7 @@ _gather_106_rule(Parser *p)
+         void *elem;
+         asdl_seq * seq;
+         if (
+-            (elem = _tmp_147_rule(p))  // starred_expression | named_expression !'='
++            (elem = _tmp_148_rule(p))  // starred_expression | named_expression !'='
+             &&
+             (seq = _loop0_107_rule(p))  // _loop0_107
+         )
+@@ -22689,12 +22821,12 @@ _loop0_117_rule(Parser *p)
+             return NULL;
+         }
+         D(fprintf(stderr, "%*c> _loop0_117[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)"));
+-        void *_tmp_148_var;
++        void *_tmp_149_var;
+         while (
+-            (_tmp_148_var = _tmp_148_rule(p))  // ',' star_target
++            (_tmp_149_var = _tmp_149_rule(p))  // ',' star_target
+         )
+         {
+-            _res = _tmp_148_var;
++            _res = _tmp_149_var;
+             if (_n == _children_capacity) {
+                 _children_capacity *= 2;
+                 void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
+@@ -22842,9 +22974,80 @@ _gather_118_rule(Parser *p)
+     return _res;
+ }
+-// _tmp_120: !'*' star_target
++// _loop1_120: (',' star_target)
++static asdl_seq *
++_loop1_120_rule(Parser *p)
++{
++    D(p->level++);
++    if (p->error_indicator) {
++        D(p->level--);
++        return NULL;
++    }
++    void *_res = NULL;
++    int _mark = p->mark;
++    int _start_mark = p->mark;
++    void **_children = PyMem_Malloc(sizeof(void *));
++    if (!_children) {
++        p->error_indicator = 1;
++        PyErr_NoMemory();
++        D(p->level--);
++        return NULL;
++    }
++    ssize_t _children_capacity = 1;
++    ssize_t _n = 0;
++    { // (',' star_target)
++        if (p->error_indicator) {
++            D(p->level--);
++            return NULL;
++        }
++        D(fprintf(stderr, "%*c> _loop1_120[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(',' star_target)"));
++        void *_tmp_150_var;
++        while (
++            (_tmp_150_var = _tmp_150_rule(p))  // ',' star_target
++        )
++        {
++            _res = _tmp_150_var;
++            if (_n == _children_capacity) {
++                _children_capacity *= 2;
++                void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
++                if (!_new_children) {
++                    p->error_indicator = 1;
++                    PyErr_NoMemory();
++                    D(p->level--);
++                    return NULL;
++                }
++                _children = _new_children;
++            }
++            _children[_n++] = _res;
++            _mark = p->mark;
++        }
++        p->mark = _mark;
++        D(fprintf(stderr, "%*c%s _loop1_120[%d-%d]: %s failed!\n", p->level, ' ',
++                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(',' star_target)"));
++    }
++    if (_n == 0 || p->error_indicator) {
++        PyMem_Free(_children);
++        D(p->level--);
++        return NULL;
++    }
++    asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
++    if (!_seq) {
++        PyMem_Free(_children);
++        p->error_indicator = 1;
++        PyErr_NoMemory();
++        D(p->level--);
++        return NULL;
++    }
++    for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
++    PyMem_Free(_children);
++    _PyPegen_insert_memo(p, _start_mark, _loop1_120_type, _seq);
++    D(p->level--);
++    return _seq;
++}
++
++// _tmp_121: !'*' star_target
+ static void *
+-_tmp_120_rule(Parser *p)
++_tmp_121_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -22858,7 +23061,7 @@ _tmp_120_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_120[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!'*' star_target"));
++        D(fprintf(stderr, "%*c> _tmp_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "!'*' star_target"));
+         expr_ty star_target_var;
+         if (
+             _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 16)  // token='*'
+@@ -22866,12 +23069,12 @@ _tmp_120_rule(Parser *p)
+             (star_target_var = star_target_rule(p))  // star_target
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_120[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!'*' star_target"));
++            D(fprintf(stderr, "%*c+ _tmp_121[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "!'*' star_target"));
+             _res = star_target_var;
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_120[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_121[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "!'*' star_target"));
+     }
+     _res = NULL;
+@@ -22880,9 +23083,9 @@ _tmp_120_rule(Parser *p)
+     return _res;
+ }
+-// _loop0_122: ',' del_target
++// _loop0_123: ',' del_target
+ static asdl_seq *
+-_loop0_122_rule(Parser *p)
++_loop0_123_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -22906,7 +23109,7 @@ _loop0_122_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _loop0_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' del_target"));
++        D(fprintf(stderr, "%*c> _loop0_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' del_target"));
+         Token * _literal;
+         expr_ty elem;
+         while (
+@@ -22937,7 +23140,7 @@ _loop0_122_rule(Parser *p)
+             _mark = p->mark;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _loop0_122[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _loop0_123[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' del_target"));
+     }
+     asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
+@@ -22950,14 +23153,14 @@ _loop0_122_rule(Parser *p)
+     }
+     for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
+     PyMem_Free(_children);
+-    _PyPegen_insert_memo(p, _start_mark, _loop0_122_type, _seq);
++    _PyPegen_insert_memo(p, _start_mark, _loop0_123_type, _seq);
+     D(p->level--);
+     return _seq;
+ }
+-// _gather_121: del_target _loop0_122
++// _gather_122: del_target _loop0_123
+ static asdl_seq *
+-_gather_121_rule(Parser *p)
++_gather_122_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -22966,27 +23169,27 @@ _gather_121_rule(Parser *p)
+     }
+     asdl_seq * _res = NULL;
+     int _mark = p->mark;
+-    { // del_target _loop0_122
++    { // del_target _loop0_123
+         if (p->error_indicator) {
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _gather_121[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "del_target _loop0_122"));
++        D(fprintf(stderr, "%*c> _gather_122[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "del_target _loop0_123"));
+         expr_ty elem;
+         asdl_seq * seq;
+         if (
+             (elem = del_target_rule(p))  // del_target
+             &&
+-            (seq = _loop0_122_rule(p))  // _loop0_122
++            (seq = _loop0_123_rule(p))  // _loop0_123
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _gather_121[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "del_target _loop0_122"));
++            D(fprintf(stderr, "%*c+ _gather_122[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "del_target _loop0_123"));
+             _res = _PyPegen_seq_insert_in_front(p, elem, seq);
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _gather_121[%d-%d]: %s failed!\n", p->level, ' ',
+-                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "del_target _loop0_122"));
++        D(fprintf(stderr, "%*c%s _gather_122[%d-%d]: %s failed!\n", p->level, ' ',
++                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "del_target _loop0_123"));
+     }
+     _res = NULL;
+   done:
+@@ -22994,9 +23197,9 @@ _gather_121_rule(Parser *p)
+     return _res;
+ }
+-// _loop0_124: ',' target
++// _loop0_125: ',' target
+ static asdl_seq *
+-_loop0_124_rule(Parser *p)
++_loop0_125_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -23020,7 +23223,7 @@ _loop0_124_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _loop0_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' target"));
++        D(fprintf(stderr, "%*c> _loop0_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' target"));
+         Token * _literal;
+         expr_ty elem;
+         while (
+@@ -23051,7 +23254,7 @@ _loop0_124_rule(Parser *p)
+             _mark = p->mark;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _loop0_124[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _loop0_125[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' target"));
+     }
+     asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
+@@ -23064,14 +23267,14 @@ _loop0_124_rule(Parser *p)
+     }
+     for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
+     PyMem_Free(_children);
+-    _PyPegen_insert_memo(p, _start_mark, _loop0_124_type, _seq);
++    _PyPegen_insert_memo(p, _start_mark, _loop0_125_type, _seq);
+     D(p->level--);
+     return _seq;
+ }
+-// _gather_123: target _loop0_124
++// _gather_124: target _loop0_125
+ static asdl_seq *
+-_gather_123_rule(Parser *p)
++_gather_124_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -23080,27 +23283,27 @@ _gather_123_rule(Parser *p)
+     }
+     asdl_seq * _res = NULL;
+     int _mark = p->mark;
+-    { // target _loop0_124
++    { // target _loop0_125
+         if (p->error_indicator) {
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _gather_123[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "target _loop0_124"));
++        D(fprintf(stderr, "%*c> _gather_124[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "target _loop0_125"));
+         expr_ty elem;
+         asdl_seq * seq;
+         if (
+             (elem = target_rule(p))  // target
+             &&
+-            (seq = _loop0_124_rule(p))  // _loop0_124
++            (seq = _loop0_125_rule(p))  // _loop0_125
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _gather_123[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "target _loop0_124"));
++            D(fprintf(stderr, "%*c+ _gather_124[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "target _loop0_125"));
+             _res = _PyPegen_seq_insert_in_front(p, elem, seq);
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _gather_123[%d-%d]: %s failed!\n", p->level, ' ',
+-                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "target _loop0_124"));
++        D(fprintf(stderr, "%*c%s _gather_124[%d-%d]: %s failed!\n", p->level, ' ',
++                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "target _loop0_125"));
+     }
+     _res = NULL;
+   done:
+@@ -23108,9 +23311,9 @@ _gather_123_rule(Parser *p)
+     return _res;
+ }
+-// _tmp_125: args | expression for_if_clauses
++// _tmp_126: args | expression for_if_clauses
+ static void *
+-_tmp_125_rule(Parser *p)
++_tmp_126_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -23124,18 +23327,18 @@ _tmp_125_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args"));
++        D(fprintf(stderr, "%*c> _tmp_126[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "args"));
+         expr_ty args_var;
+         if (
+             (args_var = args_rule(p))  // args
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_125[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args"));
++            D(fprintf(stderr, "%*c+ _tmp_126[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "args"));
+             _res = args_var;
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_125[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_126[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "args"));
+     }
+     { // expression for_if_clauses
+@@ -23143,7 +23346,7 @@ _tmp_125_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_125[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses"));
++        D(fprintf(stderr, "%*c> _tmp_126[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses"));
+         expr_ty expression_var;
+         asdl_seq* for_if_clauses_var;
+         if (
+@@ -23152,12 +23355,12 @@ _tmp_125_rule(Parser *p)
+             (for_if_clauses_var = for_if_clauses_rule(p))  // for_if_clauses
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_125[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses"));
++            D(fprintf(stderr, "%*c+ _tmp_126[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "expression for_if_clauses"));
+             _res = _PyPegen_dummy_name(p, expression_var, for_if_clauses_var);
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_125[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_126[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "expression for_if_clauses"));
+     }
+     _res = NULL;
+@@ -23166,9 +23369,9 @@ _tmp_125_rule(Parser *p)
+     return _res;
+ }
+-// _loop0_126: star_named_expressions
++// _loop0_127: star_named_expressions
+ static asdl_seq *
+-_loop0_126_rule(Parser *p)
++_loop0_127_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -23192,7 +23395,7 @@ _loop0_126_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _loop0_126[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expressions"));
++        D(fprintf(stderr, "%*c> _loop0_127[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_named_expressions"));
+         asdl_seq* star_named_expressions_var;
+         while (
+             (star_named_expressions_var = star_named_expressions_rule(p))  // star_named_expressions
+@@ -23214,7 +23417,7 @@ _loop0_126_rule(Parser *p)
+             _mark = p->mark;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _loop0_126[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _loop0_127[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_named_expressions"));
+     }
+     asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
+@@ -23227,14 +23430,14 @@ _loop0_126_rule(Parser *p)
+     }
+     for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
+     PyMem_Free(_children);
+-    _PyPegen_insert_memo(p, _start_mark, _loop0_126_type, _seq);
++    _PyPegen_insert_memo(p, _start_mark, _loop0_127_type, _seq);
+     D(p->level--);
+     return _seq;
+ }
+-// _loop0_127: (star_targets '=')
++// _loop0_128: (star_targets '=')
+ static asdl_seq *
+-_loop0_127_rule(Parser *p)
++_loop0_128_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -23258,13 +23461,13 @@ _loop0_127_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _loop0_127[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')"));
+-        void *_tmp_149_var;
++        D(fprintf(stderr, "%*c> _loop0_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')"));
++        void *_tmp_151_var;
+         while (
+-            (_tmp_149_var = _tmp_149_rule(p))  // star_targets '='
++            (_tmp_151_var = _tmp_151_rule(p))  // star_targets '='
+         )
+         {
+-            _res = _tmp_149_var;
++            _res = _tmp_151_var;
+             if (_n == _children_capacity) {
+                 _children_capacity *= 2;
+                 void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
+@@ -23280,7 +23483,7 @@ _loop0_127_rule(Parser *p)
+             _mark = p->mark;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _loop0_127[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _loop0_128[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(star_targets '=')"));
+     }
+     asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
+@@ -23293,14 +23496,14 @@ _loop0_127_rule(Parser *p)
+     }
+     for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
+     PyMem_Free(_children);
+-    _PyPegen_insert_memo(p, _start_mark, _loop0_127_type, _seq);
++    _PyPegen_insert_memo(p, _start_mark, _loop0_128_type, _seq);
+     D(p->level--);
+     return _seq;
+ }
+-// _loop0_128: (star_targets '=')
++// _loop0_129: (star_targets '=')
+ static asdl_seq *
+-_loop0_128_rule(Parser *p)
++_loop0_129_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -23324,13 +23527,13 @@ _loop0_128_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _loop0_128[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')"));
+-        void *_tmp_150_var;
++        D(fprintf(stderr, "%*c> _loop0_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "(star_targets '=')"));
++        void *_tmp_152_var;
+         while (
+-            (_tmp_150_var = _tmp_150_rule(p))  // star_targets '='
++            (_tmp_152_var = _tmp_152_rule(p))  // star_targets '='
+         )
+         {
+-            _res = _tmp_150_var;
++            _res = _tmp_152_var;
+             if (_n == _children_capacity) {
+                 _children_capacity *= 2;
+                 void **_new_children = PyMem_Realloc(_children, _children_capacity*sizeof(void *));
+@@ -23346,7 +23549,7 @@ _loop0_128_rule(Parser *p)
+             _mark = p->mark;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _loop0_128[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _loop0_129[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "(star_targets '=')"));
+     }
+     asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
+@@ -23359,14 +23562,14 @@ _loop0_128_rule(Parser *p)
+     }
+     for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
+     PyMem_Free(_children);
+-    _PyPegen_insert_memo(p, _start_mark, _loop0_128_type, _seq);
++    _PyPegen_insert_memo(p, _start_mark, _loop0_129_type, _seq);
+     D(p->level--);
+     return _seq;
+ }
+-// _tmp_129: yield_expr | star_expressions
++// _tmp_130: yield_expr | star_expressions
+ static void *
+-_tmp_129_rule(Parser *p)
++_tmp_130_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -23380,18 +23583,18 @@ _tmp_129_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr"));
++        D(fprintf(stderr, "%*c> _tmp_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "yield_expr"));
+         expr_ty yield_expr_var;
+         if (
+             (yield_expr_var = yield_expr_rule(p))  // yield_expr
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_129[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr"));
++            D(fprintf(stderr, "%*c+ _tmp_130[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "yield_expr"));
+             _res = yield_expr_var;
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_129[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_130[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "yield_expr"));
+     }
+     { // star_expressions
+@@ -23399,18 +23602,18 @@ _tmp_129_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_129[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions"));
++        D(fprintf(stderr, "%*c> _tmp_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_expressions"));
+         expr_ty star_expressions_var;
+         if (
+             (star_expressions_var = star_expressions_rule(p))  // star_expressions
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_129[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions"));
++            D(fprintf(stderr, "%*c+ _tmp_130[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_expressions"));
+             _res = star_expressions_var;
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_129[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_130[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_expressions"));
+     }
+     _res = NULL;
+@@ -23419,9 +23622,9 @@ _tmp_129_rule(Parser *p)
+     return _res;
+ }
+-// _tmp_130: '[' | '(' | '{'
++// _tmp_131: '[' | '(' | '{'
+ static void *
+-_tmp_130_rule(Parser *p)
++_tmp_131_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -23435,18 +23638,18 @@ _tmp_130_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['"));
++        D(fprintf(stderr, "%*c> _tmp_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'['"));
+         Token * _literal;
+         if (
+             (_literal = _PyPegen_expect_token(p, 9))  // token='['
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_130[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['"));
++            D(fprintf(stderr, "%*c+ _tmp_131[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'['"));
+             _res = _literal;
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_130[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_131[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'['"));
+     }
+     { // '('
+@@ -23454,18 +23657,18 @@ _tmp_130_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('"));
++        D(fprintf(stderr, "%*c> _tmp_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'('"));
+         Token * _literal;
+         if (
+             (_literal = _PyPegen_expect_token(p, 7))  // token='('
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_130[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('"));
++            D(fprintf(stderr, "%*c+ _tmp_131[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'('"));
+             _res = _literal;
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_130[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_131[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'('"));
+     }
+     { // '{'
+@@ -23473,18 +23676,18 @@ _tmp_130_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_130[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'"));
++        D(fprintf(stderr, "%*c> _tmp_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'{'"));
+         Token * _literal;
+         if (
+             (_literal = _PyPegen_expect_token(p, 25))  // token='{'
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_130[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'"));
++            D(fprintf(stderr, "%*c+ _tmp_131[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'{'"));
+             _res = _literal;
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_130[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_131[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'{'"));
+     }
+     _res = NULL;
+@@ -23493,9 +23696,9 @@ _tmp_130_rule(Parser *p)
+     return _res;
+ }
+-// _loop0_131: param_no_default
++// _loop0_132: param_no_default
+ static asdl_seq *
+-_loop0_131_rule(Parser *p)
++_loop0_132_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -23519,7 +23722,7 @@ _loop0_131_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _loop0_131[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default"));
++        D(fprintf(stderr, "%*c> _loop0_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_no_default"));
+         arg_ty param_no_default_var;
+         while (
+             (param_no_default_var = param_no_default_rule(p))  // param_no_default
+@@ -23541,7 +23744,7 @@ _loop0_131_rule(Parser *p)
+             _mark = p->mark;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _loop0_131[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _loop0_132[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_no_default"));
+     }
+     asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
+@@ -23554,14 +23757,14 @@ _loop0_131_rule(Parser *p)
+     }
+     for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
+     PyMem_Free(_children);
+-    _PyPegen_insert_memo(p, _start_mark, _loop0_131_type, _seq);
++    _PyPegen_insert_memo(p, _start_mark, _loop0_132_type, _seq);
+     D(p->level--);
+     return _seq;
+ }
+-// _tmp_132: slash_with_default | param_with_default+
++// _tmp_133: slash_with_default | param_with_default+
+ static void *
+-_tmp_132_rule(Parser *p)
++_tmp_133_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -23575,18 +23778,18 @@ _tmp_132_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default"));
++        D(fprintf(stderr, "%*c> _tmp_133[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "slash_with_default"));
+         SlashWithDefault* slash_with_default_var;
+         if (
+             (slash_with_default_var = slash_with_default_rule(p))  // slash_with_default
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_132[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_with_default"));
++            D(fprintf(stderr, "%*c+ _tmp_133[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "slash_with_default"));
+             _res = slash_with_default_var;
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_132[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_133[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "slash_with_default"));
+     }
+     { // param_with_default+
+@@ -23594,18 +23797,18 @@ _tmp_132_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_132[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default+"));
+-        asdl_seq * _loop1_151_var;
++        D(fprintf(stderr, "%*c> _tmp_133[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default+"));
++        asdl_seq * _loop1_153_var;
+         if (
+-            (_loop1_151_var = _loop1_151_rule(p))  // param_with_default+
++            (_loop1_153_var = _loop1_153_rule(p))  // param_with_default+
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_132[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_with_default+"));
+-            _res = _loop1_151_var;
++            D(fprintf(stderr, "%*c+ _tmp_133[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "param_with_default+"));
++            _res = _loop1_153_var;
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_132[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_133[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default+"));
+     }
+     _res = NULL;
+@@ -23614,9 +23817,9 @@ _tmp_132_rule(Parser *p)
+     return _res;
+ }
+-// _loop0_133: lambda_param_no_default
++// _loop0_134: lambda_param_no_default
+ static asdl_seq *
+-_loop0_133_rule(Parser *p)
++_loop0_134_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -23640,7 +23843,7 @@ _loop0_133_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _loop0_133[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default"));
++        D(fprintf(stderr, "%*c> _loop0_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_no_default"));
+         arg_ty lambda_param_no_default_var;
+         while (
+             (lambda_param_no_default_var = lambda_param_no_default_rule(p))  // lambda_param_no_default
+@@ -23662,7 +23865,7 @@ _loop0_133_rule(Parser *p)
+             _mark = p->mark;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _loop0_133[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _loop0_134[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_no_default"));
+     }
+     asdl_seq *_seq = _Py_asdl_seq_new(_n, p->arena);
+@@ -23675,14 +23878,14 @@ _loop0_133_rule(Parser *p)
+     }
+     for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
+     PyMem_Free(_children);
+-    _PyPegen_insert_memo(p, _start_mark, _loop0_133_type, _seq);
++    _PyPegen_insert_memo(p, _start_mark, _loop0_134_type, _seq);
+     D(p->level--);
+     return _seq;
+ }
+-// _tmp_134: lambda_slash_with_default | lambda_param_with_default+
++// _tmp_135: lambda_slash_with_default | lambda_param_with_default+
+ static void *
+-_tmp_134_rule(Parser *p)
++_tmp_135_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -23696,18 +23899,18 @@ _tmp_134_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default"));
++        D(fprintf(stderr, "%*c> _tmp_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default"));
+         SlashWithDefault* lambda_slash_with_default_var;
+         if (
+             (lambda_slash_with_default_var = lambda_slash_with_default_rule(p))  // lambda_slash_with_default
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_134[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default"));
++            D(fprintf(stderr, "%*c+ _tmp_135[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_slash_with_default"));
+             _res = lambda_slash_with_default_var;
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_134[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_135[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_slash_with_default"));
+     }
+     { // lambda_param_with_default+
+@@ -23715,18 +23918,18 @@ _tmp_134_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_134[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+"));
+-        asdl_seq * _loop1_152_var;
++        D(fprintf(stderr, "%*c> _tmp_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+"));
++        asdl_seq * _loop1_154_var;
+         if (
+-            (_loop1_152_var = _loop1_152_rule(p))  // lambda_param_with_default+
++            (_loop1_154_var = _loop1_154_rule(p))  // lambda_param_with_default+
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_134[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+"));
+-            _res = _loop1_152_var;
++            D(fprintf(stderr, "%*c+ _tmp_135[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default+"));
++            _res = _loop1_154_var;
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_134[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_135[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default+"));
+     }
+     _res = NULL;
+@@ -23735,9 +23938,9 @@ _tmp_134_rule(Parser *p)
+     return _res;
+ }
+-// _tmp_135: ')' | ',' (')' | '**')
++// _tmp_136: ')' | ',' (')' | '**')
+ static void *
+-_tmp_135_rule(Parser *p)
++_tmp_136_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -23751,18 +23954,18 @@ _tmp_135_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'"));
++        D(fprintf(stderr, "%*c> _tmp_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'"));
+         Token * _literal;
+         if (
+             (_literal = _PyPegen_expect_token(p, 8))  // token=')'
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_135[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'"));
++            D(fprintf(stderr, "%*c+ _tmp_136[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'"));
+             _res = _literal;
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_135[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_136[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'"));
+     }
+     { // ',' (')' | '**')
+@@ -23770,21 +23973,21 @@ _tmp_135_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_135[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')"));
++        D(fprintf(stderr, "%*c> _tmp_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')"));
+         Token * _literal;
+-        void *_tmp_153_var;
++        void *_tmp_155_var;
+         if (
+             (_literal = _PyPegen_expect_token(p, 12))  // token=','
+             &&
+-            (_tmp_153_var = _tmp_153_rule(p))  // ')' | '**'
++            (_tmp_155_var = _tmp_155_rule(p))  // ')' | '**'
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_135[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')"));
+-            _res = _PyPegen_dummy_name(p, _literal, _tmp_153_var);
++            D(fprintf(stderr, "%*c+ _tmp_136[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (')' | '**')"));
++            _res = _PyPegen_dummy_name(p, _literal, _tmp_155_var);
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_135[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_136[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (')' | '**')"));
+     }
+     _res = NULL;
+@@ -23793,9 +23996,9 @@ _tmp_135_rule(Parser *p)
+     return _res;
+ }
+-// _tmp_136: ':' | ',' (':' | '**')
++// _tmp_137: ':' | ',' (':' | '**')
+ static void *
+-_tmp_136_rule(Parser *p)
++_tmp_137_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -23809,18 +24012,18 @@ _tmp_136_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'"));
++        D(fprintf(stderr, "%*c> _tmp_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'"));
+         Token * _literal;
+         if (
+             (_literal = _PyPegen_expect_token(p, 11))  // token=':'
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_136[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'"));
++            D(fprintf(stderr, "%*c+ _tmp_137[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'"));
+             _res = _literal;
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_136[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_137[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'"));
+     }
+     { // ',' (':' | '**')
+@@ -23828,21 +24031,21 @@ _tmp_136_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_136[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')"));
++        D(fprintf(stderr, "%*c> _tmp_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')"));
+         Token * _literal;
+-        void *_tmp_154_var;
++        void *_tmp_156_var;
+         if (
+             (_literal = _PyPegen_expect_token(p, 12))  // token=','
+             &&
+-            (_tmp_154_var = _tmp_154_rule(p))  // ':' | '**'
++            (_tmp_156_var = _tmp_156_rule(p))  // ':' | '**'
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_136[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')"));
+-            _res = _PyPegen_dummy_name(p, _literal, _tmp_154_var);
++            D(fprintf(stderr, "%*c+ _tmp_137[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' (':' | '**')"));
++            _res = _PyPegen_dummy_name(p, _literal, _tmp_156_var);
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_136[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_137[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' (':' | '**')"));
+     }
+     _res = NULL;
+@@ -23851,9 +24054,9 @@ _tmp_136_rule(Parser *p)
+     return _res;
+ }
+-// _tmp_137: star_targets '='
++// _tmp_138: star_targets '='
+ static void *
+-_tmp_137_rule(Parser *p)
++_tmp_138_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -23867,7 +24070,7 @@ _tmp_137_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_137[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
++        D(fprintf(stderr, "%*c> _tmp_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
+         Token * _literal;
+         expr_ty z;
+         if (
+@@ -23876,7 +24079,7 @@ _tmp_137_rule(Parser *p)
+             (_literal = _PyPegen_expect_token(p, 22))  // token='='
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_137[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
++            D(fprintf(stderr, "%*c+ _tmp_138[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
+             _res = z;
+             if (_res == NULL && PyErr_Occurred()) {
+                 p->error_indicator = 1;
+@@ -23886,7 +24089,7 @@ _tmp_137_rule(Parser *p)
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_137[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_138[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='"));
+     }
+     _res = NULL;
+@@ -23895,9 +24098,9 @@ _tmp_137_rule(Parser *p)
+     return _res;
+ }
+-// _tmp_138: '.' | '...'
++// _tmp_139: '.' | '...'
+ static void *
+-_tmp_138_rule(Parser *p)
++_tmp_139_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -23911,18 +24114,18 @@ _tmp_138_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'"));
++        D(fprintf(stderr, "%*c> _tmp_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'"));
+         Token * _literal;
+         if (
+             (_literal = _PyPegen_expect_token(p, 23))  // token='.'
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_138[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'"));
++            D(fprintf(stderr, "%*c+ _tmp_139[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'"));
+             _res = _literal;
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_138[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_139[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'"));
+     }
+     { // '...'
+@@ -23930,18 +24133,18 @@ _tmp_138_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_138[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'"));
++        D(fprintf(stderr, "%*c> _tmp_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'"));
+         Token * _literal;
+         if (
+             (_literal = _PyPegen_expect_token(p, 52))  // token='...'
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_138[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'"));
++            D(fprintf(stderr, "%*c+ _tmp_139[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'"));
+             _res = _literal;
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_138[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_139[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'"));
+     }
+     _res = NULL;
+@@ -23950,9 +24153,9 @@ _tmp_138_rule(Parser *p)
+     return _res;
+ }
+-// _tmp_139: '.' | '...'
++// _tmp_140: '.' | '...'
+ static void *
+-_tmp_139_rule(Parser *p)
++_tmp_140_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -23966,18 +24169,18 @@ _tmp_139_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'"));
++        D(fprintf(stderr, "%*c> _tmp_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'.'"));
+         Token * _literal;
+         if (
+             (_literal = _PyPegen_expect_token(p, 23))  // token='.'
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_139[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'"));
++            D(fprintf(stderr, "%*c+ _tmp_140[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'.'"));
+             _res = _literal;
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_139[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_140[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'.'"));
+     }
+     { // '...'
+@@ -23985,18 +24188,18 @@ _tmp_139_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_139[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'"));
++        D(fprintf(stderr, "%*c> _tmp_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'...'"));
+         Token * _literal;
+         if (
+             (_literal = _PyPegen_expect_token(p, 52))  // token='...'
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_139[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'"));
++            D(fprintf(stderr, "%*c+ _tmp_140[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'...'"));
+             _res = _literal;
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_139[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_140[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'...'"));
+     }
+     _res = NULL;
+@@ -24005,9 +24208,9 @@ _tmp_139_rule(Parser *p)
+     return _res;
+ }
+-// _tmp_140: '@' named_expression NEWLINE
++// _tmp_141: '@' named_expression NEWLINE
+ static void *
+-_tmp_140_rule(Parser *p)
++_tmp_141_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -24021,7 +24224,7 @@ _tmp_140_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_140[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE"));
++        D(fprintf(stderr, "%*c> _tmp_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE"));
+         Token * _literal;
+         expr_ty f;
+         Token * newline_var;
+@@ -24033,7 +24236,7 @@ _tmp_140_rule(Parser *p)
+             (newline_var = _PyPegen_expect_token(p, NEWLINE))  // token='NEWLINE'
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_140[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE"));
++            D(fprintf(stderr, "%*c+ _tmp_141[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'@' named_expression NEWLINE"));
+             _res = f;
+             if (_res == NULL && PyErr_Occurred()) {
+                 p->error_indicator = 1;
+@@ -24043,7 +24246,7 @@ _tmp_140_rule(Parser *p)
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_140[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_141[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'@' named_expression NEWLINE"));
+     }
+     _res = NULL;
+@@ -24052,9 +24255,9 @@ _tmp_140_rule(Parser *p)
+     return _res;
+ }
+-// _tmp_141: ',' star_expression
++// _tmp_142: ',' star_expression
+ static void *
+-_tmp_141_rule(Parser *p)
++_tmp_142_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -24068,7 +24271,7 @@ _tmp_141_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_141[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression"));
++        D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_expression"));
+         Token * _literal;
+         expr_ty c;
+         if (
+@@ -24077,7 +24280,7 @@ _tmp_141_rule(Parser *p)
+             (c = star_expression_rule(p))  // star_expression
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_141[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression"));
++            D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_expression"));
+             _res = c;
+             if (_res == NULL && PyErr_Occurred()) {
+                 p->error_indicator = 1;
+@@ -24087,7 +24290,7 @@ _tmp_141_rule(Parser *p)
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_141[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_expression"));
+     }
+     _res = NULL;
+@@ -24096,9 +24299,9 @@ _tmp_141_rule(Parser *p)
+     return _res;
+ }
+-// _tmp_142: ',' expression
++// _tmp_143: ',' expression
+ static void *
+-_tmp_142_rule(Parser *p)
++_tmp_143_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -24112,7 +24315,7 @@ _tmp_142_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_142[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression"));
++        D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' expression"));
+         Token * _literal;
+         expr_ty c;
+         if (
+@@ -24121,7 +24324,7 @@ _tmp_142_rule(Parser *p)
+             (c = expression_rule(p))  // expression
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_142[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression"));
++            D(fprintf(stderr, "%*c+ _tmp_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' expression"));
+             _res = c;
+             if (_res == NULL && PyErr_Occurred()) {
+                 p->error_indicator = 1;
+@@ -24131,7 +24334,7 @@ _tmp_142_rule(Parser *p)
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_142[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_143[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' expression"));
+     }
+     _res = NULL;
+@@ -24140,9 +24343,9 @@ _tmp_142_rule(Parser *p)
+     return _res;
+ }
+-// _tmp_143: 'or' conjunction
++// _tmp_144: 'or' conjunction
+ static void *
+-_tmp_143_rule(Parser *p)
++_tmp_144_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -24156,7 +24359,7 @@ _tmp_143_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_143[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction"));
++        D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'or' conjunction"));
+         Token * _keyword;
+         expr_ty c;
+         if (
+@@ -24165,7 +24368,7 @@ _tmp_143_rule(Parser *p)
+             (c = conjunction_rule(p))  // conjunction
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_143[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction"));
++            D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'or' conjunction"));
+             _res = c;
+             if (_res == NULL && PyErr_Occurred()) {
+                 p->error_indicator = 1;
+@@ -24175,7 +24378,7 @@ _tmp_143_rule(Parser *p)
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_143[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'or' conjunction"));
+     }
+     _res = NULL;
+@@ -24184,9 +24387,9 @@ _tmp_143_rule(Parser *p)
+     return _res;
+ }
+-// _tmp_144: 'and' inversion
++// _tmp_145: 'and' inversion
+ static void *
+-_tmp_144_rule(Parser *p)
++_tmp_145_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -24200,7 +24403,7 @@ _tmp_144_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_144[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion"));
++        D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'and' inversion"));
+         Token * _keyword;
+         expr_ty c;
+         if (
+@@ -24209,7 +24412,7 @@ _tmp_144_rule(Parser *p)
+             (c = inversion_rule(p))  // inversion
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_144[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion"));
++            D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'and' inversion"));
+             _res = c;
+             if (_res == NULL && PyErr_Occurred()) {
+                 p->error_indicator = 1;
+@@ -24219,7 +24422,7 @@ _tmp_144_rule(Parser *p)
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_144[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'and' inversion"));
+     }
+     _res = NULL;
+@@ -24228,9 +24431,9 @@ _tmp_144_rule(Parser *p)
+     return _res;
+ }
+-// _tmp_145: 'if' disjunction
++// _tmp_146: 'if' disjunction
+ static void *
+-_tmp_145_rule(Parser *p)
++_tmp_146_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -24244,7 +24447,7 @@ _tmp_145_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_145[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
++        D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
+         Token * _keyword;
+         expr_ty z;
+         if (
+@@ -24253,7 +24456,7 @@ _tmp_145_rule(Parser *p)
+             (z = disjunction_rule(p))  // disjunction
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_145[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
++            D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
+             _res = z;
+             if (_res == NULL && PyErr_Occurred()) {
+                 p->error_indicator = 1;
+@@ -24263,7 +24466,7 @@ _tmp_145_rule(Parser *p)
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_145[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction"));
+     }
+     _res = NULL;
+@@ -24272,9 +24475,9 @@ _tmp_145_rule(Parser *p)
+     return _res;
+ }
+-// _tmp_146: 'if' disjunction
++// _tmp_147: 'if' disjunction
+ static void *
+-_tmp_146_rule(Parser *p)
++_tmp_147_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -24288,7 +24491,7 @@ _tmp_146_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_146[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
++        D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
+         Token * _keyword;
+         expr_ty z;
+         if (
+@@ -24297,7 +24500,7 @@ _tmp_146_rule(Parser *p)
+             (z = disjunction_rule(p))  // disjunction
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_146[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
++            D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'if' disjunction"));
+             _res = z;
+             if (_res == NULL && PyErr_Occurred()) {
+                 p->error_indicator = 1;
+@@ -24307,7 +24510,7 @@ _tmp_146_rule(Parser *p)
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_146[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'if' disjunction"));
+     }
+     _res = NULL;
+@@ -24316,9 +24519,9 @@ _tmp_146_rule(Parser *p)
+     return _res;
+ }
+-// _tmp_147: starred_expression | named_expression !'='
++// _tmp_148: starred_expression | named_expression !'='
+ static void *
+-_tmp_147_rule(Parser *p)
++_tmp_148_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -24332,18 +24535,18 @@ _tmp_147_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression"));
++        D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "starred_expression"));
+         expr_ty starred_expression_var;
+         if (
+             (starred_expression_var = starred_expression_rule(p))  // starred_expression
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression"));
++            D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "starred_expression"));
+             _res = starred_expression_var;
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "starred_expression"));
+     }
+     { // named_expression !'='
+@@ -24351,7 +24554,7 @@ _tmp_147_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_147[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression !'='"));
++        D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "named_expression !'='"));
+         expr_ty named_expression_var;
+         if (
+             (named_expression_var = named_expression_rule(p))  // named_expression
+@@ -24359,12 +24562,12 @@ _tmp_147_rule(Parser *p)
+             _PyPegen_lookahead_with_int(0, _PyPegen_expect_token, p, 22)  // token='='
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_147[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "named_expression !'='"));
++            D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "named_expression !'='"));
+             _res = named_expression_var;
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_147[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "named_expression !'='"));
+     }
+     _res = NULL;
+@@ -24373,9 +24576,9 @@ _tmp_147_rule(Parser *p)
+     return _res;
+ }
+-// _tmp_148: ',' star_target
++// _tmp_149: ',' star_target
+ static void *
+-_tmp_148_rule(Parser *p)
++_tmp_149_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -24389,7 +24592,7 @@ _tmp_148_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_148[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target"));
++        D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target"));
+         Token * _literal;
+         expr_ty c;
+         if (
+@@ -24398,7 +24601,7 @@ _tmp_148_rule(Parser *p)
+             (c = star_target_rule(p))  // star_target
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_148[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target"));
++            D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target"));
+             _res = c;
+             if (_res == NULL && PyErr_Occurred()) {
+                 p->error_indicator = 1;
+@@ -24408,7 +24611,7 @@ _tmp_148_rule(Parser *p)
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_148[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_149[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target"));
+     }
+     _res = NULL;
+@@ -24417,9 +24620,53 @@ _tmp_148_rule(Parser *p)
+     return _res;
+ }
+-// _tmp_149: star_targets '='
++// _tmp_150: ',' star_target
+ static void *
+-_tmp_149_rule(Parser *p)
++_tmp_150_rule(Parser *p)
++{
++    D(p->level++);
++    if (p->error_indicator) {
++        D(p->level--);
++        return NULL;
++    }
++    void * _res = NULL;
++    int _mark = p->mark;
++    { // ',' star_target
++        if (p->error_indicator) {
++            D(p->level--);
++            return NULL;
++        }
++        D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "',' star_target"));
++        Token * _literal;
++        expr_ty c;
++        if (
++            (_literal = _PyPegen_expect_token(p, 12))  // token=','
++            &&
++            (c = star_target_rule(p))  // star_target
++        )
++        {
++            D(fprintf(stderr, "%*c+ _tmp_150[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "',' star_target"));
++            _res = c;
++            if (_res == NULL && PyErr_Occurred()) {
++                p->error_indicator = 1;
++                D(p->level--);
++                return NULL;
++            }
++            goto done;
++        }
++        p->mark = _mark;
++        D(fprintf(stderr, "%*c%s _tmp_150[%d-%d]: %s failed!\n", p->level, ' ',
++                  p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "',' star_target"));
++    }
++    _res = NULL;
++  done:
++    D(p->level--);
++    return _res;
++}
++
++// _tmp_151: star_targets '='
++static void *
++_tmp_151_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -24433,7 +24680,7 @@ _tmp_149_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_149[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
++        D(fprintf(stderr, "%*c> _tmp_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
+         Token * _literal;
+         expr_ty star_targets_var;
+         if (
+@@ -24442,12 +24689,12 @@ _tmp_149_rule(Parser *p)
+             (_literal = _PyPegen_expect_token(p, 22))  // token='='
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_149[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
++            D(fprintf(stderr, "%*c+ _tmp_151[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
+             _res = _PyPegen_dummy_name(p, star_targets_var, _literal);
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_149[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_151[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='"));
+     }
+     _res = NULL;
+@@ -24456,9 +24703,9 @@ _tmp_149_rule(Parser *p)
+     return _res;
+ }
+-// _tmp_150: star_targets '='
++// _tmp_152: star_targets '='
+ static void *
+-_tmp_150_rule(Parser *p)
++_tmp_152_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -24472,7 +24719,7 @@ _tmp_150_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_150[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
++        D(fprintf(stderr, "%*c> _tmp_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
+         Token * _literal;
+         expr_ty star_targets_var;
+         if (
+@@ -24481,12 +24728,12 @@ _tmp_150_rule(Parser *p)
+             (_literal = _PyPegen_expect_token(p, 22))  // token='='
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_150[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
++            D(fprintf(stderr, "%*c+ _tmp_152[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "star_targets '='"));
+             _res = _PyPegen_dummy_name(p, star_targets_var, _literal);
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_150[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_152[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "star_targets '='"));
+     }
+     _res = NULL;
+@@ -24495,9 +24742,9 @@ _tmp_150_rule(Parser *p)
+     return _res;
+ }
+-// _loop1_151: param_with_default
++// _loop1_153: param_with_default
+ static asdl_seq *
+-_loop1_151_rule(Parser *p)
++_loop1_153_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -24521,7 +24768,7 @@ _loop1_151_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _loop1_151[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default"));
++        D(fprintf(stderr, "%*c> _loop1_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "param_with_default"));
+         NameDefaultPair* param_with_default_var;
+         while (
+             (param_with_default_var = param_with_default_rule(p))  // param_with_default
+@@ -24543,7 +24790,7 @@ _loop1_151_rule(Parser *p)
+             _mark = p->mark;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _loop1_151[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _loop1_153[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "param_with_default"));
+     }
+     if (_n == 0 || p->error_indicator) {
+@@ -24561,14 +24808,14 @@ _loop1_151_rule(Parser *p)
+     }
+     for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
+     PyMem_Free(_children);
+-    _PyPegen_insert_memo(p, _start_mark, _loop1_151_type, _seq);
++    _PyPegen_insert_memo(p, _start_mark, _loop1_153_type, _seq);
+     D(p->level--);
+     return _seq;
+ }
+-// _loop1_152: lambda_param_with_default
++// _loop1_154: lambda_param_with_default
+ static asdl_seq *
+-_loop1_152_rule(Parser *p)
++_loop1_154_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -24592,7 +24839,7 @@ _loop1_152_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _loop1_152[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default"));
++        D(fprintf(stderr, "%*c> _loop1_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "lambda_param_with_default"));
+         NameDefaultPair* lambda_param_with_default_var;
+         while (
+             (lambda_param_with_default_var = lambda_param_with_default_rule(p))  // lambda_param_with_default
+@@ -24614,7 +24861,7 @@ _loop1_152_rule(Parser *p)
+             _mark = p->mark;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _loop1_152[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _loop1_154[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "lambda_param_with_default"));
+     }
+     if (_n == 0 || p->error_indicator) {
+@@ -24632,14 +24879,14 @@ _loop1_152_rule(Parser *p)
+     }
+     for (int i = 0; i < _n; i++) asdl_seq_SET(_seq, i, _children[i]);
+     PyMem_Free(_children);
+-    _PyPegen_insert_memo(p, _start_mark, _loop1_152_type, _seq);
++    _PyPegen_insert_memo(p, _start_mark, _loop1_154_type, _seq);
+     D(p->level--);
+     return _seq;
+ }
+-// _tmp_153: ')' | '**'
++// _tmp_155: ')' | '**'
+ static void *
+-_tmp_153_rule(Parser *p)
++_tmp_155_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -24653,18 +24900,18 @@ _tmp_153_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'"));
++        D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "')'"));
+         Token * _literal;
+         if (
+             (_literal = _PyPegen_expect_token(p, 8))  // token=')'
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'"));
++            D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "')'"));
+             _res = _literal;
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "')'"));
+     }
+     { // '**'
+@@ -24672,18 +24919,18 @@ _tmp_153_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_153[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'"));
++        D(fprintf(stderr, "%*c> _tmp_155[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'"));
+         Token * _literal;
+         if (
+             (_literal = _PyPegen_expect_token(p, 35))  // token='**'
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_153[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'"));
++            D(fprintf(stderr, "%*c+ _tmp_155[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'"));
+             _res = _literal;
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_153[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_155[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'"));
+     }
+     _res = NULL;
+@@ -24692,9 +24939,9 @@ _tmp_153_rule(Parser *p)
+     return _res;
+ }
+-// _tmp_154: ':' | '**'
++// _tmp_156: ':' | '**'
+ static void *
+-_tmp_154_rule(Parser *p)
++_tmp_156_rule(Parser *p)
+ {
+     D(p->level++);
+     if (p->error_indicator) {
+@@ -24708,18 +24955,18 @@ _tmp_154_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'"));
++        D(fprintf(stderr, "%*c> _tmp_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "':'"));
+         Token * _literal;
+         if (
+             (_literal = _PyPegen_expect_token(p, 11))  // token=':'
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'"));
++            D(fprintf(stderr, "%*c+ _tmp_156[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "':'"));
+             _res = _literal;
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_156[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "':'"));
+     }
+     { // '**'
+@@ -24727,18 +24974,18 @@ _tmp_154_rule(Parser *p)
+             D(p->level--);
+             return NULL;
+         }
+-        D(fprintf(stderr, "%*c> _tmp_154[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'"));
++        D(fprintf(stderr, "%*c> _tmp_156[%d-%d]: %s\n", p->level, ' ', _mark, p->mark, "'**'"));
+         Token * _literal;
+         if (
+             (_literal = _PyPegen_expect_token(p, 35))  // token='**'
+         )
+         {
+-            D(fprintf(stderr, "%*c+ _tmp_154[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'"));
++            D(fprintf(stderr, "%*c+ _tmp_156[%d-%d]: %s succeeded!\n", p->level, ' ', _mark, p->mark, "'**'"));
+             _res = _literal;
+             goto done;
+         }
+         p->mark = _mark;
+-        D(fprintf(stderr, "%*c%s _tmp_154[%d-%d]: %s failed!\n", p->level, ' ',
++        D(fprintf(stderr, "%*c%s _tmp_156[%d-%d]: %s failed!\n", p->level, ' ',
+                   p->error_indicator ? "ERROR!" : "-", _mark, p->mark, "'**'"));
+     }
+     _res = NULL;
+diff --git a/Parser/pegen/parse_string.c b/Parser/pegen/parse_string.c
+index fb0c4aff9d..c852e5b827 100644
+--- a/Parser/pegen/parse_string.c
++++ b/Parser/pegen/parse_string.c
+@@ -410,7 +410,7 @@ fstring_compile_expr(Parser *p, const char *expr_start, const char *expr_end,
+     Parser *p2 = _PyPegen_Parser_New(tok, Py_fstring_input, p->flags, p->feature_version,
+                                      NULL, p->arena);
+     p2->starting_lineno = t->lineno + lines - 1;
+-    p2->starting_col_offset = p->tok->first_lineno == p->tok->lineno ? t->col_offset + cols : cols;
++    p2->starting_col_offset = t->col_offset + cols;
+     expr = _PyPegen_run_parser(p2);
+diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
+index 199b09c4d8..614012df9b 100644
+--- a/Python/bltinmodule.c
++++ b/Python/bltinmodule.c
+@@ -2619,6 +2619,11 @@ zip_next(zipobject *lz)
+             PyTuple_SET_ITEM(result, i, item);
+             Py_DECREF(olditem);
+         }
++        // bpo-42536: The GC may have untracked this result tuple. Since we're
++        // recycling it, make sure it's tracked again:
++        if (!_PyObject_GC_IS_TRACKED(result)) {
++            _PyObject_GC_TRACK(result);
++        }
+     } else {
+         result = PyTuple_New(tuplesize);
+         if (result == NULL)
+diff --git a/Python/fileutils.c b/Python/fileutils.c
+index 397ac34e80..ddc090988f 100644
+--- a/Python/fileutils.c
++++ b/Python/fileutils.c
+@@ -1165,6 +1165,13 @@ set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works)
+             return 0;
+         }
++#ifdef __linux__
++        if (errno == EBADF) {
++            // On Linux, ioctl(FIOCLEX) will fail with EBADF for O_PATH file descriptors
++            // Fall through to the fcntl() path
++        }
++        else
++#endif
+         if (errno != ENOTTY && errno != EACCES) {
+             if (raise)
+                 PyErr_SetFromErrno(PyExc_OSError);
+diff --git a/Python/getcopyright.c b/Python/getcopyright.c
+index 299ccc08c4..7fdeb314d5 100644
+--- a/Python/getcopyright.c
++++ b/Python/getcopyright.c
+@@ -4,7 +4,7 @@
+ static const char cprt[] =
+ "\
+-Copyright (c) 2001-2020 Python Software Foundation.\n\
++Copyright (c) 2001-2021 Python Software Foundation.\n\
+ All Rights Reserved.\n\
+ \n\
+ Copyright (c) 2000 BeOpen.com.\n\
+diff --git a/Python/pythonrun.c b/Python/pythonrun.c
+index 70748dc584..04540989f3 100644
+--- a/Python/pythonrun.c
++++ b/Python/pythonrun.c
+@@ -64,11 +64,15 @@ extern Py_EXPORTED_SYMBOL grammar _PyParser_Grammar; /* From graminit.c */
+ static void flush_io(void);
+ static PyObject *run_mod(mod_ty, PyObject *, PyObject *, PyObject *,
+                           PyCompilerFlags *, PyArena *);
+-static PyObject *run_pyc_file(FILE *, const char *, PyObject *, PyObject *,
++static PyObject *run_pyc_file(FILE *, PyObject *, PyObject *,
+                               PyCompilerFlags *);
+ static void err_input(perrdetail *);
+ static void err_free(perrdetail *);
+ static int PyRun_InteractiveOneObjectEx(FILE *, PyObject *, PyCompilerFlags *);
++static PyObject* pyrun_file(FILE *fp, PyObject *filename, int start,
++                            PyObject *globals, PyObject *locals, int closeit,
++                            PyCompilerFlags *flags);
++
+ /* Parse input from a file and execute it */
+ int
+@@ -310,82 +314,89 @@ PyRun_InteractiveOneFlags(FILE *fp, const char *filename_str, PyCompilerFlags *f
+    the file type, and, if we may close it, at the first few bytes. */
+ static int
+-maybe_pyc_file(FILE *fp, const char* filename, const char* ext, int closeit)
++maybe_pyc_file(FILE *fp, PyObject *filename, int closeit)
+ {
+-    if (strcmp(ext, ".pyc") == 0)
++    PyObject *ext = PyUnicode_FromString(".pyc");
++    if (ext == NULL) {
++        return -1;
++    }
++    Py_ssize_t endswith = PyUnicode_Tailmatch(filename, ext, 0, PY_SSIZE_T_MAX, +1);
++    Py_DECREF(ext);
++    if (endswith) {
+         return 1;
++    }
+     /* Only look into the file if we are allowed to close it, since
+        it then should also be seekable. */
+-    if (closeit) {
+-        /* Read only two bytes of the magic. If the file was opened in
+-           text mode, the bytes 3 and 4 of the magic (\r\n) might not
+-           be read as they are on disk. */
+-        unsigned int halfmagic = PyImport_GetMagicNumber() & 0xFFFF;
+-        unsigned char buf[2];
+-        /* Mess:  In case of -x, the stream is NOT at its start now,
+-           and ungetc() was used to push back the first newline,
+-           which makes the current stream position formally undefined,
+-           and a x-platform nightmare.
+-           Unfortunately, we have no direct way to know whether -x
+-           was specified.  So we use a terrible hack:  if the current
+-           stream position is not 0, we assume -x was specified, and
+-           give up.  Bug 132850 on SourceForge spells out the
+-           hopelessness of trying anything else (fseek and ftell
+-           don't work predictably x-platform for text-mode files).
+-        */
+-        int ispyc = 0;
+-        if (ftell(fp) == 0) {
+-            if (fread(buf, 1, 2, fp) == 2 &&
+-                ((unsigned int)buf[1]<<8 | buf[0]) == halfmagic)
+-                ispyc = 1;
+-            rewind(fp);
+-        }
+-        return ispyc;
++    if (!closeit) {
++        return 0;
+     }
+-    return 0;
++
++    /* Read only two bytes of the magic. If the file was opened in
++       text mode, the bytes 3 and 4 of the magic (\r\n) might not
++       be read as they are on disk. */
++    unsigned int halfmagic = PyImport_GetMagicNumber() & 0xFFFF;
++    unsigned char buf[2];
++    /* Mess:  In case of -x, the stream is NOT at its start now,
++       and ungetc() was used to push back the first newline,
++       which makes the current stream position formally undefined,
++       and a x-platform nightmare.
++       Unfortunately, we have no direct way to know whether -x
++       was specified.  So we use a terrible hack:  if the current
++       stream position is not 0, we assume -x was specified, and
++       give up.  Bug 132850 on SourceForge spells out the
++       hopelessness of trying anything else (fseek and ftell
++       don't work predictably x-platform for text-mode files).
++    */
++    int ispyc = 0;
++    if (ftell(fp) == 0) {
++        if (fread(buf, 1, 2, fp) == 2 &&
++            ((unsigned int)buf[1]<<8 | buf[0]) == halfmagic)
++            ispyc = 1;
++        rewind(fp);
++    }
++    return ispyc;
+ }
++
+ static int
+-set_main_loader(PyObject *d, const char *filename, const char *loader_name)
++set_main_loader(PyObject *d, PyObject *filename, const char *loader_name)
+ {
+-    PyObject *filename_obj, *bootstrap, *loader_type = NULL, *loader;
+-    int result = 0;
+-
+-    filename_obj = PyUnicode_DecodeFSDefault(filename);
+-    if (filename_obj == NULL)
+-        return -1;
+     PyInterpreterState *interp = _PyInterpreterState_GET();
+-    bootstrap = PyObject_GetAttrString(interp->importlib,
+-                                       "_bootstrap_external");
+-    if (bootstrap != NULL) {
+-        loader_type = PyObject_GetAttrString(bootstrap, loader_name);
+-        Py_DECREF(bootstrap);
++    PyObject *bootstrap = PyObject_GetAttrString(interp->importlib,
++                                                 "_bootstrap_external");
++    if (bootstrap == NULL) {
++        return -1;
+     }
++
++    PyObject *loader_type = PyObject_GetAttrString(bootstrap, loader_name);
++    Py_DECREF(bootstrap);
+     if (loader_type == NULL) {
+-        Py_DECREF(filename_obj);
+         return -1;
+     }
+-    loader = PyObject_CallFunction(loader_type, "sN", "__main__", filename_obj);
++
++    PyObject *loader = PyObject_CallFunction(loader_type,
++                                             "sO", "__main__", filename);
+     Py_DECREF(loader_type);
+     if (loader == NULL) {
+         return -1;
+     }
++
+     if (PyDict_SetItemString(d, "__loader__", loader) < 0) {
+-        result = -1;
++        Py_DECREF(loader);
++        return -1;
+     }
+     Py_DECREF(loader);
+-    return result;
++    return 0;
+ }
+-int
+-PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit,
+-                        PyCompilerFlags *flags)
++
++static int
++pyrun_simple_file(FILE *fp, PyObject *filename, int closeit,
++                  PyCompilerFlags *flags)
+ {
+     PyObject *m, *d, *v;
+-    const char *ext;
+     int set_file_name = 0, ret = -1;
+-    size_t len;
+     m = PyImport_AddModule("__main__");
+     if (m == NULL)
+@@ -393,29 +404,29 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit,
+     Py_INCREF(m);
+     d = PyModule_GetDict(m);
+     if (PyDict_GetItemString(d, "__file__") == NULL) {
+-        PyObject *f;
+-        f = PyUnicode_DecodeFSDefault(filename);
+-        if (f == NULL)
+-            goto done;
+-        if (PyDict_SetItemString(d, "__file__", f) < 0) {
+-            Py_DECREF(f);
++        if (PyDict_SetItemString(d, "__file__", filename) < 0) {
+             goto done;
+         }
+         if (PyDict_SetItemString(d, "__cached__", Py_None) < 0) {
+-            Py_DECREF(f);
+             goto done;
+         }
+         set_file_name = 1;
+-        Py_DECREF(f);
+     }
+-    len = strlen(filename);
+-    ext = filename + len - (len > 4 ? 4 : 0);
+-    if (maybe_pyc_file(fp, filename, ext, closeit)) {
++
++    int pyc = maybe_pyc_file(fp, filename, closeit);
++    if (pyc < 0) {
++        goto done;
++    }
++
++    if (pyc) {
+         FILE *pyc_fp;
+         /* Try to run a pyc file. First, re-open in binary */
+-        if (closeit)
++        if (closeit) {
+             fclose(fp);
+-        if ((pyc_fp = _Py_fopen(filename, "rb")) == NULL) {
++        }
++
++        pyc_fp = _Py_fopen_obj(filename, "rb");
++        if (pyc_fp == NULL) {
+             fprintf(stderr, "python: Can't reopen .pyc file\n");
+             goto done;
+         }
+@@ -426,17 +437,17 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit,
+             fclose(pyc_fp);
+             goto done;
+         }
+-        v = run_pyc_file(pyc_fp, filename, d, d, flags);
++        v = run_pyc_file(pyc_fp, d, d, flags);
+     } else {
+         /* When running from stdin, leave __main__.__loader__ alone */
+-        if (strcmp(filename, "<stdin>") != 0 &&
++        if (PyUnicode_CompareWithASCIIString(filename, "<stdin>") != 0 &&
+             set_main_loader(d, filename, "SourceFileLoader") < 0) {
+             fprintf(stderr, "python: failed to set __main__.__loader__\n");
+             ret = -1;
+             goto done;
+         }
+-        v = PyRun_FileExFlags(fp, filename, Py_file_input, d, d,
+-                              closeit, flags);
++        v = pyrun_file(fp, filename, Py_file_input, d, d,
++                       closeit, flags);
+     }
+     flush_io();
+     if (v == NULL) {
+@@ -459,6 +470,21 @@ PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit,
+     return ret;
+ }
++
++int
++PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit,
++                        PyCompilerFlags *flags)
++{
++    PyObject *filename_obj = PyUnicode_DecodeFSDefault(filename);
++    if (filename_obj == NULL) {
++        return -1;
++    }
++    int res = pyrun_simple_file(fp, filename_obj, closeit, flags);
++    Py_DECREF(filename_obj);
++    return res;
++}
++
++
+ int
+ PyRun_SimpleStringFlags(const char *command, PyCompilerFlags *flags)
+ {
+@@ -1081,24 +1107,18 @@ PyRun_StringFlags(const char *str, int start, PyObject *globals,
+     return ret;
+ }
+-PyObject *
+-PyRun_FileExFlags(FILE *fp, const char *filename_str, int start, PyObject *globals,
+-                  PyObject *locals, int closeit, PyCompilerFlags *flags)
++
++static PyObject *
++pyrun_file(FILE *fp, PyObject *filename, int start, PyObject *globals,
++           PyObject *locals, int closeit, PyCompilerFlags *flags)
+ {
+-    PyObject *ret = NULL;
++    PyArena *arena = PyArena_New();
++    if (arena == NULL) {
++        return NULL;
++    }
++
+     mod_ty mod;
+-    PyArena *arena = NULL;
+-    PyObject *filename;
+     int use_peg = _PyInterpreterState_GET()->config._use_peg_parser;
+-
+-    filename = PyUnicode_DecodeFSDefault(filename_str);
+-    if (filename == NULL)
+-        goto exit;
+-
+-    arena = PyArena_New();
+-    if (arena == NULL)
+-        goto exit;
+-
+     if (use_peg) {
+         mod = PyPegen_ASTFromFileObject(fp, filename, start, NULL, NULL, NULL,
+                                         flags, NULL, arena);
+@@ -1108,20 +1128,40 @@ PyRun_FileExFlags(FILE *fp, const char *filename_str, int start, PyObject *globa
+                                          flags, NULL, arena);
+     }
+-    if (closeit)
++    if (closeit) {
+         fclose(fp);
+-    if (mod == NULL) {
+-        goto exit;
+     }
+-    ret = run_mod(mod, filename, globals, locals, flags, arena);
+-exit:
+-    Py_XDECREF(filename);
+-    if (arena != NULL)
+-        PyArena_Free(arena);
++    PyObject *ret;
++    if (mod != NULL) {
++        ret = run_mod(mod, filename, globals, locals, flags, arena);
++    }
++    else {
++        ret = NULL;
++    }
++    PyArena_Free(arena);
++
+     return ret;
+ }
++
++PyObject *
++PyRun_FileExFlags(FILE *fp, const char *filename, int start, PyObject *globals,
++                  PyObject *locals, int closeit, PyCompilerFlags *flags)
++{
++    PyObject *filename_obj = PyUnicode_DecodeFSDefault(filename);
++    if (filename_obj == NULL) {
++        return NULL;
++    }
++
++    PyObject *res = pyrun_file(fp, filename_obj, start, globals,
++                               locals, closeit, flags);
++    Py_DECREF(filename_obj);
++    return res;
++
++}
++
++
+ static void
+ flush_io(void)
+ {
+@@ -1202,8 +1242,8 @@ run_mod(mod_ty mod, PyObject *filename, PyObject *globals, PyObject *locals,
+ }
+ static PyObject *
+-run_pyc_file(FILE *fp, const char *filename, PyObject *globals,
+-             PyObject *locals, PyCompilerFlags *flags)
++run_pyc_file(FILE *fp, PyObject *globals, PyObject *locals,
++             PyCompilerFlags *flags)
+ {
+     PyThreadState *tstate = _PyThreadState_GET();
+     PyCodeObject *co;
+diff --git a/Python/traceback.c b/Python/traceback.c
+index 99b63af11f..5d3a65cc16 100644
+--- a/Python/traceback.c
++++ b/Python/traceback.c
+@@ -622,7 +622,8 @@ PyTraceBack_Print(PyObject *v, PyObject *f)
+     return err;
+ }
+-/* Reverse a string. For example, "abcd" becomes "dcba".
++/* Format an integer in range [0; 0xffffffff] to decimal and write it
++   into the file fd.
+    This function is signal safe. */
+diff --git a/README.rst b/README.rst
+index a9ab26056c..bb43311ad2 100644
+--- a/README.rst
++++ b/README.rst
+@@ -22,7 +22,7 @@ This is Python version 3.9.1
+    :target: https://python.zulipchat.com
+-Copyright (c) 2001-2020 Python Software Foundation.  All rights reserved.
++Copyright (c) 2001-2021 Python Software Foundation.  All rights reserved.
+ See the end of this file for further copyright and license information.
+@@ -250,7 +250,7 @@ See :pep:`596` for Python 3.9 release details.
+ Copyright and License Information
+ ---------------------------------
+-Copyright (c) 2001-2020 Python Software Foundation.  All rights reserved.
++Copyright (c) 2001-2021 Python Software Foundation.  All rights reserved.
+ Copyright (c) 2000 BeOpen.com.  All rights reserved.
+diff --git a/Tools/freeze/freeze.py b/Tools/freeze/freeze.py
+index 83aa508a46..d66e1e2708 100755
+--- a/Tools/freeze/freeze.py
++++ b/Tools/freeze/freeze.py
+@@ -93,6 +93,7 @@ import modulefinder
+ import getopt
+ import os
+ import sys
++import sysconfig
+ # Import the freeze-private modules
+@@ -226,7 +227,7 @@ def main():
+         extensions_c = 'frozen_extensions.c'
+     if ishome:
+         print("(Using Python source directory)")
+-        binlib = exec_prefix
++        configdir = exec_prefix
+         incldir = os.path.join(prefix, 'Include')
+         config_h_dir = exec_prefix
+         config_c_in = os.path.join(prefix, 'Modules', 'config.c.in')
+@@ -235,22 +236,21 @@ def main():
+         if win:
+             frozendllmain_c = os.path.join(exec_prefix, 'Pc\\frozen_dllmain.c')
+     else:
+-        binlib = os.path.join(exec_prefix,
+-                              'lib', 'python%s' % version,
+-                              'config-%s' % flagged_version)
++        configdir = sysconfig.get_config_var('LIBPL')
+         incldir = os.path.join(prefix, 'include', 'python%s' % flagged_version)
+         config_h_dir = os.path.join(exec_prefix, 'include',
+                                     'python%s' % flagged_version)
+-        config_c_in = os.path.join(binlib, 'config.c.in')
+-        frozenmain_c = os.path.join(binlib, 'frozenmain.c')
+-        makefile_in = os.path.join(binlib, 'Makefile')
+-        frozendllmain_c = os.path.join(binlib, 'frozen_dllmain.c')
++        config_c_in = os.path.join(configdir, 'config.c.in')
++        frozenmain_c = os.path.join(configdir, 'frozenmain.c')
++        makefile_in = os.path.join(configdir, 'Makefile')
++        frozendllmain_c = os.path.join(configdir, 'frozen_dllmain.c')
++    libdir = sysconfig.get_config_var('LIBDIR')
+     supp_sources = []
+     defines = []
+     includes = ['-I' + incldir, '-I' + config_h_dir]
+     # sanity check of directories and files
+-    check_dirs = [prefix, exec_prefix, binlib, incldir]
++    check_dirs = [prefix, exec_prefix, configdir, incldir]
+     if not win:
+         # These are not directories on Windows.
+         check_dirs = check_dirs + extensions
+@@ -457,7 +457,7 @@ def main():
+     cflags = ['$(OPT)']
+     cppflags = defines + includes
+-    libs = [os.path.join(binlib, '$(LDLIBRARY)')]
++    libs = [os.path.join(libdir, '$(LDLIBRARY)')]
+     somevars = {}
+     if os.path.exists(makefile_in):
+diff --git a/Tools/gdb/libpython.py b/Tools/gdb/libpython.py
+index 33bf5ac821..aeaa63e540 100755
+--- a/Tools/gdb/libpython.py
++++ b/Tools/gdb/libpython.py
+@@ -468,7 +468,7 @@ class InstanceProxy(object):
+     def __repr__(self):
+         if isinstance(self.attrdict, dict):
+             kwargs = ', '.join(["%s=%r" % (arg, val)
+-                                for arg, val in self.attrdict.iteritems()])
++                                for arg, val in self.attrdict.items()])
+             return '<%s(%s) at remote 0x%x>' % (self.cl_name,
+                                                 kwargs, self.address)
+         else:
+diff --git a/Tools/pynche/PyncheWidget.py b/Tools/pynche/PyncheWidget.py
+index ef12198a21..ea456e577e 100644
+--- a/Tools/pynche/PyncheWidget.py
++++ b/Tools/pynche/PyncheWidget.py
+@@ -36,15 +36,11 @@ class PyncheWidget:
+         else:
+             # Is there already a default root for Tk, say because we're
+             # running under Guido's IDE? :-) Two conditions say no, either the
+-            # import fails or _default_root is None.
+-            tkroot = None
+-            try:
+-                from Tkinter import _default_root
+-                tkroot = self.__tkroot = _default_root
+-            except ImportError:
+-                pass
++            # _default_root is None or it is unset.
++            tkroot = getattr(tkinter, '_default_root', None)
+             if not tkroot:
+-                tkroot = self.__tkroot = Tk(className='Pynche')
++                tkroot = Tk(className='Pynche')
++            self.__tkroot = tkroot
+             # but this isn't our top level widget, so make it invisible
+             tkroot.withdraw()
+         # create the menubar
+diff --git a/configure.ac b/configure.ac
+index c968d149c2..972287a9c4 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -3313,10 +3313,10 @@ if test "$posix_threads" = "yes"; then
+       main() {
+         pthread_attr_t attr;
+         pthread_t id;
+-        if (pthread_attr_init(&attr)) exit(-1);
+-        if (pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM)) exit(-1);
+-        if (pthread_create(&id, &attr, foo, NULL)) exit(-1);
+-        exit(0);
++        if (pthread_attr_init(&attr)) return (-1);
++        if (pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM)) return (-1);
++        if (pthread_create(&id, &attr, foo, NULL)) return (-1);
++        return (0);
+       }]])],
+       [ac_cv_pthread_system_supported=yes],
+       [ac_cv_pthread_system_supported=no],
+@@ -4725,7 +4725,7 @@ then
+   int main()
+   {
+       /* Success: exit code 0 */
+-        exit((((wchar_t) -1) < ((wchar_t) 0)) ? 0 : 1);
++        return ((((wchar_t) -1) < ((wchar_t) 0)) ? 0 : 1);
+   }
+   ]])],
+   [ac_cv_wchar_t_signed=yes],
+@@ -4783,12 +4783,7 @@ if test "$Py_DEBUG" = 'true' -a "$with_trace_refs" != "yes"; then
+ fi
+ AC_SUBST(EXT_SUFFIX)
+-case $ac_sys_system in
+-    Linux*|GNU*|Darwin|VxWorks)
+-      EXT_SUFFIX=.${SOABI}${SHLIB_SUFFIX};;
+-    *)
+-      EXT_SUFFIX=${SHLIB_SUFFIX};;
+-esac
++EXT_SUFFIX=.${SOABI}${SHLIB_SUFFIX}
+ AC_MSG_CHECKING(LDVERSION)
+ LDVERSION='$(VERSION)$(ABIFLAGS)'
+@@ -4847,7 +4842,7 @@ AC_CACHE_VAL(ac_cv_rshift_extends_sign, [
+ AC_RUN_IFELSE([AC_LANG_SOURCE([[
+ int main()
+ {
+-      exit(((-1)>>3 == -1) ? 0 : 1);
++      return (((-1)>>3 == -1) ? 0 : 1);
+ }
+ ]])],
+ [ac_cv_rshift_extends_sign=yes],
+@@ -4994,6 +4989,7 @@ AC_MSG_CHECKING(for broken poll())
+ AC_CACHE_VAL(ac_cv_broken_poll,
+ AC_RUN_IFELSE([AC_LANG_SOURCE([[
+ #include <poll.h>
++#include <unistd.h>
+ int main()
+ {
+diff --git a/setup.py b/setup.py
+index bd5f736924..d42eb9d117 100644
+--- a/setup.py
++++ b/setup.py
+@@ -1013,7 +1013,7 @@ class PyBuildExt(build_ext):
+             os_release = int(os.uname()[2].split('.')[0])
+             dep_target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
+             if (dep_target and
+-                    (tuple(int(n) for n in str(dep_target).split('.')[0:2])
++                    (tuple(int(n) for n in dep_target.split('.')[0:2])
+                         < (10, 5) ) ):
+                 os_release = 8
+             if os_release < 9:
+--- a/Misc/NEWS
++++ b/Misc/NEWS
+@@ -2,6 +2,291 @@
+ Python News
+ +++++++++++
++What's New in Python next?
++==========================
++
++*Release date: XXXX-XX-XX*
++
++Security
++--------
++
++- bpo-42938: Avoid static buffers when computing the repr of
++  :class:`ctypes.c_double` and :class:`ctypes.c_longdouble` values.
++
++Core and Builtins
++-----------------
++
++- bpo-42806: Fix the column offsets for f-strings :mod:`ast` nodes
++  surrounded by parentheses and for nodes that spawn multiple lines. Patch
++  by Pablo Galindo.
++
++- bpo-40631: Fix regression where a single parenthesized starred expression
++  was a valid assignment target.
++
++- bpo-32381: Fix encoding name when running a ``.pyc`` file on Windows:
++  :c:func:`PyRun_SimpleFileExFlags()` now uses the correct encoding to
++  decode the filename.
++
++- bpo-42536: Several built-in and standard library types now ensure that
++  their internal result tuples are always tracked by the :term:`garbage
++  collector <garbage collection>`:
++
++  - :meth:`collections.OrderedDict.items() <collections.OrderedDict>`
++
++  - :meth:`dict.items`
++
++  - :func:`enumerate`
++
++  - :func:`functools.reduce`
++
++  - :func:`itertools.combinations`
++
++  - :func:`itertools.combinations_with_replacement`
++
++  - :func:`itertools.permutations`
++
++  - :func:`itertools.product`
++
++  - :func:`itertools.zip_longest`
++
++  - :func:`zip`
++
++  Previously, they could have become untracked by a prior garbage
++  collection. Patch by Brandt Bucher.
++
++- bpo-42195: The ``__args__`` of the parameterized generics for
++  :data:`typing.Callable` and :class:`collections.abc.Callable` are now
++  consistent.  The ``__args__`` for :class:`collections.abc.Callable` are
++  now flattened while :data:`typing.Callable`'s have not changed.  To allow
++  this change, :class:`types.GenericAlias` can now be subclassed and
++  ``collections.abc.Callable``'s ``__class_getitem__`` will now return a
++  subclass of ``types.GenericAlias``.  Tests for typing were also updated to
++  not subclass things like ``Callable[..., T]`` as that is not a valid base
++  class.  Finally, both types no longer validate their ``argtypes``, in
++  ``Callable[[argtypes], resulttype]`` to prepare for :pep:`612`.  Patch by
++  Ken Jin.
++
++Library
++-------
++
++- bpo-43102: The namedtuple __new__ method had its __builtins__ set to None
++  instead of an actual dictionary.  This created problems for introspection
++  tools.
++
++- bpo-43108: Fixed a reference leak in the :mod:`curses` module. Patch by
++  Pablo Galindo
++
++- bpo-42944: Fix ``random.Random.sample`` when ``counts`` argument is not
++  ``None``.
++
++- bpo-42931: Add :func:`randbytes` to ``random.__all__``.
++
++- bpo-42780: Fix os.set_inheritable() for O_PATH file descriptors on Linux.
++
++- bpo-42851: remove __init_subclass__ support for Enum members
++
++- bpo-41748: Fix HTMLParser parsing rules for element attributes containing
++  commas with spaces. Patch by Karl Dubost.
++
++- bpo-42759: Fixed equality comparison of :class:`tkinter.Variable` and
++  :class:`tkinter.font.Font`. Objects which belong to different Tcl
++  interpreters are now always different, even if they have the same name.
++
++- bpo-42756: Configure LMTP Unix-domain socket to use socket global default
++  timeout when a timeout is not explicitly provided.
++
++- bpo-23328: Allow / character in username, password fields on _PROXY
++  envars.
++
++- bpo-42655: :mod:`subprocess` *extra_groups* is now correctly passed into
++  setgroups() system call.
++
++- bpo-42727: ``EnumMeta.__prepare__`` now accepts ``**kwds`` to properly
++  support ``__init_subclass__``
++
++- bpo-42681: Fixed range checks for color and pair numbers in :mod:`curses`.
++
++- bpo-37961: Fix crash in :func:`tracemalloc.Traceback.__repr__` (regressed
++  in Python 3.9).
++
++- bpo-42630: :mod:`tkinter` functions and constructors which need a default
++  root window raise now :exc:`RuntimeError` with descriptive message instead
++  of obscure :exc:`AttributeError` or :exc:`NameError` if it is not created
++  yet or cannot be created automatically.
++
++- bpo-42644: `logging.disable` will now validate the types and value of its
++  parameter. It also now accepts strings representing the levels (as does
++  `loging.setLevel`) instead of only the numerical values.
++
++- bpo-36541: Fixed lib2to3.pgen2 to be able to parse PEP-570 positional only
++  argument syntax.
++
++- bpo-42517: Enum: private names will raise a DeprecationWarning; in 3.10
++  they will become normal attributes
++
++- bpo-42678: `Enum`: call `__init_subclass__` after members have been added
++
++- bpo-42532: Remove unexpected call of ``__bool__`` when passing a
++  ``spec_arg`` argument to a Mock.
++
++- bpo-42388: Fix subprocess.check_output(..., input=None) behavior when
++  text=True to be consistent with that of the documentation and
++  universal_newlines=True.
++
++- bpo-34463: Fixed discrepancy between :mod:`traceback` and the interpreter
++  in formatting of SyntaxError with lineno not set (:mod:`traceback` was
++  changed to match interpreter).
++
++- bpo-42375: subprocess module update for DragonFlyBSD support.
++
++- bpo-42384: Make pdb populate sys.path[0] exactly the same as regular
++  python execution.
++
++- bpo-42383: Fix pdb: previously pdb would fail to restart the debugging
++  target if it was specified using a relative path and the current directory
++  changed.
++
++- bpo-42318: Fixed support of non-BMP characters in :mod:`tkinter` on macOS.
++
++- bpo-42163: Restore compatibility for ``uname_result`` around deepcopy and
++  _replace.
++
++- bpo-39825: Windows: Change ``sysconfig.get_config_var('EXT_SUFFIX')`` to
++  the expected full ``platform_tag.extension`` format. Previously it was
++  hard-coded to ``.pyd``, now it is compatible with ``distutils.sysconfig``
++  and will result in something like ``.cp38-win_amd64.pyd``. This brings
++  windows into conformance with the other platforms.
++
++- bpo-42059: :class:`typing.TypedDict` types created using the alternative
++  call-style syntax now correctly respect the ``total`` keyword argument
++  when setting their ``__required_keys__`` and ``__optional_keys__`` class
++  attributes.
++
++- bpo-39101: Fixed tests using IsolatedAsyncioTestCase from hanging on
++  BaseExceptions.
++
++- bpo-42005: Fix CLI of :mod:`cProfile` and :mod:`profile` to catch
++  :exc:`BrokenPipeError`.
++
++- bpo-41907: fix `format()` behavior for `IntFlag`
++
++- bpo-41889: Enum: fix regression involving inheriting a multiply-inherited
++  enum
++
++- bpo-41891: Ensure asyncio.wait_for waits for task completion
++
++- bpo-41604: Don't decrement the reference count of the previous user_ptr
++  when set_panel_userptr fails.
++
++- bpo-40219: Lowered :class:`tkinter.ttk.LabeledScale` dummy widget to
++  prevent hiding part of the content label.
++
++- bpo-40084: Fix ``Enum.__dir__``: dir(Enum.member) now includes attributes
++  as well as methods.
++
++- bpo-39068: Fix initialization race condition in :func:`a85encode` and
++  :func:`b85encode` in :mod:`base64`. Patch by Brandon Stansbury.
++
++- bpo-33289: Correct call to :mod:`tkinter.colorchooser` to return RGB
++  triplet of ints instead of floats.  Patch by Cheryl Sabella.
++
++Documentation
++-------------
++
++- bpo-40304: Fix doc for type(name, bases, dict).  Patch by Boris
++  Verkhovskiy and Ã‰ric Araujo.
++
++- bpo-42811: Updated importlib.utils.resolve_name() doc to use
++  __spec__.parent instead of __package__. (Thanks Yair Frid.)
++
++- bpo-17140: Add documentation for the
++  :class:`multiprocessing.pool.ThreadPool` class.
++
++Tests
++-----
++
++- bpo-42794: Update test_nntplib to use offical group name of news.aioe.org
++  for testing. Patch by Dong-hee Na.
++
++- bpo-40810: In :mod:`sqlite3`, fix ``CheckTraceCallbackContent`` for SQLite
++  pre 3.7.15.
++
++Build
++-----
++
++- bpo-42692: Fix __builtin_available check on older compilers. Patch by
++  Joshua Root.
++
++- bpo-42604: Now all platforms use a value for the "EXT_SUFFIX" build
++  variable derived from SOABI (for instance in freeBSD, "EXT_SUFFIX" is now
++  ".cpython-310d.so" instead of ".so"). Previosuly only Linux, Mac and
++  VxWorks were using a value for "EXT_SUFFIX" that included "SOABI".
++
++- bpo-42598: Fix implicit function declarations in configure which could
++  have resulted in incorrect configuration checks.  Patch contributed by
++  Joshua Root.
++
++- bpo-29076: Add fish shell support to macOS installer.
++
++Windows
++-------
++
++- bpo-41837: Updated Windows installer to include OpenSSL 1.1.1i
++
++- bpo-42584: Upgrade Windows installer to use SQLite 3.34.0.
++
++macOS
++-----
++
++- bpo-42504: Ensure that the value of
++  sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET') is always a string,
++  even in when the value is parsable as an integer.
++
++- bpo-42361: Update macOS installer build to use Tcl/Tk 8.6.11 (rc2,
++  expected to be final release).
++
++- bpo-41837: Update macOS installer build to use OpenSSL 1.1.1i.
++
++- bpo-42584: Update macOS installer to use SQLite 3.34.0.
++
++IDLE
++----
++
++- bpo-43008: Make IDLE invoke :func:`sys.excepthook` in normal, 2-process
++  mode. Patch by Ken Hilton.
++
++- bpo-33065: Fix problem debugging user classes with __repr__ method.
++
++- bpo-23544: Disable Debug=>Stack Viewer when user code is running or
++  Debugger is active, to prevent hang or crash.  Patch by Zackery Spytz.
++
++- bpo-32631: Finish zzdummy example extension module: make menu entries
++  work; add docstrings and tests with 100% coverage.
++
++Tools/Demos
++-----------
++
++- bpo-42726: Fixed Python 3 compatibility issue with gdb/libpython.py
++  handling of attribute dictionaries.
++
++- bpo-42613: Fix ``freeze.py`` tool to use the prope config and library
++  directories. Patch by Victor Stinner.
++
++C API
++-----
++
++- bpo-43030: Fixed a compiler warning in :c:func:`Py_UNICODE_ISSPACE()` on
++  platforms with signed ``wchar_t``.
++
++- bpo-42591: Export the :c:func:`Py_FrozenMain` function: fix a Python 3.9.0
++  regression. Python 3.9 uses ``-fvisibility=hidden`` and the function was
++  not exported explicitly and so not exported.
++
++- bpo-40052: Fix an alignment build warning/error in function
++  ``PyVectorcall_Function()``. Patch by Andreas Schneider, Antoine Pitrou
++  and Petr Viktorin.
++
++
+ What's New in Python 3.9.1 final?
+ =================================
+@@ -148,8 +433,6 @@
+   rules that only generate better error messages to gain performance. If
+   there's a parse failure, run the parser a second time with those enabled.
+-- bpo-41910: Document the default implementation of `object.__eq__`.
+-
+ - bpo-42057: Fix peephole optimizer misoptimize conditional jump +
+   JUMP_IF_NOT_EXC_MATCH pair.
+@@ -265,7 +548,7 @@
+ - bpo-41316: Fix the :mod:`tarfile` module to write only basename of TAR
+   file to GZIP compression header.
+-- bpo-16936: Allow ``ctypes.wintypes`` to be imported on non-Windows
++- bpo-16396: Allow ``ctypes.wintypes`` to be imported on non-Windows
+   systems.
+ - bpo-40592: :func:`shutil.which` now ignores empty entries in
+@@ -291,6 +574,8 @@
+ - bpo-42061: Document __format__ functionality for IP addresses.
++- bpo-41910: Document the default implementation of `object.__eq__`.
++
+ - bpo-42010: Clarify that subscription expressions are also valid for
+   certain :term:`classes <class>` and :term:`types <type>` in the standard
+   library, and for user-defined classes and types if the classmethod
diff --git a/patches/hurd_kfreebsd_thread_native_id.diff b/patches/hurd_kfreebsd_thread_native_id.diff
new file mode 100644 (file)
index 0000000..49eddbf
--- /dev/null
@@ -0,0 +1,52 @@
+--- a/Include/pythread.h
++++ b/Include/pythread.h
+@@ -25,7 +25,7 @@ PyAPI_FUNC(unsigned long) PyThread_start
+ PyAPI_FUNC(void) _Py_NO_RETURN PyThread_exit_thread(void);
+ PyAPI_FUNC(unsigned long) PyThread_get_thread_ident(void);
+-#if defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(_WIN32) || defined(_AIX)
++#if defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(_WIN32) || defined(_AIX) || defined(__GNU__)
+ #define PY_HAVE_THREAD_NATIVE_ID
+ PyAPI_FUNC(unsigned long) PyThread_get_thread_native_id(void);
+ #endif
+--- a/Python/thread_pthread.h
++++ b/Python/thread_pthread.h
+@@ -17,12 +17,17 @@
+ #   include <sys/syscall.h>     /* syscall(SYS_gettid) */
+ #elif defined(__FreeBSD__)
+ #   include <pthread_np.h>      /* pthread_getthreadid_np() */
++#elif defined(__FreeBSD_kernel__)
++#   include <sys/syscall.h>     /* syscall(SYS_thr_self) */
+ #elif defined(__OpenBSD__)
+ #   include <unistd.h>          /* getthrid() */
+ #elif defined(_AIX)
+ #   include <sys/thread.h>      /* thread_self() */
+ #elif defined(__NetBSD__)
+ #   include <lwp.h>             /* _lwp_self() */
++#elif defined(__GNU__)
++#   include <mach.h>            /* mach_thread_self(), mach_task_self(),
++                                   mach_port_deallocate() */
+ #endif
+ /* The POSIX spec requires that use of pthread_attr_setstacksize
+@@ -338,6 +343,9 @@ PyThread_get_thread_native_id(void)
+ #elif defined(__FreeBSD__)
+     int native_id;
+     native_id = pthread_getthreadid_np();
++#elif defined(__FreeBSD_kernel__)
++    long native_id;
++    syscall(SYS_thr_self, &native_id);
+ #elif defined(__OpenBSD__)
+     pid_t native_id;
+     native_id = getthrid();
+@@ -347,6 +355,10 @@ PyThread_get_thread_native_id(void)
+ #elif defined(__NetBSD__)
+     lwpid_t native_id;
+     native_id = _lwp_self();
++#elif defined(__GNU__)
++    mach_port_t native_id;
++    native_id = mach_thread_self();
++    mach_port_deallocate(mach_task_self(), mach_thread_self());
+ #endif
+     return (unsigned long) native_id;
+ }
diff --git a/patches/langpack-gettext.diff b/patches/langpack-gettext.diff
new file mode 100644 (file)
index 0000000..ede50bc
--- /dev/null
@@ -0,0 +1,34 @@
+# DP: Description: support alternative gettext tree in
+# DP: /usr/share/locale-langpack; if a file is present in both trees,
+# DP: prefer the newer one
+# DP: Upstream status: Ubuntu-Specific
+
+--- a/Lib/gettext.py
++++ b/Lib/gettext.py
+@@ -567,11 +567,26 @@ def find(domain, localedir=None, languag
+         if lang == 'C':
+             break
+         mofile = os.path.join(localedir, lang, 'LC_MESSAGES', '%s.mo' % domain)
++        mofile_lp = os.path.join("/usr/share/locale-langpack", lang,
++                               'LC_MESSAGES', '%s.mo' % domain)
++
++      # first look into the standard locale dir, then into the 
++      # langpack locale dir
++
++      # standard mo file
+         if os.path.exists(mofile):
+             if all:
+                 result.append(mofile)
+             else:
+                 return mofile
++        
++      # langpack mofile -> use it
++        if os.path.exists(mofile_lp): 
++            if all:
++                result.append(mofile_lp)
++            else:
++                return mofile_lp
++
+     return result
diff --git a/patches/lib-argparse.diff b/patches/lib-argparse.diff
new file mode 100644 (file)
index 0000000..8ea5cb5
--- /dev/null
@@ -0,0 +1,22 @@
+# DP: argparse.py: Make the gettext import conditional
+
+--- a/Lib/argparse.py
++++ b/Lib/argparse.py
+@@ -89,7 +89,16 @@ import os as _os
+ import re as _re
+ import sys as _sys
+-from gettext import gettext as _, ngettext
++try:
++    from gettext import gettext as _, ngettext
++except ImportError:
++    def _(message):
++        return message
++    def ngettext(singular,plural,n):
++        if n == 1:
++            return singular
++        else:
++            return plural
+ SUPPRESS = '==SUPPRESS=='
diff --git a/patches/lib2to3-no-pickled-grammar.diff b/patches/lib2to3-no-pickled-grammar.diff
new file mode 100644 (file)
index 0000000..a1dd900
--- /dev/null
@@ -0,0 +1,100 @@
+--- a/Lib/lib2to3/pgen2/driver.py
++++ b/Lib/lib2to3/pgen2/driver.py
+@@ -119,7 +119,10 @@ def load_grammar(gt="Grammar.txt", gp=No
+     if force or not _newer(gp, gt):
+         logger.info("Generating grammar tables from %s", gt)
+         g = pgen.generate_grammar(gt)
+-        if save:
++        # the pickle files mismatch, when built on different architectures.
++        # don't save these for now. An alternative solution might be to
++        # include the multiarch triplet into the file name
++        if False:
+             logger.info("Writing grammar tables to %s", gp)
+             try:
+                 g.dump(gp)
+--- a/Lib/lib2to3/tests/test_parser.py
++++ b/Lib/lib2to3/tests/test_parser.py
+@@ -38,83 +38,6 @@ class TestDriver(support.TestCase):
+         self.assertEqual(t.children[1].children[0].type, syms.print_stmt)
+-class TestPgen2Caching(support.TestCase):
+-    def test_load_grammar_from_txt_file(self):
+-        pgen2_driver.load_grammar(support.grammar_path, save=False, force=True)
+-
+-    def test_load_grammar_from_pickle(self):
+-        # Make a copy of the grammar file in a temp directory we are
+-        # guaranteed to be able to write to.
+-        tmpdir = tempfile.mkdtemp()
+-        try:
+-            grammar_copy = os.path.join(
+-                    tmpdir, os.path.basename(support.grammar_path))
+-            shutil.copy(support.grammar_path, grammar_copy)
+-            pickle_name = pgen2_driver._generate_pickle_name(grammar_copy)
+-
+-            pgen2_driver.load_grammar(grammar_copy, save=True, force=True)
+-            self.assertTrue(os.path.exists(pickle_name))
+-
+-            os.unlink(grammar_copy)  # Only the pickle remains...
+-            pgen2_driver.load_grammar(grammar_copy, save=False, force=False)
+-        finally:
+-            shutil.rmtree(tmpdir)
+-
+-    @unittest.skipIf(sys.executable is None, 'sys.executable required')
+-    def test_load_grammar_from_subprocess(self):
+-        tmpdir = tempfile.mkdtemp()
+-        tmpsubdir = os.path.join(tmpdir, 'subdir')
+-        try:
+-            os.mkdir(tmpsubdir)
+-            grammar_base = os.path.basename(support.grammar_path)
+-            grammar_copy = os.path.join(tmpdir, grammar_base)
+-            grammar_sub_copy = os.path.join(tmpsubdir, grammar_base)
+-            shutil.copy(support.grammar_path, grammar_copy)
+-            shutil.copy(support.grammar_path, grammar_sub_copy)
+-            pickle_name = pgen2_driver._generate_pickle_name(grammar_copy)
+-            pickle_sub_name = pgen2_driver._generate_pickle_name(
+-                     grammar_sub_copy)
+-            self.assertNotEqual(pickle_name, pickle_sub_name)
+-
+-            # Generate a pickle file from this process.
+-            pgen2_driver.load_grammar(grammar_copy, save=True, force=True)
+-            self.assertTrue(os.path.exists(pickle_name))
+-
+-            # Generate a new pickle file in a subprocess with a most likely
+-            # different hash randomization seed.
+-            sub_env = dict(os.environ)
+-            sub_env['PYTHONHASHSEED'] = 'random'
+-            subprocess.check_call(
+-                    [sys.executable, '-c', """
+-from lib2to3.pgen2 import driver as pgen2_driver
+-pgen2_driver.load_grammar(%r, save=True, force=True)
+-                    """ % (grammar_sub_copy,)],
+-                    env=sub_env)
+-            self.assertTrue(os.path.exists(pickle_sub_name))
+-
+-            with open(pickle_name, 'rb') as pickle_f_1, \
+-                    open(pickle_sub_name, 'rb') as pickle_f_2:
+-                self.assertEqual(
+-                    pickle_f_1.read(), pickle_f_2.read(),
+-                    msg='Grammar caches generated using different hash seeds'
+-                    ' were not identical.')
+-        finally:
+-            shutil.rmtree(tmpdir)
+-
+-    def test_load_packaged_grammar(self):
+-        modname = __name__ + '.load_test'
+-        class MyLoader:
+-            def get_data(self, where):
+-                return pickle.dumps({'elephant': 19})
+-        class MyModule:
+-            __file__ = 'parsertestmodule'
+-            __spec__ = importlib.util.spec_from_loader(modname, MyLoader())
+-        sys.modules[modname] = MyModule()
+-        self.addCleanup(operator.delitem, sys.modules, modname)
+-        g = pgen2_driver.load_packaged_grammar(modname, 'Grammar.txt')
+-        self.assertEqual(g.elephant, 19)
+-
+-
+ class GrammarTest(support.TestCase):
+     def validate(self, code):
+         support.parse_string(code)
diff --git a/patches/link-opt.diff b/patches/link-opt.diff
new file mode 100644 (file)
index 0000000..83c30d3
--- /dev/null
@@ -0,0 +1,24 @@
+# DP: Call the linker with -O1 -Bsymbolic-functions
+
+--- a/configure.ac
++++ b/configure.ac
+@@ -2646,8 +2646,8 @@ then
+               fi
+               ;;
+       Linux*|GNU*|QNX*|VxWorks*)
+-              LDSHARED='$(CC) -shared'
+-              LDCXXSHARED='$(CXX) -shared';;
++              LDSHARED='$(CC) -shared -Wl,-O1 -Wl,-Bsymbolic-functions'
++              LDCXXSHARED='$(CXX) -shared -Wl,-O1 -Wl,-Bsymbolic-functions';;
+       FreeBSD*)
+               if [[ "`$CC -dM -E - </dev/null | grep __ELF__`" != "" ]]
+               then
+@@ -2740,7 +2740,7 @@ then
+           LINKFORSHARED="-Wl,-E -Wl,+s";;
+ #         LINKFORSHARED="-Wl,-E -Wl,+s -Wl,+b\$(BINLIBDEST)/lib-dynload";;
+       Linux-android*) LINKFORSHARED="-pie -Xlinker -export-dynamic";;
+-      Linux*|GNU*) LINKFORSHARED="-Xlinker -export-dynamic";;
++      Linux*|GNU*) LINKFORSHARED="-Xlinker -export-dynamic -Wl,-O1 -Wl,-Bsymbolic-functions";;
+       # -u libsys_s pulls in all symbols in libsys
+       Darwin/*)
+               LINKFORSHARED="$extra_undefs -framework CoreFoundation"
diff --git a/patches/link-timemodule.diff b/patches/link-timemodule.diff
new file mode 100644 (file)
index 0000000..45e4153
--- /dev/null
@@ -0,0 +1,13 @@
+Index: b/Modules/Setup.dist
+===================================================================
+--- a/Modules/Setup.dist
++++ b/Modules/Setup.dist
+@@ -118,7 +118,7 @@ _collections _collectionsmodule.c # Cont
+ itertools itertoolsmodule.c    # Functions creating iterators for efficient looping
+ atexit atexitmodule.c      # Register functions to be run at interpreter-shutdown
+ _stat _stat.c                 # stat.h interface
+-time timemodule.c     # -lm # time operations and variables
++time timemodule.c -lrt        # -lm # time operations and variables
+ # access to ISO C locale support
+ _locale _localemodule.c  # -lintl
diff --git a/patches/local-doc-references.diff b/patches/local-doc-references.diff
new file mode 100644 (file)
index 0000000..e18f2fb
--- /dev/null
@@ -0,0 +1,22 @@
+--- a/Doc/tools/templates/layout.html
++++ b/Doc/tools/templates/layout.html
+@@ -24,7 +24,7 @@
+ {% endblock %}
+ {% block extrahead %}
+-    <link rel="canonical" href="https://docs.python.org/3/{{pagename}}.html" />
++    <link rel="canonical" href="file:///usr/share/doc/python3.8/html/{{pagename}}.html" />
+     {% if builder != "htmlhelp" %}
+       {% if switchers is defined and not embedded %}
+       <script type="text/javascript" src="{{ pathto('_static/switchers.js', 1) }}"></script>{% endif %}
+--- a/Lib/idlelib/help.html
++++ b/Lib/idlelib/help.html
+@@ -25,7 +25,7 @@
+     <link rel="copyright" title="Copyright" href="../copyright.html" />
+     <link rel="next" title="Other Graphical User Interface Packages" href="othergui.html" />
+     <link rel="prev" title="tkinter.tix â€” Extension widgets for Tk" href="tkinter.tix.html" />
+-    <link rel="canonical" href="https://docs.python.org/3/library/idle.html" />
++    <link rel="canonical" href="file:///usr/share/doc/python3.8/html/library/idle.html" />
diff --git a/patches/locale-module.diff b/patches/locale-module.diff
new file mode 100644 (file)
index 0000000..7daf263
--- /dev/null
@@ -0,0 +1,17 @@
+# DP:   * Lib/locale.py:
+# DP:     - Don't map 'utf8', 'utf-8' to 'utf', which is not a known encoding
+# DP:       for glibc.
+
+--- a/Lib/locale.py
++++ b/Lib/locale.py
+@@ -1409,8 +1409,8 @@ locale_alias = {
+     'ug_cn':                                'ug_CN.UTF-8',
+     'uk':                                   'uk_UA.KOI8-U',
+     'uk_ua':                                'uk_UA.KOI8-U',
+-    'univ':                                 'en_US.utf',
+-    'universal':                            'en_US.utf',
++    'univ':                                 'en_US.UTF-8',
++    'universal':                            'en_US.UTF-8',
+     'universal.utf8@ucs4':                  'en_US.UTF-8',
+     'unm_us':                               'unm_US.UTF-8',
+     'ur':                                   'ur_PK.CP1256',
diff --git a/patches/lto-link-flags.diff b/patches/lto-link-flags.diff
new file mode 100644 (file)
index 0000000..57d5d85
--- /dev/null
@@ -0,0 +1,22 @@
+Index: b/Makefile.pre.in
+===================================================================
+--- a/Makefile.pre.in
++++ b/Makefile.pre.in
+@@ -147,7 +147,7 @@ CONFINCLUDEPY=     $(CONFINCLUDEDIR)/python$
+ SHLIB_SUFFIX= @SHLIB_SUFFIX@
+ EXT_SUFFIX=   @EXT_SUFFIX@
+ LDSHARED=     @LDSHARED@ $(PY_LDFLAGS)
+-BLDSHARED=    @BLDSHARED@ $(PY_LDFLAGS)
++BLDSHARED=    @BLDSHARED@ $(PY_LDFLAGS) $(PY_CFLAGS) $(CCSHARED)
+ LDCXXSHARED=  @LDCXXSHARED@
+ DESTSHARED=   $(BINLIBDEST)/lib-dynload
+@@ -577,7 +577,7 @@ clinic: check-clean-src $(srcdir)/Module
+ # Build the interpreter
+ $(BUILDPYTHON):       Programs/python.o $(LIBRARY) $(LDLIBRARY) $(PY3LIBRARY)
+-      $(LINKCC) $(PY_LDFLAGS) $(LINKFORSHARED) -o $@ Programs/python.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST)
++      $(LINKCC) $(PY_LDFLAGS) $(PY_CFLAGS) $(LINKFORSHARED) -o $@ Programs/python.o $(BLDLIBRARY) $(LIBS) $(MODLIBS) $(SYSLIBS) $(LDLAST)
+ platform: $(BUILDPYTHON) pybuilddir.txt
+       $(RUNSHARED) $(PYTHON_FOR_BUILD) -c 'import sys ; from sysconfig import get_platform ; print("%s-%d.%d" % (get_platform(), *sys.version_info[:2]))' >platform
diff --git a/patches/mangle-fstack-protector.diff b/patches/mangle-fstack-protector.diff
new file mode 100644 (file)
index 0000000..d562c80
--- /dev/null
@@ -0,0 +1,24 @@
+# DP: When using GCC versions older than 4.9, automagically mangle
+# DP: -fstack-protector-strong to -fstack-protector
+
+--- a/Lib/distutils/sysconfig.py
++++ b/Lib/distutils/sysconfig.py
+@@ -13,6 +13,7 @@ import _imp
+ import os
+ import re
+ import sys
++import fnmatch
+ from .errors import DistutilsPlatformError
+@@ -220,6 +221,10 @@ def customize_compiler(compiler):
+             cc = newcc
+         if 'CXX' in os.environ:
+             cxx = os.environ['CXX']
++        if fnmatch.filter([cc, cxx], '*-4.[0-8]'):
++            configure_cflags = configure_cflags.replace('-fstack-protector-strong', '-fstack-protector')
++            ldshared = ldshared.replace('-fstack-protector-strong', '-fstack-protector')
++            cflags = cflags.replace('-fstack-protector-strong', '-fstack-protector')
+         if 'LDSHARED' in os.environ:
+             ldshared = os.environ['LDSHARED']
+         if 'CPP' in os.environ:
diff --git a/patches/mpdecimal-2.5.1.diff b/patches/mpdecimal-2.5.1.diff
new file mode 100644 (file)
index 0000000..1917c70
--- /dev/null
@@ -0,0 +1,35 @@
+diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c
+index 664d45a90481d..bbd540bc376e2 100644
+--- a/Modules/_decimal/_decimal.c
++++ b/Modules/_decimal/_decimal.c
+@@ -3295,7 +3295,7 @@ dec_format(PyObject *dec, PyObject *args)
+     }
+     else {
+         size_t n = strlen(spec.dot);
+-        if (n > 1 || (n == 1 && !isascii((uchar)spec.dot[0]))) {
++        if (n > 1 || (n == 1 && !isascii((unsigned char)spec.dot[0]))) {
+             /* fix locale dependent non-ascii characters */
+             dot = dotsep_as_utf8(spec.dot);
+             if (dot == NULL) {
+@@ -3304,7 +3304,7 @@ dec_format(PyObject *dec, PyObject *args)
+             spec.dot = PyBytes_AS_STRING(dot);
+         }
+         n = strlen(spec.sep);
+-        if (n > 1 || (n == 1 && !isascii((uchar)spec.sep[0]))) {
++        if (n > 1 || (n == 1 && !isascii((unsigned char)spec.sep[0]))) {
+             /* fix locale dependent non-ascii characters */
+             sep = dotsep_as_utf8(spec.sep);
+             if (sep == NULL) {
+diff --git a/setup.py b/setup.py
+index ddc0bd067d4e4..c547a68664e8c 100644
+--- a/setup.py
++++ b/setup.py
+@@ -2199,7 +2199,7 @@ def detect_decimal(self):
+         undef_macros = []
+         if '--with-system-libmpdec' in sysconfig.get_config_var("CONFIG_ARGS"):
+             include_dirs = []
+-            libraries = [':libmpdec.so.2']
++            libraries = ['mpdec']
+             sources = ['_decimal/_decimal.c']
+             depends = ['_decimal/docstrings.h']
+         else:
diff --git a/patches/multiarch-extname.diff b/patches/multiarch-extname.diff
new file mode 100644 (file)
index 0000000..680cafc
--- /dev/null
@@ -0,0 +1,86 @@
+# DP: Make sure to rename extensions to a tag including the MULTIARCH name
+this patch can be dropped for python3.5 final, if the upstream chage is kept.
+
+--- a/Lib/distutils/dir_util.py
++++ b/Lib/distutils/dir_util.py
+@@ -96,6 +96,9 @@ def create_tree(base_dir, files, mode=0o
+     for dir in sorted(need_dir):
+         mkpath(dir, mode, verbose=verbose, dry_run=dry_run)
++import sysconfig
++_multiarch = None
++
+ def copy_tree(src, dst, preserve_mode=1, preserve_times=1,
+               preserve_symlinks=0, update=0, verbose=1, dry_run=0):
+     """Copy an entire directory tree 'src' to a new location 'dst'.
+@@ -131,6 +134,13 @@ def copy_tree(src, dst, preserve_mode=1,
+             raise DistutilsFileError(
+                   "error listing files in '%s': %s" % (src, e.strerror))
++    ext_suffix = sysconfig.get_config_var ('EXT_SUFFIX')
++    _multiarch = sysconfig.get_config_var ('MULTIARCH')
++    if ext_suffix.endswith(_multiarch + ext_suffix[-3:]):
++        new_suffix = None
++    else:
++        new_suffix = "%s-%s%s" % (ext_suffix[:-3], _multiarch, ext_suffix[-3:])
++
+     if not dry_run:
+         mkpath(dst, verbose=verbose)
+@@ -139,6 +149,9 @@ def copy_tree(src, dst, preserve_mode=1,
+     for n in names:
+         src_name = os.path.join(src, n)
+         dst_name = os.path.join(dst, n)
++        if new_suffix and _multiarch and n.endswith(ext_suffix) and not n.endswith(new_suffix):
++            dst_name = os.path.join(dst, n.replace(ext_suffix, new_suffix))
++            log.info("renaming extension %s -> %s", n, n.replace(ext_suffix, new_suffix))
+         if n.startswith('.nfs'):
+             # skip NFS rename files
+--- a/Lib/distutils/command/install_lib.py
++++ b/Lib/distutils/command/install_lib.py
+@@ -56,6 +56,7 @@ class install_lib(Command):
+         self.compile = None
+         self.optimize = None
+         self.skip_build = None
++        self.multiarch = None # if we should rename the extensions
+     def finalize_options(self):
+         # Get all the information we need to install pure Python modules
+@@ -68,6 +69,7 @@ class install_lib(Command):
+                                    ('compile', 'compile'),
+                                    ('optimize', 'optimize'),
+                                    ('skip_build', 'skip_build'),
++                                   ('multiarch', 'multiarch'),
+                                   )
+         if self.compile is None:
+@@ -108,6 +110,8 @@ class install_lib(Command):
+     def install(self):
+         if os.path.isdir(self.build_dir):
++            import distutils.dir_util
++            distutils.dir_util._multiarch = self.multiarch
+             outfiles = self.copy_tree(self.build_dir, self.install_dir)
+         else:
+             self.warn("'%s' does not exist -- no Python modules to install" %
+--- a/Lib/distutils/command/install.py
++++ b/Lib/distutils/command/install.py
+@@ -192,6 +192,7 @@ class install(Command):
+         # enable custom installation, known values: deb
+         self.install_layout = None
++        self.multiarch = None
+         
+         self.compile = None
+         self.optimize = None
+@@ -452,6 +453,8 @@ class install(Command):
+             self.install_platbase = self.exec_prefix
+             if self.install_layout:
+                 if self.install_layout.lower() in ['deb']:
++                    import sysconfig
++                    self.multiarch = sysconfig.get_config_var('MULTIARCH')
+                     self.select_scheme("deb_system")
+                 elif self.install_layout.lower() in ['unix']:
+                     self.select_scheme("unix_prefix")
diff --git a/patches/multiarch.diff b/patches/multiarch.diff
new file mode 100644 (file)
index 0000000..ac38033
--- /dev/null
@@ -0,0 +1,46 @@
+--- a/Lib/sysconfig.py
++++ b/Lib/sysconfig.py
+@@ -558,6 +558,12 @@ def get_config_vars(*args):
+         # the init-function.
+         _CONFIG_VARS['userbase'] = _getuserbase()
++        multiarch = get_config_var('MULTIARCH')
++        if multiarch:
++            _CONFIG_VARS['multiarchsubdir'] = '/' + multiarch
++        else:
++            _CONFIG_VARS['multiarchsubdir'] = ''
++
+         # Always convert srcdir to an absolute path
+         srcdir = _CONFIG_VARS.get('srcdir', _PROJECT_BASE)
+         if os.name == 'posix':
+--- a/Lib/distutils/sysconfig.py
++++ b/Lib/distutils/sysconfig.py
+@@ -110,6 +110,9 @@ def get_python_inc(plat_specific=0, pref
+                 incdir = os.path.join(get_config_var('srcdir'), 'Include')
+                 return os.path.normpath(incdir)
+         python_dir = 'python' + get_python_version() + build_flags
++        if not python_build and plat_specific:
++            import sysconfig
++            return sysconfig.get_path('platinclude')
+         return os.path.join(prefix, "include", python_dir)
+     elif os.name == "nt":
+         if python_build:
+--- a/Makefile.pre.in
++++ b/Makefile.pre.in
+@@ -813,6 +813,7 @@ Modules/signalmodule.o: $(srcdir)/Module
+ Python/dynload_shlib.o: $(srcdir)/Python/dynload_shlib.c Makefile
+       $(CC) -c $(PY_CORE_CFLAGS) \
++              $(if $(MULTIARCH),-DMULTIARCH='"$(MULTIARCH)"') \
+               -DSOABI='"$(SOABI)"' \
+               -o $@ $(srcdir)/Python/dynload_shlib.c
+@@ -1629,7 +1630,7 @@ inclinstall:
+ LIBPL=                @LIBPL@
+ # pkgconfig directory
+-LIBPC=                $(LIBDIR)/pkgconfig
++LIBPC=                $(LIBDIR)/$(MULTIARCH)/pkgconfig
+ libainstall:  @DEF_MAKE_RULE@ python-config
+       @for i in $(LIBDIR) $(LIBPL) $(LIBPC); \
diff --git a/patches/profiled-build.diff b/patches/profiled-build.diff
new file mode 100644 (file)
index 0000000..0b33096
--- /dev/null
@@ -0,0 +1,21 @@
+# DP: Ignore errors in the profile task.
+
+--- a/Makefile.pre.in
++++ b/Makefile.pre.in
+@@ -521,6 +521,16 @@ build_all_generate_profile:
+ run_profile_task:
+       @ # FIXME: can't run for a cross build
+       $(LLVM_PROF_FILE) $(RUNSHARED) ./$(BUILDPYTHON) $(PROFILE_TASK) || true
++      task="$(PROFILE_TASK)"; \
++      case "$$task" in \
++      *-s\ *) \
++        $(LLVM_PROF_FILE) $(RUNSHARED) ./$(BUILDPYTHON) $$task; \
++        while [ -f $(abs_builddir)/build/pynexttest ]; do \
++          $(LLVM_PROF_FILE) $(RUNSHARED) ./$(BUILDPYTHON) $$task; \
++        done;; \
++      *) \
++        $(LLVM_PROF_FILE) $(RUNSHARED) ./$(BUILDPYTHON) $$task; \
++      esac
+ build_all_merge_profile:
+       $(LLVM_PROF_MERGER)
diff --git a/patches/pydoc-use-pager.diff b/patches/pydoc-use-pager.diff
new file mode 100644 (file)
index 0000000..a7480c6
--- /dev/null
@@ -0,0 +1,13 @@
+# DP: pydoc: use the pager command if available.
+
+--- a/Lib/pydoc.py
++++ b/Lib/pydoc.py
+@@ -1578,6 +1578,8 @@ def getpager():
+         return plainpager
+     if sys.platform == 'win32':
+         return lambda text: tempfilepager(plain(text), 'more <')
++    if hasattr(os, 'system') and os.system('(pager) 2>/dev/null') == 0:
++        return lambda text: pipepager(text, 'pager')
+     if hasattr(os, 'system') and os.system('(less) 2>/dev/null') == 0:
+         return lambda text: pipepager(text, 'less')
diff --git a/patches/reproducible-buildinfo.diff b/patches/reproducible-buildinfo.diff
new file mode 100644 (file)
index 0000000..807d180
--- /dev/null
@@ -0,0 +1,13 @@
+# DP: Build getbuildinfo.o with DATE/TIME values when defined
+
+--- a/Makefile.pre.in
++++ b/Makefile.pre.in
+@@ -785,6 +785,8 @@ Modules/getbuildinfo.o: $(PARSER_OBJS) \
+             -DGITVERSION="\"`LC_ALL=C $(GITVERSION)`\"" \
+             -DGITTAG="\"`LC_ALL=C $(GITTAG)`\"" \
+             -DGITBRANCH="\"`LC_ALL=C $(GITBRANCH)`\"" \
++            $(if $(BUILD_DATE),-DDATE='"$(BUILD_DATE)"') \
++            $(if $(BUILD_TIME),-DTIME='"$(BUILD_TIME)"') \
+             -o $@ $(srcdir)/Modules/getbuildinfo.c
+ Modules/getpath.o: $(srcdir)/Modules/getpath.c Makefile
diff --git a/patches/series b/patches/series
new file mode 100644 (file)
index 0000000..3f4e6f5
--- /dev/null
@@ -0,0 +1,41 @@
+git-updates.diff
+deb-setup.diff
+deb-locations.diff
+distutils-install-layout.diff
+locale-module.diff
+distutils-link.diff
+distutils-sysconfig.diff
+#sysconfig-debian-schemes.diff
+tkinter-import.diff
+gdbm-import.diff
+link-opt.diff
+setup-modules.diff
+bdist-wininst-notfound.diff
+profiled-build.diff
+langpack-gettext.diff
+disable-sem-check.diff
+lib-argparse.diff
+ctypes-arm.diff
+# link-timemodule.diff
+#lto-link-flags.diff
+multiarch.diff
+lib2to3-no-pickled-grammar.diff
+ext-no-libpython-link.diff
+test-no-random-order.diff
+multiarch-extname.diff
+tempfile-minimal.diff
+disable-some-tests.diff
+ensurepip-wheels.diff
+ensurepip-disabled.diff
+mangle-fstack-protector.diff
+reproducible-buildinfo.diff
+pydoc-use-pager.diff
+local-doc-references.diff
+doc-build-texinfo.diff
+build-math-object.diff
+argparse-no-shutil.diff
+arm-alignment.diff
+sysconfigdata-name.diff
+hurd_kfreebsd_thread_native_id.diff
+sphinx3.diff
+mpdecimal-2.5.1.diff
diff --git a/patches/setup-modules.diff b/patches/setup-modules.diff
new file mode 100644 (file)
index 0000000..2d2e918
--- /dev/null
@@ -0,0 +1,48 @@
+--- a/Modules/Setup
++++ b/Modules/Setup
+@@ -178,7 +178,7 @@ _symtable symtablemodule.c
+ #_testcapi _testcapimodule.c    # Python C API test module
+ #_testinternalcapi _testinternalcapi.c -I$(srcdir)/Include/internal -DPy_BUILD_CORE_MODULE  # Python internal C API test module
+ #_random _randommodule.c -DPy_BUILD_CORE_MODULE       # Random number generator
+-#_elementtree -I$(srcdir)/Modules/expat -DHAVE_EXPAT_CONFIG_H -DUSE_PYEXPAT_CAPI _elementtree.c       # elementtree accelerator
++#_elementtree _elementtree.c -lexpat  # elementtree accelerator
+ #_pickle _pickle.c    # pickle accelerator
+ #_datetime _datetimemodule.c  # datetime accelerator
+ #_zoneinfo _zoneinfo.c        # zoneinfo accelerator
+@@ -211,10 +211,7 @@ _symtable symtablemodule.c
+ # Socket module helper for SSL support; you must comment out the other
+ # socket line above, and possibly edit the SSL variable:
+-#SSL=/usr/local/ssl
+-#_ssl _ssl.c \
+-#     -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
+-#     -L$(SSL)/lib -lssl -lcrypto
++#_ssl _ssl.c -lssl -lcrypto
+ # The crypt module is now disabled by default because it breaks builds
+ # on many systems (where -lcrypt is needed), e.g. Linux (I believe).
+@@ -247,6 +244,7 @@ _symtable symtablemodule.c
+ #_md5 md5module.c
++#_hashlib _hashopenssl.c -lssl -lcrypto
+ # The _sha module implements the SHA checksum algorithms.
+ # (NIST's Secure Hash Algorithms.)
+@@ -334,6 +332,7 @@ _symtable symtablemodule.c
+ # Fred Drake's interface to the Python parser
+ #parser parsermodule.c
++#_ctypes _ctypes/_ctypes.c _ctypes/callbacks.c _ctypes/callproc.c _ctypes/stgdict.c _ctypes/cfield.c _ctypes/malloc_closure.c -lffi
+ # Andrew Kuchling's zlib module.
+ # This require zlib 1.1.3 (or later).
+@@ -343,7 +342,7 @@ _symtable symtablemodule.c
+ # Interface to the Expat XML parser
+ # More information on Expat can be found at www.libexpat.org.
+ #
+-#pyexpat expat/xmlparse.c expat/xmlrole.c expat/xmltok.c pyexpat.c -I$(srcdir)/Modules/expat -DHAVE_EXPAT_CONFIG_H -DXML_POOR_ENTROPY -DUSE_PYEXPAT_CAPI
++pyexpat pyexpat.c -lexpat
+ # Hye-Shik Chang's CJKCodecs
diff --git a/patches/sphinx3.diff b/patches/sphinx3.diff
new file mode 100644 (file)
index 0000000..5903830
--- /dev/null
@@ -0,0 +1,24 @@
+--- a/Doc/conf.py
++++ b/Doc/conf.py
+@@ -62,6 +62,10 @@ smartquotes_excludes = {
+ # Avoid a warning with Sphinx >= 2.0
+ master_doc = 'contents'
++# Allow to build with Sphinx >= 3.2
++c_allow_pre_v3 = True
++c_warn_on_allowed_pre_v3 = False
++
+ # Options for HTML output
+ # -----------------------
+--- a/Doc/Makefile
++++ b/Doc/Makefile
+@@ -11,7 +11,7 @@ BLURB        = PATH=$(VENVDIR)/bin:$$PAT
+ PAPER        =
+ SOURCES      =
+ DISTVERSION  = $(shell $(PYTHON) tools/extensions/patchlevel.py)
+-SPHINXERRORHANDLING = -W
++#SPHINXERRORHANDLING = -W
+ # Internal variables.
+ PAPEROPT_a4     = -D latex_elements.papersize=a4paper
diff --git a/patches/sysconfig-debian-schemes.diff b/patches/sysconfig-debian-schemes.diff
new file mode 100644 (file)
index 0000000..07eb5bf
--- /dev/null
@@ -0,0 +1,88 @@
+# DP: Add schemes 'deb_system' and 'posix_local', make the latter the default
+
+Index: b/Lib/sysconfig.py
+===================================================================
+--- a/Lib/sysconfig.py
++++ b/Lib/sysconfig.py
+@@ -31,6 +31,30 @@ _INSTALL_SCHEMES = {
+         'scripts': '{base}/bin',
+         'data': '{base}',
+         },
++    'deb_system': {
++        'stdlib': '{installed_base}/lib/python{py_version_short}',
++        'platstdlib': '{platbase}/lib/python{py_version_short}',
++        'purelib': '{base}/lib/python3/dist-packages',
++        'platlib': '{platbase}/lib/python3/dist-packages',
++        'include':
++            '{installed_base}/include/python{py_version_short}{abiflags}',
++        'platinclude':
++            '{installed_platbase}/include/python{py_version_short}{abiflags}',
++        'scripts': '{base}/bin',
++        'data': '{base}',
++        },
++    'posix_local': {
++        'stdlib': '{installed_base}/lib/python{py_version_short}',
++        'platstdlib': '{platbase}/lib/python{py_version_short}',
++        'purelib': '{base}/local/lib/python{py_version_short}/dist-packages',
++        'platlib': '{platbase}/local/lib/python{py_version_short}/dist-packages',
++        'include':
++            '{installed_base}/local/include/python{py_version_short}{abiflags}',
++        'platinclude':
++            '{installed_platbase}/local/include/python{py_version_short}{abiflags}',
++        'scripts': '{base}/local/bin',
++        'data': '{base}',
++        },
+     'posix_home': {
+         'stdlib': '{installed_base}/lib/python',
+         'platstdlib': '{base}/lib/python',
+@@ -136,7 +160,7 @@ def is_python_build(check_home=False):
+ _PYTHON_BUILD = is_python_build(True)
+ if _PYTHON_BUILD:
+-    for scheme in ('posix_prefix', 'posix_home'):
++    for scheme in ('posix_prefix', 'posix_home', 'posix_local', 'deb_system'):
+         _INSTALL_SCHEMES[scheme]['include'] = '{srcdir}/Include'
+         _INSTALL_SCHEMES[scheme]['platinclude'] = '{projectbase}/.'
+@@ -174,7 +198,16 @@ def _expand_vars(scheme, vars):
+ def _get_default_scheme():
+     if os.name == 'posix':
+         # the default scheme for posix is posix_prefix
+-        return 'posix_prefix'
++        if 'real_prefix' in sys.__dict__ or 'VIRTUAL_ENV' in os.environ:
++            # virtual environments
++            return 'posix_prefix'
++        else:
++            # default to /usr for package builds, /usr/local otherwise
++            deb_build = os.environ.get('DEB_PYTHON_INSTALL_LAYOUT', 'posix_local')
++            if deb_build in ('deb', 'deb_system'):
++                return 'deb_system'
++            else:
++                return 'posix_local'
+     return os.name
+@@ -472,7 +505,7 @@ def get_config_h_filename():
+         else:
+             inc_dir = _sys_home or _PROJECT_BASE
+     else:
+-        inc_dir = get_path('platinclude')
++        inc_dir = get_path('platinclude', 'posix_prefix')
+     return os.path.join(inc_dir, 'pyconfig.h')
+Index: b/Lib/test/test_sysconfig.py
+===================================================================
+--- a/Lib/test/test_sysconfig.py
++++ b/Lib/test/test_sysconfig.py
+@@ -227,8 +227,8 @@ class TestSysConfig(unittest.TestCase):
+         self.assertTrue(os.path.isfile(config_h), config_h)
+     def test_get_scheme_names(self):
+-        wanted = ('nt', 'nt_user', 'osx_framework_user',
+-                  'posix_home', 'posix_prefix', 'posix_user')
++        wanted = ('deb_system', 'nt', 'nt_user', 'osx_framework_user',
++                  'posix_home', 'posix_local', 'posix_prefix', 'posix_user')
+         self.assertEqual(get_scheme_names(), wanted)
+     @skip_unless_symlink
diff --git a/patches/sysconfigdata-name.diff b/patches/sysconfigdata-name.diff
new file mode 100644 (file)
index 0000000..dff60b4
--- /dev/null
@@ -0,0 +1,60 @@
+--- a/Lib/sysconfig.py
++++ b/Lib/sysconfig.py
+@@ -343,9 +343,8 @@ def get_makefile_filename():
+ def _get_sysconfigdata_name():
+     return os.environ.get('_PYTHON_SYSCONFIGDATA_NAME',
+-        '_sysconfigdata_{abi}_{platform}_{multiarch}'.format(
++        '_sysconfigdata_{abi}_{multiarch}'.format(
+         abi=sys.abiflags,
+-        platform=sys.platform,
+         multiarch=getattr(sys.implementation, '_multiarch', ''),
+     ))
+--- a/Makefile.pre.in
++++ b/Makefile.pre.in
+@@ -1536,8 +1536,10 @@ libinstall:     build_all $(srcdir)/Modules/
+                       esac; \
+               done; \
+       done
+-      $(INSTALL_DATA) `cat pybuilddir.txt`/_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH).py \
+-              $(DESTDIR)$(LIBDEST); \
++      $(INSTALL_DATA) `cat pybuilddir.txt`/_sysconfigdata_$(ABIFLAGS)_$(MULTIARCH).py \
++              $(DESTDIR)$(LIBDEST)
++      $(LN) -s _sysconfigdata_$(ABIFLAGS)_$(MULTIARCH).py \
++              $(DESTDIR)$(LIBDEST)/_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH).py
+       $(INSTALL_DATA) $(srcdir)/LICENSE $(DESTDIR)$(LIBDEST)/LICENSE.txt
+       if test -d $(DESTDIR)$(LIBDEST)/distutils/tests; then \
+               $(INSTALL_DATA) $(srcdir)/Modules/xxmodule.c \
+@@ -1692,6 +1694,7 @@ sharedinstall: sharedmods
+               --install-scripts=$(BINDIR) \
+               --install-platlib=$(DESTSHARED) \
+               --root=$(DESTDIR)/
++      -rm $(DESTDIR)$(DESTSHARED)/_sysconfigdata_$(ABIFLAGS)_$(MULTIARCH).py
+       -rm $(DESTDIR)$(DESTSHARED)/_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH).py
+       -rm -r $(DESTDIR)$(DESTSHARED)/__pycache__
+--- a/Lib/distutils/sysconfig.py
++++ b/Lib/distutils/sysconfig.py
+@@ -465,9 +465,8 @@ def _init_posix():
+     """Initialize the module as appropriate for POSIX systems."""
+     # _sysconfigdata is generated at build time, see the sysconfig module
+     name = os.environ.get('_PYTHON_SYSCONFIGDATA_NAME',
+-        '_sysconfigdata_{abi}_{platform}_{multiarch}'.format(
++        '_sysconfigdata_{abi}_{multiarch}'.format(
+         abi=sys.abiflags,
+-        platform=sys.platform,
+         multiarch=getattr(sys.implementation, '_multiarch', ''),
+     ))
+     _temp = __import__(name, globals(), locals(), ['build_time_vars'], 0)
+--- a/configure.ac
++++ b/configure.ac
+@@ -75,7 +75,7 @@ if test "$cross_compiling" = yes; then
+           AC_MSG_ERROR([python$PACKAGE_VERSION interpreter not found])
+       fi
+         AC_MSG_RESULT($interp)
+-      PYTHON_FOR_BUILD='_PYTHON_PROJECT_BASE=$(abs_builddir) _PYTHON_HOST_PLATFORM=$(_PYTHON_HOST_PLATFORM) PYTHONPATH=$(shell test -f pybuilddir.txt && echo $(abs_builddir)/`cat pybuilddir.txt`:)$(srcdir)/Lib _PYTHON_SYSCONFIGDATA_NAME=_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH) '$interp
++      PYTHON_FOR_BUILD='_PYTHON_PROJECT_BASE=$(abs_builddir) _PYTHON_HOST_PLATFORM=$(_PYTHON_HOST_PLATFORM) PYTHONPATH=$(shell test -f pybuilddir.txt && echo $(abs_builddir)/`cat pybuilddir.txt`:)$(srcdir)/Lib _PYTHON_SYSCONFIGDATA_NAME=_sysconfigdata_$(ABIFLAGS)_$(MULTIARCH) '$interp
+     fi
+ elif test "$cross_compiling" = maybe; then
+     AC_MSG_ERROR([Cross compiling required --host=HOST-TUPLE and --build=ARCH])
diff --git a/patches/tempfile-minimal.diff b/patches/tempfile-minimal.diff
new file mode 100644 (file)
index 0000000..2931b63
--- /dev/null
@@ -0,0 +1,161 @@
+# DP: Avoid shutil import when it is not available.
+
+--- a/Lib/tempfile.py
++++ b/Lib/tempfile.py
+@@ -40,7 +40,146 @@ import functools as _functools
+ import warnings as _warnings
+ import io as _io
+ import os as _os
+-import shutil as _shutil
++try:
++  import shutil as _shutil
++  _rmtree = _shutil.rmtree
++except ImportError:
++  import sys as _sys
++  import stat as _stat
++  # version vulnerable to race conditions
++  def _rmtree_unsafe(path, onerror):
++    try:
++        if _os.path.islink(path):
++            # symlinks to directories are forbidden, see bug #1669
++            raise OSError("Cannot call rmtree on a symbolic link")
++    except OSError:
++        onerror(_os.path.islink, path, _sys.exc_info())
++        # can't continue even if onerror hook returns
++        return
++    names = []
++    try:
++        names = _os.listdir(path)
++    except OSError:
++        onerror(_os.listdir, path, _sys.exc_info())
++    for name in names:
++        fullname = _os.path.join(path, name)
++        try:
++            mode = _os.lstat(fullname).st_mode
++        except OSError:
++            mode = 0
++        if _stat.S_ISDIR(mode):
++            _rmtree_unsafe(fullname, onerror)
++        else:
++            try:
++                _os.unlink(fullname)
++            except OSError:
++                onerror(_os.unlink, fullname, _sys.exc_info())
++    try:
++        _os.rmdir(path)
++    except OSError:
++        onerror(_os.rmdir, path, _sys.exc_info())
++
++  # Version using fd-based APIs to protect against races
++  def _rmtree_safe_fd(topfd, path, onerror):
++    names = []
++    try:
++        names = _os.listdir(topfd)
++    except OSError as err:
++        err.filename = path
++        onerror(_os.listdir, path, _sys.exc_info())
++    for name in names:
++        fullname = _os.path.join(path, name)
++        try:
++            orig_st = _os.stat(name, dir_fd=topfd, follow_symlinks=False)
++            mode = orig_st.st_mode
++        except OSError:
++            mode = 0
++        if _stat.S_ISDIR(mode):
++            try:
++                dirfd = _os.open(name, _os.O_RDONLY, dir_fd=topfd)
++            except OSError:
++                onerror(_os.open, fullname, _sys.exc_info())
++            else:
++                try:
++                    if _os.path.samestat(orig_st, _os.fstat(dirfd)):
++                        _rmtree_safe_fd(dirfd, fullname, onerror)
++                        try:
++                            _os.rmdir(name, dir_fd=topfd)
++                        except OSError:
++                            onerror(_os.rmdir, fullname, _sys.exc_info())
++                    else:
++                        try:
++                            # This can only happen if someone replaces
++                            # a directory with a symlink after the call to
++                            # stat.S_ISDIR above.
++                            raise OSError("Cannot call rmtree on a symbolic "
++                                          "link")
++                        except OSError:
++                            onerror(_os.path.islink, fullname, _sys.exc_info())
++                finally:
++                    _os.close(dirfd)
++        else:
++            try:
++                _os.unlink(name, dir_fd=topfd)
++            except OSError:
++                onerror(_os.unlink, fullname, _sys.exc_info())
++
++  _use_fd_functions = ({_os.open, _os.stat, _os.unlink, _os.rmdir} <=
++                     _os.supports_dir_fd and
++                     _os.listdir in _os.supports_fd and
++                     _os.stat in _os.supports_follow_symlinks)
++
++  def _rmtree(path, ignore_errors=False, onerror=None):
++    """Recursively delete a directory tree.
++
++    If ignore_errors is set, errors are ignored; otherwise, if onerror
++    is set, it is called to handle the error with arguments (func,
++    path, exc_info) where func is platform and implementation dependent;
++    path is the argument to that function that caused it to fail; and
++    exc_info is a tuple returned by sys.exc_info().  If ignore_errors
++    is false and onerror is None, an exception is raised.
++
++    """
++    if ignore_errors:
++        def onerror(*args):
++            pass
++    elif onerror is None:
++        def onerror(*args):
++            raise
++    if _use_fd_functions:
++        # While the unsafe rmtree works fine on bytes, the fd based does not.
++        if isinstance(path, bytes):
++            path = _os.fsdecode(path)
++        # Note: To guard against symlink races, we use the standard
++        # lstat()/open()/fstat() trick.
++        try:
++            orig_st = _os.lstat(path)
++        except Exception:
++            onerror(_os.lstat, path, _sys.exc_info())
++            return
++        try:
++            fd = _os.open(path, _os.O_RDONLY)
++        except Exception:
++            onerror(_os.lstat, path, _sys.exc_info())
++            return
++        try:
++            if _os.path.samestat(orig_st, _os.fstat(fd)):
++                _rmtree_safe_fd(fd, path, onerror)
++                try:
++                    _os.rmdir(path)
++                except OSError:
++                    onerror(_os.rmdir, path, _sys.exc_info())
++            else:
++                try:
++                    # symlinks to directories are forbidden, see bug #1669
++                    raise OSError("Cannot call rmtree on a symbolic link")
++                except OSError:
++                    onerror(_os.path.islink, path, _sys.exc_info())
++        finally:
++            _os.close(fd)
++    else:
++        return _rmtree_unsafe(path, onerror)
++
+ import errno as _errno
+ from random import Random as _Random
+ import sys as _sys
+@@ -809,7 +948,7 @@ class TemporaryDirectory(object):
+             else:
+                 raise
+-        _shutil.rmtree(name, onerror=onerror)
++        _rmtree(name, onerror=onerror)
+     @classmethod
+     def _cleanup(cls, name, warn_message):
diff --git a/patches/test-no-random-order.diff b/patches/test-no-random-order.diff
new file mode 100644 (file)
index 0000000..15a45ff
--- /dev/null
@@ -0,0 +1,12 @@
+# DP: Don't run the test suite in random order.
+
+--- a/Tools/scripts/run_tests.py
++++ b/Tools/scripts/run_tests.py
+@@ -33,7 +33,6 @@ def main(regrtest_args):
+     args.extend(test.support.args_from_interpreter_flags())
+     args.extend(['-m', 'test',    # Run the test suite
+-                 '-r',            # Randomize test order
+                  '-w',            # Re-run failed tests in verbose mode
+                  ])
+     if sys.platform == 'win32':
diff --git a/patches/tkinter-import.diff b/patches/tkinter-import.diff
new file mode 100644 (file)
index 0000000..4a0df51
--- /dev/null
@@ -0,0 +1,16 @@
+# DP: suggest installation of python-tk package on failing _tkinter import
+
+--- a/Lib/tkinter/__init__.py
++++ b/Lib/tkinter/__init__.py
+@@ -34,7 +34,10 @@ import enum
+ import sys
+ import types
+-import _tkinter # If this fails your Python may not be configured for Tk
++try:
++    import _tkinter
++except ImportError as msg:
++    raise ImportError(str(msg) + ', please install the python3-tk package')
+ TclError = _tkinter.TclError
+ from tkinter.constants import *
+ import re
diff --git a/pdb.1.in b/pdb.1.in
new file mode 100644 (file)
index 0000000..1b38538
--- /dev/null
+++ b/pdb.1.in
@@ -0,0 +1,16 @@
+.TH PDB@VER@ 1
+.SH NAME
+pdb@VER@ \- the Python debugger
+.SH SYNOPSIS
+.PP
+.B pdb@VER@
+.I script [...]
+.SH DESCRIPTION
+.PP
+See the chapter "The Python Debugger" in the Python Library Reference
+for more information on the use of pdb.  When the debugger is started,
+help is available via the help command.
+.SH SEE ALSO
+python@VER@(1). Chapter "The Python Debugger" of the Python Library
+Reference. Available in the python@VER@-doc package at
+/usr/share/doc/python@VER@/html/library/pdb.html.
diff --git a/pydoc.1.in b/pydoc.1.in
new file mode 100644 (file)
index 0000000..a646e15
--- /dev/null
@@ -0,0 +1,53 @@
+.TH PYDOC@VER@ 1
+.SH NAME
+pydoc@VER@ \- the Python documentation tool
+.SH SYNOPSIS
+.PP
+.B pydoc@VER@
+.I name
+.PP
+.B pydoc@VER@ -k
+.I keyword
+.PP
+.B pydoc@VER@ -p
+.I port
+.PP
+.B pydoc@VER@ -g
+.PP
+.B pydoc@VER@ -w
+.I module [...]
+.SH DESCRIPTION
+.PP
+.B pydoc@VER@
+.I name
+Show text documentation on something.
+.I name
+may be the name of a
+Python keyword, topic, function, module, or package, or a dotted
+reference to a class or function within a module or module in a
+package.  If
+.I name
+contains a '/', it is used as the path to a
+Python source file to document. If name is 'keywords', 'topics',
+or 'modules', a listing of these things is displayed.
+.PP
+.B pydoc@VER@ -k
+.I keyword
+Search for a keyword in the synopsis lines of all available modules.
+.PP
+.B pydoc@VER@ -p
+.I port
+Start an HTTP server on the given port on the local machine.
+.PP
+.B pydoc@VER@ -g
+Pop up a graphical interface for finding and serving documentation.
+.PP
+.B pydoc@VER@ -w
+.I name [...]
+Write out the HTML documentation for a module to a file in the current
+directory.  If
+.I name
+contains a '/', it is treated as a filename; if
+it names a directory, documentation is written for all the contents.
+.SH AUTHOR
+Moshe Zadka, based on "pydoc --help"
diff --git a/pygettext.1 b/pygettext.1
new file mode 100644 (file)
index 0000000..1140167
--- /dev/null
@@ -0,0 +1,108 @@
+.TH PYGETTEXT 1 "" "pygettext 1.4"
+.SH NAME
+pygettext \- Python equivalent of xgettext(1)
+.SH SYNOPSIS
+.B pygettext
+[\fIOPTIONS\fR] \fIINPUTFILE \fR...
+.SH DESCRIPTION
+pygettext is deprecated. The current version of xgettext supports
+many languages, including Python.
+
+pygettext uses Python's standard tokenize module to scan Python
+source code, generating .pot files identical to what GNU xgettext generates
+for C and C++ code.  From there, the standard GNU tools can be used.
+.PP
+pygettext searches only for _() by default, even though GNU xgettext
+recognizes the following keywords: gettext, dgettext, dcgettext,
+and gettext_noop. See the \fB\-k\fR/\fB\--keyword\fR flag below for how to
+augment this.
+.PP
+.SH OPTIONS
+.TP
+\fB\-a\fR, \fB\-\-extract\-all\fR
+Extract all strings.
+.TP
+\fB\-d\fR, \fB\-\-default\-domain\fR=\fINAME\fR
+Rename the default output file from messages.pot to name.pot.
+.TP
+\fB\-E\fR, \fB\-\-escape\fR
+Replace non-ASCII characters with octal escape sequences.
+.TP
+\fB\-D\fR, \fB\-\-docstrings\fR
+Extract module, class, method, and function docstrings.
+These do not need to be wrapped in _() markers, and in fact cannot
+be for Python to consider them docstrings. (See also the \fB\-X\fR option).
+.TP
+\fB\-h\fR, \fB\-\-help\fR
+Print this help message and exit.
+.TP
+\fB\-k\fR, \fB\-\-keyword\fR=\fIWORD\fR
+Keywords to look for in addition to the default set, which are: _
+.IP
+You can have multiple \fB\-k\fR flags on the command line.
+.TP
+\fB\-K\fR, \fB\-\-no\-default\-keywords\fR
+Disable the default set of keywords (see above).
+Any keywords explicitly added with the \fB\-k\fR/\fB\--keyword\fR option
+are still recognized.
+.TP
+\fB\-\-no\-location\fR
+Do not write filename/lineno location comments.
+.TP
+\fB\-n\fR, \fB\-\-add\-location\fR
+Write filename/lineno location comments indicating where each
+extracted string is found in the source.  These lines appear before
+each msgid.  The style of comments is controlled by the
+\fB\-S\fR/\fB\--style\fR option.  This is the default.
+.TP
+\fB\-o\fR, \fB\-\-output\fR=\fIFILENAME\fR
+Rename the default output file from messages.pot to FILENAME.
+If FILENAME is `-' then the output is sent to standard out.
+.TP
+\fB\-p\fR, \fB\-\-output\-dir\fR=\fIDIR\fR
+Output files will be placed in directory DIR.
+.TP
+\fB\-S\fR, \fB\-\-style\fR=\fISTYLENAME\fR
+Specify which style to use for location comments.
+Two styles are supported:
+.RS
+.IP \(bu 4
+Solaris        # File: filename, line: line-number
+.IP \(bu 4
+GNU            #: filename:line
+.RE
+.IP
+The style name is case insensitive.
+GNU style is the default.
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Print the names of the files being processed.
+.TP
+\fB\-V\fR, \fB\-\-version\fR
+Print the version of pygettext and exit.
+.TP
+\fB\-w\fR, \fB\-\-width\fR=\fICOLUMNS\fR
+Set width of output to columns.
+.TP
+\fB\-x\fR, \fB\-\-exclude\-file\fR=\fIFILENAME\fR
+Specify a file that contains a list of strings that are not be
+extracted from the input files.  Each string to be excluded must
+appear on a line by itself in the file.
+.TP
+\fB\-X\fR, \fB\-\-no\-docstrings\fR=\fIFILENAME\fR
+Specify a file that contains a list of files (one per line) that
+should not have their docstrings extracted.  This is only useful in
+conjunction with the \fB\-D\fR option above.
+.PP
+If `INPUTFILE' is -, standard input is read.
+.SH BUGS
+pygettext attempts to be option and feature compatible with GNU xgettext
+where ever possible.  However some options are still missing or are not fully
+implemented.  Also, xgettext's use of command line switches with option
+arguments is broken, and in these cases, pygettext just defines additional
+switches.
+.SH AUTHOR
+pygettext is written by Barry Warsaw <barry@zope.com>.
+.PP
+Joonas Paalasmaa <joonas.paalasmaa@iki.fi> put this manual page together
+based on "pygettext --help".
diff --git a/pyhtml2devhelp.py b/pyhtml2devhelp.py
new file mode 100644 (file)
index 0000000..7d1c8d9
--- /dev/null
@@ -0,0 +1,279 @@
+#! /usr/bin/python3
+
+from html.parser import HTMLParser
+from xml.sax.saxutils import escape
+import os, sys, re
+
+class PyHTMLParser(HTMLParser):
+    pages_to_include = set(('whatsnew/index.html', 'tutorial/index.html', 'using/index.html',
+                            'reference/index.html', 'library/index.html', 'howto/index.html',
+                            'extending/index.html', 'c-api/index.html', 'install/index.html',
+                            'distutils/index.html'))
+
+    def __init__(self, basedir, fn, indent, parents=set()):
+        HTMLParser.__init__(self, convert_charrefs=True)
+        self.basedir = basedir
+        self.dir, self.fn = os.path.split(fn)
+        self.data = ''
+        self.parents = parents
+        self.link = {}
+        self.indent = indent
+        self.last_indent = indent - 1
+        self.sub_indent = 0
+        self.sub_count = 0
+        self.next_link = False
+
+    def escape(self, text):
+        return escape(text, {'"': '&quot;'})
+
+    def process_link(self):
+        new_href = self.escape(os.path.join(self.dir, self.link['href']))
+        text = self.escape(self.link['text'])
+        indent = self.indent + self.sub_indent
+        if self.last_indent == indent:
+            print('%s</sub>' % ('  ' * self.last_indent))
+            self.sub_count -= 1
+        print('%s<sub link="%s" name="%s">' % ('  ' * indent, new_href, text))
+        self.sub_count += 1
+        self.last_indent = self.indent + self.sub_indent
+
+    def handle_starttag(self, tag, attrs):
+        if tag == 'a':
+            self.start_a(attrs)
+        elif tag == 'li':
+            self.start_li(attrs)
+
+    def handle_endtag(self, tag):
+        if tag == 'a':
+            self.end_a()
+        elif tag == 'li':
+            self.end_li()
+
+    def start_li(self, attrs):
+        self.sub_indent += 1
+        self.next_link = True
+
+    def end_li(self):
+        indent = self.indent + self.sub_indent
+        if self.sub_count > 0:
+            print('%s</sub>' % ('  ' * self.last_indent))
+            self.sub_count -= 1
+            self.last_indent -= 1
+        self.sub_indent -= 1
+
+    def start_a(self, attrs):
+        self.link = {}
+        for attr in attrs:
+            self.link[attr[0]] = attr[1]
+        self.data = ''
+        
+    def end_a(self):
+        process = False
+        text = self.escape(self.data.replace('\t', '').replace('\n', ' '))
+        self.link['text'] = text
+        # handle a tag without href attribute
+        try:
+            href = self.link['href']
+        except KeyError:
+            return
+
+        abs_href = os.path.join(self.basedir, href)
+        if abs_href in self.parents:
+            return
+        if href.startswith('..') or href.startswith('http:') \
+               or href.startswith('mailto:') or href.startswith('news:'):
+            return
+        if href in ('', 'about.html', 'modindex.html', 'genindex.html', 'glossary.html',
+                    'search.html', 'contents.html', 'download.html', 'bugs.html',
+                    'license.html', 'copyright.html'):
+            return
+
+        if 'class' in self.link:
+            if self.link['class'] in ('biglink'):
+                process = True
+            if self.link['class'] in ('reference external'):
+                if self.next_link:
+                    process = True
+                    next_link = False
+
+        if process == True:
+            self.process_link()
+            if href in self.pages_to_include:
+                self.parse_file(os.path.join(self.dir, href))
+
+    def finish(self):
+        if self.sub_count > 0:
+            print('%s</sub>' % ('  ' * self.last_indent))
+
+    def handle_data(self, data):
+        self.data += data
+
+    def parse_file(self, href):
+        # TODO basedir bestimmen
+        parent = os.path.join(self.basedir, self.fn)
+        self.parents.add(parent)
+        parser = PyHTMLParser(self.basedir, href, self.indent + 1,
+                              self.parents)
+        text = open(self.basedir + '/' + href, encoding='latin_1').read()
+        parser.feed(text)
+        parser.finish()
+        parser.close()
+        if parent in self.parents:
+            self.parents.remove(parent)
+
+class PyIdxHTMLParser(HTMLParser):
+    def __init__(self, basedir, fn, indent):
+        HTMLParser.__init__(self, convert_charrefs=True)
+        self.basedir = basedir
+        self.dir, self.fn = os.path.split(fn)
+        self.data = ''
+        self.link = {}
+        self.indent = indent
+        self.active = False
+        self.indented = False
+        self.nolink = False
+        self.header = ''
+        self.last_letter = 'Z'
+        self.last_text = ''
+
+    def escape(self, text):
+        return escape(text, {'"': '&quot;'})
+
+    def process_link(self):
+        new_href = self.escape(os.path.join(self.dir, self.link['href']))
+        text = self.escape(self.link['text'])
+        if not self.active:
+            return
+        if text.startswith('['):
+            return
+        if self.link.get('rel', None) in ('prev', 'parent', 'next', 'contents', 'index'):
+            return
+        if self.indented:
+            text = self.last_text + ' ' + text
+        else:
+            # Save it in case we need it again
+            self.last_text = re.sub(' \([\w\-\.\s]+\)', '', text)
+        indent = self.indent
+        print('%s<function link="%s" name="%s"/>' % ('  ' * indent, new_href, text))
+
+    def handle_starttag(self, tag, attrs):
+        if tag == 'a':
+            self.start_a(attrs)
+        elif tag == 'dl':
+            self.start_dl(attrs)
+        elif tag == 'dt':
+            self.start_dt(attrs)
+        elif tag == 'h2':
+            self.start_h2(attrs)
+        elif tag == 'td':
+            self.start_td(attrs)
+        elif tag == 'table':
+            self.start_table(attrs)
+
+    def handle_endtag(self, tag):
+        if tag == 'a':
+            self.end_a()
+        elif tag == 'dl':
+            self.end_dl()
+        elif tag == 'dt':
+            self.end_dt()
+        elif tag == 'h2':
+            self.end_h2()
+        elif tag == 'td':
+            self.end_td()
+        elif tag == 'table':
+            self.end_table()
+
+    def start_dl(self, attrs):
+        if self.last_text:
+            # Looks like we found the second part to a command
+            self.indented = True
+
+    def end_dl(self):
+        self.indented = False
+
+    def start_dt(self, attrs):
+        self.data = ''
+        self.nolink = True
+
+    def end_dt(self):
+        if not self.active:
+            return
+        if self.nolink == True:
+            # Looks like we found the first part to a command
+            self.last_text = re.sub(' \([\w\-\.\s]+\)', '', self.data)
+            self.nolink = False
+
+    def start_h2(self, attrs):
+        for k, v in attrs:
+            if k == 'id':
+                self.header = v
+                if v == '_':
+                    self.active = True
+
+    def end_h2(self):
+        pass
+
+    def start_td(self, attrs):
+        self.indented = False
+        self.last_text = ''
+
+    def end_td(self):
+        pass
+
+    def start_table(self, attrs):
+        pass
+
+    def end_table(self):
+        if self.header == self.last_letter:
+            self.active = False
+
+    def start_a(self, attrs):
+        self.nolink = False
+        self.link = {}
+        for attr in attrs:
+            self.link[attr[0]] = attr[1]
+        self.data = ''
+        
+    def end_a(self):
+        text = self.data.replace('\t', '').replace('\n', ' ')
+        text = text.replace("Whats ", "What's ")
+        self.link['text'] = text
+        # handle a tag without href attribute
+        try:
+            href = self.link['href']
+        except KeyError:
+            return
+        self.process_link()
+
+    def handle_data(self, data):
+        self.data += data
+
+    def handle_entityref(self, name):
+        # not meant to be called while convert_charrefs is true
+        raise AssertionError('entityrefs should not be handled any more')
+
+def main():
+    base = sys.argv[1]
+    fn = sys.argv[2]
+    version = escape(sys.argv[3])
+
+    parser = PyHTMLParser(base, fn, indent=0)
+    print('<?xml version="1.0" encoding="iso-8859-1"?>')
+    print('<book title="Python %s Documentation" name="Python %s" version="%s" link="index.html">' % (version, version, version))
+    print('<chapters>')
+    parser.parse_file(fn)
+    print('</chapters>')
+
+    print('<functions>')
+
+    fn = 'genindex-all.html'
+    parser = PyIdxHTMLParser(base, fn, indent=1)
+    text = open(base + '/' + fn, encoding='latin_1').read()
+    parser.feed(text)
+    parser.close()
+
+    print('</functions>')
+    print('</book>')
+
+main()
diff --git a/pylogo.xpm b/pylogo.xpm
new file mode 100644 (file)
index 0000000..15e80ec
--- /dev/null
@@ -0,0 +1,351 @@
+/* XPM */
+static char * pylogo_xpm[] = {
+"32 32 316 2",
+"      c None",
+".     c #8DB0CE",
+"+     c #6396BF",
+"@     c #4985B7",
+"#     c #4181B5",
+"$     c #417EB2",
+"%     c #417EB1",
+"&     c #4D83B0",
+"*     c #6290B6",
+"=     c #94B2CA",
+"-     c #70A1C8",
+";     c #3D83BC",
+">     c #3881BD",
+",     c #387DB6",
+"'     c #387CB5",
+")     c #387BB3",
+"!     c #3779B0",
+"~     c #3778AE",
+"{     c #3776AB",
+"]     c #3776AA",
+"^     c #3775A9",
+"/     c #4A7FAC",
+"(     c #709FC5",
+"_     c #3A83BE",
+":     c #5795C7",
+"<     c #94B9DB",
+"[     c #73A4CE",
+"}     c #3D80B7",
+"|     c #387CB4",
+"1     c #377AB2",
+"2     c #377AB0",
+"3     c #3777AC",
+"4     c #3774A7",
+"5     c #3773A5",
+"6     c #3C73A5",
+"7     c #4586BB",
+"8     c #4489C1",
+"9     c #A7C7E1",
+"0     c #F7F9FD",
+"a     c #E1E9F1",
+"b     c #4C89BC",
+"c     c #3779AF",
+"d     c #3778AD",
+"e     c #3873A5",
+"f     c #4B7CA4",
+"g     c #3982BE",
+"h     c #4389C1",
+"i     c #A6C6E1",
+"j     c #F6F9FC",
+"k     c #D6E4F0",
+"l     c #4A88BB",
+"m     c #3773A6",
+"n     c #366F9F",
+"o     c #366E9D",
+"p     c #376E9C",
+"q     c #4A8BC0",
+"r     c #79A7CD",
+"s     c #548EBD",
+"t     c #387AB0",
+"u     c #3773A4",
+"v     c #366D9C",
+"w     c #387FBA",
+"x     c #387DB7",
+"y     c #387BB4",
+"z     c #3775A8",
+"A     c #366FA0",
+"B     c #4981AF",
+"C     c #427BAA",
+"D     c #3772A4",
+"E     c #376B97",
+"F     c #77A3C8",
+"G     c #4586BC",
+"H     c #3882BE",
+"I     c #3B76A7",
+"J     c #3B76A6",
+"K     c #366E9E",
+"L     c #376B98",
+"M     c #376B96",
+"N     c #5681A3",
+"O     c #F5EEB8",
+"P     c #FFED60",
+"Q     c #FFE85B",
+"R     c #FFE659",
+"S     c #FDE55F",
+"T     c #5592C4",
+"U     c #3A83BF",
+"V     c #3882BD",
+"W     c #387FB9",
+"X     c #3779AE",
+"Y     c #366F9E",
+"Z     c #366C98",
+"`     c #376A94",
+" .    c #5D85A7",
+"..    c #F5EDB7",
+"+.    c #FFEA5D",
+"@.    c #FFE75A",
+"#.    c #FFE354",
+"$.    c #FDDD56",
+"%.    c #669DC8",
+"&.    c #3885C3",
+"*.    c #3884C2",
+"=.    c #387EB8",
+"-.    c #387CB6",
+";.    c #377AB1",
+">.    c #3772A3",
+",.    c #366D9B",
+"'.    c #F5EBB5",
+").    c #FFE557",
+"!.    c #FFE455",
+"~.    c #FFDF50",
+"{.    c #FFDB4C",
+"].    c #FAD862",
+"^.    c #8EB4D2",
+"/.    c #3C86C1",
+"(.    c #3883C0",
+"_.    c #3882BF",
+":.    c #3881BC",
+"<.    c #3880BB",
+"[.    c #3775AA",
+"}.    c #F5EAB3",
+"|.    c #FFE051",
+"1.    c #FFDE4F",
+"2.    c #FFDA4A",
+"3.    c #FED446",
+"4.    c #F5DF9D",
+"5.    c #77A5CA",
+"6.    c #3885C2",
+"7.    c #387BB2",
+"8.    c #6B8EA8",
+"9.    c #F8E7A1",
+"0.    c #FFE153",
+"a.    c #FFDD4E",
+"b.    c #FFDB4B",
+"c.    c #FFD746",
+"d.    c #FFD645",
+"e.    c #FFD342",
+"f.    c #F6DB8D",
+"g.    c #508DBE",
+"h.    c #3771A3",
+"i.    c #376A95",
+"j.    c #3D6F97",
+"k.    c #C3CBC2",
+"l.    c #FBD964",
+"m.    c #FFDC4D",
+"n.    c #FFD544",
+"o.    c #FFD040",
+"p.    c #F9CF58",
+"q.    c #3F83BB",
+"r.    c #376B95",
+"s.    c #3A6C95",
+"t.    c #4E7BA0",
+"u.    c #91AABC",
+"v.    c #F6E4A3",
+"w.    c #FFDA4B",
+"x.    c #FFD646",
+"y.    c #FFD443",
+"z.    c #FFD241",
+"A.    c #FFCE3D",
+"B.    c #FFCC3B",
+"C.    c #FCC83E",
+"D.    c #3880BC",
+"E.    c #3C79AC",
+"F.    c #5F8DB4",
+"G.    c #7AA0C0",
+"H.    c #82A6C3",
+"I.    c #82A3BF",
+"J.    c #82A2BE",
+"K.    c #82A1BB",
+"L.    c #82A1B9",
+"M.    c #8BA4B5",
+"N.    c #C1C5AE",
+"O.    c #F2E19F",
+"P.    c #FDD74C",
+"Q.    c #FFD94A",
+"R.    c #FFD343",
+"S.    c #FFCE3E",
+"T.    c #FFCB39",
+"U.    c #FFC937",
+"V.    c #FEC636",
+"W.    c #3D79AB",
+"X.    c #9DB6C6",
+"Y.    c #D0CFA2",
+"Z.    c #EFE598",
+"`.    c #F8EE9B",
+" +    c #F8EB97",
+".+    c #F8E996",
+"++    c #F8E894",
+"@+    c #FAE489",
+"#+    c #FCDB64",
+"$+    c #FFDA4D",
+"%+    c #FFCF3E",
+"&+    c #FFCB3A",
+"*+    c #FFC734",
+"=+    c #FFC532",
+"-+    c #3F82B7",
+";+    c #387EB9",
+">+    c #9EB9D0",
+",+    c #F2E287",
+"'+    c #FDEB69",
+")+    c #FEEC60",
+"!+    c #FFEB5E",
+"~+    c #FFE254",
+"{+    c #FFE152",
+"]+    c #FFD747",
+"^+    c #FFC633",
+"/+    c #FCC235",
+"(+    c #578FBE",
+"_+    c #6996BC",
+":+    c #DED9A8",
+"<+    c #FEEC62",
+"[+    c #FFE658",
+"}+    c #FFDF51",
+"|+    c #FFDE50",
+"1+    c #FFD03F",
+"2+    c #FFCD3C",
+"3+    c #FFC431",
+"4+    c #FFBF2C",
+"5+    c #FAC244",
+"6+    c #85AACA",
+"7+    c #A1BBD2",
+"8+    c #F7E47C",
+"9+    c #FFE456",
+"0+    c #FFC735",
+"a+    c #FFBC29",
+"b+    c #F7D280",
+"c+    c #9DBAD2",
+"d+    c #3B7CB2",
+"e+    c #ABC2D6",
+"f+    c #FDEB7B",
+"g+    c #FFC12E",
+"h+    c #FDBD30",
+"i+    c #F4DEA8",
+"j+    c #5F91BA",
+"k+    c #ABC1D4",
+"l+    c #FDEE7E",
+"m+    c #FFE253",
+"n+    c #FFCC3C",
+"o+    c #FFBA27",
+"p+    c #FAC75B",
+"q+    c #4A82B0",
+"r+    c #3877AB",
+"s+    c #3774A6",
+"t+    c #AAC0D4",
+"u+    c #FDEE7D",
+"v+    c #FFEC5F",
+"w+    c #FFE255",
+"x+    c #FFD848",
+"y+    c #FFD444",
+"z+    c #FFCF3F",
+"A+    c #FFBC2A",
+"B+    c #FFBB28",
+"C+    c #FDBA32",
+"D+    c #447AA8",
+"E+    c #4379A7",
+"F+    c #FFE95C",
+"G+    c #FFE558",
+"H+    c #FFE355",
+"I+    c #FED84B",
+"J+    c #FCD149",
+"K+    c #FBCE47",
+"L+    c #FBCD46",
+"M+    c #FBC840",
+"N+    c #FBC63E",
+"O+    c #FBC037",
+"P+    c #FAC448",
+"Q+    c #FDD44C",
+"R+    c #FCD14E",
+"S+    c #FFC836",
+"T+    c #FFC22F",
+"U+    c #FFC02D",
+"V+    c #FFE052",
+"W+    c #FFC636",
+"X+    c #FFCF5C",
+"Y+    c #FFD573",
+"Z+    c #FFC33E",
+"`+    c #FEBD2D",
+" @    c #FFDB4D",
+".@    c #FFD949",
+"+@    c #FFD545",
+"@@    c #FFD140",
+"#@    c #FFCB48",
+"$@    c #FFF7E4",
+"%@    c #FFFCF6",
+"&@    c #FFE09D",
+"*@    c #FFBA2E",
+"=@    c #FDBE2F",
+"-@    c #FFD748",
+";@    c #FFCA38",
+">@    c #FFC844",
+",@    c #FFF2D7",
+"'@    c #FFF9EC",
+")@    c #FFDB94",
+"!@    c #FFB92D",
+"~@    c #FAC54D",
+"{@    c #FDD54E",
+"]@    c #FFBD2D",
+"^@    c #FFC858",
+"/@    c #FFD174",
+"(@    c #FFBF3E",
+"_@    c #FCBD3C",
+":@    c #FAD66A",
+"<@    c #FECD3F",
+"[@    c #FFC330",
+"}@    c #FFBD2A",
+"|@    c #FFB724",
+"1@    c #FFB521",
+"2@    c #FFB526",
+"3@    c #FBC457",
+"4@    c #F7E09E",
+"5@    c #F8D781",
+"6@    c #FAC349",
+"7@    c #FCC134",
+"8@    c #FEBE2C",
+"9@    c #FBBE3F",
+"0@    c #F7CF79",
+"a@    c #F5D795",
+"                      . + @ # $ % % & * =                       ",
+"                  - ; > > , ' ) ! ~ { ] ^ /                     ",
+"                ( _ : < [ } | 1 2 ~ 3 4 5 5 6                   ",
+"                7 8 9 0 a b 2 c d 3 { 5 5 5 e f                 ",
+"                g h i j k l c ~ { { m 5 5 n o p                 ",
+"                > > q r s t c c d 4 5 u n v v v                 ",
+"                w x ' y 2 c d d z 5 u A v v v v                 ",
+"                              B C 5 D v v v v E                 ",
+"      F G H H H x ' ) c c c d I J 5 K v v L M N O P Q R S       ",
+"    T U H V V W ' ) c c X ~ 5 5 5 Y v v Z ` `  ...+.@.#.#.$.    ",
+"  %.&.*.> w W =.-.;.c 3 { ^ 5 5 >.o v ,.E ` `  .'.).!.#.~.{.].  ",
+"^./.(._.:.<., ' ) ;.X d [.5 5 >.K v ,.E ` ` `  .}.#.|.1.{.2.3.4.",
+"5.6.(.H H x ' 7.c c 3 3 4 5 D K v v ,.` ` ` ` 8.9.0.a.b.c.d.e.f.",
+"g._.> <.w ' ' | 2 3 { z 5 5 h.v v v i.` ` ` j.k.l.m.{.d.n.e.o.p.",
+"q.> > :.-.' 1 c c c ] 5 5 >.v v ,.r.` ` s.t.u.v.{.w.x.y.z.A.B.C.",
+"D.D.w -.' 1 c c c E.F.G.H.I.J.J.K.L.L.L.M.N.O.P.Q.c.R.S.B.T.U.V.",
+"D.D.=.' ' 1 c c W.X.Y.Z.`.`.`.`.`. +.+++@+#+$+Q.d.R.%+B.&+*+=+=+",
+"-+;+-.' ;.2 c c >+,+'+)+P P P !+Q R ~+{+1.{.]+d.y.%+B.&+^+=+=+/+",
+"(+' ' ;.c X X _+:+<+P P P P !+R [+~+}+|+{.]+n.R.1+2+&+^+=+3+4+5+",
+"6+' ) ! ~ { { 7+8+P P P P !+R 9+#.{+{.w.]+y.z.S.&+0+=+=+3+4+a+b+",
+"c+d+7.! d 3 z e+f+P P P !+R 9+#.{+m.{.]+y.1+B.&+0+=+=+g+4+a+h+i+",
+"  j+c d 3 { 4 k+l+P P !+@.9+m+1.m.{.]+y.1+n+B.*+=+=+g+a+a+o+p+  ",
+"    q+r+{ s+m t+u+v+@.R w+{+}+{.x+d.y+z+n+B.0+=+=+g+A+a+B+C+    ",
+"      * D+E+E+  +.F+G+H+}+}+{.I+J+K+L+M+M+M+M+N+O+O+O+O+P+      ",
+"                ).).#.{+a.{.x+Q+R+                              ",
+"                #.m+1.a.{.x+y.o.2+B.S+=+=+T+U+O+                ",
+"                0.V+{.{.x+n.o.2+B.B.W+X+Y+Z+a+`+                ",
+"                 @{..@+@n.@@B.B.S+^+#@$@%@&@*@=@                ",
+"                ].-@x.y.o.%+;@S+=+=+>@,@'@)@!@~@                ",
+"                  {@z.z+2+U.=+=+=+T+]@^@/@(@_@                  ",
+"                    :@<@U.=+=+[@4+}@|@1@2@3@                    ",
+"                      4@5@6@7@8@a+a+9@0@a@                      "};
diff --git a/pymindeps.py b/pymindeps.py
new file mode 100644 (file)
index 0000000..bfede8f
--- /dev/null
@@ -0,0 +1,186 @@
+#! /usr/bin/python3
+
+# Matthias Klose
+# Modified to only exclude module imports from a given module.
+
+# Copyright 2004 Toby Dickenson
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject
+# to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+import os, sys, pprint
+import modulefinder
+import imp
+
+class mymf(modulefinder.ModuleFinder):
+    def __init__(self,*args,**kwargs):
+        self._depgraph = {}
+        self._types = {}
+        self._last_caller = None
+        modulefinder.ModuleFinder.__init__(self, *args, **kwargs)
+        
+    def import_hook(self, name, caller=None, fromlist=None, level=-1):
+        old_last_caller = self._last_caller
+        try:
+            self._last_caller = caller
+            return modulefinder.ModuleFinder.import_hook(self, name, caller,
+                                                         fromlist, level)
+        finally:
+            self._last_caller = old_last_caller
+            
+    def import_module(self, partnam, fqname, parent):
+        m = modulefinder.ModuleFinder.import_module(self,
+                                                    partnam, fqname, parent)
+        if m is not None and self._last_caller:
+            caller = self._last_caller.__name__
+            if '.' in caller:
+                caller = caller[:caller.index('.')]
+            callee =  m.__name__
+            if '.' in callee:
+                callee = callee[:callee.index('.')]
+            #print("XXX last_caller", caller, "MOD", callee)
+            #self._depgraph.setdefault(self._last_caller.__name__,{})[r.__name__] = 1
+            #if caller in ('pdb', 'doctest', 'importlib') or callee in ('pdb', 'doctest', 'importlib'):
+            #    print(caller, "-->", callee)
+            if caller != callee:
+                self._depgraph.setdefault(caller,{})[callee] = 1
+        return m
+    
+    def find_module(self, name, path, parent=None):
+        if parent is not None:
+            # assert path is not None
+            fullname = parent.__name__+'.'+name
+        elif name == "__init__":
+            fullname = os.path.basename(path[0])
+        else:
+            fullname = name
+        if self._last_caller:
+            caller = self._last_caller.__name__
+            if fullname in excluded_imports.get(caller, []):
+                #self.msgout(3, "find_module -> Excluded", fullname)
+                raise ImportError(name)
+
+        if fullname in self.excludes:
+            #self.msgout(3, "find_module -> Excluded", fullname)
+            raise ImportError(name)
+
+        if path is None:
+            if name in sys.builtin_module_names:
+                return (None, None, ("", "", imp.C_BUILTIN))
+
+            path = self.path
+        return imp.find_module(name, path)
+
+    def load_module(self, fqname, fp, pathname, file_info):
+        suffix, mode, type = file_info
+        m = modulefinder.ModuleFinder.load_module(self, fqname,
+                                                  fp, pathname, file_info)
+        if m is not None:
+            self._types[m.__name__] = type
+        return m
+
+    def load_package(self, fqname, pathname):
+        m = modulefinder.ModuleFinder.load_package(self, fqname,pathname)
+        if m is not None:
+            self._types[m.__name__] = imp.PKG_DIRECTORY
+        return m
+def reduce_depgraph(dg):
+    pass
+
+# guarded imports, which don't need to be included in python-minimal
+excluded_imports = {
+    'argparse': set(('gettext', 'shutil')),
+    'codecs': set(('encodings',)),
+    'collections': set(('cPickle', 'pickle', 'doctest')),
+    'compileall': set(('concurrent',)),
+    'copy': set(('reprlib',)),
+    #'functools': set(('_dummy_thread',)),
+    'hashlib': set(('logging', '_hashlib')),
+    #'hashlib': set(('_hashlib', '_md5', '_sha', '_sha256','_sha512',)),
+    'heapq': set(('doctest',)),
+    'importlib': set(('csv', 'email', 'zipfile')),
+    #'io': set(('_dummy_thread',)),
+    'logging': set(('multiprocessing',)),
+    'os': set(('nt', 'ntpath', 'os2', 'os2emxpath', 'mac', 'macpath',
+               'riscos', 'riscospath', 'riscosenviron')),
+    'optparse': set(('gettext',)),
+    'pathlib': set(('urllib',)), # Windows only
+    'pickle': set(('argparse', 'doctest', 'pprint')),
+    'platform': set(('ctypes', 'plistlib', 'tempfile')),
+    'reprlib': set(('_dummy_thread',)),
+    'shutil': set(('bz2','lzma', 'tarfile', 'zipfile')),
+    #'socket': set(('_ssl',)),
+    '_sitebuiltins': set(('pydoc',)),
+    'subprocess': set(('dummy_threading',)),
+    'sysconfig': set(('pprint','_osx_support', '_aix_support')),
+    'tempfile': set(('_dummy_thread', 'shutil')),
+    'functools': set(('typing',)),
+    'platform': set(('distutils','plistlib')),
+    'zipfile': set(('bz2','lzma')),
+    'random': set(('statistics',)),
+    }
+
+def main(argv):
+    # Parse command line
+    import getopt
+    try:
+        opts, args = getopt.getopt(sys.argv[1:], "dmp:qx:")
+    except getopt.error as msg:
+        print(msg)
+        return
+
+    # Process options
+    debug = 1
+    domods = 0
+    addpath = []
+    exclude = []
+    for o, a in opts:
+        if o == '-d':
+            debug = debug + 1
+        if o == '-m':
+            domods = 1
+        if o == '-p':
+            addpath = addpath + a.split(os.pathsep)
+        if o == '-q':
+            debug = 0
+        if o == '-x':
+            exclude.append(a)
+
+    path = sys.path[:]
+    path = addpath + path
+
+    if debug > 1:
+        print(("version:", sys.version))
+        print("path:")
+        for item in path:
+            print(("   ", repr(item)))
+
+    #exclude = ['__builtin__', 'sys', 'os']
+    exclude = []
+    mf = mymf(path, debug, exclude)
+    for arg in args:
+        mf.run_script(arg)
+
+    depgraph = reduce_depgraph(mf._depgraph)
+    
+    pprint.pprint({'depgraph':mf._depgraph, 'types':mf._types})
+    
+if __name__=='__main__':
+    main(sys.argv[1:])
diff --git a/pysetup3.1 b/pysetup3.1
new file mode 100644 (file)
index 0000000..293bfae
--- /dev/null
@@ -0,0 +1,42 @@
+.\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.40.4.
+.TH PYSETUP3.3 "1" "January 2012" "pysetup3.3 3.3" "User Commands"
+.SH NAME
+pysetup3.3 \- pysetup tool
+.SH SYNOPSIS
+.B pysetup
+[\fIoptions\fR] \fIaction \fR[\fIaction_options\fR]
+.SH DESCRIPTION
+.SS "Actions:"
+.IP
+run: Run one or several commands
+metadata: Display the metadata of a project
+install: Install a project
+remove: Remove a project
+search: Search for a project in the indexes
+list: List installed projects
+graph: Display a graph
+create: Create a project
+generate\-setup: Generate a backward\-compatible setup.py
+.PP
+To get more help on an action, use:
+.IP
+pysetup action \fB\-\-help\fR
+.SS "Global options:"
+.TP
+\fB\-\-verbose\fR (\fB\-v\fR)
+run verbosely (default)
+.TP
+\fB\-\-quiet\fR (\fB\-q\fR)
+run quietly (turns verbosity off)
+.TP
+\fB\-\-dry\-run\fR (\fB\-n\fR)
+don't actually do anything
+.TP
+\fB\-\-help\fR (\fB\-h\fR)
+show detailed help message
+.TP
+\fB\-\-no\-user\-cfg\fR
+ignore pydistutils.cfg in your home directory
+.TP
+\fB\-\-version\fR
+Display the version
diff --git a/python3-config.1 b/python3-config.1
new file mode 100644 (file)
index 0000000..e8f5ada
--- /dev/null
@@ -0,0 +1,102 @@
+.TH PYTHON\-CONFIG 1 "November 27, 2011"
+.SH NAME
+python\-config \- output build options for python C/C++ extensions or embedding
+.SH SYNOPSIS
+.BI "python\-config"
+[
+.BI "\-\-prefix"
+]
+[
+.BI "\-\-exec\-prefix"
+]
+[
+.BI "\-\-includes"
+]
+[
+.BI "\-\-libs"
+]
+[
+.BI "\-\-cflags"
+]
+[
+.BI "\-\-ldflags"
+]
+[
+.BI "\-\-extension\-suffix"
+]
+[
+.BI "\-\-abiflags"
+]
+[
+.BI "\-\-help"
+]
+.SH DESCRIPTION
+.B python\-config
+helps compiling and linking programs, which embed the Python interpreter, or
+extension modules that can be loaded dynamically (at run time) into
+the interpreter.
+.SH OPTIONS
+.TP
+.BI "\-\-abiflags"
+print the the ABI flags as specified by PEP 3149.
+.TP
+.BI "\-\-cflags"
+print the C compiler flags.
+.TP
+.BI "\-\-ldflags"
+print the flags that should be passed to the linker.
+.TP
+.BI "\-\-includes"
+similar to \fI\-\-cflags\fP but only with \-I options (path to python header files).
+.TP
+.BI "\-\-libs"
+similar to \fI\-\-ldflags\fP but only with \-l options (used libraries).
+.TP
+.BI "\-\-prefix"
+prints the prefix (base directory) under which python can be found.
+.TP
+.BI "\-\-exec\-prefix"
+print the prefix used for executable program directories (such as bin, sbin, etc).
+.TP
+.BI "\-\-extension\-suffix"
+print the extension suffix used for binary extensions.
+.TP
+.BI "\-\-help"
+print the usage message.
+.PP
+
+.SH EXAMPLES
+To build the singe\-file c program \fIprog\fP against the python library, use
+.PP
+.RS
+gcc $(python\-config \-\-cflags \-\-ldflags) progr.cpp \-o progr.cpp
+.RE
+.PP
+The same in a makefile:
+.PP
+.RS
+CFLAGS+=$(shell python\-config \-\-cflags)
+.RE
+.RS
+LDFLAGS+=$(shell python\-config \-\-ldflags)
+.RE
+.RS
+all: progr
+.RE
+
+To build a dynamically loadable python module, use
+.PP
+.RS
+gcc $(python\-config \-\-cflags \-\-ldflags) \-shared \-fPIC progr.cpp \-o progr.so
+.RE
+
+.SH "SEE ALSO"
+python (1)
+.br
+http://docs.python.org/extending/extending.html
+.br
+/usr/share/doc/python/faq/extending.html
+
+.SH AUTHORS
+This manual page was written by Johann Felix Soden <johfel@gmx.de>
+for the Debian project (and may be used by others).
diff --git a/rules b/rules
new file mode 100755 (executable)
index 0000000..5628b67
--- /dev/null
+++ b/rules
@@ -0,0 +1,1535 @@
+#!/usr/bin/make -f
+
+unexport LANG LC_ALL LC_CTYPE LC_COLLATE LC_TIME LC_NUMERIC LC_MESSAGES
+unexport CFLAGS CXXFLAGS LDFLAGS CPPFLAGS
+
+export DEB_BUILD_MAINT_OPTIONS=hardening=-pie
+dpkg_buildflags = DEB_BUILD_MAINT_OPTIONS=$(DEB_BUILD_MAINT_OPTIONS) dpkg-buildflags
+
+export SHELL = /bin/bash
+
+# Uncomment this to turn on verbose mode.
+#export DH_VERBOSE=1
+
+vafilt         = $(subst $(2)=,,$(filter $(2)=%,$(1)))
+DPKG_VARS      := $(shell dpkg-architecture)
+DEB_BUILD_ARCH         ?= $(call vafilt,$(DPKG_VARS),DEB_BUILD_ARCH)
+DEB_BUILD_GNU_TYPE     ?= $(call vafilt,$(DPKG_VARS),DEB_BUILD_GNU_TYPE)
+DEB_HOST_ARCH          ?= $(call vafilt,$(DPKG_VARS),DEB_HOST_ARCH)
+DEB_HOST_ARCH_ENDIAN   ?= $(call vafilt,$(DPKG_VARS),DEB_HOST_ARCH_ENDIAN)
+DEB_HOST_ARCH_OS       ?= $(call vafilt,$(DPKG_VARS),DEB_HOST_ARCH_OS)
+DEB_HOST_GNU_TYPE      ?= $(call vafilt,$(DPKG_VARS),DEB_HOST_GNU_TYPE)
+DEB_HOST_MULTIARCH     ?= $(call vafilt,$(DPKG_VARS),DEB_HOST_MULTIARCH)
+
+ifeq ($(DEB_HOST_ARCH_OS),linux)
+  PLAT = linux
+else ifeq ($(DEB_HOST_ARCH_OS),kfreebsd)
+  PLAT = gnukfreebsd10
+else ifeq ($(DEB_HOST_ARCH_OS),hurd)
+  PLAT = gnu0
+else
+  $(warning unhandled operating system name: $(DEB_HOST_ARCH_OS))
+  PLAT = unknown
+endif
+
+CHANGELOG_VARS := $(shell dpkg-parsechangelog | \
+       sed -n 's/ /_/g;/^[^_]/s/^\([^:]*\):_\(.*\)/\1=\2/p')
+PKGSOURCE  := $(call vafilt,$(CHANGELOG_VARS),Source)
+PKGVERSION := $(call vafilt,$(CHANGELOG_VARS),Version)
+
+LAST_CHANGE := $(shell dpkg-parsechangelog -S Date)
+export BUILD_DATE := $(shell LC_ALL=C date -u +'%b %e %Y' -d '$(LAST_CHANGE)')
+export BUILD_TIME := $(shell LC_ALL=C date -u +'%H:%M:%S' -d '$(LAST_CHANGE)')
+
+SPHINXOPTS := -D today='$(shell LC_ALL=C date -u +'%B %d, %Y' -d '$(LAST_CHANGE)')'
+SPHINXOPTS += -D html_last_updated_fmt='$(shell LC_ALL=C date -u +'%B %d, %Y' -d '$(LAST_CHANGE)')'
+export SPHINXOPTS
+
+on_buildd := $(shell [ -f /CurrentlyBuilding -o "$$LOGNAME" = buildd -o "$$USER" = buildd ] && echo yes)
+
+dh_compat2 := $(shell dpkg --compare-versions "$$(dpkg-query -f '$${Version}' -W debhelper)" lt 9.20150811ubuntu2 && echo DH_COMPAT=2)
+
+ifneq (,$(findstring nocheck, $(DEB_BUILD_OPTIONS)))
+  WITHOUT_CHECK := yes
+endif
+WITHOUT_BENCH :=
+ifneq (,$(findstring nobench, $(DEB_BUILD_OPTIONS)))
+  WITHOUT_BENCH := yes
+endif
+ifeq ($(on_buildd),yes)
+  ifneq (,$(filter $(DEB_HOST_ARCH), armel hppa mips mipsel mips64 mips64el riscv64 s390 hurd-i386 kfreebsd-amd64 kfreebsd-i386))
+    WITHOUT_CHECK := yes
+  endif
+  ifneq (,$(filter $(DEB_HOST_ARCH), armel hppa mips mipsel mips64 mips64el riscv64 s390 hurd-i386 kfreebsd-amd64 kfreebsd-i386))
+    WITHOUT_BENCH := yes
+  endif
+endif
+ifneq ($(DEB_HOST_GNU_TYPE),$(DEB_BUILD_GNU_TYPE))
+  WITHOUT_BENCH := yes
+  WITHOUT_CHECK := yes
+endif
+
+COMMA = ,
+ifneq (,$(filter parallel=%,$(subst $(COMMA), ,$(DEB_BUILD_OPTIONS))))
+  NJOBS := -j $(subst parallel=,,$(filter parallel=%,$(subst $(COMMA), ,$(DEB_BUILD_OPTIONS))))
+endif
+
+distribution := $(shell lsb_release -is)
+distrelease  := $(shell lsb_release -cs)
+derivative      := $(shell \
+       if dpkg-vendor --derives-from Ubuntu; then echo Ubuntu; \
+       elif dpkg-vendor --derives-from Debian; then echo Debian; \
+       else echo Unknown; fi)
+
+VER=3.9
+SVER=3.9.0~b4
+NVER=3.10
+PVER=python$(VER)
+EXT_VER=$(subst .,,$(VER))
+PRIORITY=$(shell echo $(VER) | tr -d '.')0
+
+PREVVER        := $(shell awk '/^python/ && NR > 1 {print substr($$2,2,length($$2)-2); exit}' debian/changelog)
+
+# default versions are built from the python-defaults source package
+# keep the definition to adjust package priorities.
+DEFAULT_VERSION = no
+STATIC_PYTHON=yes
+
+MIN_MODS := $(shell awk '/^  / && $$2 == "module" { print $$1 }' \
+               debian/PVER-minimal.README.Debian.in)
+MIN_EXTS := $(shell awk '/^  / && $$2 ~ /^extension/ { print $$1 }' \
+               debian/PVER-minimal.README.Debian.in)
+MIN_BUILTINS := $(shell awk '/^  / && $$2 == "builtin" { print $$1 }' \
+               debian/PVER-minimal.README.Debian.in)
+MIN_PACKAGES := $(shell awk '/^  / && $$2 == "package" { print $$1 }' \
+               debian/PVER-minimal.README.Debian.in)
+MIN_ENCODINGS := $(foreach i, \
+                       $(filter-out \
+                         big5% bz2% cp932.py cp949.py cp950.py euc_% \
+                         gb% iso2022% johab.py shift_jis% , \
+                         $(shell cd Lib/encodings && echo *.py)), \
+                       encodings/$(i)) \
+                codecs.py stringprep.py
+
+with_tk := no
+with_interp := static
+#with_interp := shared
+
+PY_INTERPRETER = /usr/bin/python$(VER)
+
+ifeq ($(DEFAULT_VERSION),yes)
+  PY_PRIO = standard
+  #PYSTDDEP = , python (>= $(VER))
+else
+  PY_PRIO = optional
+endif
+ifeq ($(distribution),Ubuntu)
+  PY_MINPRIO = required
+  PY_MINPRIO = optional
+  #with_udeb = yes
+  # test_ssl assumes that openssl is compiled with security level set to 1
+  # make it so, during the build
+  export OPENSSL_CONF = $(CURDIR)/debian/openssl.cnf
+else
+  PY_MINPRIO = $(PY_PRIO)
+endif
+ifeq (,$(filter $(distrelease),lenny etch squeeze wheezy lucid maverick natty oneiric))
+  bd_qual = :any
+endif
+ifeq (,$(filter $(distrelease),lenny etch squeeze wheezy lucid maverick natty oneiric))
+  ma_filter = cat
+else
+  ma_filter = grep -v '^Multi-Arch:'
+endif
+ifeq (,$(filter $(distrelease),lenny etch squeeze wheezy lucid maverick natty oneiric precise quantal raring saucy trusty))
+  bd_dpkgdev = dpkg-dev (>= 1.17.11),
+endif
+
+CC=$(DEB_HOST_GNU_TYPE)-gcc
+CXX=$(DEB_HOST_GNU_TYPE)-g++
+ifneq (,$(filter $(distrelease),bionic))
+  CC=$(DEB_HOST_GNU_TYPE)-gcc-8
+  CXX=$(DEB_HOST_GNU_TYPE)-g++-8
+  bd_gcc = g++-8,
+endif
+
+AR=$(DEB_HOST_GNU_TYPE)-ar
+RANLIB=$(DEB_HOST_GNU_TYPE)-ranlib
+
+# configure and dtrace consume these
+export CC CXX
+
+DPKG_CPPFLAGS= $(shell $(dpkg_buildflags) --get CPPFLAGS)
+DPKG_CFLAGS  := $(shell $(dpkg_buildflags) --get CFLAGS)
+DPKG_CFLAGS  := $(subst -fstack-protector-strong,-fstack-protector,$(DPKG_CFLAGS))
+DPKG_LDFLAGS = $(shell $(dpkg_buildflags) --get LDFLAGS)
+OPT_CFLAGS   := $(filter-out -O%,$(DPKG_CFLAGS)) # default is -O3
+DEBUG_CFLAGS := $(patsubst -O%,-Og,$(DPKG_CFLAGS))
+
+# on ia64, disable -O3 until gcc bug #85412 is fixed
+ifeq ($(DEB_HOST_ARCH),ia64)
+    EXTRA_OPT_CFLAGS += -O2
+endif
+# see #972202, and https://gcc.gnu.org/PR97431
+ifneq (,$(filter $(DEB_HOST_ARCH), hppa sh4))
+    EXTRA_OPT_CFLAGS += -fno-inline-small-functions
+endif
+ifneq (,$(filter $(DEB_HOST_ARCH), ppc64 ppc64el))
+    OPT_CFLAGS += -fexceptions
+    DEBUG_CFLAGS += -fexceptions
+endif
+
+ifeq ($(DEB_HOST_GNU_TYPE),$(DEB_BUILD_GNU_TYPE))
+  ifeq ($(DEB_HOST_ARCH_OS),linux)
+    ifneq (,$(findstring $(DEB_HOST_ARCH), amd64 armel armhf arm64 i386 powerpc ppc64 ppc64el s390x))
+      with_pgo := yes
+    endif
+  endif
+endif
+
+ifneq (,$(findstring $(DEB_HOST_ARCH), amd64 armel armhf arm64 i386 powerpc ppc64 ppc64el s390x))
+  with_lto := yes
+endif
+
+ifneq (,$(findstring nopgo, $(DEB_BUILD_OPTIONS)))
+  with_pgo :=
+endif
+
+ifneq (,$(findstring nolto, $(DEB_BUILD_OPTIONS)))
+  with_lto :=
+endif
+
+ifneq (,$(findstring noopt, $(DEB_BUILD_OPTIONS)))
+    OPT_CFLAGS := $(filter-out -O%, $(OPT_CFLAGS))
+    EXTRA_OPT_CFLAGS = -O0
+    with_pgo =
+    with_lto =
+endif
+
+BASE_LTO_CFLAGS = -g -fwrapv -O3
+ifeq ($(with_lto),yes)
+    LTO_CFLAGS = $(BASE_LTO_CFLAGS) -flto -fuse-linker-plugin
+    with_fat_lto := $(shell dpkg --compare-versions $$($(CC) --version \
+                       | sed -n '/^$(CC)/s,.* ,,p') ge 4.9 && echo yes)
+    ifeq ($(with_fat_lto),yes)
+      LTO_CFLAGS += -ffat-lto-objects
+    endif
+    EXTRA_OPT_CFLAGS += $(LTO_CFLAGS)
+    AR=$(DEB_HOST_GNU_TYPE)-gcc-ar
+    RANLIB=$(DEB_HOST_GNU_TYPE)-gcc-ranlib
+endif
+
+sysconfig_substflags = \
+       -e 's,gcc-8,gcc,;s,g++-8,g++,' \
+       $(if $(with_lto),$(foreach i,-flto -fuse-linker-plugin -ffat-lto-objects,-e 's/$(i)//g')) \
+       -e '/^OPT/s,-O3,-O2,' \
+       -e 's/-O3/-O2/g' \
+       -e 's/-fprofile-use *-fprofile-correction//g' \
+       -e 's/-fstack-protector /-fstack-protector-strong /g' \
+       -e 's/-specs=[^ ]*//g' \
+       -e 's/-fdebug-prefix-map=[^ ]*//g' \
+       -e 's,^RUNSHARED *=.*,RUNSHARED=,' \
+       -e '/BLDLIBRARY/s/-L\. //'
+
+ifeq ($(derivative),Ubuntu)
+  arch_substvars =
+else ifeq ($(derivative),Debian)
+  arch_substvars = # '-Vpython38:Breaks=$(shell tr '\n' ' ' < debian/py38-breaks.$(derivative))'
+endif
+
+make_build_target = $(if $(filter yes, $(with_pgo)),profile-opt)
+
+buildd_static  := $(CURDIR)/build-static
+buildd_shared  := $(CURDIR)/build-shared
+buildd_debug   := $(CURDIR)/build-debug
+buildd_shdebug := $(CURDIR)/build-shdebug
+
+d              := debian/tmp
+scriptdir      =  usr/share/lib/python$(VER)
+scriptdir      =  usr/share/python$(VER)
+scriptdir      =  usr/lib/python$(VER)
+
+# package names and directories
+p_base := $(PVER)
+p_min  := $(PVER)-minimal
+p_lib  := lib$(PVER)
+p_tk   := $(PVER)-tk
+p_dev  := $(PVER)-dev
+p_exam := $(PVER)-examples
+p_idle := idle-$(PVER)
+p_doc  := $(PVER)-doc
+p_dbg  := $(PVER)-dbg
+p_udeb := $(PVER)-udeb
+p_venv := $(PVER)-venv
+
+p_lbase        := lib$(PVER)-stdlib
+p_lmin := lib$(PVER)-minimal
+p_ldev := lib$(PVER)-dev
+p_ldbg := lib$(PVER)-dbg
+p_ltst := lib$(PVER)-testsuite
+
+d_base := debian/$(p_base)
+d_min  := debian/$(p_min)
+d_lib  := debian/$(p_lib)
+d_tk   := debian/$(p_tk)
+d_dev  := debian/$(p_dev)
+d_exam := debian/$(p_exam)
+d_idle := debian/$(p_idle)
+d_doc  := debian/$(p_doc)
+d_dbg  := debian/$(p_dbg)
+d_udeb := debian/$(p_udeb)
+d_venv := debian/$(p_venv)
+
+d_lbase        := debian/$(p_lbase)
+d_lmin := debian/$(p_lmin)
+d_ldev := debian/$(p_ldev)
+d_ldbg := debian/$(p_ldbg)
+d_ltst := debian/$(p_ltst)
+
+build-arch: stamps/stamp-build
+build-indep: stamps/stamp-build-doc
+build: build-arch
+stamps/stamp-build: stamps/stamp-build-static stamps/stamp-mincheck \
+    stamps/stamp-build-shared stamps/stamp-build-debug \
+    stamps/stamp-build-shared-debug \
+    stamps/stamp-check stamps/stamp-pybench
+       touch $@
+
+PROFILE_EXCLUDES = test_compiler test_distutils test_subprocess \
+       test_multiprocessing test_socket test_socketserver \
+       test_thread test_threaded_import test_threadedtempfile \
+       test_threading test_threading_local test_threadsignals \
+       test_concurrent_futures test_ctypes \
+       test_dbm_dumb test_dbm_ndbm test_pydoc test_sundry \
+       test_signal test_ioctl test_gdb test_ensurepip test_venv
+
+# TODO: these hang/fail with new OpenSSL
+PROFILE_EXCLUDES += \
+       test_asyncio test_ftplib test_httplib test_imaplib test_nntplib test_poplib test_ssl
+
+# TODO: these fail in the profile build
+PROFILE_EXCLUDES += \
+       test_cmd_line_script test_zipimport_support
+
+# TODO: update profiled-build.diff to support --next
+#       --next=20
+PROFILE_TASK = ../Lib/test/regrtest.py \
+       -s \
+       -j 1 -unone,decimal \
+       -x $(sort $(TEST_EXCLUDES) $(PROFILE_EXCLUDES))
+
+stamps/stamp-build-static: stamps/stamp-configure-static
+       dh_testdir
+       $(MAKE) $(NJOBS) -C $(buildd_static) \
+               EXTRA_CFLAGS="$(EXTRA_OPT_CFLAGS)" \
+               CONFIGURE_LDFLAGS="$(DPKG_LDFLAGS) $(LTO_CFLAGS)" \
+               PROFILE_TASK='$(PROFILE_TASK)' $(make_build_target)
+
+ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
+       : # check that things are correctly built
+  ifneq (,$(filter $(DEB_HOST_ARCH_OS), linux))
+       cd $(buildd_static) && ./python -c 'from _multiprocessing import SemLock'
+  endif
+       cd $(buildd_static) && ./python -c 'import _decimal'
+       cd $(buildd_static) && ./python -c 'import math, cmath'
+endif
+
+       touch stamps/stamp-build-static
+
+run-profile-task:
+       $(MAKE) -C $(buildd_static) \
+               PROFILE_TASK='$(PROFILE_TASK)' run_profile_task
+
+stamps/stamp-build-shared: stamps/stamp-configure-shared
+       dh_testdir
+       $(MAKE) $(NJOBS) -C $(buildd_shared) \
+               EXTRA_CFLAGS="$(EXTRA_OPT_CFLAGS)"
+       : # build a static library with PIC objects
+       $(MAKE) $(NJOBS) -C $(buildd_shared) \
+               EXTRA_CFLAGS="$(EXTRA_OPT_CFLAGS)" \
+               LIBRARY=libpython$(VER)-pic.a libpython$(VER)-pic.a
+       touch stamps/stamp-build-shared
+
+stamps/stamp-build-debug: stamps/stamp-configure-debug
+       dh_testdir
+       $(MAKE) $(NJOBS) -C $(buildd_debug) \
+               EXTRA_CFLAGS="$(DEBUG_CFLAGS)"
+
+ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
+       cd $(buildd_static) && ./python -c 'import _decimal'
+       cd $(buildd_debug) && ./python -c 'import math, cmath'
+endif
+
+       touch stamps/stamp-build-debug
+
+stamps/stamp-build-shared-debug: stamps/stamp-configure-shared-debug
+       dh_testdir
+       : # build the shared debug library
+       $(MAKE) $(NJOBS) -C $(buildd_shdebug) \
+               EXTRA_CFLAGS="$(DEBUG_CFLAGS)"
+       touch stamps/stamp-build-shared-debug
+
+common_configure_args = \
+               --prefix=/usr \
+               --enable-ipv6 \
+               --enable-loadable-sqlite-extensions \
+               --with-dbmliborder=bdb:gdbm \
+               --with-computed-gotos \
+               --without-ensurepip \
+               --with-system-expat \
+               --with-dtrace \
+               --with-system-libmpdec \
+
+ifneq (,$(filter $(DEB_HOST_ARCH), avr32 or1k))
+  common_configure_args += --without-ffi
+else
+  common_configure_args += --with-system-ffi
+endif
+
+ifneq ($(DEB_HOST_GNU_TYPE),$(DEB_BUILD_GNU_TYPE))
+  common_configure_args += --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE)
+  config_site = ac_cv_file__dev_ptmx=yes ac_cv_file__dev_ptc=yes
+  ifeq (,$(filter $(DEB_HOST_ARCH),arm m68k))
+    ifeq ($(DEB_HOST_ARCH_ENDIAN),little)
+      config_site += ac_cv_little_endian_double=yes
+    else
+      config_site += ac_cv_big_endian_double=yes
+    endif
+  endif
+endif
+
+stamps/stamp-configure-shared: stamps/stamp-patch
+       rm -rf $(buildd_shared)
+       mkdir -p $(buildd_shared)
+       cd $(buildd_shared) && \
+         AR="$(AR)" RANLIB="$(RANLIB)" CFLAGS="$(OPT_CFLAGS)" \
+         CPPFLAGS="$(DPKG_CPPFLAGS)" LDFLAGS="$(DPKG_LDFLAGS) $(LTO_CFLAGS)" \
+           $(config_site) \
+           ../configure \
+               --enable-shared \
+               $(common_configure_args)
+
+       $(call __post_configure,$(buildd_shared))
+
+       @echo XXXXXXX pyconfig.h
+       -cat $(buildd_shared)/pyconfig.h
+
+       touch $@
+
+stamps/stamp-configure-static: stamps/stamp-patch
+       rm -rf $(buildd_static)
+       mkdir -p $(buildd_static)
+       cd $(buildd_static) && \
+         AR="$(AR)" RANLIB="$(RANLIB)" CFLAGS="$(OPT_CFLAGS)" \
+         CPPFLAGS="$(DPKG_CPPFLAGS)" LDFLAGS="$(DPKG_LDFLAGS) $(LTO_CFLAGS)" \
+           $(config_site) \
+           ../configure \
+               $(common_configure_args)
+
+       $(call __post_configure,$(buildd_static))
+       touch $@
+
+stamps/stamp-configure-debug: stamps/stamp-patch
+       rm -rf $(buildd_debug)
+       mkdir -p $(buildd_debug)
+       cd $(buildd_debug) && \
+         AR="$(AR)" RANLIB="$(RANLIB)" CFLAGS="$(DEBUG_CFLAGS)" \
+         CPPFLAGS="$(DPKG_CPPFLAGS)" LDFLAGS="$(DPKG_LDFLAGS)" \
+           $(config_site) \
+           ../configure \
+               $(common_configure_args) \
+               --with-pydebug
+
+       $(call __post_configure,$(buildd_debug))
+       touch $@
+
+stamps/stamp-configure-shared-debug: stamps/stamp-patch
+       rm -rf $(buildd_shdebug)
+       mkdir -p $(buildd_shdebug)
+       cd $(buildd_shdebug) && \
+         AR="$(AR)" RANLIB="$(RANLIB)" CFLAGS="$(DEBUG_CFLAGS)" \
+         CPPFLAGS="$(DPKG_CPPFLAGS)" LDFLAGS="$(DPKG_LDFLAGS)" \
+           $(config_site) \
+           ../configure \
+               $(common_configure_args) \
+               --enable-shared \
+               --with-pydebug
+
+       $(call __post_configure,$(buildd_shdebug))
+       touch $@
+
+define __post_configure
+       egrep \
+         "^#($$(awk -v ORS='|' '$$2 ~ /^extension$$/ {print $$1}' debian/PVER-minimal.README.Debian.in)XX)" \
+         Modules/Setup \
+           | sed -e 's/^#//' -e 's/-Wl,-Bdynamic//;s/-Wl,-Bstatic//' \
+           >> $(1)/Modules/Setup.local
+
+       : # unconditionally run makesetup
+       cd $(1) && \
+         ../Modules/makesetup -c ../Modules/config.c.in -s Modules \
+           Modules/Setup.local ../Modules/Setup
+       mv $(1)/config.c $(1)/Modules/
+
+       : # and fix the timestamps
+       $(MAKE) -C $(1) Makefile Modules/config.c
+
+       : # this second rule doesn't build with -fPIC, remove it.
+       sed '/^Modules\/_math.o: .*PY_STDMODULE_CFLAGS/d' $(1)/Makefile > $(1)/Makefile.fixed
+       touch -r $(1)/Makefile $(1)/Makefile.fixed
+       mv -f $(1)/Makefile.fixed $(1)/Makefile
+endef
+
+stamps/stamp-mincheck: stamps/stamp-build-static debian/PVER-minimal.README.Debian.in
+ifeq ($(DEB_HOST_GNU_TYPE),$(DEB_BUILD_GNU_TYPE))
+       for m in $(MIN_MODS) $(MIN_PACKAGES) $(MIN_EXTS) $(MIN_BUILTINS); do \
+         echo "import $$m"; \
+       done > $(buildd_static)/minmods.py
+       cd $(buildd_static) && ./python ../debian/pymindeps.py minmods.py \
+         > mindeps.txt
+       -if [ -x /usr/bin/dot ]; then \
+         cd $(buildd_static) && ./python ../debian/depgraph.py \
+           < mindeps.txt > mindeps.dot; \
+         dot -Tpng -o mindeps.png mindeps.dot; \
+       else true; fi
+       cd $(buildd_static) && ./python ../debian/mincheck.py \
+               minmods.py mindeps.txt
+endif
+       touch stamps/stamp-mincheck
+
+TEST_DIR := $(shell [ -f debian/testdir ] || mktemp -d > debian/testdir; cat debian/testdir)
+
+TEST_RESOURCES = all
+ifeq ($(on_buildd),yes)
+  TEST_RESOURCES := $(TEST_RESOURCES),-network,-urlfetch
+endif
+TESTOPTS = -j 1 -w -u$(TEST_RESOURCES)
+TEST_EXCLUDES =
+TEST_EXCLUDES += test_ensurepip test_venv
+ifeq ($(on_buildd),yes)
+  TEST_EXCLUDES += test_tcl test_codecmaps_cn test_codecmaps_hk \
+        test_codecmaps_jp test_codecmaps_kr test_codecmaps_tw \
+        test_normalization test_ossaudiodev
+endif
+ifeq (,$(wildcard /dev/dsp))
+  TEST_EXCLUDES += test_linuxaudiodev test_ossaudiodev
+endif
+ifneq (,$(filter $(DEB_HOST_ARCH), hppa))
+  TEST_EXCLUDES += test_fork1 test_multiprocessing test_socketserver test_threading test_wait3 test_wait4 test_gdb
+endif
+# hangs on Aarch64, see LP: #1264354
+ifneq (,$(filter $(DEB_HOST_ARCH),arm64))
+  TEST_EXCLUDES += test_faulthandler
+endif
+ifneq (,$(filter $(DEB_HOST_ARCH), arm avr32))
+  TEST_EXCLUDES += test_ctypes
+endif
+TEST_EXCLUDES += test_socket
+ifneq (,$(filter $(DEB_HOST_ARCH), arm armel avr32 m68k))
+  ifeq ($(on_buildd),yes)
+    TEST_EXCLUDES += test_compiler
+  endif
+endif
+TEST_EXCLUDES += test_ttk_guionly
+# https://buildd.debian.org/status/logs.php?pkg=python3.5&ver=3.5.1-1&arch=alpha&suite=sid
+ifneq (,$(filter $(DEB_HOST_ARCH), alpha))
+  TEST_EXCLUDES += test_signal
+endif
+ifneq (,$(filter $(DEB_HOST_ARCH), sparc sparc64))
+  TEST_EXCLUDES += test_gdb
+endif
+
+ifneq (,$(filter $(DEB_HOST_ARCH), riscv64))
+  TEST_EXCLUDES += test_concurrent_futures
+endif
+
+# fail/hang with new OpenSSL
+TEST_EXCLUDES += test_asyncio test_ftplib test_httplib test_imaplib test_nntplib test_poplib test_ssl
+
+# TODO: re-enable once fixed, see #708652
+ifneq (,$(filter $(DEB_HOST_ARCH_OS), hurd))
+  TEST_EXCLUDES += test_asyncore test_curses test_exceptions \
+       test_faulthandler test_imaplib test_io test_logging test_mmap \
+       test_random test_signal test_socket test_socketserver test_ssl \
+       test_threading test_pydoc test_runpy test_telnetlib test_tk
+endif
+
+# TODO: re-enable once fixed, see #708653
+ifneq (,$(filter $(DEB_HOST_ARCH_OS), kfreebsd))
+  TEST_EXCLUDES += test_io test_signal test_socket test_socketserver \
+       test_threading test_threadsignals test_threaded_import \
+       test_time test_pty test_curses
+endif
+
+# for debug builds only
+TEST_EXCLUDES += test_gdb
+
+ifneq (,$(TEST_EXCLUDES))
+  TESTOPTS += -x $(sort $(TEST_EXCLUDES))
+endif
+
+ifneq (,$(wildcard /usr/bin/localedef))
+  SET_LOCPATH = LOCPATH=$(CURDIR)/locales
+endif
+
+stamps/stamp-check:
+ifeq ($(WITHOUT_CHECK),yes)
+       echo "check run disabled for this build" > $(buildd_static)/test_results
+else
+       : # build locales needed by the testsuite
+       rm -rf locales
+       mkdir locales
+       if which localedef >/dev/null 2>&1; then \
+         sh debian/locale-gen; \
+       fi
+
+       @echo ========== test environment ============
+       @env
+       @echo ========================================
+
+  ifeq (,$(findstring $(DEB_HOST_ARCH), alpha))
+       ( \
+         echo '#! /bin/sh'; \
+         echo 'set -x'; \
+         echo 'export $(SET_LOCPATH)'; \
+         echo '$(buildd_static)/python $(CURDIR)/debian/script.py test_results '\''make test TESTOPTS="$(filter-out test_gdb,$(TESTOPTS))"'\'; \
+         echo 'echo DONE'; \
+       ) > $(buildd_debug)/run_tests
+       chmod 755 $(buildd_debug)/run_tests
+       @echo "BEGIN test debug"
+       mkdir -p $(TEST_DIR)/debug/.local/lib/$(PVER)/site-packages
+       -cd $(buildd_debug) && HOME=$(TEST_DIR)/debug time xvfb-run -a -e xvfb-run.log ./run_tests
+       find $(TEST_DIR)/debug
+       rm -rf $(TEST_DIR)/debug
+       @echo "END test debug"
+  endif
+
+       ( \
+         echo '#! /bin/sh'; \
+         echo 'set -x'; \
+         echo 'export $(SET_LOCPATH)'; \
+         echo '$(buildd_static)/python $(CURDIR)/debian/script.py test_results '\''make test EXTRA_CFLAGS="$(EXTRA_OPT_CFLAGS)" TESTOPTS="$(TESTOPTS)"'\'; \
+         echo 'echo DONE'; \
+       ) > $(buildd_static)/run_tests
+       chmod 755 $(buildd_static)/run_tests
+       @echo "BEGIN test static"
+       mkdir -p $(TEST_DIR)/static/.local/lib/$(PVER)/site-packages
+       -cd $(buildd_static) && HOME=$(TEST_DIR)/static time xvfb-run -a -e xvfb-run.log ./run_tests
+       find $(TEST_DIR)/static
+       rm -rf $(TEST_DIR)/static
+       @echo "END test static"
+
+       ( \
+         echo '#! /bin/sh'; \
+         echo 'set -x'; \
+         echo 'export $(SET_LOCPATH)'; \
+         echo '$(buildd_static)/python $(CURDIR)/debian/script.py test_results '\''make test EXTRA_CFLAGS="$(EXTRA_OPT_CFLAGS)" TESTOPTS="$(TESTOPTS)"'\'; \
+         echo 'echo DONE'; \
+       ) > $(buildd_shared)/run_tests
+       chmod 755 $(buildd_shared)/run_tests
+       @echo "BEGIN test shared"
+       mkdir -p $(TEST_DIR)/shared/.local/lib/$(PVER)/site-packages
+       -cd $(buildd_shared) && HOME=$(TEST_DIR)/shared time xvfb-run -a -e xvfb-run.log ./run_tests
+       find $(TEST_DIR)/shared
+       rm -rf $(TEST_DIR)/shared
+       @echo "END test shared"
+endif
+       cp -p $(buildd_static)/test_results debian/
+       touch stamps/stamp-check
+
+stamps/stamp-pybench:
+       echo "pybench run disabled for this build" > $(buildd_static)/pybench.log
+
+#ifeq (,$(filter $(DEB_HOST_ARCH), arm armel avr32 hppa mips mipsel mips64 mips64el m68k))
+  pybench_options = -C 2 -n 5 -w 4
+#endif
+
+stamps/stamp-pybenchx:
+ifeq ($(WITHOUT_BENCH),yes)
+       echo "pybench run disabled for this build" > $(buildd_static)/pybench.log
+else
+       @echo "BEGIN pybench static"
+       cd $(buildd_static) \
+         && time ./python ../Tools/pybench/pybench.py -f run1.pybench $(pybench_options)
+       cd $(buildd_static) \
+         && ./python ../Tools/pybench/pybench.py -f run2.pybench -c run1.pybench $(pybench_options)
+       @echo "END pybench static"
+       @echo "BEGIN pybench shared"
+       cd $(buildd_shared) \
+         && LD_LIBRARY_PATH=. ./python ../Tools/pybench/pybench.py -f run1.pybench $(pybench_options)
+       cd $(buildd_shared) \
+         && LD_LIBRARY_PATH=. ./python ../Tools/pybench/pybench.py -f run2.pybench -c run1.pybench $(pybench_options)
+       @echo "END pybench shared"
+       @echo "BEGIN shared/static comparision"
+       $(buildd_static)/python Tools/pybench/pybench.py \
+         -s $(buildd_static)/run2.pybench -c $(buildd_shared)/run2.pybench \
+         | tee $(buildd_static)/pybench.log
+       @echo "END shared/static comparision"
+endif
+       touch stamps/stamp-pybench
+
+minimal-test:
+       rm -rf mintest
+       mkdir -p mintest/lib mintest/dynlib mintest/testlib mintest/all-lib
+       cp -p $(buildd_static)/python mintest/
+       cp -p $(foreach i,$(MIN_MODS),Lib/$(i).py) \
+               mintest/lib/
+       cp -a $(foreach i,$(MIN_PACKAGES),Lib/$(i)) \
+               mintest/lib/
+       cp -p $(wildcard $(foreach i,$(MIN_EXTS),$(buildd_static)/build/lib*/$(i).*.so)) \
+               mintest/dynlib/
+       cp -p Lib/unittest.py mintest/lib/
+       cp -pr Lib/test mintest/lib/
+       cp -pr Lib mintest/all-lib
+       cp -p $(buildd_static)/build/lib*/*.so mintest/all-lib/
+       ( \
+         echo "import sys"; \
+         echo "sys.path = ["; \
+         echo "    '$(CURDIR)/mintest/lib',"; \
+         echo "    '$(CURDIR)/mintest/dynlib',"; \
+         echo "]"; \
+         cat Lib/test/regrtest.py; \
+       ) > mintest/lib/test/mintest.py
+       cd mintest && ./python -E -S lib/test/mintest.py \
+            -x test_codecencodings_cn test_codecencodings_hk \
+               test_codecencodings_jp test_codecencodings_kr \
+               test_codecencodings_tw test_codecs test_multibytecodec \
+
+stamps/stamp-doc-html:
+       dh_testdir
+       $(MAKE) -C Doc html
+       @mkdir -p stamps
+       touch stamps/stamp-doc-html
+
+stamps/stamp-doc-info:
+       dh_testdir
+       rm -rf Doc/build/texinfo
+       $(MAKE) -C Doc texinfo
+# - Change name of info file (@setfilename) to include the version.
+# - Change the directory entry to include the version and point to the
+#   correct filename.
+# - Change image links (@image) to point to a subdirectory.
+# - Remove trailing whitespace.
+       sed -e 's/^@setfilename .*/@setfilename $(PVER).info/' \
+           -e '/^@direntry/,/^@/s/^\*[^:]*: ([^)]*)/* Python $(VER): ($(PVER))/' \
+           -e 's,@image{,@image{$(PVER)/,g' \
+           -e 's/ *$$//' \
+         < Doc/build/texinfo/python.texi \
+         > Doc/build/texinfo/$(PVER).texi
+       rm -f Doc/build/texinfo/python.texi
+# - Create a symbolic link so that makeinfo will be able to find the
+#   image files.
+       ln -s . Doc/build/texinfo/$(PVER)
+       $(MAKE) -C Doc/build/texinfo
+       @mkdir -p stamps
+       touch stamps/stamp-doc-info
+
+build-doc: stamps/stamp-patch stamps/stamp-build-doc
+stamps/stamp-build-doc: stamps/stamp-doc-html stamps/stamp-doc-info
+       @mkdir -p stamps
+       touch stamps/stamp-build-doc
+
+control-file:
+       sed -e "s/@PVER@/$(PVER)/g" \
+           -e "s/@VER@/$(VER)/g" \
+           -e "s/@PYSTDDEP@/$(PYSTDDEP)/g" \
+           -e "s/@PRIO@/$(PY_PRIO)/g" \
+           -e "s/@MINPRIO@/$(PY_MINPRIO)/g" \
+           -e "s/@bd_qual@/$(bd_qual)/g" \
+           -e "s/@bd_gcc@/$(bd_gcc)/g" \
+           -e "s/@bd_dpkgdev@/$(bd_dpkgdev)/g" \
+               debian/control.in \
+               $(if $(with_udeb),debian/control.udeb) \
+             | $(ma_filter) \
+             > debian/control.tmp
+ifeq ($(distribution),Ubuntu)
+  ifneq (,$(findstring ubuntu, $(PKGVERSION)))
+       m='Ubuntu Core Developers <ubuntu-devel-discuss@lists.ubuntu.com>'; \
+       sed -i "/^Maintainer:/s/\(.*\)/Maintainer: $$m\nXSBC-Original-\1/" \
+         debian/control.tmp
+  endif
+endif
+       [ -e debian/control ] \
+         && cmp -s debian/control debian/control.tmp \
+         && rm -f debian/control.tmp && exit 0; \
+         mv debian/control.tmp debian/control
+
+
+
+clean: control-file
+       dh_testdir
+       dh_testroot
+       rm -rf stamps
+       rm -f debian/test_results
+
+       $(MAKE) -C Doc clean
+       sed 's/^@/#/' Makefile.pre.in | $(MAKE) -f - srcdir=. distclean
+       rm -rf $(buildd_static) $(buildd_shared) $(buildd_debug) $(buildd_shdebug)
+       find -name '*.py[co]' | xargs -r rm -f
+       rm -f Lib/lib2to3/*.pickle
+       rm -f Lib/dist-packages
+       rm -rf locales
+       rm -rf $(d)-dbg
+       rm -f configure
+       rm -f netlify.toml
+       rm -rf $(TEST_DIR) debian/testdir
+
+       for f in debian/*.in; do \
+         f2=`echo $$f | sed "s,PVER,$(PVER),g;s/@VER@/$(VER)/g;s,\.in$$,,"`; \
+         if [ $$f2 != debian/control ] && [ $$f2 != debian/source.lintian-overrides ]; then \
+           rm -f $$f2; \
+         fi; \
+       done
+
+       dh_clean
+
+stamps/stamp-control:
+       : # We have to prepare the various control files
+
+       for f in debian/*.in; do \
+         f2=`echo $$f | sed "s,PVER,$(PVER),g;s/@VER@/$(VER)/g;s,\.in$$,,"`; \
+         if [ $$f2 != debian/control ]; then \
+           sed -e "s/@PVER@/$(PVER)/g;s/@VER@/$(VER)/g;s/@SVER@/$(SVER)/g" \
+                   -e "s/@PRIORITY@/$(PRIORITY)/g" \
+                   -e "s,@SCRIPTDIR@,/$(scriptdir),g" \
+                   -e "s,@INFO@,$(info_docs),g" \
+                   -e "s,@HOST_QUAL@,:$(DEB_HOST_ARCH),g" \
+                 <$$f >$$f2; \
+         fi; \
+       done
+
+2to3-man:
+       help2man --no-info --version-string=$(VER) --no-discard-stderr \
+         --name 'Python2 to Python3 converter' \
+         2to3-$(VER) > debian/2to3-3.1
+       help2man --no-info --version-string=$(VER) --no-discard-stderr \
+         --name 'pysetup tool' \
+         pysetup$(VER) > debian/pysetup3.1
+
+install: build-arch stamps/stamp-install
+stamps/stamp-install: stamps/stamp-build control-file stamps/stamp-control
+       dh_testdir
+       dh_testroot
+       dh_prep
+       dh_installdirs
+
+       : # make install into tmp and subsequently move the files into
+       : # their packages' directories.
+       install -d $(d)/usr
+ifeq ($(with_interp),static)
+       $(MAKE) -C $(buildd_static) install DESTDIR=$(CURDIR)/$(d)
+       ls -l $(d)/$(scriptdir)/_sysconfigdata*
+       sed $(sysconfig_substflags) \
+               $(buildd_shared)/$(shell cat $(buildd_shared)/pybuilddir.txt)/_sysconfigdata__$(DEB_HOST_MULTIARCH).py \
+               > $(d)/$(scriptdir)/_sysconfigdata__$(DEB_HOST_MULTIARCH).py
+else
+       $(MAKE) -C $(buildd_shared) install DESTDIR=$(CURDIR)/$(d)
+endif
+       mkdir -p $(d)/usr/include/$(DEB_HOST_MULTIARCH)/$(PVER)
+       mv $(d)/usr/include/$(PVER)/pyconfig.h \
+               $(d)/usr/include/$(DEB_HOST_MULTIARCH)/$(PVER)/.
+       rm -f $(d)/$(scriptdir)/lib-dynload/*.py
+       ls -l $(d)/$(scriptdir)/_sysconfigdata*
+       sed -i $(sysconfig_substflags) \
+               $(d)/$(scriptdir)/_sysconfigdata__$(DEB_HOST_MULTIARCH).py
+
+       -find $(d)/usr/lib/python$(VER) -name '*_failed*.so'
+       find $(d)/usr/lib/python$(VER) -name '*_failed*.so' | xargs -r rm -f
+
+       for i in $(d)/$(scriptdir)/lib-dynload/*.so; do \
+         case "$$i" in *$(DEB_HOST_MULTIARCH)*) continue; esac; \
+         b=$$(basename $$i .cpython-$(EXT_VER)m.so); \
+         d=$${b}.cpython-$(EXT_VER)m-$(DEB_HOST_MULTIARCH).so; \
+         mv $$i $(d)/$(scriptdir)/lib-dynload/$$d; \
+       done
+
+       mv $(d)/usr/lib/libpython*.a $(d)/usr/lib/$(DEB_HOST_MULTIARCH)/
+
+       mkdir -p $(d)/usr/lib/python3
+       mv $(d)/usr/lib/python$(VER)/site-packages \
+               $(d)/usr/lib/python3/dist-packages
+       rm -f $(d)/usr/lib/python3/dist-packages/README*
+
+       : # remove files, which are not packaged
+       rm -rf $(d)/usr/lib/python$(VER)/ctypes/macholib
+       rm -f $(d)/$(scriptdir)/lib2to3/*.pickle
+       rm -f $(d)/usr/share/man/man1/python3.1
+
+       if [ -d $(d)/$(scriptdir)/ensurepip/_bundled ]; then \
+         echo "don't ship the prebuilt ensurepip/_bundled wheels."; \
+         rm -rf $(d)/$(scriptdir)/ensurepip/_bundled; \
+       fi
+
+       : # cannot build it, zlib maintainer won't provide a mingw build
+       find $(d) -name 'wininst*.exe' | xargs -r rm -f
+
+       : # fix some file permissions
+       chmod a-x $(d)/$(scriptdir)/{runpy,fractions,lib2to3/refactor,tkinter/tix}.py
+       chmod a-x $(d)/$(scriptdir)/test/test_pathlib.py
+
+#      : # move manpages to new names
+#      if [ -d $(d)/usr/man/man1 ]; then \
+#          mkdir -p $(d)/usr/share/man
+#          mv $(d)/usr/man/man1/* $(d)/usr/share/man/man1/; \
+#          rm -rf $(d)/usr/man/; \
+#      fi
+
+       mkdir -p $(d)/usr/share/man/man1
+       cp -p Misc/python.man $(d)/usr/share/man/man1/python$(VER).1
+       cp -p debian/pydoc.1 $(d)/usr/share/man/man1/pydoc$(VER).1
+
+       : # Symlinks to /usr/bin for some tools
+       ln -sf ../lib/python$(VER)/pdb.py $(d)/usr/bin/pdb$(VER)
+       cp -p debian/pdb.1 $(d)/usr/share/man/man1/pdb$(VER).1
+       cp -p debian/pysetup3.1 $(d)/usr/share/man/man1/pysetup$(VER).1
+
+       : # versioned install only
+       rm -f $(d)/usr/bin/{2to3,idle3,pydoc3,pysetup3,python3,python3-config}
+       rm -f $(d)/usr/lib/*/pkgconfig/python3.pc
+       rm -f $(d)/usr/lib/*/pkgconfig/python3-embed.pc
+
+       dh_installdirs -p$(p_lib) \
+               usr/lib/$(DEB_HOST_MULTIARCH) \
+               $(scriptdir)/config-$(VER)m-$(DEB_HOST_MULTIARCH) \
+               usr/share/doc
+       : # install the shared library
+       cp -p $(buildd_shared)/libpython$(VER).so.1.0 \
+               $(d_lib)/usr/lib/$(DEB_HOST_MULTIARCH)/
+       dh_link -p$(p_lib) \
+           /usr/lib/$(DEB_HOST_MULTIARCH)/libpython$(VER).so.1.0 \
+               /usr/lib/$(DEB_HOST_MULTIARCH)/libpython$(VER).so.1 \
+           /usr/lib/$(DEB_HOST_MULTIARCH)/libpython$(VER).so.1 \
+               /$(scriptdir)/config-$(VER)-$(DEB_HOST_MULTIARCH)/libpython$(VER).so \
+           /usr/lib/$(DEB_HOST_MULTIARCH)/libpython$(VER).so.1 \
+               /$(scriptdir)/config-$(VER)-$(DEB_HOST_MULTIARCH)/libpython$(VER).so
+
+       ln -sf $(p_base) $(d_lib)/usr/share/doc/$(p_lib)
+
+       ln -sf libpython$(VER).so.1 $(d)/usr/lib/$(DEB_HOST_MULTIARCH)/libpython$(VER).so
+
+ifeq ($(with_interp),shared)
+       : # install the statically linked runtime
+       install -m755 $(buildd_static)/python $(d)/usr/bin/python$(VER)-static
+endif
+
+       cp -p Tools/i18n/pygettext.py $(d)/usr/bin/pygettext$(VER)
+       cp -p debian/pygettext.1 $(d)/usr/share/man/man1/pygettext$(VER).1
+
+       : # install the Makefile of the shared python build
+       sed $(sysconfig_substflags) \
+               $(buildd_shared)/Makefile \
+               > $(d)/$(scriptdir)/config-$(VER)-$(DEB_HOST_MULTIARCH)/Makefile
+
+       : # Move the minimal libraries into $(p_lmin).
+       dh_installdirs -p$(p_lmin) \
+               etc/$(PVER) \
+               usr/bin \
+               usr/share/man/man1 \
+               $(scriptdir)/lib-dynload
+       -cd $(d); for i in $(MIN_EXTS); do \
+                       test -e $(scriptdir)/lib-dynload/$$i.*.so \
+                         && echo $(scriptdir)/lib-dynload/$$i.*.so; \
+                 done
+
+       $(dh_compat2) dh_movefiles -p$(p_lmin) --sourcedir=$(d) \
+               $(foreach i,$(MIN_MODS),$(scriptdir)/$(i).py) \
+               $(foreach i,$(MIN_PACKAGES),$(scriptdir)/$(i)) \
+               $(foreach i,$(MIN_ENCODINGS),$(scriptdir)/$(i)) \
+               $(scriptdir)/site.py \
+               $(scriptdir)/_sysconfigdata__$(DEB_HOST_MULTIARCH).py \
+               `cd $(d); for i in $(MIN_EXTS); do \
+                       test -e $(scriptdir)/lib-dynload/$$i.*.so \
+                         && echo $(scriptdir)/lib-dynload/$$i.*.so; \
+                 done`
+       ls -l  $(d_lmin)/$(scriptdir)/lib-dynload/*.so
+
+       : # Move the binary into $(p_min).
+       dh_installdirs -p$(p_min) \
+               usr/bin \
+               usr/share/man/man1
+       $(dh_compat2) dh_movefiles -p$(p_min) --sourcedir=$(d) \
+               usr/bin/python$(VER) \
+               usr/share/man/man1/python$(VER).1
+
+       rv=0; \
+       for i in $(MIN_EXTS); do \
+         if [ -f $(d)/$(scriptdir)/lib-dynload/$$i.so ]; then \
+           echo >&2 "extension $$i not mentioned in Setup.dist"; \
+           rv=1; \
+         fi; \
+       done; \
+       exit $$rv;
+
+       : # Install sitecustomize.py
+       cp -p debian/sitecustomize.py $(d_lmin)/etc/$(PVER)/
+       dh_link -p$(p_lmin) \
+               /etc/$(PVER)/sitecustomize.py /$(scriptdir)/sitecustomize.py
+
+       : # Move the static library and the header files into $(p_dev).
+#      mv $(d)/usr/share/include/python$(VER)/* $(d)/usr/include/python$(VER)/.
+#      rm -rf $(d)/usr/share/include
+
+       cp $(d)/usr/bin/$(PVER)-config $(d)/usr/bin/$(DEB_HOST_MULTIARCH)-$(PVER)-config
+
+       dh_installdirs -p$(p_ldev) \
+               usr/bin \
+               $(scriptdir) \
+               usr/include \
+               usr/share/man/man1
+
+       $(dh_compat2) dh_movefiles -p$(p_ldev) --sourcedir=$(d) \
+               usr/bin/$(DEB_HOST_MULTIARCH)-$(PVER)*-config \
+               usr/lib/python$(VER)/config-$(VER)-$(DEB_HOST_MULTIARCH) \
+               usr/include \
+               usr/lib/$(DEB_HOST_MULTIARCH)/libpython$(VER).{a,so} \
+               usr/lib/$(DEB_HOST_MULTIARCH)/pkgconfig/python-$(VER)*.pc \
+               usr/lib/python$(VER)/distutils/command/wininst-*.exe
+
+       sed 's/@subdir@/$(PVER)/;s/@header@/pyconfig.h/' \
+               debian/multiarch.h.in > $(d_ldev)/usr/include/$(PVER)/pyconfig.h
+
+       sed -i \
+           -e '/^Cflags:/s,$$, -I$${includedir}/$(DEB_HOST_MULTIARCH)/python$(VER),' \
+           -e '/^libdir=/d;s/-L\$${libdir} *//' \
+               $(d_ldev)/usr/lib/$(DEB_HOST_MULTIARCH)/pkgconfig/python-$(VER).pc
+
+       dh_link -p$(p_ldev) \
+           /usr/lib/$(PVER)/config-$(VER)-$(DEB_HOST_MULTIARCH)/libpython$(VER).a \
+               /usr/lib/$(DEB_HOST_MULTIARCH)/libpython$(VER).a
+
+       cp -p $(buildd_shared)/libpython$(VER)-pic.a \
+               $(d_ldev)/usr/lib/python$(VER)/config-$(VER)-$(DEB_HOST_MULTIARCH)/
+
+# FIXME
+#      : # symlinks for the "old" include directory name
+#      ln -sf python$(VER)m $(d_ldev)/usr/include/python$(VER)
+
+       dh_installdirs -p$(p_dev) \
+               usr/share/doc/python$(VER) \
+               usr/share/man/man1 \
+               $(scriptdir) \
+               $(scriptdir)/doc/html
+       cp -p Misc/HISTORY Misc/README.valgrind Misc/gdbinit \
+               debian/README.maintainers \
+               debian/test_results $(buildd_static)/pybench.log \
+           $(d_dev)/usr/share/doc/python$(VER)/
+
+       $(dh_compat2) dh_movefiles -p$(p_dev) --sourcedir=$(d) \
+               usr/bin/python$(VER)*-config
+
+       : # in $(p_ldev), prefix python-config with triplets
+       cp -p debian/python3-config.1 \
+               $(d_ldev)/usr/share/man/man1/$(DEB_HOST_MULTIARCH)-$(PVER)-config.1
+ifneq ($(DEB_HOST_MULTIARCH),$(DEB_HOST_GNU_TYPE))
+       ln -sf $(DEB_HOST_MULTIARCH)-$(PVER)-config \
+               $(d_ldev)/usr/bin/$(DEB_HOST_GNU_TYPE)-$(PVER)-config
+       ln -sf $(DEB_HOST_MULTIARCH)-$(PVER)-config.1.gz \
+               $(d_ldev)/usr/share/man/man1/$(DEB_HOST_GNU_TYPE)-$(PVER)-config.1.gz
+endif
+
+       ln -sf $(DEB_HOST_MULTIARCH)-$(PVER)-config $(d_dev)/usr/bin/$(PVER)-config
+       ln -sf $(DEB_HOST_MULTIARCH)-$(PVER)-config.1.gz $(d_dev)/usr/share/man/man1/$(PVER)-config.1.gz
+
+ifeq ($(with_tk),yes)
+       : # Move the Tkinter extension files into $(p_tk).
+       dh_installdirs -p$(p_tk) \
+               $(scriptdir) \
+               usr/lib/python$(VER)/lib-dynload
+       $(dh_compat2) dh_movefiles -p$(p_tk) --sourcedir=$(d) \
+               usr/lib/python$(VER)/lib-dynload/_tkinter*.so
+endif
+
+       : # The test framework into $(p_lbase)
+       $(dh_compat2) dh_movefiles -p$(p_lbase) --sourcedir=$(d) \
+               $(scriptdir)/test/{libregrtest,support} \
+               $(scriptdir)/test/{ann_module,ann_module2,ann_module3}.py \
+               $(scriptdir)/test/{regrtest,test_support,__init__,__main__}.py
+
+       : # The complete testsuite into $(p_lbase)
+       $(dh_compat2) dh_movefiles -p$(p_ltst) --sourcedir=$(d) \
+               $(scriptdir)/test \
+               $(scriptdir)/ctypes/test \
+               $(scriptdir)/distutils/tests \
+               $(scriptdir)/lib2to3/tests \
+               $(scriptdir)/sqlite3/test \
+               $(scriptdir)/idlelib/idle_test \
+               $(scriptdir)/tkinter/test \
+               $(scriptdir)/unittest/test
+       : # test_ctypes fails with test_macholib.py installed
+       rm -f $(d_ltst)/$(scriptdir)/ctypes/test/test_macholib.py
+       : # test_bdist_wininst fails, '*.exe' files are not installed
+       rm -f $(d_ltst)/$(scriptdir)/distutils/tests/test_bdist_wininst.py
+
+       : # fixed upstream ...
+       chmod -x $(d_ltst)/$(scriptdir)/test/{test_dbm_gnu,test_dbm_ndbm}.py
+
+       : # Tkinter library files shipped in python3-tk
+       rm -rf $(d)/usr/lib/python$(VER)/tkinter
+
+       : # distutils shipped in python3-distutils
+       rm -rf $(d)/usr/lib/python$(VER)/distutils/*
+       : # ... except for distutils.version
+       cp Lib/distutils/{__init__,version}.py \
+               $(d)/usr/lib/python$(VER)/distutils/.
+
+       : # lib2to3 shipped in python3-lib2to3
+       rm -rf \
+               $(d)/usr/bin/2to3-$(VER) \
+               $(d)/usr/share/man/man1/2to3-$(VER).1 \
+               $(d)/usr/lib/python$(VER)/lib2to3
+
+       : # Move the demos and tools into $(p_exam)'s doc directory
+       dh_installdirs -p$(p_exam) \
+               usr/share/doc/python$(VER)/examples
+       $(dh_compat2) dh_movefiles -p$(p_exam) --sourcedir=$(d) \
+               $(scriptdir)/turtledemo
+
+       cp -rp Tools/* $(d_exam)/usr/share/doc/python$(VER)/examples/
+       rm -rf $(d_exam)/usr/share/doc/python$(VER)/examples/Tools/{buildbot,msi}
+       : # XXX: We don't need rgb.txt, we'll use our own:
+       rm -rf $(d_exam)/usr/share/doc/python$(VER)/examples/Tools/pynche/X
+
+       : # IDLE
+       mv $(d)/usr/bin/idle$(VER) $(d)/usr/bin/idle-python$(VER)
+       rm -f $(d)/usr/lib/python$(VER)/idlelib/idle.bat
+       dh_installdirs -p$(p_idle) \
+               usr/bin \
+               usr/share/man/man1
+       $(dh_compat2) dh_movefiles -p$(p_idle) --sourcedir=$(d) \
+               usr/bin/idle-python$(VER) \
+               usr/lib/python$(VER)/idlelib
+       cp -p debian/idle-$(PVER).1 $(d_idle)/usr/share/man/man1/
+
+       : # Replace all '#!' calls to python with $(PY_INTERPRETER)
+       : # and make them executable
+       for p in $(shell dh_listpackages); do \
+       [ -d debian/$$p ] || continue; \
+       for i in `find debian/$$p -type f`; do \
+         sed '1s,#!.*python[^ ]*\(.*\),#! $(PY_INTERPRETER)\1,' \
+               $$i > $$i.temp; \
+         if cmp --quiet $$i $$i.temp; then \
+           rm -f $$i.temp; \
+         else \
+           if [ ! -x $$i ]; then \
+             echo "fixed x file permissions: $$i"; \
+           fi; \
+           mv -f $$i.temp $$i; \
+           chmod 755 $$i; \
+           echo "fixed interpreter: $$i"; \
+         fi; \
+       done; \
+       done
+
+       : # Move the docs into $(p_base)'s /usr/share/doc/$(PVER) directory,
+       : # all other packages only have a copyright file.
+       dh_installdocs -p$(p_base) \
+               README.rst Misc/NEWS Misc/ACKS
+       ln -sf NEWS.gz $(d_base)/usr/share/doc/$(p_base)/changelog.gz
+       dh_installdocs --all \
+               -N$(p_base) -N$(p_dev) -N$(p_dbg) -N$(p_lib) \
+               debian/README.Debian
+
+       : # IDLE has its own changelogs, docs...
+       dh_installchangelogs -p$(p_idle) Lib/idlelib/ChangeLog
+       dh_installdocs -p$(p_idle) Lib/idlelib/{NEWS,README,TODO,extend}.txt
+
+       mkdir -p $(d_idle)/usr/share/applications
+       cp -p debian/idle.desktop \
+               $(d_idle)/usr/share/applications/idle-$(PVER).desktop
+
+       : # those packages have own README.Debian's
+       install -m 644 -p debian/README.$(p_base) \
+               $(d_base)/usr/share/doc/$(PVER)/README.Debian
+       install -m 644 -p debian/README.$(p_idle) \
+               $(d_idle)/usr/share/doc/$(p_idle)/README.Debian
+ifeq ($(with_tk),yes)
+       cp -p debian/README.Tk $(d_tk)/usr/share/doc/$(p_tk)/
+endif
+
+       : # pyvenv and ensurepip files into $(p_venv)
+       dh_installdirs -p$(p_venv) \
+               usr/lib/python$(VER)
+       dh_movefiles -p$(p_venv) \
+               usr/lib/python$(VER)/ensurepip
+
+       : # library files into $(p_lbase)
+       dh_installdirs -p$(p_lbase) \
+               usr/lib
+       dh_movefiles -p$(p_lbase) \
+               usr/lib/python$(VER)
+
+       : # The rest goes into $(p_base)
+       mkdir -p $(d)/usr/lib/python3/dist-packages
+       (cd $(d) && tar cf - .) | (cd $(d_base) && tar xpf -)
+       rm -f $(d_base)/usr/bin/python
+
+       : # Install menu icon
+       dh_installdirs -p$(p_base) usr/share/pixmaps
+       cp -p debian/pylogo.xpm $(d_base)/usr/share/pixmaps/$(PVER).xpm
+
+       : # generate binfmt file
+       mkdir -p $(d_min)/usr/share/binfmts
+ifeq ($(DEB_HOST_GNU_TYPE),$(DEB_BUILD_GNU_TYPE))
+       $(buildd_static)/python debian/mkbinfmt.py $(PVER) \
+               > $(d_min)/usr/share/binfmts/$(PVER)
+else
+       $(PVER) debian/mkbinfmt.py $(PVER) > $(d_min)/usr/share/binfmts/$(PVER)
+endif
+
+       : # desktop entry
+       mkdir -p $(d_base)/usr/share/applications
+       cp -p debian/$(PVER).desktop \
+               $(d_base)/usr/share/applications/$(PVER).desktop
+
+       : # remove some things
+       -find debian -name .cvsignore | xargs rm -f
+       -find debian -name '*.py[co]' | xargs rm -f
+
+       : # remove empty directories, when all components are in place
+       -find debian ! -name lib-dynload ! -name dist-packages -type d -empty -delete
+
+       : # install debug package
+       rm -rf $(d)-dbg
+       $(MAKE) -C $(buildd_debug) install DESTDIR=$(CURDIR)/$(d)-dbg
+       : # install the Makefile of the shared python debug build
+       sed $(sysconfig_substflags) \
+               $(buildd_shdebug)/Makefile \
+               > $(d)-dbg/$(scriptdir)/config-$(VER)d-$(DEB_HOST_MULTIARCH)/Makefile
+       sed $(sysconfig_substflags) \
+               $(buildd_shdebug)/$(shell cat $(buildd_shdebug)/pybuilddir.txt)/_sysconfigdata_d_$(DEB_HOST_MULTIARCH).py \
+               > $(d)-dbg/$(scriptdir)/_sysconfigdata_d_$(DEB_HOST_MULTIARCH).py
+       sed -i $(sysconfig_substflags) \
+               $(d)-dbg/$(scriptdir)/_sysconfigdata_d_$(DEB_HOST_MULTIARCH).py
+
+       mv $(d)-dbg/usr/lib/libpython*.a $(d)-dbg/usr/lib/$(DEB_HOST_MULTIARCH)/
+
+       for i in $(d)-dbg/$(scriptdir)/lib-dynload/*.so; do \
+         case "$$i" in *$(DEB_HOST_MULTIARCH)*) continue; esac; \
+         b=$$(basename $$i .cpython-$(EXT_VER)d.so); \
+         d=$${b}.cpython-$(EXT_VER)d-$(DEB_HOST_MULTIARCH).so; \
+         mv $$i $(d)-dbg/$(scriptdir)/lib-dynload/$$d; \
+       done
+
+       dh_installdirs -p$(p_ldbg) \
+               usr/bin \
+               usr/share/man/man1 \
+               $(scriptdir)/lib-dynload \
+               usr/include/$(PVER)d \
+               usr/include/$(DEB_HOST_MULTIARCH)/$(PVER)d \
+               usr/lib/$(DEB_HOST_MULTIARCH)/pkgconfig
+
+       cp -p $(d)-dbg/$(scriptdir)/lib-dynload/*.so \
+               $(d_ldbg)/$(scriptdir)/lib-dynload/
+       cp -p $(d)-dbg/$(scriptdir)/_sysconfigdata_d_$(DEB_HOST_MULTIARCH).py \
+               $(d_ldbg)/$(scriptdir)/
+       cp -p $(buildd_shdebug)/libpython$(VER)d.so.1.0 \
+               $(d_ldbg)/usr/lib/$(DEB_HOST_MULTIARCH)/
+       dh_link -p$(p_ldbg) \
+           /usr/lib/$(DEB_HOST_MULTIARCH)/libpython$(VER)d.so.1.0 \
+               /usr/lib/$(DEB_HOST_MULTIARCH)/libpython$(VER)d.so.1 \
+           /usr/lib/$(DEB_HOST_MULTIARCH)/libpython$(VER)d.so.1 \
+               /usr/lib/$(DEB_HOST_MULTIARCH)/libpython$(VER)d.so
+       cp $(d)-dbg/usr/lib/$(DEB_HOST_MULTIARCH)/pkgconfig/python-$(VER)d.pc \
+         $(d_ldbg)/usr/lib/$(DEB_HOST_MULTIARCH)/pkgconfig/.
+       ln -s python-$(VER)d.pc \
+         $(d_ldbg)/usr/lib/$(DEB_HOST_MULTIARCH)/pkgconfig/python-$(VER)-dbg.pc
+       cp $(d)-dbg/usr/lib/$(DEB_HOST_MULTIARCH)/pkgconfig/python-$(VER)d-embed.pc \
+         $(d_ldbg)/usr/lib/$(DEB_HOST_MULTIARCH)/pkgconfig/.
+       ln -s python-$(VER)d-embed.pc \
+         $(d_ldbg)/usr/lib/$(DEB_HOST_MULTIARCH)/pkgconfig/python-$(VER)-dbg-embed.pc
+
+       dh_installdirs -p$(p_dbg) \
+               usr/bin \
+               usr/share/man/man1 \
+               usr/share/doc/$(p_base)
+       cp -p Misc/SpecialBuilds.txt $(d_dbg)/usr/share/doc/$(p_base)/
+       cp -p debian/$(PVER)-dbg.README.Debian \
+               $(d_dbg)/usr/share/doc/$(p_base)/README.debug
+       cp -p $(buildd_debug)/python $(d_dbg)/usr/bin/$(PVER)d
+       ln -sf python$(VER)d $(d_dbg)/usr/bin/$(PVER)-dbg
+
+ifneq ($(with_tk),yes)
+       rm -f $(d_ldbg)/$(scriptdir)/lib-dynload/_tkinter*.so
+       rm -f $(d_ldbg)/usr/lib/debug/$(scriptdir)/lib-dynload/_tkinter*.so
+endif
+ifneq ($(with_gdbm),yes)
+       rm -f $(d_ldbg)/$(scriptdir)/lib-dynload/_gdbm*.so
+       rm -f $(d_ldbg)/usr/lib/debug/$(scriptdir)/lib-dynload/_gdbm*.so
+endif
+
+       cp -a $(d)-dbg/$(scriptdir)/config-$(VER)d-$(DEB_HOST_MULTIARCH) \
+               $(d_ldbg)/$(scriptdir)/
+       dh_link -p$(p_ldbg) \
+           /usr/lib/$(DEB_HOST_MULTIARCH)/libpython$(VER)d.so \
+               /$(scriptdir)/config-$(VER)d-$(DEB_HOST_MULTIARCH)/libpython$(VER)d.so \
+           /usr/lib/$(DEB_HOST_MULTIARCH)/libpython$(VER)d.so \
+               /$(scriptdir)/config-$(VER)d-$(DEB_HOST_MULTIARCH)/libpython$(VER).so \
+           /$(scriptdir)/config-$(VER)d-$(DEB_HOST_MULTIARCH)/libpython$(VER)d.a \
+               /usr/lib/$(DEB_HOST_MULTIARCH)/libpython$(VER)d.a
+
+       for i in $(d_ldev)/usr/include/$(PVER)/*; do \
+         i=$$(basename $$i); \
+         case $$i in pyconfig.h) continue; esac; \
+         ln -sf ../$(PVER)/$$i $(d_ldbg)/usr/include/$(PVER)d/$$i; \
+       done
+       cp -p $(buildd_debug)/pyconfig.h $(d_ldbg)/usr/include/$(DEB_HOST_MULTIARCH)/$(PVER)d/
+       sed 's/@subdir@/$(PVER)d/;s/@header@/pyconfig.h/' \
+               debian/multiarch.h.in > $(d_ldbg)/usr/include/$(PVER)d/pyconfig.h
+
+       ln -sf $(PVER).1.gz $(d_dbg)/usr/share/man/man1/$(PVER)-dbg.1.gz
+
+       : # in $(p_ldbg), prefix python-config with triplets
+       cp $(d)-dbg/usr/bin/$(PVER)d-config \
+               $(d_ldbg)/usr/bin/$(DEB_HOST_MULTIARCH)-$(PVER)d-config
+       ln -sf $(DEB_HOST_MULTIARCH)-$(PVER)d-config \
+               $(d_ldbg)/usr/bin/$(DEB_HOST_MULTIARCH)-$(PVER)-dbg-config
+       ln -sf $(DEB_HOST_MULTIARCH)-$(PVER)-config.1.gz \
+               $(d_ldbg)/usr/share/man/man1/$(DEB_HOST_MULTIARCH)-$(PVER)d-config.1.gz
+       ln -sf $(DEB_HOST_MULTIARCH)-$(PVER)-config.1.gz \
+               $(d_ldbg)/usr/share/man/man1/$(DEB_HOST_MULTIARCH)-$(PVER)-dbg-config.1.gz
+ifneq ($(DEB_HOST_MULTIARCH),$(DEB_HOST_GNU_TYPE))
+       ln -sf $(DEB_HOST_MULTIARCH)-$(PVER)d-config \
+               $(d_ldbg)/usr/bin/$(DEB_HOST_GNU_TYPE)-$(PVER)d-config
+       ln -sf $(DEB_HOST_MULTIARCH)-$(PVER)-config.1.gz \
+               $(d_ldbg)/usr/share/man/man1/$(DEB_HOST_GNU_TYPE)-$(PVER)d-config.1.gz
+       ln -sf $(DEB_HOST_MULTIARCH)-$(PVER)d-config \
+               $(d_ldbg)/usr/bin/$(DEB_HOST_GNU_TYPE)-$(PVER)-dbg-config
+       ln -sf $(DEB_HOST_MULTIARCH)-$(PVER)d-config.1.gz \
+               $(d_ldbg)/usr/share/man/man1/$(DEB_HOST_GNU_TYPE)-$(PVER)-dbg-config.1.gz
+endif
+       ln -sf $(DEB_HOST_MULTIARCH)-$(PVER)d-config $(d_dbg)/usr/bin/$(PVER)d-config
+       ln -sf $(DEB_HOST_MULTIARCH)-$(PVER)d-config.1.gz $(d_dbg)/usr/share/man/man1/$(PVER)d-config.1.gz
+
+       ln -sf $(DEB_HOST_MULTIARCH)-$(PVER)-dbg-config $(d_dbg)/usr/bin/$(PVER)-dbg-config
+       ln -sf $(DEB_HOST_MULTIARCH)-$(PVER)-dbg-config.1.gz $(d_dbg)/usr/share/man/man1/$(PVER)-dbg-config.1.gz
+
+       : # symlinks for the "old" include / config directory names
+       ln -sf $(PVER)-config.1.gz $(d_dbg)/usr/share/man/man1/$(PVER)-dbg-config.1.gz
+       ln -sf $(PVER).1.gz $(d_dbg)/usr/share/man/man1/$(PVER)d.1.gz
+       ln -sf $(PVER)-config.1.gz $(d_dbg)/usr/share/man/man1/$(PVER)d-config.1.gz
+
+ifeq ($(with_udeb),yes)
+       : # Copy the most important files from $(p_min) into $(p_udeb).
+       dh_installdirs -p$(p_udeb) \
+               etc/$(PVER) \
+               usr/bin \
+               usr/include/$(PVER)u \
+               $(scriptdir)/lib-dynload \
+               $(scriptdir)/config-$(VER)-$(DEB_HOST_MULTIARCH)
+       cp -p $(d_min)/usr/bin/python$(VER) $(d_udeb)/usr/bin/
+       ln -sf python$(VER)u $(d_udeb)/usr/bin/python$(VER)
+       ln -sf python$(VER) $(d_udeb)/usr/bin/python3
+       cp -p $(foreach i,$(MIN_MODS),$(d_min)/$(scriptdir)/$(i).py) \
+               $(d_udeb)/$(scriptdir)/
+       cp -a $(foreach i,$(MIN_PACKAGES),$(d_min)/$(scriptdir)/$(i)) \
+               $(d_udeb)/$(scriptdir)/
+       cp -p $(foreach i,$(MIN_ENCODINGS),$(d_min)/$(scriptdir)/$(i)) \
+               $(d_udeb)/$(scriptdir)/
+       cp -p $(d_min)/$(scriptdir)/config-$(VER)-$(DEB_HOST_MULTIARCH)/Makefile \
+               $(d_udeb)/$(scriptdir)/config-$(VER)-$(DEB_HOST_MULTIARCH)/
+       cp -p $(d_min)/usr/include/$(DEB_HOST_MULTIARCH)/$(PVER)/pyconfig.h \
+               $(d_udeb)/usr/include/$(DEB_HOST_MULTIARCH)/$(PVER)/
+       cp -p $(d_min)/$(scriptdir)/site.py $(d_udeb)/$(scriptdir)/
+       cp -p debian/sitecustomize.py $(d_udeb)/etc/$(PVER)/
+       dh_link -p$(p_udeb) /etc/$(PVER)/sitecustomize.py \
+               /$(scriptdir)/sitecustomize.py
+endif
+
+       for i in debian/*.overrides; do \
+         b=$$(basename $$i .overrides); \
+         install -D -m 644 $$i debian/$$b/usr/share/lintian/overrides/$$b; \
+       done
+
+       touch stamps/stamp-install
+
+# Build architecture-independent files here.
+binary-indep: build-indep install stamps/stamp-control
+       dh_testdir -i
+       dh_testroot -i
+
+       : # $(p_doc) package
+       dh_installdirs -p$(p_doc) \
+               usr/share/doc/$(p_base) \
+               usr/share/doc/$(p_doc)
+       dh_installdocs -p$(p_doc)
+       cp -a Doc/build/html $(d_doc)/usr/share/doc/$(p_base)/
+       rm -f $(d_doc)/usr/share/doc/$(p_base)/html/_static/jquery.js
+       dh_link -p$(p_doc) \
+               /usr/share/doc/$(p_base)/html /usr/share/doc/$(p_doc)/html \
+               /usr/share/javascript/jquery/jquery.js /usr/share/doc/$(p_base)/html/_static/jquery.js \
+               /usr/share/javascript/underscore/underscore.js /usr/share/doc/$(p_base)/html/_static/underscore.js
+       dh_installinfo -p$(p_doc)
+       for f in $(d_doc)/usr/share/doc/$(p_base)/html/_images/*.png; do \
+         b=$$(basename $$f); \
+         dh_link -p$(p_doc) /usr/share/doc/$(p_base)/html/_images/$$b /usr/share/info/$(PVER)/$$b; \
+       done
+
+       : # devhelp docs
+       cd $(buildd_static) && ./python ../debian/pyhtml2devhelp.py \
+               ../$(d_doc)/usr/share/doc/$(p_base)/html index.html $(VER) \
+               > ../$(d_doc)/usr/share/doc/$(p_base)/html/$(PVER).devhelp
+       gzip -9nv $(d_doc)/usr/share/doc/$(p_base)/html/$(PVER).devhelp
+       dh_link -p$(p_doc) \
+               /usr/share/doc/$(p_base)/html /usr/share/devhelp/books/$(PVER)
+
+       for i in $(p_ltst); do \
+         rm -rf debian/$$i/usr/share/doc/$$i; \
+         ln -s $(p_base) debian/$$i/usr/share/doc/$$i; \
+       done
+
+       dh_installdebconf -i $(dh_args)
+       dh_installexamples -i $(dh_args)
+       -dh_icons -i $(dh_args) || dh_iconcache -i $(dh_args)
+       dh_installchangelogs -i $(dh_args)
+       dh_link -i $(dh_args)
+       dh_compress -i $(dh_args) -X.py -X.cls -X.css -X.txt -X.json -X.js -Xobjects.inv -Xgdbinit
+       dh_fixperms -i $(dh_args)
+
+       : # make python scripts starting with '#!' executable
+       for i in `find debian -mindepth 3 -type f ! -name '*.dpatch' ! -perm 755`; do \
+         if head -1 $$i | grep -q '^#!'; then \
+           chmod 755 $$i; \
+           echo "make executable: $$i"; \
+         fi; \
+       done
+       -find $(d_doc) -name '*.txt' -perm 755 -exec chmod 644 {} \;
+
+       dh_installdeb -i $(dh_args)
+       dh_gencontrol -i $(dh_args)
+       dh_md5sums -i $(dh_args)
+       dh_builddeb -i $(dh_args)
+
+# Build architecture-dependent files here.
+binary-arch: build-arch install
+       dh_testdir -a
+       dh_testroot -a
+#      dh_installdebconf -a
+       dh_installexamples -a
+       dh_installmenu -a
+       -dh_icons -a || dh_iconcache -a
+#      dh_installmime -a
+       dh_installchangelogs -a
+       for i in $(p_dev) $(p_dbg) $(p_venv); do \
+         rm -rf debian/$$i/usr/share/doc/$$i; \
+         ln -s $(p_base) debian/$$i/usr/share/doc/$$i; \
+       done
+       for i in $(p_lbase); do \
+         rm -rf debian/$$i/usr/share/doc/$$i; \
+         ln -s $(p_lmin) debian/$$i/usr/share/doc/$$i; \
+       done
+       for i in $(p_ldev) $(p_ldbg) $(p_lib); do \
+         rm -rf debian/$$i/usr/share/doc/$$i; \
+         ln -s $(p_lbase) debian/$$i/usr/share/doc/$$i; \
+       done
+       -find debian ! -perm -200 -print -exec chmod +w {} \;
+ifneq ($(with_tk),yes)
+       rm -f $(d_lbase)/$(scriptdir)/lib-dynload/_tkinter*.so
+endif
+ifneq ($(with_gdbm),yes)
+       rm -f $(d_lbase)/$(scriptdir)/lib-dynload/_gdbm*.so
+endif
+
+       find $(d_ldbg) $(d_ldev) -name '*.a' ! -type l \
+               | xargs -n 1 $(DEB_HOST_GNU_TYPE)-objcopy -p --remove-section=.gnu.lto_.*
+       dh_strip -a -N$(p_dbg) -N$(p_ldbg) -Xdebug -Xdbg --dbg-package=$(p_dbg)
+       mkdir -p $(d_dbg)/usr/share/gdb/auto-load/usr/bin
+       cp Tools/gdb/libpython.py $(d_dbg)/usr/share/gdb/auto-load/usr/bin/$(PVER)m-gdb.py
+       ln -sf $(PVER)m-gdb.py $(d_dbg)/usr/share/gdb/auto-load/usr/bin/$(PVER)-gdb.py
+       ln -sf $(PVER)m-gdb.py $(d_dbg)/usr/share/gdb/auto-load/usr/bin/$(PVER)dm-gdb.py
+       ln -sf $(PVER)m-gdb.py $(d_dbg)/usr/share/gdb/auto-load/usr/bin/$(PVER)-dbg-gdb.py
+       mkdir -p $(d_dbg)/usr/share/gdb/auto-load/usr/lib/$(DEB_HOST_MULTIARCH)
+       ln -sf ../../bin/$(PVER)m-gdb.py \
+               $(d_dbg)/usr/share/gdb/auto-load/usr/lib/$(DEB_HOST_MULTIARCH)/lib$(PVER)m.so.1.0-gdb.py
+       ln -sf ../../bin/$(PVER)m-gdb.py \
+               $(d_dbg)/usr/share/gdb/auto-load/usr/lib/$(DEB_HOST_MULTIARCH)/lib$(PVER)dm.so.1.0-gdb.py
+       dh_link -a
+       dh_compress -a -X.py
+       dh_fixperms -a
+       chmod 644 $(d_lmin)/$(scriptdir)/token.py
+
+       : # make python scripts starting with '#!' executable
+       for i in `find debian -mindepth 3 -type f ! -perm 755`; do \
+         if head -1 $$i | grep -q '^#!'; then \
+           chmod 755 $$i; \
+           echo "make executable: $$i"; \
+         fi; \
+       done
+
+       dh_makeshlibs -p$(p_lib) -V '$(p_lib)'
+       dh_makeshlibs -p$(p_ldbg) -V '$(p_ldbg)'
+# don't include the following symbols, found in extensions
+# which either can be built as builtin or extension.
+       sed -ri \
+         -e '/^ (PyInit_|_add_one_to_index|asdl_)/d' \
+         -e '/^ (PyExpat_XML_|PyExpat_Xml)/d' \
+         -e '/^ (ffi_type_|_ctypes_)/d' \
+           $(d_lib)/DEBIAN/symbols $(d_ldbg)/DEBIAN/symbols
+       dh_installdeb -a
+       dh_shlibdeps -a
+       dep=`sed -n '/^shlibs:Depends/s/[^=]*=\(.*\)/\1/p' $(d_min).substvars | awk -v RS=', ' -v ORS=', ' '/^libc6/ { print }'`; \
+       echo "shlibs:Pre-Depends=$$dep" >> $(d_min).substvars
+       sed -i '/^shlibs:Depends/s/libc6[^,]*[, ]*//g' $(d_min).substvars
+       dh_gencontrol -a -- $(arch_substvars)
+       dh_md5sums -a
+       dh_builddeb -a
+
+# rules to patch the unpacked files in the source directory
+# ---------------------------------------------------------------------------
+# various rules to unpack addons and (un)apply patches.
+#      - patch / apply-patches
+#      - unpatch / reverse-patches
+
+patchdir       = debian/patches
+
+patch: stamps/stamp-patch
+stamps/stamp-patch:
+       dh_testdir
+       uname -a
+       @echo USER=$$USER, LOGNAME=$$LOGNAME
+       @grep ^Mem /proc/meminfo
+       @echo "DEB_BUILD_OPTIONS: $$DEB_BUILD_OPTIONS"
+
+       rm -rf autom4te.cache configure
+       autoconf
+       mkdir -p stamps
+       echo ""; echo "Patches applied in this version:" > stamps/pxx
+       for i in $$(cat $(patchdir)/series); do \
+         case "$$i" in \#*) continue; esac; \
+         echo ""; echo "$$i:"; \
+         sed -n 's/^# *DP: */  /p' $(patchdir)/$$i; \
+       done >> stamps/pxx
+
+       touch Parser/acceler.c Parser/grammar1.c Parser/listnode.c \
+         Parser/node.c Parser/parser.c Parser/token.c
+
+       touch Objects/obmalloc.c Python/dynamic_annotations.c \
+         Python/mysnprintf.c Python/pyctype.c
+       @sleep 1
+       touch Grammar/Grammar 
+       @sleep 1
+       touch Include/graminit.h
+       @sleep 1
+       touch Python/graminit.c
+
+       ln -sf site-packages Lib/dist-packages
+
+       mv stamps/pxx $@
+
+reverse-patches: unpatch
+unpatch:
+       rm -rf configure autom4te.cache
+
+update-patches: $(patchdir)/series
+       export QUILT_PATCHES=$(patchdir); \
+       export QUILT_REFRESH_ARGS="--no-timestamps --no-index -pab"; \
+       export QUILT_DIFF_ARGS="--no-timestamps --no-index -pab"; \
+       while quilt push; do quilt refresh; done
+
+binary: binary-indep binary-arch
+
+.NOTPARALLEL:
+.PHONY: control-file configure build clean binary-indep binary-arch binary install
+
+# Local Variables:
+# mode: makefile
+# end:
diff --git a/script.py b/script.py
new file mode 100644 (file)
index 0000000..c871b54
--- /dev/null
+++ b/script.py
@@ -0,0 +1,64 @@
+#! /usr/bin/python3
+
+# Copyright (C) 2012 Colin Watson <cjwatson@ubuntu.com>.
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject
+# to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+"""Trivial script(1) workalike, but without reading from standard input."""
+
+import os
+import pty
+import select
+import sys
+
+filename = sys.argv[1]
+command = sys.argv[2]
+
+pid, master = pty.fork()
+if pid == 0:  # child
+    os.execlp("sh", "sh", "-c", command)
+
+# parent
+with open(filename, "wb") as logfile:
+    try:
+        while True:
+            rfds, _, _ = select.select([master], [], [])
+            if master in rfds:
+                data = os.read(master, 65536)
+                # Check for EOF
+                if not data:
+                    break
+                os.write(1, data)
+                logfile.write(data)
+                logfile.flush()
+    except (IOError, OSError):
+        pass
+
+pid, status = os.wait()
+returncode = 0
+if os.WIFSIGNALED(status):
+    returncode = -os.WTERMSIG(status)
+elif os.WIFEXITED(status):
+    returncode = os.WEXITSTATUS(status)
+else:
+    # Should never happen
+    raise RuntimeError("Unknown child exit status!")
+os.close(master)
+sys.exit(returncode)
diff --git a/sitecustomize.py.in b/sitecustomize.py.in
new file mode 100644 (file)
index 0000000..89c6712
--- /dev/null
@@ -0,0 +1,7 @@
+# install the apport exception handler if available
+try:
+    import apport_python_hook
+except ImportError:
+    pass
+else:
+    apport_python_hook.install()
diff --git a/source/format b/source/format
new file mode 100644 (file)
index 0000000..163aaf8
--- /dev/null
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/source/lintian-overrides b/source/lintian-overrides
new file mode 100644 (file)
index 0000000..421c3f3
--- /dev/null
@@ -0,0 +1,5 @@
+# generated during the build
+quilt-build-dep-but-no-series-file
+
+# in the source only, and can be built with mingw64
+source-contains-prebuilt-windows-binary
diff --git a/tests/control b/tests/control
new file mode 100644 (file)
index 0000000..4dc7a02
--- /dev/null
@@ -0,0 +1,63 @@
+Tests: testsuite
+Depends: build-essential,
+  locales-all,
+  python3.9-dev,
+  libpython3.9-testsuite:native,
+  python3-gdbm,
+  python3-distutils,
+  python3-tk,
+  idle-python3.9,
+  systemtap-sdt-dev,
+# need to turn off apport
+Restrictions: needs-root
+
+Tests: testsuite-dbg
+Depends: build-essential,
+  locales-all, python3.9-dev,
+  python3.9-dbg,
+  libpython3.9-testsuite:native,
+  python3-gdbm-dbg,
+  gdb,
+  python3-distutils,
+  python3-tk-dbg,
+  idle-python3.9,
+  systemtap-sdt-dev,
+# need to turn off apport
+Restrictions: needs-root
+
+Tests: failing-tests
+Depends: build-essential,
+  locales-all,
+  python3.9-dev,
+  libpython3.9-testsuite:native,
+  python3-gdbm,
+  python3-distutils,
+  python3-tk,
+# need to turn off apport
+Restrictions: needs-root allow-stderr
+
+Tests: failing-tests-dbg
+Depends: build-essential,
+  locales-all,
+  python3.9-dev,
+  python3.9-dbg,
+  libpython3.9-testsuite:native,
+  python3-gdbm-dbg,
+  gdb,
+  python3-distutils,
+  python3-tk-dbg,
+# need to turn off apport
+Restrictions: needs-root allow-stderr
+
+Tests: module-install-local
+Depends: build-essential, python3.9-dev, python3-setuptools, shunit2
+Restrictions: needs-root
+
+Tests: module-install-user
+Depends: build-essential, python3.9-dev, python3-setuptools, shunit2
+
+Tests: module-install-venv
+Depends: build-essential, python3.9-dev, python3.9-venv, shunit2
+
+Tests: module-install-virtualenv
+Depends: build-essential, python3.9-dev, shunit2, virtualenv
diff --git a/tests/failing-tests b/tests/failing-tests
new file mode 100755 (executable)
index 0000000..9313ad9
--- /dev/null
@@ -0,0 +1,75 @@
+#!/bin/sh
+
+set -e
+
+if [ "$(whoami)" = root ]; then
+  if [ -n "$SUDO_USER" ] && getent passwd "$SUDO_USER" > /dev/null; then
+    su_user="$SUDO_USER"
+  else
+    su_user=nobody
+  fi
+
+  if [ -e /etc/default/apport ]; then
+    # stop apport
+    service apport stop 2>/dev/null || true
+    sed -i '/^enabled=/s/=.*/=0/' /etc/default/apport 2>/dev/null
+  fi
+fi
+
+tmphome=$AUTOPKGTEST_TMP/home
+mkdir -p $tmphome/.local/lib/python3.9/site-packages
+if [ -n "$su_user" ]; then
+  chmod go+rx $AUTOPKGTEST_TMP
+  chown $su_user:nogroup $tmphome
+fi
+ls -la $AUTOPKGTEST_TMP
+
+debian_dir=$(dirname $(dirname $0))
+
+# no root access needed after this point
+
+TESTPYTHON="python3.9 -W default -bb -E -R -m test"
+TESTEXCLUSIONS=""
+
+. $debian_dir/tests/test-common.sh
+
+if [ "$su_user" = nobody ]; then
+  log=/dev/null
+else
+  log=testsuite.log
+fi
+
+script=$debian_dir/script.py
+echo "Running the failing tests with the standard interpreter:"
+progressions=
+for tst in $TESTEXCLUSIONS; do
+  if [ -f "$script" ]; then
+    cmd="HOME=$tmphome python3.9 $script \"$log\" \"$TESTPYTHON $TESTOPTS $tst\""
+  else
+    cmd="HOME=$tmphome $TESTPYTHON $TESTOPTS $tst"
+  fi
+
+  echo "Running $tst ..."
+  if [ "$(whoami)" = root ]; then
+    echo "su -s /bin/sh -c $cmd $su_user"
+    if su -s /bin/sh -c "$cmd" $su_user; then
+      progressions="$progressions $tst"
+    else
+      :
+    fi
+  else
+    echo "$cmd"
+    if eval $cmd; then
+      progressions="$progressions $tst"
+    else
+      :
+    fi
+  fi
+done
+
+if [ -n "$progressions" ]; then
+  echo "Tests run: $TESTEXCLUSIONS"
+  echo "Progressions:$progressions"
+fi
+
+exit 0
diff --git a/tests/failing-tests-dbg b/tests/failing-tests-dbg
new file mode 100755 (executable)
index 0000000..670a622
--- /dev/null
@@ -0,0 +1,75 @@
+#!/bin/sh
+
+set -e
+
+if [ "$(whoami)" = root ]; then
+  if [ -n "$SUDO_USER" ] && getent passwd "$SUDO_USER" > /dev/null; then
+    su_user="$SUDO_USER"
+  else
+    su_user=nobody
+  fi
+
+  if [ -e /etc/default/apport ]; then
+    # stop apport
+    service apport stop 2>/dev/null || true
+    sed -i '/^enabled=/s/=.*/=0/' /etc/default/apport 2>/dev/null
+  fi
+fi
+
+tmphome=$AUTOPKGTEST_TMP/home
+mkdir -p $tmphome/.local/lib/python3.9/site-packages
+if [ -n "$su_user" ]; then
+  chmod go+rx $AUTOPKGTEST_TMP
+  chown $su_user:nogroup $tmphome
+fi
+ls -la $AUTOPKGTEST_TMP
+
+debian_dir=$(dirname $(dirname $0))
+
+# no root access needed after this point
+
+TESTPYTHON="python3.9d -W default -bb -E -R -m test"
+TESTEXCLUSIONS=""
+
+. $debian_dir/tests/test-common.sh
+
+if [ "$su_user" = nobody ]; then
+  log=/dev/null
+else
+  log=testsuite-dbg.log
+fi
+
+script=$debian_dir/script.py
+echo "Running the failing tests with the debug enabled interpreter:"
+progressions=
+for tst in $TESTEXCLUSIONS; do
+  if [ -f "$script" ]; then
+    cmd="HOME=$tmphome python3.9 $script \"$log\" \"$TESTPYTHON $TESTOPTS $tst\""
+  else
+    cmd="HOME=$tmphome $TESTPYTHON $TESTOPTS $tst"
+  fi
+
+  echo "Running $tst ..."
+  if [ "$(whoami)" = root ]; then
+    echo "su -s /bin/sh -c $cmd $su_user"
+    if su -s /bin/sh -c "$cmd" $su_user; then
+      progressions="$progressions $tst"
+    else
+      :
+    fi
+  else
+    echo "$cmd"
+    if eval $cmd; then
+      progressions="$progressions $tst"
+    else
+      :
+    fi
+  fi
+done
+
+if [ -n "$progressions" ]; then
+  echo "Tests run: $TESTEXCLUSIONS"
+  echo "Progressions:$progressions"
+fi
+
+exit 0
diff --git a/tests/module-install-local b/tests/module-install-local
new file mode 100755 (executable)
index 0000000..11c266a
--- /dev/null
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+cp -a debian/tests/packages "$AUTOPKGTEST_TMP"
+
+setUp() {
+       mount -t tmpfs tmpfs /usr/local/lib/python3.9/dist-packages
+}
+
+tearDown() {
+       umount /usr/local/lib/python3.9/dist-packages
+}
+
+testFibPy() {
+       cd "$AUTOPKGTEST_TMP/packages/fibpy"
+       python3.9 setup.py install
+       assertTrue 'Install fibpy in /usr/local' $?
+       cd "$AUTOPKGTEST_TMP"
+       stdout=$(python3.9 -m fibpy 5)
+       assertTrue 'Execute fibpy from a virtualenv' $?
+       assertEquals 'Correct result' 8 "$stdout"
+}
+
+testFibC() {
+       cd "$AUTOPKGTEST_TMP/packages/fibc"
+       python3.9 setup.py install
+       assertTrue 'Install fibc in /usr/local' $?
+       cd "$AUTOPKGTEST_TMP"
+       stdout=$(python3.9 -c 'from fibc import fib; print(fib(5))')
+       assertTrue 'Execute fibc from a virtualenv' $?
+       assertEquals 'Correct result' 8 "$stdout"
+}
+
+. shunit2
diff --git a/tests/module-install-user b/tests/module-install-user
new file mode 100755 (executable)
index 0000000..8217338
--- /dev/null
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+cp -a debian/tests/packages "$AUTOPKGTEST_TMP"
+
+HOME="$AUTOPKGTEST_TMP/home"
+mkdir "$HOME"
+
+tearDown() {
+       # Remove the --user install directory
+       rm -rf "$HOME/.local/lib/python3.9/site-packages"
+}
+
+testFibPy() {
+       cd "$AUTOPKGTEST_TMP/packages/fibpy"
+       python3.9 setup.py install --user
+       assertTrue 'Install fibpy in --user' $?
+       cd "$AUTOPKGTEST_TMP"
+       stdout=$(python3.9 -m fibpy 5)
+       assertTrue 'Execute fibpy from a virtualenv' $?
+       assertEquals 'Correct result' 8 "$stdout"
+}
+
+testFibC() {
+       cd "$AUTOPKGTEST_TMP/packages/fibc"
+       python3.9 setup.py install --user
+       assertTrue 'Install fibc in --user' $?
+       cd "$AUTOPKGTEST_TMP"
+       stdout=$(python3.9 -c 'from fibc import fib; print(fib(5))')
+       assertTrue 'Execute fibc from a virtualenv' $?
+       assertEquals 'Correct result' 8 "$stdout"
+}
+
+. shunit2
diff --git a/tests/module-install-venv b/tests/module-install-venv
new file mode 100755 (executable)
index 0000000..e00a84b
--- /dev/null
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+cp -a debian/tests/packages "$AUTOPKGTEST_TMP"
+HOME="$AUTOPKGTEST_TMP/home"
+mkdir -p "$HOME"
+python3.9 -m venv "$AUTOPKGTEST_TMP/ve"
+
+VP="$AUTOPKGTEST_TMP/ve/bin/python"
+
+testFibPy() {
+       cd "$AUTOPKGTEST_TMP/packages/fibpy"
+       $VP setup.py install
+       assertTrue 'Install fibpy in a virtualenv' $?
+       cd "$AUTOPKGTEST_TMP"
+       stdout=$($VP -m fibpy 5)
+       assertTrue 'Execute fibpy from a virtualenv' $?
+       assertEquals 'Correct result' 8 "$stdout"
+}
+
+testFibC() {
+       cd "$AUTOPKGTEST_TMP/packages/fibc"
+       $VP setup.py install
+       assertTrue 'Install fibc in a virtualenv' $?
+       cd "$AUTOPKGTEST_TMP"
+       stdout=$($VP -c 'from fibc import fib; print(fib(5))')
+       assertTrue 'Execute fibc from a virtualenv' $?
+       assertEquals 'Correct result' 8 "$stdout"
+}
+
+. shunit2
diff --git a/tests/module-install-virtualenv b/tests/module-install-virtualenv
new file mode 100755 (executable)
index 0000000..8020f46
--- /dev/null
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+cp -a debian/tests/packages "$AUTOPKGTEST_TMP"
+HOME="$AUTOPKGTEST_TMP/home"
+mkdir -p "$HOME"
+virtualenv -p python3.9 "$AUTOPKGTEST_TMP/ve"
+
+VP="$AUTOPKGTEST_TMP/ve/bin/python"
+
+testFibPy() {
+       cd "$AUTOPKGTEST_TMP/packages/fibpy"
+       $VP setup.py install
+       assertTrue 'Install fibpy in a virtualenv' $?
+       cd "$AUTOPKGTEST_TMP"
+       stdout=$($VP -m fibpy 5)
+       assertTrue 'Execute fibpy from a virtualenv' $?
+       assertEquals 'Correct result' 8 "$stdout"
+}
+
+testFibC() {
+       cd "$AUTOPKGTEST_TMP/packages/fibc"
+       $VP setup.py install
+       assertTrue 'Install fibc in a virtualenv' $?
+       cd "$AUTOPKGTEST_TMP"
+       stdout=$($VP -c 'from fibc import fib; print(fib(5))')
+       assertTrue 'Execute fibc from a virtualenv' $?
+       assertEquals 'Correct result' 8 "$stdout"
+}
+
+. shunit2
diff --git a/tests/packages/fibc/fibc.c b/tests/packages/fibc/fibc.c
new file mode 100644 (file)
index 0000000..8680874
--- /dev/null
@@ -0,0 +1,37 @@
+#include <Python.h>
+
+int fib(int n) {
+       if (n < 0) {
+               return -1; // Raise
+       }
+       if (n < 2) {
+               return 1;
+       }
+       return fib(n - 1) + fib(n - 2);
+}
+
+static PyObject * fibc_fib(PyObject *self, PyObject *args) {
+       int n;
+
+       if (!PyArg_ParseTuple(args, "i", &n))
+               return NULL;
+       int r = fib(n);
+       return PyLong_FromLong(r);
+}
+
+static PyMethodDef FibcMethods[] = {
+       {"fib",  fibc_fib, METH_VARARGS, "Calculate a fibonacci sequence value."},
+       {NULL, NULL, 0, NULL},
+};
+
+static PyModuleDef fibcmodule = {
+       PyModuleDef_HEAD_INIT,
+       "fibc",
+       NULL,  // documentation
+       -1,  // state in global vars
+       FibcMethods
+};
+
+PyMODINIT_FUNC PyInit_fibc(void) {
+       return PyModule_Create(&fibcmodule);
+};
diff --git a/tests/packages/fibc/setup.py b/tests/packages/fibc/setup.py
new file mode 100755 (executable)
index 0000000..d974289
--- /dev/null
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+
+from setuptools import setup, Extension
+
+setup(
+    name='fibc',
+    version='42.0.0',
+    description='C Fibonacci',
+    ext_modules=[Extension(
+        'fibc',
+        sources=['fibc.c'],
+    )],
+    zip_safe=False,
+)
diff --git a/tests/packages/fibpy/fibpy.py b/tests/packages/fibpy/fibpy.py
new file mode 100644 (file)
index 0000000..1d1374a
--- /dev/null
@@ -0,0 +1,13 @@
+import sys
+
+
+def fib(n):
+    if n < 0:
+        raise ValueError()
+    if n < 2:
+        return 1
+    return fib(n - 1) + fib(n - 2)
+
+
+if __name__ == '__main__':
+    print(fib(int(sys.argv[1])))
diff --git a/tests/packages/fibpy/setup.py b/tests/packages/fibpy/setup.py
new file mode 100755 (executable)
index 0000000..6c47db9
--- /dev/null
@@ -0,0 +1,11 @@
+#!/usr/bin/env python
+
+from setuptools import setup
+
+setup(
+    name='fibpy',
+    version='42.0.0',
+    description='Pure Python Fibonacci',
+    py_modules=['fibpy'],
+    zip_safe=True,
+)
diff --git a/tests/test-common.sh b/tests/test-common.sh
new file mode 100644 (file)
index 0000000..bcbbf1b
--- /dev/null
@@ -0,0 +1,67 @@
+
+if dpkg-vendor --derives-from Ubuntu; then
+  vendor=Ubuntu
+elif dpkg-vendor --derives-from Debian; then
+  vendor=Debian
+else
+  vendor=Unknown
+fi
+
+export LOCPATH=$(pwd)/locales
+sh $debian_dir/locale-gen
+
+export LANG=C.UTF-8
+
+export DEB_PYTHON_INSTALL_LAYOUT=deb_system
+
+TESTOPTS="-j 1 -w -uall,-network,-urlfetch,-gui"
+
+# test_dbm: Fails from time to time ...
+#TESTEXCLUSIONS="$TESTEXCLUSIONS test_dbm"
+
+# test_ensurepip: not yet installed, http://bugs.debian.org/732703
+# ... and then test_venv fails too
+TESTEXCLUSIONS="$TESTEXCLUSIONS test_ensurepip test_venv "
+
+# test_lib2to3: see https://bugs.python.org/issue34286
+TESTEXCLUSIONS="$TESTEXCLUSIONS test_lib2to3"
+
+# test_tcl: see https://bugs.python.org/issue34178
+TESTEXCLUSIONS="$TESTEXCLUSIONS test_tcl"
+
+# FIXME: Failing with OpenSSL 1.2 ...
+# ssl.SSLError: [SSL: CA_MD_TOO_WEAK] ca md too weak (_ssl.c:3401)
+if [ "$vendor" = Debian ]; then
+  TESTEXCLUSIONS="$TESTEXCLUSIONS test_asyncio test_ftplib test_httplib test_imaplib test_nntplib test_poplib test_ssl"
+fi
+
+# FIXME: testWithTimeoutTriggeredSend: timeout not raised by _sendfile_use_sendfile
+TESTEXCLUSIONS="$TESTEXCLUSIONS test_socket"
+
+# FIXME: issue 34806: some distutils tests fail recently
+TESTEXCLUSIONS="$TESTEXCLUSIONS test_distutils"
+
+# FIXME: test_site tests fail with 3.9
+TESTEXCLUSIONS="$TESTEXCLUSIONS test_site"
+
+# FIXME, failing on the Ubuntu autopkg testers
+if [ "$vendor" = Ubuntu ]; then
+  TESTEXCLUSIONS="$TESTEXCLUSIONS test_code_module test_platform test_site"
+fi
+
+# test_ssl currently assumes that OpenSSL is compiled with SECURITY_LEVEL=1
+# set security level to 1 for now, to make test_ssl pass
+export OPENSSL_CONF=$debian_dir/openssl.cnf
+
+# FIXME: Fails with Ubuntu's autopkg test infrastructure
+if [ "$vendor" = Ubuntu ]; then
+  if [ "$(dpkg --print-architecture)" = arm64 ]; then
+    TESTEXCLUSIONS="$TESTEXCLUSIONS test_io"
+  fi
+fi
+
+# FIXME: test_ttk_guionly times out on many buildds
+TESTEXCLUSIONS="$TESTEXCLUSIONS test_ttk_guionly"
+
+# FIXME: test_ttk_textonly started failing in 3.9.1 rc1
+TESTEXCLUSIONS="$TESTEXCLUSIONS test_ttk_textonly"
diff --git a/tests/testsuite b/tests/testsuite
new file mode 100755 (executable)
index 0000000..eb0a449
--- /dev/null
@@ -0,0 +1,61 @@
+#!/bin/sh
+
+env
+
+set -e
+
+if [ "$(whoami)" = root ]; then
+  if [ -n "$SUDO_USER" ] && getent passwd "$SUDO_USER" > /dev/null; then
+    su_user="$SUDO_USER"
+  else
+    su_user=nobody
+  fi
+
+  if [ -e /etc/default/apport ]; then
+    # stop apport
+    service apport stop 2>/dev/null || true
+    sed -i '/^enabled=/s/=.*/=0/' /etc/default/apport 2>/dev/null
+  fi
+fi
+tmphome=$AUTOPKGTEST_TMP/home
+mkdir -p $tmphome
+if [ -n "$su_user" ]; then
+  chmod go+rx $AUTOPKGTEST_TMP
+  chown $su_user:nogroup $tmphome
+fi
+ls -la $AUTOPKGTEST_TMP
+
+debian_dir=$(dirname $(dirname $0))
+
+# no root access needed after this point
+
+TESTPYTHON="python3.9 -W default -bb -E -R -m test"
+TESTEXCLUSIONS="-x"
+
+. $debian_dir/tests/test-common.sh
+
+if [ "$su_user" = nobody ]; then
+  log=/dev/null
+else
+  log=testsuite.log
+fi
+
+# several tests fail with configured proxy; we don't need internet access, so
+# unset proxy variables
+EXTRAENV="env -u https_proxy -u http_proxy -u no_proxy HOME=$tmphome"
+
+script=$debian_dir/script.py
+if [ -f "$script" ]; then
+  cmd="$EXTRAENV python3.9 $script \"$log\" \"$TESTPYTHON $TESTOPTS $TESTEXCLUSIONS\""
+else
+  cmd="$EXTRAENV $TESTPYTHON $TESTOPTS $TESTEXCLUSIONS"
+fi
+
+echo "Running the python testsuite with the standard interpreter:"
+if [ "$(whoami)" = root ]; then
+  echo "su -s /bin/sh -c $cmd $su_user"
+  su -s /bin/sh -c "$cmd" $su_user
+else
+  echo "$cmd"
+  eval $cmd
+fi
diff --git a/tests/testsuite-dbg b/tests/testsuite-dbg
new file mode 100755 (executable)
index 0000000..036fea1
--- /dev/null
@@ -0,0 +1,60 @@
+#!/bin/sh
+
+set -e
+
+if [ "$(whoami)" = root ]; then
+  if [ -n "$SUDO_USER" ] && getent passwd "$SUDO_USER" > /dev/null; then
+    su_user="$SUDO_USER"
+  else
+    su_user=nobody
+  fi
+
+  if [ -e /etc/default/apport ]; then
+    # stop apport
+    service apport stop 2>/dev/null || true
+    sed -i '/^enabled=/s/=.*/=0/' /etc/default/apport 2>/dev/null
+  fi
+fi
+
+tmphome=$AUTOPKGTEST_TMP/home
+mkdir -p $tmphome/.local/lib/python3.9/site-packages
+if [ -n "$su_user" ]; then
+  chmod -R go+rx $AUTOPKGTEST_TMP
+  chown -R $su_user:nogroup $tmphome
+fi
+ls -la $AUTOPKGTEST_TMP
+
+debian_dir=$(dirname $(dirname $0))
+
+# no root access needed after this point
+
+TESTPYTHON="python3.9d -W default -bb -E -R -m test"
+TESTEXCLUSIONS="-x"
+
+. $debian_dir/tests/test-common.sh
+
+if [ "$su_user" = nobody ]; then
+  log=/dev/null
+else
+  log=testsuite-dbg.log
+fi
+
+# several tests fail with configured proxy; we don't need internet access, so
+# unset proxy variables
+EXTRAENV="env -u https_proxy -u http_proxy -u no_proxy HOME=$tmphome"
+
+script=$debian_dir/script.py
+if [ -f "$script" ]; then
+  cmd="$EXTRAENV python3.9 $script \"$log\" \"$TESTPYTHON $TESTOPTS $TESTEXCLUSIONS\""
+else
+  cmd="$EXTRAENV $TESTPYTHON $TESTOPTS $TESTEXCLUSIONS"
+fi
+
+echo "Running the python testsuite with the debug enabled interpreter:"
+if [ "$(whoami)" = root ]; then
+  echo "su -s /bin/sh -c $cmd $su_user"
+  su -s /bin/sh -c "$cmd" $su_user
+else
+  echo "$cmd"
+  eval $cmd
+fi
diff --git a/watch b/watch
new file mode 100644 (file)
index 0000000..4d8e200
--- /dev/null
+++ b/watch
@@ -0,0 +1,3 @@
+version=3
+opts=dversionmangle=s/.*\+//,uversionmangle=s/([abcr]+[1-9])$/~$1/ \
+  http://www.python.org/ftp/python/3\.9(\.\d)?/Python-(3\.9[.\dabcr]*)\.tgz